|
|
1.1 ! root 1: ! 2: ! 3: ! 4: SML MODE ! 5: ! 6: Version 2.4 ! 7: ! 8: ! 9: A major mode for editing and running SML. ! 10: ! 11: ! 12: Lars Bo Nielsen ! 13: ([email protected]) ! 14: ! 15: ! 16: ! 17: Sml-mode is a major GnuEmacs mode for editing and running (Standard) ML ! 18: (sml). It features: ! 19: ! 20: o Automatic indentation of sml code. With a number of constants to ! 21: customize the indentation. ! 22: ! 23: o Short cut insertion of commonly used structures, like ! 24: "let in end", "signature xxx = sig end", etc. ! 25: ! 26: o Short cut insertion of "|". Will automaticly determine if ! 27: "|" is used after a "case", "fun" etc. If used after a "fun" ! 28: automaticly insert the name of the function, used after ! 29: case automaticly insert "=>" etc. ! 30: ! 31: o Inferior shell running sml. No need to leave emacs, just ! 32: keep right on editing while sml runs in another window. ! 33: ! 34: o Automatic "use file" in inferior shell. Send regions of code ! 35: to the running sml program. ! 36: ! 37: o Parsing of errors in the inferior shell. Like the next-error ! 38: function used in c-mode (This will only work with SML of ! 39: New Jersey). ! 40: ! 41: ! 42: ! 43: 1. HOW TO USE THE SML-MODE ! 44: ========================== ! 45: ! 46: Here is a short introduction to the mode. If you are an experienced user of ! 47: Emacs, just skip the first section, and go straight to 1.2. ! 48: ! 49: If you run into any problems, your local emacs-administrator should be able ! 50: to help you. You are also wellcome to send me a note asking for help. ! 51: ! 52: ! 53: 1.1 GETTING STARTED ! 54: ------------------- ! 55: ! 56: The mode for sml is in the file "sml-mode.el". We will have to tell Emacs ! 57: where to find this file and when to use it. ! 58: ! 59: Insert this in your "~/.emacs" file : ! 60: ! 61: (setq auto-mode-alist (cons '("\\.sml$" . sml-mode) ! 62: auto-mode-alist)) ! 63: (autoload 'sml-mode "sml-mode" "Major mode for editing SML." t) ! 64: ! 65: Now every time a file with the extension `.sml' is found, it is ! 66: automatically started up in sml-mode. ! 67: ! 68: You will also have to specify the path to the "sml-mode.el" file, so you ! 69: will have to add this as well: ! 70: ! 71: (setq load-path (cons "/usr/me/emacs" load-path)) ! 72: ! 73: where "/usr/me/emacs" is the directory where the file "sml-mode.el" is ! 74: located. ! 75: ! 76: You may also want to compile the file (M-x byte-compile-file) ! 77: for speed. ! 78: ! 79: You are now ready to start using sml-mode. If you have tried other ! 80: language modes (like lisp-mode or C-mode), you should have no ! 81: problems. There are only a few extra functions in this mode. ! 82: ! 83: ! 84: 1.2. EDITING COMMANDS. ! 85: ---------------------- ! 86: ! 87: The following editing and inferior-shell commands can ONLY be issued ! 88: from within a buffer in sml-mode. (The names in parenthesis is the ! 89: Emacs-lisp name of the function, that is associated with the keystroke ! 90: command). ! 91: ! 92: M-| (sml-electric-pipe). ! 93: In the case you are typing in a case expression, a function with ! 94: patterns etc., this function will give you some help. First of all ! 95: it will put the `|' on a line by itself. If it is used in the ! 96: definition of a function it inserts the functions name, else it ! 97: inserts `=>'. Just try it, you will like it. ! 98: ! 99: LFD (reindent-then-newline-and-indent). ! 100: This is probably the function you will be using the most (press ! 101: CTRL while you press Return, press C-j or press Newline). It ! 102: will reindent the line, then make a new line and perform a new ! 103: indentation. ! 104: ! 105: TAB (sml-indent-line). ! 106: This function indents the current line. ! 107: ! 108: C-c TAB (sml-indent-region). ! 109: This function indents the current region (be patient if the ! 110: region is large). ! 111: ! 112: M-; (indent-for-comment). ! 113: Like in other language modes, this command will give you a comment ! 114: at the of the current line. The column where the comment starts is ! 115: determined by the variable comment-column (default: 40). ! 116: ! 117: C-c C-v (sml-mode-version). ! 118: Get the version of the sml-mode. ! 119: ! 120: ! 121: 1.3. COMMANDS RELATED TO THE INFERIOR SHELL ! 122: ------------------------------------------- ! 123: ! 124: C-c C-s (sml-pop-to-shell). ! 125: This command starts up an inferior shell running sml. If the shell ! 126: is running, it will just pop up the shell window. ! 127: ! 128: C-c C-u (sml-save-buffer-use-file). ! 129: This command will save the current buffer and send a "use file", ! 130: where file is the file visited by the current buffer, to the ! 131: inferior shell running sml. ! 132: ! 133: C-c i (sml-import-file) ! 134: Will save the current buffer and send an "import file", where file ! 135: is the file visited by the current buffer, to the inferior shell ! 136: running sml. ! 137: ! 138: C-c C-f (sml-run-on-file). ! 139: Will send a "use file" to the inferior shell running sml, ! 140: prompting you for the file name. ! 141: ! 142: C-c ' (sml-next-error). ! 143: This function parses the buffer of the inferior shell running sml, ! 144: and finds the errors one by one. The cursor is positioned at the ! 145: line of the file indicated by the error message, while the ! 146: inferior shell buffer running sml will be positioned at the error ! 147: message in another window. ! 148: ! 149: C-c C-k (sml-skip-errors) ! 150: This function will skip past the rest of the error messages in ! 151: the inferior shell ! 152: ! 153: IMPORTANT: These two functions only knows the syntax of error ! 154: messages produced by SML of New Jersey. To have these functions ! 155: working with other implementations of sml you will have to ! 156: rewrite them. ! 157: ! 158: C-c C-r (sml-send-region). ! 159: Will send region, from point to mark, to the inferior shell ! 160: running sml. ! 161: ! 162: C-c C-c (sml-send-function). ! 163: Will send function to the inferior shell running sml. (This only ! 164: sends the paragraph, so you might prefer the sml-send-region ! 165: instead. Paragraphs are separated by blank lines only). ! 166: ! 167: C-c C-b (sml-send-buffer). ! 168: Will send whole buffer to inferior shell running sml. ! 169: ! 170: ! 171: 2. INDENTATION ! 172: ============== ! 173: ! 174: The indentation algorithm has been the hardest one to implement. ! 175: ! 176: What is the standard way of indenting sml-code? ! 177: ! 178: The algorithm has its own view of the right way to indent code, ! 179: according to the constants you can set to control the mode. ! 180: ! 181: ! 182: 2.1. CONSTANTS CONTROLLING THE INDENTATION ! 183: ------------------------------------------ ! 184: ! 185: sml-indent-level (default 4) ! 186: Indentation of blocks in sml. ! 187: ! 188: sml-pipe-indent (default -2) ! 189: The amount of extra indentation (negative) of lines beginning ! 190: with "|". ! 191: ! 192: sml-case-indent (default nil) ! 193: How to indent case-of expressions. ! 194: ! 195: If t: case expr If nil: case expr of ! 196: of exp1 => ... exp1 => ... ! 197: | exp2 => ... | exp2 => ... ! 198: ! 199: The first seems to be the standard in NJ-SML. The second is the ! 200: default. ! 201: ! 202: sml-nested-if-indent (default nil) ! 203: If set to t, nested if-then-else expressions will have the ! 204: indentation: ! 205: ! 206: if exp1 then exp2 ! 207: else if exp3 then exp4 ! 208: else if exp5 then exp6 ! 209: else exp7 ! 210: ! 211: If nil, they will be indented as: ! 212: ! 213: if exp1 then exp2 ! 214: else if exp3 then exp4 ! 215: else if exp5 then exp6 ! 216: else exp7 ! 217: ! 218: With the "else" at the same column as the matching "if". ! 219: ! 220: sml-type-of-indent (default t) ! 221: Determines how to indent `let', `struct' etc. ! 222: ! 223: If t: fun foo bar = let ! 224: val p = 4 ! 225: in ! 226: bar + p ! 227: end ! 228: ! 229: If nil: fun foo bar = let ! 230: val p = 4 ! 231: in ! 232: bar + p ! 233: end ! 234: ! 235: Will not have any effect if the starting keyword is first on the ! 236: line. ! 237: ! 238: sml-electric-semi-mode (default t) ! 239: If t, a ";" will reindent the current line, and make a newline. To ! 240: override this (to type in a ";" without a newline) just type: C-q ; ! 241: ! 242: sml-paren-lookback (default 200) ! 243: Determines how far back (in chars) the indentation algorithm ! 244: should look for open parenthesis. High value means slow ! 245: indentation algorithm. A value of 200 (being the equivalent of ! 246: 4-6 lines) should suffice most uses. (A value of nil, means do ! 247: not look at all). ! 248: ! 249: To change these constants, See CUSTOMIZING YOUR SML-MODE below. ! 250: ! 251: ! 252: 3. INFERIOR SHELL. ! 253: ================== ! 254: ! 255: The mode for Standard ML also contains a mode for an inferior shell ! 256: running sml. The mode is the same as the shell-mode, with just one ! 257: extra command. ! 258: ! 259: ! 260: 3.1. INFERIOR SHELL COMMANDS ! 261: ---------------------------- ! 262: ! 263: C-c C-f (sml-run-on-file). Send a `use file' to the process running ! 264: sml. ! 265: ! 266: ! 267: 3.2. CONSTANTS CONTROLLING THE INFERIOR SHELL MODE ! 268: -------------------------------------------------- ! 269: ! 270: Because sml is called differently on various machines, and the ! 271: sml-systems have their own command for reading in a file, a set of ! 272: constants controls the behavior of the inferior shell running sml (to ! 273: change these constants: See CUSTOMIZING YOUR SML-MODE below). ! 274: ! 275: sml-prog-name (default "sml"). ! 276: This constant is a string, containing the command to invoke ! 277: Standard ML on your system. ! 278: ! 279: sml-prog-name-ask-p (default nil) ! 280: If t, you will be asked which program to run when the inferior ! 281: shell starts up. Usefull if you have exported images of sml. ! 282: ! 283: sml-use-right-delim (default "\"") ! 284: sml-use-left-delim (default "\"") ! 285: The left and right delimiter used by your version of sml, for ! 286: `use file-name'. ! 287: ! 288: sml-process-name (default "SML"). ! 289: The name of the process running sml. (This will be the name ! 290: appearing on the mode line of the buffer) ! 291: ! 292: NOTE: The sml-mode functions: sml-send-buffer, sml-send-function and ! 293: sml-send-region, creates temporary files (I could not figure out how ! 294: to send large amounts of data to a process). These files will be ! 295: removed when you leave emacs. ! 296: ! 297: ! 298: 4. CUSTOMIZING YOUR SML-MODE ! 299: ============================ ! 300: ! 301: If you have to change some of the constants, you will have to add a ! 302: `hook' to the sml-mode. Insert this in your "~/.emacs" file. ! 303: ! 304: (setq sml-mode-hook 'my-sml-constants) ! 305: ! 306: Your function "my-sml-constants" will then be executed every time ! 307: "sml-mode" is invoked. Now you only have to write the emacs-lisp ! 308: function "my-sml-constants", and put it in your "~/.emacs" file. ! 309: ! 310: Say you are running a version of sml that uses the syntax `use ! 311: ["file"]', is invoked by the command "OurSML" and you don't want the ! 312: indentation algorithm to indent according to open parenthesis, your ! 313: function should look like this: ! 314: ! 315: (defun my-sml-constants () ! 316: (setq sml-prog-name "OurSML") ! 317: (setq sml-use-left-delim "[\"") ! 318: (setq sml-use-right-delim "\"]") ! 319: (setq sml-paren-lookback nil)) ! 320: ! 321: Other things could be added to this function. As an example: ! 322: ! 323: (setq sml-paren-lookback 1000) ; Look back 1000 chars for open ! 324: ; parenthesis. ! 325: ! 326: (setq sml-case-indent t) ; Select other type of case ! 327: ; expressions ! 328: ! 329: (turn-on-auto-fill) ; Turn on auto-fill ! 330: ! 331: (setq sml-indent-level 8) ; change the indentation to 8 ! 332: ! 333: (setq sml-prog-name-ask-p t) ; Ask which program to run when the ! 334: ; inferior shell starts up. ! 335: ! 336: (define-key sml-mode-map "|" ; Let "|" be electric, ! 337: 'sml-electric-pipe) ; like M-| ! 338: ! 339: The sml-shell also runs a `hook' (sml-shell-hook) when it is invoked. ! 340: ! 341: ! 342: 5. CHANGES FROM PREVIOUS VERSIONS ! 343: ================================ ! 344: ! 345: For those of you who have been using sml-mode in an earlier version, ! 346: here is a compiled list of the changes made. ! 347: ! 348: ! 349: 5.1 VERSION 1.0 TO 2.0 ! 350: ---------------------- ! 351: ! 352: o Some bugs fixed. ! 353: ! 354: o The indentation algorithm has become better at determining the ! 355: right indentation, and faster. ! 356: ! 357: o A number of constants have been introduced to customize the mode ! 358: to your needs. ! 359: ! 360: o The indentation algorithm recognizes `else if' (nested if then ! 361: else), but only if the variable "sml-nested-if-indent" has been ! 362: set to t, the default is nil. ! 363: ! 364: o By setting the variable sml-case-indent to either nil or t you now ! 365: can have two different indentations of case-expr-of. ! 366: ! 367: o The constant sml-type-of-indent now determines the way to indent ! 368: blocks, if the starting keyword is not first on the line. ! 369: ! 370: o The indentation algorithm now indents to same level as an open ! 371: parenthesis if this was left open at a previous line (the variable ! 372: sml-paren-lookback controls this action.) ! 373: ! 374: o A couple of extra functions have been added: ! 375: sml-next-error and sml-save-buffer-use-file. ! 376: ! 377: o If temporary files are created, these files will be removed when ! 378: emacs is killed. ! 379: ! 380: o Thanks to Andy Norman (ange%[email protected]) you are no ! 381: longer placed in the inferior shell when you send a `use file' to ! 382: the inferior shell. The shell window will pop up, and the window ! 383: will scroll. He also added a shell-prompt-pattern variable for the ! 384: inferior sml shell mode. This will allow you to move the cursor ! 385: backwards in the buffer, and re-execute lines that begin with this ! 386: pattern (pattern is found in the variable sml-shell-prompt-pattern). ! 387: ! 388: ! 389: 5.2 VERSION 2.0 TO 2.1 ! 390: ---------------------- ! 391: ! 392: o Some bugs fixed. ! 393: ! 394: o Due to a bug in the Un*x function mktemp, you could only send ! 395: 26 temporary files. This has been fixed by adding an extra letter ! 396: to the file-name (sml-tmp-file-name) in the function that sends ! 397: the files (sml-simulate-send-region). ! 398: ! 399: ! 400: 5.3 VERSION 2.1 TO 2.2 ! 401: ---------------------- ! 402: ! 403: o Some bugs fixed. ! 404: ! 405: o A new function (sml-skip-errors, bound to C-c C-k) has been ! 406: added. It skips the rest of the error messages. Very handy if a ! 407: lot of errors follows a simple mistake. ! 408: ! 409: o Sending something to the process running sml, will call ! 410: sml-skip-errors first, so old errors will be forgotten. ! 411: ! 412: o sml-indent-line (TAB) now leaves the point where it is (unless ! 413: if it is before the indentation). ! 414: ! 415: 5.3 VERSION 2.2 TO 2.3 ! 416: ---------------------- ! 417: ! 418: o Some bugs fixed. ! 419: ! 420: o New variable (sml-prog-name-ask-p). If t, you will be asked which ! 421: program to run when the inferior shell starts up. Usefull if you have ! 422: exported images of sml. ! 423: ! 424: 5.4 VERSION 2.2 TO 2.4 ! 425: ---------------------- ! 426: ! 427: o Some bugs fixed. ! 428: ! 429: o Added sml-import-file. ! 430: ! 431: 6. THINGS TO DO ! 432: =============== ! 433: ! 434: And there are still things to do: ! 435: ! 436: o Find a better way to send regions to the inferior shell (the command ! 437: process-send-region does not work on larger regions, that is why the ! 438: function sml-simulate-send-region uses temporary files). ! 439: ! 440: o Have sml-next-error recognizing more than just SML of New Jersey ! 441: syntax of error messages. ! 442: ! 443: o The indentation algorithm still can be fooled. I don't know if it ! 444: will ever be 100% right, as this means it will have to actually ! 445: parse all of the buffer up to the actual line (this can get -very- ! 446: slow). ! 447: ! 448: o Add tags. ! 449: ! 450: ! 451: Thanks ! 452: ====== ! 453: ! 454: Thanks to Andy Norman (ange%[email protected]) for helping me a ! 455: lot. Not only did he tell me about the bugs, he also included fixes. ! 456: ! 457: ! 458: Author ! 459: ====== ! 460: Lars Bo Nielsen ! 461: Aalborg University ! 462: Computer Science Dept. ! 463: 9000 Aalborg ! 464: Denmark ! 465: ! 466: [email protected] ! 467: or: ...!mcvax!diku!iesd!lbn ! 468: or: [email protected] ! 469: ! 470: Please let me know if you come up with any ideas, bugs, or fixes. ! 471: ! 472:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.