|
|
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:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.