Annotation of researchv10no/cmd/sml/lib/emacs/sml-mode.el, revision 1.1.1.1

1.1       root        1: ;; sml-mode.el. Major mode for editing (Standard) ML.
                      2: ;; Copyright (C) 1989, Free Software Foundation, Inc.
                      3: 
                      4: ;; This file is part of GNU Emacs.
                      5: 
                      6: ;; GNU Emacs is distributed in the hope that it will be useful,
                      7: ;; but WITHOUT ANY WARRANTY.  No author or distributor
                      8: ;; accepts responsibility to anyone for the consequences of using it
                      9: ;; or for whether it serves any particular purpose or works at all,
                     10: ;; unless he says so in writing.  Refer to the GNU Emacs General Public
                     11: ;; License for full details.
                     12: 
                     13: ;; Everyone is granted permission to copy, modify and redistribute
                     14: ;; GNU Emacs, but only under the conditions described in the
                     15: ;; GNU Emacs General Public License.   A copy of this license is
                     16: ;; supposed to have been given to you along with GNU Emacs so you
                     17: ;; can know your rights and responsibilities.  It should be in a
                     18: ;; file named COPYING.  Among other things, the copyright notice
                     19: ;; and this notice must be preserved on all copies.
                     20: 
                     21: ;; AUTHOR      Lars Bo Nielsen
                     22: ;;             Aalborg University
                     23: ;;             Computer Science Dept.
                     24: ;;             9000 Aalborg
                     25: ;;             Denmark
                     26: ;;
                     27: ;; EMAIL       [email protected]
                     28: ;;             or: ...!mcvax!diku!iesd!lbn
                     29: ;;             or: [email protected]
                     30: ;;
                     31: ;; Please let me know if you come up with any ideas, bugs, or fixes.
                     32: ;;
                     33: 
                     34: 
                     35: (provide 'sml-mode)
                     36: 
                     37: (defconst sml-mode-version-string
                     38:   "SML-MODE, Version 2.4 (Oct 1989) ([email protected])")
                     39: 
                     40: ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
                     41: ;;;
                     42: ;;; CONSTANTS CONTROLLING THE MODE.
                     43: ;;;
                     44: ;;; These are the constants you might want to change
                     45: ;;; 
                     46: 
                     47: ;; The amount of indentation of blocks
                     48: (defconst sml-indent-level 4 "*Indentation of blocks in sml.")
                     49: 
                     50: ;; The amount of negative indentation of lines beginning with "|"
                     51: (defconst sml-pipe-indent -2
                     52:   "*Extra (negative) indentation for lines beginning with |.") ;
                     53: 
                     54: ;; How do we indent case-of expressions.
                     55: (defconst sml-case-indent nil
                     56:   "*How to indent case-of expressions.
                     57:   If t:   case expr              If nil:   case expr of
                     58:             of exp1 => ...                     exp1 => ...
                     59:              | exp2 => ...                   | exp2 => ...
                     60: \nThe first seems to be the standard in NJ-SML. The second is the default.")
                     61: 
                     62: (defconst sml-nested-if-indent nil
                     63:   "*If set to t, nested if-then-else expression will have the same
                     64: indentation as:
                     65:                  if exp1 then exp2
                     66:                  else if exp3 then exp4
                     67:                  else if exp5 then exp6
                     68:                       else exp7")
                     69: 
                     70: (defconst sml-type-of-indent t
                     71:   "*How to indent `let' `struct' etc.
                     72: 
                     73: If t:  fun foo bar = let                If nil:  fun foo bar = let
                     74:                          val p = 4                   val p = 4
                     75:                      in                          in
                     76:                          bar + p                     bar + p
                     77:                      end                         end
                     78: 
                     79: Will not have any effect if the starting keyword is first on the line.")
                     80: 
                     81: (defconst sml-electric-semi-mode t
                     82:   "*If t, a `\;' will insert itself, reindent the line, and perform a newline.
                     83: If nil, just insert a `\;'. (To insert while t, do: C-q \;).")
                     84: 
                     85: ;; How far should the indentation algorithm look to find open parenthesis 
                     86: (defconst sml-paren-lookback 200
                     87:   "*Determines how far back (in chars) the indentation algorithm
                     88: should look for open parenthesis. High value means slow indentation
                     89: algorithm. A value of 200 (being the equivalent of 4-6 lines) should
                     90: suffice most uses. (A value of nil, means do not look at all)")
                     91: 
                     92: ;; The command used to start up the sml-program.
                     93: (defconst sml-prog-name "sml" "*Name of program to run as sml.")
                     94: 
                     95: ;; If t, you will be asked which program to run when the inferior
                     96: ;; shell starts up. Usefull if you have exported images of sml.
                     97: (defconst sml-prog-name-ask-p nil
                     98:   "*Should you be asked for the name of the program to run.")
                     99: 
                    100: ;; The left delimmitter for `use file'
                    101: (defconst sml-use-left-delim "\""
                    102:   "*The left delimiter for the filename when using \"use\".
                    103:  To be set to `[\\\"' for Edinburgh SML, and `\\\"' for New Jersey SML.
                    104:  Correspondes to `sml-use-right-delim'.")
                    105: 
                    106: ;; The right delimmitter for `use file'
                    107: (defconst sml-use-right-delim "\""
                    108:   "*The right delimiter for the filename when using \"use\".
                    109:  To be set to `\\\"]' for Edinburgh SML, and `\\\"' for New Jersey SML.
                    110:  Correspondes to `sml-use-left-delim'.")
                    111: 
                    112: ;; A regular expression matching the prompt pattern in the inferior
                    113: ;; shell
                    114: (defconst sml-shell-prompt-pattern "^[^\-=]*[\-=] *"
                    115:   "*The prompt pattern for the inferion shell running sml.")
                    116: 
                    117: ;; The template used for temporary files, created when a region is
                    118: ;; send to the inferior process running sml.
                    119: (defconst sml-tmp-template "/tmp/sml.tmp."
                    120:   "*Template for the temporary file, created by sml-simulate-send-region.")
                    121: 
                    122: ;; The name of the process running sml (This will also be the name of
                    123: ;; the buffer).
                    124: (defconst sml-process-name "SML" "*The name of the SML-process")
                    125: 
                    126: ;;;
                    127: ;;; END OF CONSTANTS CONTROLLING THE MODE.
                    128: ;;;
                    129: ;;; If you change anything below, you are on your own.
                    130: ;;; 
                    131: ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
                    132: 
                    133: 
                    134: (defvar sml-mode-map nil "The mode map used in sml-mode.")
                    135: (if sml-mode-map
                    136:     ()
                    137:   (setq sml-mode-map (make-sparse-keymap))
                    138:   (define-key sml-mode-map "\C-c'" 'sml-next-error)
                    139:   (define-key sml-mode-map "\C-c\C-v" 'sml-mode-version)
                    140:   (define-key sml-mode-map "\C-c\C-u" 'sml-save-buffer-use-file)
                    141:   (define-key sml-mode-map "\C-c\C-s" 'sml-pop-to-shell)
                    142:   (define-key sml-mode-map "\C-c\C-r" 'sml-send-region)
                    143:   (define-key sml-mode-map "\C-c\C-m" 'sml-region)
                    144:   (define-key sml-mode-map "\C-c\C-k" 'sml-skip-errors)
                    145:   (define-key sml-mode-map "\C-c\C-f" 'sml-run-on-file)
                    146:   (define-key sml-mode-map "\C-c\C-c" 'sml-send-function)
                    147:   (define-key sml-mode-map "\C-c\C-b" 'sml-send-buffer)
                    148:   (define-key sml-mode-map "\C-ci" 'sml-import-file)
                    149:   (define-key sml-mode-map "\e|" 'sml-electric-pipe)
                    150:   (define-key sml-mode-map "\C-j" 'reindent-then-newline-and-indent)
                    151:   (define-key sml-mode-map "\177" 'backward-delete-char-untabify)
                    152:   (define-key sml-mode-map "\;" 'sml-electric-semi)
                    153:   (define-key sml-mode-map "\C-c\t" 'sml-indent-region)
                    154:   (define-key sml-mode-map "\t" 'sml-indent-line))
                    155: 
                    156: (defvar sml-mode-syntax-table nil "The syntax table used in sml-mode.")
                    157: (if sml-mode-syntax-table
                    158:     ()
                    159:   (setq sml-mode-syntax-table (make-syntax-table))
                    160:   (modify-syntax-entry ?\( "()1" sml-mode-syntax-table)
                    161:   (modify-syntax-entry ?\) ")(4" sml-mode-syntax-table)
                    162:   (modify-syntax-entry ?\\ "\\" sml-mode-syntax-table)
                    163:   (modify-syntax-entry ?* ". 23" sml-mode-syntax-table)
                    164:   ;; Special characters in sml-mode to be treated as normal
                    165:   ;; characters:
                    166:   (modify-syntax-entry ?_ "w" sml-mode-syntax-table)
                    167:   (modify-syntax-entry ?\' "w" sml-mode-syntax-table))
                    168: 
                    169: 
                    170: (defun sml-mode ()
                    171:   "Major mode for editing SML code.
                    172: Tab indents for SML code.
                    173: Comments are delimited with (* ... *).
                    174: Paragraphs are separated by blank lines only.
                    175: Delete converts tabs to spaces as it moves back.
                    176: 
                    177: Key bindings:
                    178: =============
                    179: 
                    180: \\[sml-indent-line]\t  - Indent current line.
                    181: \\[reindent-then-newline-and-indent]\t  - Reindent line, newline and indent.
                    182: \\[sml-indent-region]\t  - Indent region.
                    183: \\[sml-electric-pipe]\t  - Insert a \"|\". Insert function name, \"=>\" etc.
                    184: \\[sml-region]\t  - Insert a common used structure.
                    185: \\[sml-pop-to-shell]\t  - Pop to the sml window.
                    186: \\[sml-next-error]\t  - Find the next error.
                    187: \\[sml-save-buffer-use-file]\t  - Save the buffer, and send a \"use file\".
                    188: \\[sml-send-region]\t  - Send region (point and mark) to sml.
                    189: \\[sml-run-on-file]\t  - Send a \"use file\" to sml.
                    190: \\[sml-import-file]\t  - Send a \"import file\" to sml.
                    191: \\[sml-send-function]\t  - Send function to sml.
                    192: \\[sml-send-buffer]\t  - Send whole buffer to sml.
                    193: \\[sml-mode-version]\t  - Get the version of sml-mode
                    194: 
                    195: 
                    196: Variables controlling the indentation
                    197: =====================================
                    198: 
                    199: sml-indent-level (default 4)
                    200:     The indentation of a block of code.
                    201: 
                    202: sml-pipe-indent (default -2)
                    203:     Extra indentation of a line starting with \"|\".
                    204: 
                    205: sml-case-indent (default nil)
                    206:     Determine the way to indent case-of expression.
                    207:        If t:   case expr              If nil:   case expr of
                    208:                  of exp1 => ...                     exp1 => ...
                    209:                   | exp2 => ...                   | exp2 => ...
                    210: 
                    211:     The first seems to be the standard in NJ-SML. The second is the default.
                    212: 
                    213: sml-nested-if-indent (default nil)
                    214:     If set to t, nested if-then-else expression will have the same
                    215:     indentation as:
                    216:                      if exp1 then exp2
                    217:                      else if exp3 then exp4
                    218:                      else if exp5 then exp6
                    219:                           else exp7
                    220: 
                    221: sml-type-of-indent (default t)
                    222:     How to indent `let' `struct' etc.
                    223: 
                    224:     If t:  fun foo bar = let                If nil:  fun foo bar = let
                    225:                              val p = 4                   val p = 4
                    226:                          in                          in
                    227:                              bar + p                     bar + p
                    228:                          end                         end
                    229: 
                    230:     Will not have any effect if the starting keyword is first on the line.
                    231: 
                    232: sml-electric-semi-mode (default t)
                    233:      If t, a `\;' will reindent line, and perform a newline.
                    234: 
                    235: Mode map
                    236: ========
                    237: \\{sml-mode-map}
                    238: Runs sml-mode-hook if non nil."
                    239:   (interactive)
                    240:   (kill-all-local-variables)
                    241:   (use-local-map sml-mode-map)
                    242:   (setq major-mode 'sml-mode)
                    243:   (setq mode-name "Sml")
                    244:   (define-abbrev-table 'sml-mode-abbrev-table ())
                    245:   (setq local-abbrev-table sml-mode-abbrev-table)
                    246:   (set-syntax-table sml-mode-syntax-table)
                    247:   ;; A paragraph is seperated by blank lines (or ^L) only.
                    248:   (make-local-variable 'paragraph-start)
                    249:   (setq paragraph-start (concat "^[\t ]*$\\|" page-delimiter))
                    250:   (make-local-variable 'paragraph-separate)
                    251:   (setq paragraph-separate paragraph-start)
                    252:   (make-local-variable 'indent-line-function)
                    253:   (setq indent-line-function 'sml-indent-line)
                    254:   (make-local-variable 'require-final-newline) ; Always put a new-line
                    255:   (setq require-final-newline t)       ; in the end of file
                    256:   (make-local-variable 'comment-start)
                    257:   (setq comment-start "(* ")
                    258:   (make-local-variable 'comment-end)
                    259:   (setq comment-end " *)")
                    260:   (make-local-variable 'comment-column)
                    261:   (setq comment-column 39)             ; Start of comment in this column
                    262:   (make-local-variable 'comment-start-skip)
                    263:   (setq comment-start-skip "(\\*+[ \t]?") ; This matches a start of comment
                    264:   (make-local-variable 'comment-indent-hook)
                    265:   (setq comment-indent-hook 'sml-comment-indent)
                    266:   ;;
                    267:   ;; Adding these will fool the matching of parens. I really don't
                    268:   ;; know why. It would be nice to have comments treated as
                    269:   ;; white-space
                    270:   ;; 
                    271:   ;; (make-local-variable 'parse-sexp-ignore-comments)
                    272:   ;; (setq parse-sexp-ignore-comments t)
                    273:   ;; 
                    274:   (run-hooks 'sml-mode-hook))          ; Run the hook
                    275: 
                    276: (defconst sml-pipe-matchers-reg
                    277:   "\\bcase\\b\\|\\bfn\\b\\|\\bfun\\b\\|\\bhandle\\b\
                    278: \\|\\bdatatype\\b\\|\\babstype\\b\\|\\band\\b"
                    279:   "The keywords a `|' can follow.")
                    280: 
                    281: (defun sml-electric-pipe ()
                    282:   "Insert a \"|\". Depending on the context insert the name of
                    283: function, a \"=>\" etc."
                    284:   (interactive)
                    285:   (let ((here (point))
                    286:        (match (save-excursion
                    287:                 (sml-find-matching-starter sml-pipe-matchers-reg)
                    288:                 (point)))
                    289:        (tmp "  => ")
                    290:        (case-or-handle-exp t))
                    291:     (if (/= (save-excursion (beginning-of-line) (point))
                    292:            (save-excursion (skip-chars-backward "\t ") (point)))
                    293:        (insert "\n"))
                    294:     (insert "|")
                    295:     (save-excursion
                    296:       (goto-char match)
                    297:       (cond
                    298:        ;; It was a function, insert the function name
                    299:        ((looking-at "fun\\b")
                    300:        (setq tmp (concat " " (buffer-substring
                    301:                               (progn (forward-char 3)
                    302:                                      (skip-chars-forward "\t\n ") (point))
                    303:                               (progn (forward-word 1) (point))) " "))
                    304:        (setq case-or-handle-exp nil))
                    305:        ;; It was a datatype, insert nothing
                    306:        ((looking-at "datatype\\b\\|abstype\\b")
                    307:        (setq tmp " ") (setq case-or-handle-exp nil))
                    308:        ;; If is and, then we have to see what is was
                    309:        ((looking-at "and\\b")
                    310:        (let (isfun)
                    311:          (save-excursion
                    312:            (condition-case ()
                    313:                (progn
                    314:                  (re-search-backward "datatype\\b\\|abstype\\b\\|fun\\b")
                    315:                  (setq isfun (looking-at "fun\\b")))
                    316:              (error (setq isfun nil))))
                    317:          (if isfun
                    318:              (progn
                    319:                (setq tmp
                    320:                      (concat " " (buffer-substring
                    321:                                   (progn (forward-char 3)
                    322:                                          (skip-chars-forward "\t\n ") (point))
                    323:                                   (progn (forward-word 1) (point))) " "))
                    324:                (setq case-or-handle-exp nil))
                    325:        (setq tmp " ") (setq case-or-handle-exp nil))))))
                    326:     (insert tmp)
                    327:     (sml-indent-line)
                    328:     (beginning-of-line)
                    329:     (skip-chars-forward "\t ")
                    330:     (forward-char (1+ (length tmp)))
                    331:     (if case-or-handle-exp
                    332:        (forward-char -4))))
                    333: 
                    334: (defun sml-electric-semi ()
                    335:   "If sml-electric-semi-mode is t, indent the current line, and newline."
                    336:   (interactive)
                    337:   (insert "\;")
                    338:   (if sml-electric-semi-mode
                    339:       (reindent-then-newline-and-indent)))
                    340: 
                    341: (defun sml-mode-version ()
                    342:   (interactive)
                    343:   (message sml-mode-version-string))
                    344: 
                    345: 
                    346: ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
                    347: ;;;
                    348: ;;; SHORT CUTS (sml-region)
                    349: ;;; 
                    350: ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
                    351: 
                    352: (defconst sml-region-alist
                    353:   '(("let") ("local") ("signature") ("structure") ("datatype")
                    354:     ("case") ("functor") ("abstype"))  
                    355:   "The list of regions to auto-insert.")
                    356: 
                    357: (defun sml-region ()
                    358:   "Interactive short-cut. Insert a common used structure in sml."
                    359:   (interactive)
                    360:   (let ((newline nil)                  ; Did we insert a newline
                    361:        (name (completing-read "Region to insert: (default let) "
                    362:                               sml-region-alist nil t nil)))
                    363:     ;; default is "let"
                    364:     (if (string= name "") (setq name "let"))
                    365:     ;; Insert a newline if point is not at empty line
                    366:     (sml-indent-line)                  ; Indent the current line
                    367:     (if (save-excursion (beginning-of-line) (skip-chars-forward "\t ") (eolp))
                    368:        ()
                    369:       (setq newline t)
                    370:       (insert "\n"))
                    371:     (condition-case ()
                    372:        (cond
                    373:         ((string= name "let") (sml-let))
                    374:         ((string= name "local") (sml-local))
                    375:         ((string= name "structure") (sml-structure))
                    376:         ((string= name "signature") (sml-signature))
                    377:         ((string= name "functor") (sml-functor))
                    378:         ((string= name "case") (sml-case))
                    379:         ((string= name "abstype") (sml-abstype))
                    380:         ((string= name "datatype") (sml-datatype)))
                    381:       (quit (if newline 
                    382:                (progn
                    383:                  (delete-char -1)
                    384:                  (beep)))))))
                    385: 
                    386: (defun sml-let () 
                    387:   "Insert a `let in end'."
                    388:   (interactive) (sml-let-local "let"))
                    389: 
                    390: (defun sml-local ()
                    391:   "Insert a `local in end'."
                    392:   (interactive) (sml-let-local "local"))
                    393: 
                    394: (defun sml-signature ()
                    395:   "Insert a `signature ??? = sig end', prompting for name."
                    396:   (interactive) (sml-structure-signature "signature"))
                    397: 
                    398: (defun sml-structure ()
                    399:   "Insert a `structure ??? = struct end', prompting for name."
                    400:   (interactive) (sml-structure-signature "structure"))
                    401: 
                    402: (defun sml-case ()
                    403:   "Insert a case, prompting for case-expresion."
                    404:   (interactive)
                    405:   (let (indent (expr (read-string "Case expr: ")))
                    406:     (insert (concat "case " expr))
                    407:     (sml-indent-line)
                    408:     (setq indent (current-indentation))
                    409:     (end-of-line)
                    410:     (if sml-case-indent
                    411:        (progn
                    412:          (insert "\n")
                    413:          (indent-to (+ 2 indent))
                    414:          (insert "of "))
                    415:       (insert " of\n")
                    416:       (indent-to (+ indent sml-indent-level)))
                    417:     (save-excursion (insert " => "))))
                    418: 
                    419: (defun sml-let-local (starter)
                    420:   (let (indent)
                    421:     (insert starter)
                    422:     (sml-indent-line)
                    423:     (setq indent (current-indentation))
                    424:     (end-of-line)
                    425:     (insert "\n") (indent-to (+ sml-indent-level indent))
                    426:     (insert "\n") (indent-to indent)
                    427:     (insert "in\n") (indent-to (+ sml-indent-level indent))
                    428:     (insert "\n") (indent-to indent)
                    429:     (insert "end") (previous-line 3) (end-of-line)))
                    430:     
                    431: (defun sml-structure-signature (which)
                    432:   (let (indent
                    433:        (name (read-string (concat "Name of " which ": "))))
                    434:     (insert (concat which " " name " ="))
                    435:     (sml-indent-line)
                    436:     (setq indent (current-indentation))
                    437:     (end-of-line)
                    438:     (insert "\n") (indent-to (+ sml-indent-level indent))
                    439:     (insert (if (string= which "signature") "sig\n" "struct\n"))
                    440:     (indent-to (+ (* 2 sml-indent-level) indent))
                    441:     (insert "\n") (indent-to (+ sml-indent-level indent))
                    442:     (insert "end") (previous-line 1) (end-of-line)))
                    443: 
                    444: (defun sml-functor ()
                    445:   "Insert a `funtor ??? () : ??? = struct end', prompting for name and type."
                    446:   (let (indent
                    447:        (name (read-string "Name of functor: "))
                    448:        (signame (read-string "Signature type of functor: ")))
                    449:     (insert (concat "functor " name " () : " signame " ="))
                    450:     (sml-indent-line)
                    451:     (setq indent (current-indentation))
                    452:     (end-of-line)
                    453:     (insert "\n") (indent-to (+ sml-indent-level indent))
                    454:     (insert "struct\n")
                    455:     (indent-to (+ (* 2 sml-indent-level) indent))
                    456:     (insert "\n") (indent-to (+ sml-indent-level indent))
                    457:     (insert "end") (previous-line 1) (end-of-line)))
                    458: 
                    459: (defun sml-datatype ()
                    460:   "Insert a `datatype ??? =', prompting for name."
                    461:   (let (indent 
                    462:        (type (read-string (concat "Type of datatype (default none): ")))
                    463:        (name (read-string (concat "Name of datatype: "))))
                    464:     (insert (concat "datatype "
                    465:                    (if (string= type "") "" (concat type " "))
                    466:                    name " ="))
                    467:     (sml-indent-line)
                    468:     (setq indent (current-indentation))
                    469:     (end-of-line) (insert "\n") (indent-to (+ sml-indent-level indent))))
                    470: 
                    471: (defun sml-abstype ()
                    472:   "Insert an `abstype 'a ??? = with ... end'"
                    473:   (let (indent
                    474:        (typevar (read-string "Name of typevariable (default 'a): "))
                    475:        (type (read-string "Name of abstype: ")))
                    476:     (if (string= typevar "")
                    477:        (setq typevar "'a"))
                    478:     (insert (concat "abstype " typevar " " type " ="))
                    479:     (sml-indent-line)
                    480:     (setq indent (current-indentation))
                    481:     (insert "\n") (indent-to (+ sml-indent-level indent))
                    482:     (insert "\n") (indent-to indent)
                    483:     (insert "with\n") (indent-to (+ sml-indent-level indent))
                    484:     (insert "\n") (indent-to indent)
                    485:     (insert "end")
                    486:     (previous-line 3)
                    487:     (end-of-line)))
                    488: 
                    489: ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
                    490: ;;;
                    491: ;;; PARSING ERROR MESSAGES (NOTE: works only with SML of New Jersey)
                    492: ;;; 
                    493: ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
                    494: 
                    495: (defvar sml-last-error 1 "Last position of error. Initially 1.")
                    496: 
                    497: (defun sml-next-error ()
                    498:   "Find the next error by passing the *SML* buffer.\n
                    499: NOTE: This function only knows about the syntax of errors generated by
                    500:       SML of New Jersey, and will only work with this."
                    501:   (interactive)
                    502:   (let ((found t) (tmp-file nil) found-line found-file error-line tmp)
                    503:     (save-excursion
                    504:       (condition-case ()
                    505:          (progn
                    506:            (set-buffer (concat "*" sml-process-name "*" ))
                    507:            (goto-char sml-last-error)
                    508:            (re-search-forward "^.+line.+\\(Error:\\|Warning:\\)")
                    509:            (save-excursion
                    510:              (beginning-of-line)
                    511:              (if (looking-at sml-tmp-template)
                    512:                  (setq tmp-file t)))
                    513:            (setq sml-last-error (point))
                    514:            (beginning-of-line)
                    515:            (setq error-line (point))
                    516:            (search-forward ",")
                    517:            (setq found-file (buffer-substring error-line (1- (point))))
                    518:            (search-forward "line ")
                    519:            (setq tmp (point))
                    520:            (skip-chars-forward "[0-9]")
                    521:            (setq found-line (string-to-int (buffer-substring tmp (point)))))
                    522:        (error (setq found nil))))
                    523:     (if found
                    524:        (progn
                    525:          (set-window-start
                    526:           (display-buffer (concat "*" sml-process-name "*")) error-line)
                    527:          (if tmp-file
                    528:              (let ((loop t) (n 0) (tmp-list sml-tmp-files-list))
                    529:                (while loop
                    530:                  (setq tmp (car tmp-list))
                    531:                  (if (string= (car tmp) found-file)
                    532:                      (setq loop nil)
                    533:                    (setq tmp-list (cdr tmp-list)))
                    534:                  (if (null tmp-list) (setq loop nil)))
                    535:                (if (null tmp)
                    536:                    (error "Temporary file not associated with buffer.")
                    537:                  (condition-case ()
                    538:                      (progn
                    539:                        (switch-to-buffer (nth 1 tmp))
                    540:                        (message
                    541:                         (concat "Error found in temporary file "
                    542:                                 "(line number may not match)."))
                    543:                        (goto-line (1- (+ found-line (nth 2 tmp)))))
                    544:                    (error (error "Sorry, buffer doesn't exist any more.")))))
                    545:            (if (file-exists-p found-file)
                    546:                (progn
                    547:                  (condition-case ()
                    548:                      (progn
                    549:                        (find-file found-file)
                    550:                        (goto-line found-line))
                    551:                    (error ())))
                    552:              (error (concat "File not found: " found-file)))))
                    553:       ;; No error found
                    554:       (if (= sml-last-error 1)         ; Did we just start
                    555:          (message "No errors yet")
                    556:        (message "No more errors"))     ; Or have we passed all errors
                    557:       (beep))))
                    558:   
                    559: (defun sml-skip-errors ()
                    560:   "Skip past the rest of the errors."
                    561:   (interactive)
                    562:   (save-excursion
                    563:     (set-buffer (concat "*" sml-process-name "*" ))
                    564:     (setq sml-last-error (point-max))))
                    565: 
                    566: 
                    567: ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
                    568: ;;;
                    569: ;;; INDENTATION
                    570: ;;; 
                    571: ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
                    572: 
                    573: (defun sml-indent-region (begin end)
                    574:   "Indent region of sml code."
                    575:   (interactive "r")
                    576:   (message "Indenting region...")
                    577:   (save-excursion
                    578:     (goto-char end) (setq end (point-marker)) (goto-char begin)
                    579:     (while (< (point) end)
                    580:       (skip-chars-forward "\t\n ")
                    581:       (sml-indent-line)
                    582:       (end-of-line))
                    583:     (move-marker end nil))
                    584:   (message "Indenting region... done"))
                    585: 
                    586: (defun sml-indent-line ()
                    587:   "Indent current line of sml code."
                    588:   (interactive)
                    589:   (let ((indent (sml-calculate-indentation)))
                    590:     (if (/= (current-indentation) indent)
                    591:        (save-excursion                 ;; Added 890601 (point now stays)
                    592:          (let ((beg (progn (beginning-of-line) (point))))
                    593:            (skip-chars-forward "\t ")
                    594:            (delete-region beg (point))
                    595:            (indent-to indent))))
                    596:     ;; If point is before indentation, move point to indentation
                    597:     (if (< (current-column) (current-indentation))
                    598:        (skip-chars-forward "\t "))))
                    599: 
                    600: (defconst sml-indent-starters-reg
                    601:   "abstraction\\b\\|abstype\\b\\|and\\b\\|case\\b\\|datatype\\b\
                    602: \\|else\\b\\|fun\\b\\|functor\\b\\|if\\b\\|sharing\\b\
                    603: \\|in\\b\\|infix\\b\\|infixr\\b\\|let\\b\\|local\\b\
                    604: \\|nonfix\\b\\|of\\b\\|open\\b\\|raise\\b\\|sig\\b\\|signature\\b\
                    605: \\|struct\\b\\|structure\\b\\|then\\b\\|\\btype\\b\\|val\\b\
                    606: \\|while\\b\\|with\\b\\|withtype\\b"
                    607:   "The indentation starters. The next line, after one starting with
                    608: one of these, will be indented.")
                    609: 
                    610: (defconst sml-starters-reg
                    611:   "\\babstraction\\b\\|\\babstype\\b\\|\\bdatatype\\b\
                    612: \\|\\bexception\\b\\|\\bfun\\b\\|\\bfunctor\\b\\|\\blocal\\b\
                    613: \\|\\binfix\\b\\|\\binfixr\\b\\|sharing\\b\
                    614: \\|\\bnonfix\\b\\|\\bopen\\b\\|\\bsignature\\b\\|\\bstructure\\b\
                    615: \\|\\btype\\b\\|\\bval\\b\\|\\bwithtype\\b\\|\\bwith\\b"
                    616:   "The starters of new expressions.")
                    617: 
                    618: (defconst sml-end-starters-reg
                    619:   "\\blet\\b\\|\\blocal\\b\\|\\bsig\\b\\|\\bstruct\\b\\|\\bwith\\b"
                    620:   "Matching reg-expression for the \"end\" keyword.")
                    621: 
                    622: (defconst sml-starters-indent-after
                    623:   "let\\b\\|local\\b\\|struct\\b\\|in\\b\\|sig\\b\\|with\\b"
                    624:   "Indent after these.")
                    625: 
                    626: (defun sml-calculate-indentation ()
                    627:   (save-excursion
                    628:     (beginning-of-line)                        ; Go to first non whitespace
                    629:     (skip-chars-forward "\t ")         ; on the line.
                    630:     (cond
                    631:      ;; Indentation for comments alone on a line, matches the
                    632:      ;; proper indentation of the next line. Search only for the
                    633:      ;; next "*)", not for the matching.
                    634:      ((looking-at "(\\*")
                    635:       (if (not (search-forward "*)" nil t))
                    636:          (error "Comment not ended."))
                    637:       (skip-chars-forward "\n\t ")
                    638:       ;; If we are at eob, just indent 0
                    639:       (if (eobp) 0 (sml-calculate-indentation)))
                    640:      ;; Are we looking at a case expression ?
                    641:      ((looking-at "|.*=>")
                    642:       (sml-skip-block)
                    643:       ;; Dont get fooled by fn _ => in case statements (890726)
                    644:       (sml-re-search-backward "=>")
                    645:       (let ((loop t))
                    646:        (while (and loop (save-excursion
                    647:                           (beginning-of-line)
                    648:                           (looking-at ".*\\bfn\\b.*=>")))
                    649:          (setq loop (sml-re-search-backward "=>"))))
                    650:       (beginning-of-line)
                    651:       (skip-chars-forward "\t ")
                    652:       (cond
                    653:        ((looking-at "|") (current-indentation))
                    654:        ((and sml-case-indent (looking-at "of\\b"))
                    655:        (1+ (current-indentation)))
                    656:        ((looking-at "fn\\b") (1+ (current-indentation)))
                    657:        ((looking-at "handle\\b") (+ (current-indentation) 5))
                    658:        (t (+ (current-indentation) sml-pipe-indent))))
                    659:      ((looking-at "and\\b")
                    660:       (if (sml-find-matching-starter sml-starters-reg)
                    661:          (current-column)
                    662:        0))
                    663:      ((looking-at "in\\b")             ; Match the beginning let/local
                    664:       (sml-find-match-indent "in" "\\bin\\b" "\\blocal\\b\\|\\blet\\b"))
                    665:      ((looking-at "end\\b")            ; Match the beginning
                    666:       (sml-find-match-indent "end" "\\bend\\b" sml-end-starters-reg))
                    667:      ((and sml-nested-if-indent (looking-at "else[\t ]*if\\b"))
                    668:       (sml-re-search-backward "\\bif\\b\\|\\belse\\b")
                    669:       (current-indentation))
                    670:      ((looking-at "else\\b")           ; Match the if
                    671:       (sml-find-match-indent "else" "\\belse\\b" "\\bif\\b" t))
                    672:      ((looking-at "then\\b")           ; Match the if + extra indentation
                    673:       (+ (sml-find-match-indent "then" "\\bthen\\b" "\\bif\\b" t)
                    674:         sml-indent-level))
                    675:      ((and sml-case-indent (looking-at "of\\b"))
                    676:       (sml-re-search-backward "\\bcase\\b")
                    677:       (+ (current-column) 2))
                    678:      ((looking-at sml-starters-reg)
                    679:       (let ((start (point)))
                    680:        (sml-backward-sexp)
                    681:        (if (and (looking-at sml-starters-indent-after)
                    682:                 (/= start (point)))
                    683:            (+ (if sml-type-of-indent
                    684:                   (current-column)
                    685:                 (if (progn (beginning-of-line)
                    686:                            (skip-chars-forward "\t ")
                    687:                            (looking-at "|"))
                    688:                     (- (current-indentation) sml-pipe-indent)
                    689:                   (current-indentation)))
                    690:               sml-indent-level)
                    691:          (beginning-of-line)
                    692:          (skip-chars-forward "\t ")
                    693:          (if (and (looking-at sml-starters-indent-after)
                    694:                   (/= start (point)))
                    695:              (+ (if sml-type-of-indent
                    696:                     (current-column)
                    697:                   (current-indentation))
                    698:                 sml-indent-level)
                    699:            (goto-char start)
                    700:            (if (sml-find-matching-starter sml-starters-reg)
                    701:                (current-column)
                    702:              0)))))
                    703:      (t
                    704:       (let ((indent (sml-get-indent)))
                    705:        (cond
                    706:         ((looking-at "|")
                    707:          ;; Lets see if it is the follower of a function definition
                    708:          (if (sml-find-matching-starter
                    709:               "\\bfun\\b\\|\\bfn\\b\\|\\band\\b\\|\\bhandle\\b")
                    710:              (cond
                    711:               ((looking-at "fun\\b") (- (current-column) sml-pipe-indent))
                    712:               ((looking-at "fn\\b") (1+ (current-column)))
                    713:               ((looking-at "and\\b") (1+ (1+ (current-column))))
                    714:               ((looking-at "handle\\b") (+ (current-column) 5)))
                    715:            (+ indent sml-pipe-indent)))
                    716:         (t
                    717:          (if sml-paren-lookback        ; Look for open parenthesis ?
                    718:              (max indent (sml-get-paren-indent))
                    719:            indent))))))))
                    720: 
                    721: (defun sml-get-indent ()
                    722:   (save-excursion
                    723:     (beginning-of-line)
                    724:     (skip-chars-backward "\t\n; ")
                    725:     (if (looking-at ";") (sml-backward-sexp))
                    726:     (cond
                    727:      ((save-excursion (sml-backward-sexp) (looking-at "end\\b"))
                    728:       (- (current-indentation) sml-indent-level))
                    729:      (t
                    730:       (while (/= (current-column) (current-indentation))
                    731:        (sml-backward-sexp))
                    732:       (skip-chars-forward "\t |")
                    733:       (let ((indent (current-column)))
                    734:        (skip-chars-forward "\t (")
                    735:        (cond
                    736:         ;; Started val/fun/structure...
                    737:         ((looking-at sml-indent-starters-reg)
                    738:          (+ (current-column) sml-indent-level))
                    739:         ;; Indent after "=>" pattern, but only if its not an fn _ =>
                    740:         ;; (890726)
                    741:         ((looking-at ".*=>")
                    742:          (if (looking-at ".*\\bfn\\b.*=>")
                    743:              indent
                    744:            (+ indent sml-indent-level)))
                    745:         ;; else keep the same indentation as previous line
                    746:         (t indent)))))))
                    747: 
                    748: (defun sml-get-paren-indent ()
                    749:   (save-excursion
                    750:     (let ((levelpar 0)                 ; Level of "()"
                    751:           (levelcurl 0)                 ; Level of "{}"
                    752:           (levelsqr 0)                  ; Level of "[]"
                    753:           (backpoint (max (- (point) sml-paren-lookback) (point-min)))
                    754:           (loop t))
                    755:       (while (and (/= levelpar 1) (/= levelsqr 1) (/= levelcurl 1) loop)
                    756:        (if (re-search-backward "[][{}()]" backpoint t)
                    757:            (if (not (sml-inside-comment-or-string-p))
                    758:                (cond
                    759:                 ((looking-at "(") (setq levelpar (1+ levelpar)))
                    760:                 ((looking-at ")") (setq levelpar (1- levelpar)))
                    761:                 ((looking-at "\\[") (setq levelsqr (1+ levelsqr)))
                    762:                 ((looking-at "\\]") (setq levelsqr (1- levelsqr)))
                    763:                 ((looking-at "{") (setq levelcurl (1+ levelcurl)))
                    764:                 ((looking-at "}") (setq levelcurl (1- levelcurl)))))
                    765:          (setq loop nil)))
                    766:       (if loop
                    767:          (1+ (current-column))
                    768:        0))))
                    769: 
                    770: (defun sml-inside-comment-or-string-p ()
                    771:   (let ((start (point)))
                    772:     (if (save-excursion
                    773:          (condition-case ()
                    774:              (progn
                    775:                (search-backward "(*")
                    776:                (search-forward "*)")
                    777:                (forward-char -1)       ; A "*)" is not inside the comment
                    778:                (> (point) start))
                    779:            (error nil)))
                    780:        t
                    781:       (let ((numb 0))
                    782:        (save-excursion
                    783:          (save-restriction
                    784:            (narrow-to-region (progn (beginning-of-line) (point)) start)
                    785:            (condition-case ()
                    786:                (while t
                    787:                  (search-forward "\"")
                    788:                  (setq numb (1+ numb)))
                    789:              (error (if (and (not (zerop numb))
                    790:                              (not (zerop (% numb 2))))
                    791:                         t nil)))))))))
                    792:                
                    793: (defun sml-skip-block ()
                    794:   (sml-backward-sexp)
                    795:   (if (looking-at "end\\b")
                    796:       (progn
                    797:        (goto-char (sml-find-match-backward "end" "\\bend\\b"
                    798:                                            sml-end-starters-reg))
                    799:        (skip-chars-backward "\n\t "))
                    800:     ;; Here we will need to skip backward past if-then-else
                    801:     ;; and case-of expression. Please - tell me how !!
                    802:     ))
                    803: 
                    804: (defun sml-find-match-backward (unquoted-this this match &optional start)
                    805:   (save-excursion
                    806:     (let ((level 1)
                    807:          (pattern (concat this "\\|" match)))
                    808:       (if start (goto-char start))
                    809:       (while (not (zerop level))
                    810:        (if (sml-re-search-backward pattern)
                    811:            (setq level (cond
                    812:                         ((looking-at this) (1+ level))
                    813:                         ((looking-at match) (1- level))))
                    814:          ;; The right match couldn't be found
                    815:          (error (concat "Unbalanced: " unquoted-this))))
                    816:       (point))))
                    817: 
                    818: (defun sml-find-match-indent (unquoted-this this match &optional indented)
                    819:   (save-excursion
                    820:     (goto-char (sml-find-match-backward unquoted-this this match))
                    821:     (if (or sml-type-of-indent indented)
                    822:        (current-column)
                    823:       (if (progn
                    824:            (beginning-of-line)
                    825:            (skip-chars-forward "\t ")
                    826:            (looking-at "|"))
                    827:          (- (current-indentation) sml-pipe-indent)
                    828:        (current-indentation)))))
                    829: 
                    830: (defun sml-find-matching-starter (regexp)
                    831:   (let ((start-let-point (sml-point-inside-let-etc))
                    832:        (start-up-list (sml-up-list))
                    833:        (found t))
                    834:     (if (sml-re-search-backward regexp)
                    835:        (progn
                    836:          (condition-case ()
                    837:              (while (or (/= start-up-list (sml-up-list))
                    838:                         (/= start-let-point (sml-point-inside-let-etc)))
                    839:                (re-search-backward regexp))
                    840:            (error (setq found nil)))
                    841:          found)
                    842:       nil)))
                    843: 
                    844: (defun sml-point-inside-let-etc ()
                    845:   (let ((last nil) (loop t) (found t) (start (point)))
                    846:     (save-excursion
                    847:       (while loop
                    848:        (condition-case ()
                    849:            (progn
                    850:              (re-search-forward "\\bend\\b")
                    851:              (while (sml-inside-comment-or-string-p)
                    852:                (re-search-forward "\\bend\\b"))
                    853:              (forward-char -3)
                    854:              (setq last (sml-find-match-backward "end" "\\bend\\b"
                    855:                                                  sml-end-starters-reg last))
                    856:              (if (< last start)
                    857:                  (setq loop nil)
                    858:                (forward-char 3)))
                    859:          (error (progn (setq found nil) (setq loop nil)))))
                    860:       (if found
                    861:          last
                    862:        0))))
                    863:                     
                    864: (defun sml-re-search-backward (regexpr)
                    865:   (let ((found t))
                    866:     (if (re-search-backward regexpr nil t)
                    867:        (progn
                    868:          (condition-case ()
                    869:              (while (sml-inside-comment-or-string-p)
                    870:                (re-search-backward regexpr))
                    871:            (error (setq found nil)))
                    872:          found)
                    873:       nil)))
                    874: 
                    875: (defun sml-up-list ()
                    876:   (save-excursion
                    877:     (condition-case ()
                    878:        (progn
                    879:          (up-list 1)
                    880:          (point))
                    881:       (error 0))))
                    882: 
                    883: (defun sml-backward-sexp ()
                    884:   (condition-case ()
                    885:       (progn
                    886:        (let ((start (point)))
                    887:          (backward-sexp 1)
                    888:          (while (and (/= start (point)) (looking-at "(\\*"))
                    889:            (setq start (point))
                    890:            (backward-sexp 1))))
                    891:     (error (forward-char -1))))
                    892: 
                    893: (defun sml-comment-indent ()
                    894:   (if (looking-at "^(\\*")             ; Existing comment at beginning
                    895:       0                                        ; of line stays there.
                    896:     (save-excursion
                    897:       (skip-chars-backward " \t")
                    898:       (1+ (max (current-column)                ; Else indent at comment column
                    899:               comment-column)))))      ; except leave at least one space.
                    900: 
                    901: 
                    902: ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
                    903: ;;;
                    904: ;;; INFERIOR SHELL
                    905: ;;;
                    906: ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
                    907: 
                    908: (defvar sml-shell-map nil "The mode map for sml-shell.")
                    909: 
                    910: (defun sml-shell ()
                    911:   "Inferior shell invoking SML.
                    912: It is not possible to have more than one shell running SML.
                    913: Like the shell mode with the additional command:
                    914: 
                    915: \\[sml-run-on-file]\t Runs sml on the file.
                    916: \\{sml-shell-map}
                    917: Variables controlling the mode:
                    918: 
                    919: sml-prog-name (default \"sml\")
                    920:     The string used to invoke the sml program.
                    921: 
                    922: sml-prog-name-ask-p (default nil)
                    923:     If t, you will be asked which program to run when the inferior
                    924:     shell starts up. Usefull if you have exported images of sml.
                    925: 
                    926: sml-use-right-delim (default \"\\\"\")
                    927: sml-use-left-delim  (default \"\\\"\")
                    928:     The left and right delimiter used by your version of sml, for
                    929:     \"use file-name\".
                    930: 
                    931: sml-process-name (default \"SML\")
                    932:     The name of the process running sml.
                    933: 
                    934: sml-shell-prompt-pattern (default \"^[^\\-=]*[\\-=] *\")
                    935:     The prompt pattern.
                    936: 
                    937: Runs sml-shell-hook if not nil."
                    938:   (interactive)
                    939:   (if (not (process-status sml-process-name))
                    940:       (save-excursion                  ; Process is not running
                    941:        (and sml-prog-name-ask-p
                    942:             (setq sml-prog-name
                    943:                   (read-file-name
                    944:                    (concat "Sml (default " sml-prog-name "): ")
                    945:                    (file-name-directory (buffer-file-name))
                    946:                    sml-prog-name)))
                    947:        (message "Starting SML...")     ; start up a new process
                    948:        (require 'shell)
                    949:        (set-buffer
                    950:         (make-shell sml-process-name
                    951:                     (if (= (string-to-char sml-prog-name) ?~)
                    952:                         (expand-file-name sml-prog-name)
                    953:                       sml-prog-name)))
                    954:        (erase-buffer)                  ; Erase the buffer if a previous
                    955:        (if sml-shell-map               ; process died in there
                    956:            ()
                    957:          (setq sml-shell-map (copy-sequence shell-mode-map))
                    958:          (define-key sml-shell-map "\C-c\C-f" 'sml-run-on-file))
                    959:        (use-local-map sml-shell-map)
                    960:        (make-local-variable 'shell-prompt-pattern)
                    961:        (setq shell-prompt-pattern sml-shell-prompt-pattern)
                    962:        (setq major-mode 'sml-shell)
                    963:        (setq mode-name "Sml-Shell")
                    964:        (if sml-prog-name-ask-p
                    965:            (setq mode-line-process
                    966:                  (list (concat
                    967:                         ": %s ("
                    968:                         (substring sml-prog-name
                    969:                                    (string-match "[^/]*$" sml-prog-name)
                    970:                                    (string-match "$" sml-prog-name))
                    971:                         ")"))))
                    972:          (set-process-filter (get-process sml-process-name) 'sml-process-filter)
                    973:        (message "Starting SML... done.")
                    974:        (run-hooks 'sml-shell-hook))))
                    975: 
                    976: (defun sml-process-filter (proc str)
                    977:   (let ((cur (selected-window))
                    978:        (pop-up-windows t)
                    979:        (process (concat "*" sml-process-name "*")))
                    980:     (pop-to-buffer process)
                    981:     (goto-char (point-max))
                    982:     (insert str)
                    983:     (set-marker (process-mark proc) (point-max))
                    984:     (select-window cur)))
                    985: 
                    986: (defun sml-pop-to-shell ()
                    987:   "Pop to the buffer running SML"
                    988:   (interactive)
                    989:   (sml-shell)
                    990:   (pop-to-buffer (concat "*" sml-process-name "*")))
                    991: 
                    992: (defun sml-run-on-file (fil)
                    993:   "Send a use FILE to the inferior shell running sml"
                    994:   (interactive "FUse file: ")
                    995:   (sml-shell)
                    996:   (save-some-buffers)
                    997:   (sml-skip-errors)
                    998:   (send-string sml-process-name
                    999:               (concat "use " sml-use-left-delim (expand-file-name fil)
                   1000:                       sml-use-right-delim ";\n")))
                   1001: 
                   1002: (defun sml-save-buffer-use-file ()
                   1003:   "Save the buffer, and send a `use file' to the inferior shell
                   1004: running SML."
                   1005:   (interactive)
                   1006:   (let (file)
                   1007:     (if (setq file (buffer-file-name)) ; Is the buffer associated
                   1008:        (progn                          ; with file ?
                   1009:          (save-buffer)
                   1010:          (sml-shell)
                   1011:          (sml-skip-errors)
                   1012:          (message (concat "use " sml-use-left-delim file sml-use-right-delim))
                   1013:          (send-string sml-process-name
                   1014:                       (concat "use " sml-use-left-delim
                   1015:                               (expand-file-name file)
                   1016:                               sml-use-right-delim ";\n")))
                   1017:       (error "Buffer not associated with file."))))
                   1018: 
                   1019: (defun sml-import-file ()
                   1020:   "Save the buffer, and send an `import file' to the inferior shell
                   1021: running SML."
                   1022:   (interactive)
                   1023:   (let (file)
                   1024:     (if (setq file (buffer-file-name))
                   1025:        (if (string-match ".sml$" file)
                   1026:            (progn 
                   1027:              (setq file (substring file 0 (string-match ".sml$" file)))
                   1028:              (save-buffer)
                   1029:              (sml-shell)
                   1030:              (sml-skip-errors)
                   1031:              (message (concat "import \"" file "\""))
                   1032:              (send-string sml-process-name
                   1033:                           (concat "import " sml-use-left-delim
                   1034:                                   (expand-file-name file)
                   1035:                                   sml-use-right-delim ";\n")))
                   1036:          (error "Filename doesn't match \"*.sml\""))
                   1037:       (error "Buffer not associated with file."))))
                   1038: 
                   1039: (defvar sml-tmp-files-list nil
                   1040:   "List of all temporary files created by sml-simulate-send-region.
                   1041: Each element in the list is a list with the format:
                   1042: \n   (\"tmp-filename\"  buffer  start-line)")
                   1043: 
                   1044: (defvar sml-simulate-send-region-called-p nil
                   1045:   "Has sml-simulate-send-region been called previously.")
                   1046: 
                   1047: (defun sml-simulate-send-region (point1 point2)
                   1048:   "Simulate send region. As send-region only can handle what ever the
                   1049: system sets as the default, we have to make a temporary file.
                   1050: Updates the list of temporary files (sml-tmp-files-list)."
                   1051:   (let ((file (expand-file-name (make-temp-name sml-tmp-template))))
                   1052:     ;; Remove temporary files when we leave emacs
                   1053:     (if (not sml-simulate-send-region-called-p)
                   1054:        (progn
                   1055:          (setq sml-old-kill-emacs-hook kill-emacs-hook)
                   1056:          (setq kill-emacs-hook 'sml-remove-tmp-files)
                   1057:          (setq sml-simulate-send-region-called-p t)))
                   1058:     ;; As make-temp-name can only make 26 unique file names with the
                   1059:     ;; same template (bug in Un*x function mktemp), we add a new
                   1060:     ;; letter to sml-tmp-template.
                   1061:     (if (zerop (% (length sml-tmp-files-list) 25))
                   1062:        (setq sml-tmp-template (concat sml-tmp-template "A")))
                   1063:     (save-excursion
                   1064:       (goto-char point1)
                   1065:       (setq sml-tmp-files-list
                   1066:            (cons (list file
                   1067:                        (current-buffer)
                   1068:                        (save-excursion ; Calculate line no.
                   1069:                          (beginning-of-line)
                   1070:                          (1+ (count-lines 1 (point)))))
                   1071:                  sml-tmp-files-list)))
                   1072:     (write-region point1 point2 file nil 'dummy)
                   1073:     (sml-shell)
                   1074:     (message "Using temporary file: %s" file)
                   1075:     (send-string
                   1076:      sml-process-name
                   1077:      ;; string to send: use file;
                   1078:      (concat "use " sml-use-left-delim file sml-use-right-delim ";\n"))))
                   1079: 
                   1080: (defvar sml-old-kill-emacs-hook nil
                   1081:   "Old value of kill-emacs-hook")
                   1082: 
                   1083: (defun sml-remove-tmp-files ()
                   1084:   "Remove the temporary files, created by sml-simulate-send-region, if
                   1085: they still exist. Only files recorded in sml-tmp-files-list are removed."
                   1086:   (message "Removing temporary files created by sml-mode...")
                   1087:   (while sml-tmp-files-list
                   1088:     (condition-case ()
                   1089:        (delete-file (car (car sml-tmp-files-list)))
                   1090:       (error ()))
                   1091:     (setq sml-tmp-files-list (cdr sml-tmp-files-list)))
                   1092:   (message "Removing temporary files created by sml-mode... done.")
                   1093:   (run-hooks 'sml-old-kill-emacs-hook))
                   1094: 
                   1095: (defun sml-send-region ()
                   1096:   "Send region to inferior shell running SML."
                   1097:   (interactive)
                   1098:   (sml-shell)
                   1099:   (sml-skip-errors)
                   1100:   (let (start end)
                   1101:     (save-excursion
                   1102:       (setq end (point))
                   1103:       (exchange-point-and-mark)
                   1104:       (setq start (point)))
                   1105:     (sml-simulate-send-region start end)))
                   1106: 
                   1107: (defun sml-send-function ()
                   1108:   "Does NOT send the function, but the paragraph, to inferior shell
                   1109: running SML"
                   1110:   (interactive)
                   1111:   (sml-shell)
                   1112:   (sml-skip-errors)
                   1113:   (let (start end)
                   1114:     (save-excursion
                   1115:       (condition-case ()
                   1116:          (progn
                   1117:            (backward-paragraph)
                   1118:            (setq start (point)))
                   1119:        (error (setq start (point-min))))
                   1120:       (condition-case ()
                   1121:          (progn
                   1122:            (forward-paragraph)
                   1123:            (setq end (point)))
                   1124:        (error (setq end (point-max)))))
                   1125:     (sml-simulate-send-region start end)))
                   1126: 
                   1127: (defun sml-send-buffer ()
                   1128:   "Send the buffer, to inferior shell running SML"
                   1129:   (interactive)
                   1130:   (sml-shell)
                   1131:   (sml-skip-errors)
                   1132:   (sml-simulate-send-region (point-min) (point-max)))
                   1133: 
                   1134: ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
                   1135: ;;;
                   1136: ;;; END OF SML-MODE
                   1137: ;;;
                   1138: ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
                   1139: 

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.