dotfiles

My personal shell configs and stuff
git clone git://git.alex.balgavy.eu/dotfiles.git
Log | Files | Refs | Submodules | README | LICENSE

commit 47eb6d199464b5a510ec6c61a495fc57bcf4d96f
parent 7d03d1ed880f1a7356fc113635f3efd796e959b4
Author: Alex Balgavy <a.balgavy@gmail.com>
Date:   Wed,  9 Oct 2019 01:38:12 -0400

emacs: more changes

Former-commit-id: c69b943a99c546fc8f7482ee458e592e47a795fc
Diffstat:
Memacs/emacs | 11++++++++---
Demacs/emacs.d/sml-mode-5.0/BUGS | 11-----------
Demacs/emacs.d/sml-mode-5.0/ChangeLog | 573-------------------------------------------------------------------------------
Demacs/emacs.d/sml-mode-5.0/INSTALL | 39---------------------------------------
Demacs/emacs.d/sml-mode-5.0/Makefile | 176-------------------------------------------------------------------------------
Demacs/emacs.d/sml-mode-5.0/NEWS | 137-------------------------------------------------------------------------------
Demacs/emacs.d/sml-mode-5.0/README | 19-------------------
Demacs/emacs.d/sml-mode-5.0/TODO | 46----------------------------------------------
Demacs/emacs.d/sml-mode-5.0/makefile.pkg | 15---------------
Demacs/emacs.d/sml-mode-5.0/sml-mode-startup.el | 59-----------------------------------------------------------
Demacs/emacs.d/sml-mode-5.0/sml-mode.el | 1436-------------------------------------------------------------------------------
Demacs/emacs.d/sml-mode-5.0/sml-mode.info | 908-------------------------------------------------------------------------------
Demacs/emacs.d/sml-mode-5.0/sml-mode.spec | 67-------------------------------------------------------------------
Demacs/emacs.d/sml-mode-5.0/sml-mode.texi | 1161-------------------------------------------------------------------------------
Demacs/emacs.d/sml-mode-5.0/sml-oldindent.el | 713-------------------------------------------------------------------------------
Demacs/emacs.d/sml-mode-5.0/sml-proc.el | 784-------------------------------------------------------------------------------
Demacs/emacs.d/sml-mode-5.0/testcases.sml | 563-------------------------------------------------------------------------------
17 files changed, 8 insertions(+), 6710 deletions(-)

diff --git a/emacs/emacs b/emacs/emacs @@ -27,10 +27,13 @@ `(("." . ,(concat user-emacs-directory "backup/"))) tramp-backup-directory-alist backup-directory-alist) -;; Some version control for backups -(custom-set-variables - '(version-control t)) +;; Add package repositories +(require 'package) +(add-to-list 'package-archives + '("melpa-stable" . "http://stable.melpa.org/packages/") t) +(package-initialize) +;; Some version control for backups (custom-set-variables ;; custom-set-variables was added by Custom. ;; If you edit it by hand, you could mess it up, so be careful. @@ -43,6 +46,8 @@ '(custom-safe-themes (quote ("1a232652b04b68380b1cff7ceeb62787b4eb43df826a97c67831c50b0c0d1451" "3fd57a3dc99eb0e2ec438555cf801572f649c79513d3a8da7980ab54cf66121b" default))) + '(package-selected-packages (quote (haskell-mode))) + '(version-control t) '(xterm-mouse-mode t)) (custom-set-faces ;; custom-set-faces was added by Custom. diff --git a/emacs/emacs.d/sml-mode-5.0/BUGS b/emacs/emacs.d/sml-mode-5.0/BUGS @@ -1,11 +0,0 @@ --*- text -*- - -Here are the current known bugs. -If you find any other, send it to <monnier@iro.umontreal.ca>. - -* M-x next-error and other compile.el support doesn't work on XEmacs. - -* indentation of a declaration after a long `datatype' is slow. - -* buggy indentation samples - Try `make test' to see the known problems in testcases.sml diff --git a/emacs/emacs.d/sml-mode-5.0/ChangeLog b/emacs/emacs.d/sml-mode-5.0/ChangeLog @@ -1,573 +0,0 @@ -2012-04-11 Stefan Monnier <monnier@iro.umontreal.ca> - - Merge sml-defs.el into sml-mode.el. - * sml-mode.el: Merge code from sml-defs.el. - Remove ":group 'sml" since they're now redundant. - * makefile.pkg (ELFILES): Adjust. - -2012-04-11 Stefan Monnier <monnier@iro.umontreal.ca> - - * sml-mode.el (sml-mark-function): New implementation using SMIE. - * sml-defs.el (sml-mode-map): Use backtab. - Remove leftover unused sml-drag-region binding. - -2012-04-11 Stefan Monnier <monnier@iro.umontreal.ca> - - Use SMIE by default and make sml-oldindent optional. - * sml-mode.el: Only load sml-oldindent if necessary. - (sml-use-smie): Default to t. - (sml-smie-datatype-|-p): Better handle incomplete datatype branch. - (sml-mode): Use prog-mode. Setup electric-layout and electric-indent. - (sml-mode-variables): Always setup SMIE if possible. - (sml-imenu-create-index, sml-funname-of-and, sml-electric-pipe) - (sml-beginning-of-defun, sml-defuse-symdata-at-point) - (sml-yacc-font-lock-keywords, sml-yacc-indentation): - Avoid sml-oldindent functions. - (sml-find-forward): Move from sml-oldindent and re-implement. - (sml-electric-semi): Use self-insert-command so electric-layout and - electric-indent can do their job. - (sml-smie-find-matching-starter, sml-find-matching-starter) - (sml-smie-skip-siblings, sml-skip-siblings): New functions. - * sml-oldindent.el (sml-starters-indent-after, sml-exptrail-syms): - Remove, unused. - (sml-find-forward): Move back to sml-mode.el. - (sml-old-find-matching-starter): Rename from sml-find-matching-starter. - (sml-old-skip-siblings): Move&rename from sml-mode:sml-skip-siblings. - -2012-04-11 Stefan Monnier <monnier@iro.umontreal.ca> - - Move non-SMIE indentation code to a separate file. - * sml-oldindent.el: Rename from sml-move.el. - * makefile.pkg (ELFILES): Adjust. - * sml-mode.el (sml-indent-line, sml-find-comment-indent) - (sml-calculate-indentation, sml-bolp, sml-first-starter-p) - (sml-indent-starter, sml-indent-relative, sml-indent-pipe) - (sml-find-forward, sml-indent-arg, sml-get-indent, sml-dangling-sym) - (sml-delegated-indent, sml-get-sym-indent, sml-indent-default) - (sml-current-indentation, sml-find-matching-starter): - Move to sml-oldindent.el. - (comment-quote-nested, compilation-error-regexp-alist): Declare. - - * sml-defs.el (sml-begin-syms, sml-begin-syms-re) - (sml-sexp-head-symbols-re, sml-preproc-alist, sml-indent-rule) - (sml-starters-indent-after, sml-delegate, sml-symbol-indent) - (sml-open-paren, sml-close-paren, sml-agglomerate-re) - (sml-exptrail-syms): Move to sml-oldindent.el. - -2012-04-11 Stefan Monnier <monnier@iro.umontreal.ca> - - Get rid of ancient compatibility and small utility file. - * sml-proc.el (inferior-sml-mode-map): Don't use defmap. - * sml-move.el (sml-internal-syntax-table): Don't use defsyntax. - * sml-mode.el (sml-syntax-prop-table): Don't use defsyntax. - (sml-electric-space): `last-command-char' -> `last-command-event'. - (sml-defuse-jump-to-def): Don't use goto-line from Elisp. - * sml-defs.el (sml-mode-map): Don't use defmap. - (sml-mode-syntax-table): Don't use defsyntax. - (sml-preproc-alist, sml-builtin-nested-comments-flag): - Move from sml-util.el. - * sml-compat.el, sml-utils.el: Remove. - * makefile.pkg (ELFILES): Update. - -2012-04-11 Stefan Monnier <monnier@iro.umontreal.ca> - - Add SMIE support. - * .bzrignore: New file. - * makefile.pkg (test): Use sml-mode-startup. - - * sml-mode.el (sml-use-smie): New config var. - (sml-smie-grammar, sml-indent-separator-outdent): New vars. - (sml-smie-rules, sml-smie-definitional-equal-p) - (sml-smie-non-nested-of-p, sml-smie-datatype-|-p) - (sml-smie-forward-token-1, sml-smie-forward-token) - (sml-smie-backward-token-1, sml-smie-backward-token): New functions. - (sml-mode): Don't set forward-sexp-function. - (sml-mode-variables): Set it here instead, and setup SMIE instead - if applicable. - -2010-03-04 Stefan Monnier <monnier@iro.umontreal.ca> - - * Release version 4.1. - - * sml-mode.el: Don't setup load-path here any more. - * Makefile ($(PACKAGE)-startup.el): Recreate from scratch every time. - Setup load-path. - (dist): Try to update it to use Svn rather than CVS. - -2007-11-08 Stefan Monnier <monnier@iro.umontreal.ca> - - * sml-proc.el (inferior-sml-next-error-hook): Make it match one - more format. - -2007-10-31 Stefan Monnier <monnier@iro.umontreal.ca> - - * testcases.sml: Add (old) buggy case from Christopher Dutchyn. - - * sml-proc.el (inferior-sml-font-lock-keywords): Don't add - error-regexps if compile.el already highlights them anyway. - - * sml-mode.el (sml-font-lock-symbols-alist): Fix char for "not". - -2007-10-31 Stefan Monnier <monnier@iro.umontreal.ca> - - * sml-mode.el (sml-def-skeleton): If possible, only expand for - lower-case abbrevs and not inside strings or comments. - (sml-mlton-typecheck): Typo. - - * sml-proc.el (sml-proc-comint-input-filter-function): New function. - (inferior-sml-mode): Use it. - (sml-update-cursor): Don't forget errors here any more. - -2007-10-31 Stefan Monnier <monnier@iro.umontreal.ca> - - * sml-util.el (defmap, defsyntax): Avoid defconst. - (flatten): Remove. - - * sml-mode.el (sml-calculate-indentation): Avoid previous-line. - (sml-keywords-regexp): Avoid the need for `flatten'. - (sml-defuse-jump-to-def): Fix typo. - - * sml-defs.el (sml-syms-re): Don't use `flatten'. - (sml-sexp-head-symbols-re, sml-starters-indent-after) - (sml-non-nested-of-starter-re): Avoid the need for `flatten'. - - * sml-proc.el (inferior-sml-next-error-hook): New fun. - (inferior-sml-mode): Use it. - -2007-06-29 Stefan Monnier <monnier@iro.umontreal.ca> - - * sml-mode.el (sml-mlton-error-regexp-alist): New var. - (sml-mlton-typecheck): Use it. - (compilation-error-regexp-alist): Add entries after loading "compile" - so that M-x compile works. - - * sml-proc.el (inferior-sml-mode): Make TAB add a " rather than a space - at the end of a file name. - -2007-06-14 Stefan Monnier <monnier@iro.umontreal.ca> - - * sml-mode.el (sml-mode-variables): Set comment-quote-nested instead of - comment-nested. Set comment-end-skip. - (sml-first-starter-p): New function. - (sml-indent-starter): Use it to fix an indentation bug. - (sml-mlton-command, sml-mlton-mainfile): New vars. - (sml-mlton-typecheck): New command. - (sml-defuse-file): New var. - (sml-defuse-def-regexp, sml-defuse-use-regexp-format): New consts. - (sml-defuse-file, sml-defuse-symdata-at-point): New functions. - (sml-defuse-set-file, sml-defuse-jump-to-def): New commands. - -2005-11-20 Stefan Monnier <monnier@iro.umontreal.ca> - - * sml-move.el (sml-find-match-forward): Avoid infinite looping if the - construct is not properly closed (yet). - -2005-11-16 Stefan Monnier <monnier@iro.umontreal.ca> - - * sml-defs.el (sml-mode-menu): Remove left over obsolete entries. - - * sml-proc.el (inferior-sml-mode): Preserve the menu-bar of the - compilation minor mode, if any. - -2004-11-24 Stefan Monnier <monnier@iro.umontreal.ca> - - * Release version 4.0. - -2004-11-23 Stefan Monnier <monnier@iro.umontreal.ca> - - * sml-mode.el (sml-font-lock-symbols-alist): Add yet more silly entries. - -2004-11-15 Stefan Monnier <monnier@iro.umontreal.ca> - - * sml-mode.el (sml-font-lock-symbols-alist): Add entries for >= and <=. - (sml-font-lock-symbols-alist): Add entries for simple type variables. - (sml-font-lock-compose-symbol): Add support for non-punctuation syms. - -2004-11-14 Stefan Monnier <monnier@iro.umontreal.ca> - - * sml-move.el (sml-backward-sexp, sml-forward-sexp): Remove unused var. - - * sml-mode.el (sml-calculate-indentation): Remove unused var. - (sml-get-indent): Change first arg's meaning. - (sml-get-sym-indent): Adjust call. - (sml-forms-menu): Simplify. - (sml-font-lock-symbols, sml-font-lock-symbols-alist): New vars. - (sml-font-lock-compose-symbol, sml-font-lock-symbols-keywords): - New funs. - (sml-font-lock-keywords): Use them. - - * sml-compat.el (temp-directory): Get rid of warning. - - * Makefile (install_startup): Don't add to load-path any more. - - * sml-proc.el (sml-make-error): Use match-string. - (sml-error-regexp-alist): Merge regexps. - (sml-update-cursor): Check sml-temp-file is non-nil. - -2004-04-21 Stefan Monnier <monnier@iro.umontreal.ca> - - * sml-proc.el (sml-error-regexp-alist): Use new compile.el features - if available. - (sml-send-region): Remove unused var `file'. - (sml-drag-region): Remove unused function. - (sml-update-cursor): Use compilation-fake-loc if available. - (compilation-goto-locus): Only advise if necessary. - - * sml-mode.el: Add self to load-path in sml-mode-startup.el. - (sml-def-skeleton): Try to use the new `system' abbrev flag. - -2004-04-04 Stefan Monnier <monnier@iro.umontreal.ca> - - * testcases.sml: Add a nasty case that is still wrong. - - * sml-proc.el (sml-error-regexp-alist): Tune the regexp for sml/nj. - - * sml-mode.el (sml-mode): Better handle paragraphs in comments. - (sml-mode-variables): Clean up paragraph settings. - (sml-electric-pipe): Fix a boundary bug. - (sml-indent-starter, sml-get-sym-indent, sml-find-matching-starter): - Fix indentation algorithm. Can't remember what it was about. - This code is nasty, I just can't understand what's doing what. - (completion-ignored-extensions): Add the new .cm directory. - -2003-12-09 Stefan Monnier <monnier@iro.umontreal.ca> - - * sml-defs.el (sml-mode-menu): Fix typo. Use std names. - (sml-begin-syms-re): Reduce redundancy. - -2001-09-18 Stefan Monnier <monnier@cs.yale.edu> - - * sml-mode.el (sml-tyvarseq-re): Fix typo. - -2001-07-20 Stefan Monnier <monnier@cs.yale.edu> - - * sml-mode.el (sml-rightalign-and): New defcustom. - (sml-tyvarseq-re): New var. - (sml-font-lock-keywords): Use it. - (sml-imenu-create-index): Don't get confused by tyvarseq's. - (sml-mode-variables): Don't set `comment-column'. - (sml-funname-of-and): New function. - (sml-electric-pipe): Use it. - (sml-find-comment-indent): Try to ignore comment-markers in strings. - (sml-calculate-indentation): Handle closing parens specially. - (sml-indent-pipe): Recognize the case where `and' defines a datatype. - (sml-dangling-sym): Make it work if the symbol is an open-paren. - (sml-indent-default): Change the behavior when preceded by `end', - although I'm not quite sure why. - Understand dangling open-parens. - Properly skip *all* subexpressions of lower precedence. - Allow use of sml-symbol-indent to outdent lines starting with , or ;. - (sml-insert-form): Use preceding-char to avoid bug at bobp. - -2001-07-19 Stefan Monnier <monnier@cs.yale.edu> - - * sml-proc.el (sml-proc-buffer): Save excursion when calling run-sml. - - * sml-move.el (sml-syntax-prec): Split ; and , from `in' and `with'. - - * sml-mode.texi: Put the entry in `Emacs' rather than `Editors'. - - * sml-mode.spec (BuildArch): Simplify call to `install-info'. - - * sml-defs.el (sml-mode-menu): Add an explicit t for always-active. - (sml-symbol-indent): Add entries for , and ; and turn into defcustom. - - * sml-compat.el: Add more stuff. It might help for Emacs-19.34. - - * makefile.pkg (test): Use elisp files in current dir. - -2000-12-24 Stefan Monnier <monnier@cs.yale.edu> - - * Release version 3.9.5. - - * Makefile (install): Also install .el files. - (dist): Don't rely on $CVSROOT. - - * sml-mode.el: Require `skeleton'. - (sml-mode): Add the menu for XEmacs. Make sure @ is a valid skeleton. - (sml-comment-indent): Remove. - (sml-mode-variables): Don't set comment-indent-function. - (sml-def-skeleton): Nop if skeletons aren't available. - (skeletons): Use `> _' and `@'. - (sml-forms-menu): Don't bother with easy-menu-filter-return crap. - (sml-cm-mode-syntax-table, sml-cm-font-lock-keywords): New vars. - (sml-cm-mode): Use define-derived-mode rather than define-generic-mode. - (sml-lex-font-lock-keywords, sml-lex-font-lock-defaults): New vars. - (sml-yacc-font-lock-keywords): Use sml-lex-font-lock-keywords. - Refine pattern to recognize the %prec keyword. - (sml-yacc-font-lock-defaults): Fix typo. - - * sml-proc.el (inferior-sml-mode): Disable next-error for XEmacs. - - * sml-util.el (defsyntax): Don't forget to eval `doc'. - - * sml-mode.spec: Simplify. - - * sml-defs.el (sml-mode-menu): Remove bogus entry for sml-mode-version. - -2000-10-06 Stefan Monnier <monnier@cs.yale.edu> - - * sml-mode.el: Make the toplevel closer to usual practice. - (sml-imenu-regexp, sml-imenu-create-index): New var and fun. - (sml-mode): Use them. - (sml-beginning-of-defun): Add `and' as function-leader. - (sml-lex-mode): New trivial mode. - (sml-yacc-bnf-face, sml-yacc-indent-action, sml-yacc-indent-pipe) - (sml-yacc-indent-term, sml-yacc-font-lock-keywords) - (sml-yacc-font-lock-defaults): New vars. - (sml-yacc-indent-line, sml-yacc-indentation, sml-yacc-mode): New funs. - - * sml-mode.texi: Added yours truly to the list of authors. - - * sml-mode.spec: New file. - - * sml-defs.el (sml-outline-regexp): Slightly improved regexp. - -2000-08-24 Stefan Monnier <monnier@cs.yale.edu> - - * sml-proc.el (inferior-sml-mode-map): Don't inherit from sml-bindings. - Add the binding for C-c C-l explicitly instead. - (sml-run): Look in cwd (but only if the command has slashes). - - * sml-mode.el (sml-mode-abbrev-table): Remove (created by - define-derived-mode). - (sml-mode): Setup add-log's current-defun-function. - (sml-indent-line): Never indent to a negative level. - (sml-skip-siblings, sml-beginning-of-defun, sml-max-name-components) - (sml-current-fun-name): New funs and vars for add-log support. - (sml-comment-indent): Simplify. - (sml-def-skeleton): Also create the skeleton as an abbrev. - (skeletons): New for "struct", "sig", "val", "fn" and "fun". - (sml-electric-space): Rewrite to use abbrev's machinery. - - * sml-defs.el (sml-mode-map): Merge with sml-bindings. - (sml-bindings): Remove. - -2000-02-22 Stefan Monnier <monnier@cs.yale.edu> - - * sml-mode.el (sml-find-matching-starter): Use syms instead of a RE. - (sml-indent-default): Use symbol membership rather than a regexp. - Also, use `sym-indent' instead of (current-column). - This fixes a problem with a hanging `structure Foo = (struct|let)' - (due to `structure' having a sml-indent-rule, as opposed to `fun'). - Hopefully it won't introduce other problems. - (sml-font-lock-keywords): Match vars `val x : int' also. - (sml-electric-pipe): Update to the new `sml-find-matching-starter' and - return a sensible default instead of raising an error in case of - unexpected situations. - (sml-indent-line): Ignore errors and keep the cursor where it is. - (sml-calculate-indentation, sml-indent-pipe): Use syms instead of REs. - - * sml-defs.el (sml-starters-re, sml-pipehead-re): Remove. - - * testcases.sml: New file. - - * makefile.pkg (test): New target to run the test suite. - -2000-02-18 Stefan Monnier <monnier@cs.yale.edu> - - * *.el: Pass through checkdoc and use `eval-when-compile' whenever - possible for (require 'cl). - -2000-02-18 Stefan Monnier <monnier@cs.yale.edu> - - * sml-util.el (make-temp-dir, make-temp-file, temp-file-dir) - (delete-temp-dirs): Replace by the make-temp-file from Emacs-21. - (custom-create-map): Add :group arg and allow key to be a list. - (define-major-mode): Remove (use define-derived-mode instead). - (sml-builtin-nested-comments-flag): New var. - (concatq): Remove. - - * sml-proc.el (sml-host-name): New var. - (sml-make-file-name): Replace by `sml-compile-commands'. - (sml-config-file): New var. - (sml-compile-commands-alist): New var. - (inferior-sml-load-hook): Remove. - (sml-buffer): Query if the current buffer is not a *sml*. - (inferior-sml-mode): Use minor-mode-overriding-map-alist to disable - compilation-minor-mode's keybindings. - (run-sml): Turn into an alias for sml-run. - (sml-run): Query the user for the command. If prefix is set (or if - default value is not null) query for args and host. - Use `split-string' rather than our own function. - Run cmd on another host if requested and pass it an init file. - Pop to the buffer at the end. - (sml-args-to-list): Remove. - (sml-compile): Look for special files (sml-compile-command-alist) in - the current dir (and its parents) to choose a default command. - Remember the command for next time in the same buffer. - Make the `cd' explicit in the command so the user can change it. - (sml-make-error): Fix for when `endline' is absent. - - * sml-mode.el: Pass it through checkdoc. - (sml-mode-version): Remove. - (sml-load-hook): Remove. - (sml-mode-info): Use `info' rather than `Info-goto-node'. - (sml-keywords-regexp): Add "o". - (sml-syntax-prop-table): Use `defsyntax'. - (sml-font-lock-syntactic-keywords): Only use nested comments if supported. - (sml-mode): Use `define-derived-mode'. - (sml-electric-pipe): `sml-indent-line' -> `indent-according-to-mode'. - (sml-indent-line): Use `indent-line-to'. - (sml-cm-mode): New mode for CM files. - - * Makefile: Update. - - * sml-mode-startup.el: Remove since it's now auto-generated. - - * sml-defs.el (sml-bindings): Remove left over C-c` binding. - (sml-mode-map): Add binding for sml-drag-region (was in sml-proc.el). - (sml-mode-syntax-table): Only use nested comments if supported. - (sml-mode-menu): Use next-error rather than the old sml-next-error. - (sml-pipehead-re): Remove "of". - - * sml-compat.el (set-keymap-parents): Make sure it also works when - called with a single keymap rather than a list. - (temporary-file-directory): Add a default definition for XEmacs. - (make-temp-file): New function. - -1999-08-11 Stefan Monnier <monnier@cs.yale.edu> - - * Release version 3.9.3. - - * sml-mode.texi: Somewhat update the doc. - -1999-08-09 Stefan Monnier <monnier@cs.yale.edu> - - * Makefile: Update to the version of pcl-cvs. - - * sml-proc.el: Eliminate some old unused code. - - * sml-defs.el,sml-mode.el,sml-proc.el: Add simple customize support. - -1999-07-07 Stefan Monnier <monnier@cs.yale.edu> - - * sml-proc.el (sml-update-cursor): Make sure it also works if - compile.el is fixed to uses a marker. - - * sml-mode.el (sml-indent): Fix the `fixindent'. - -1999-06-22 Stefan Monnier <monnier@cs.yale.edu> - - * sml-mode-startup.el: Fix to fulfill autoload.el assumptions. - -1999-06-21 Stefan Monnier <monnier@cs.yale.edu> - - * sml-defs.el (sml-bindings): Remove bindings for TAB and M-C-\. - -1999-06-19 Stefan Monnier <monnier@cs.yale.edu> - - * sml-mode.el (sml-font-lock-keywords): Skip type vars in "fun 'a myfn" - (sml-calculate-indentation): Add a hack to allow the user to manually - override the indentation algorithm with a magic comment. - - * sml-mode-startup.el: Update the autoloads automatically. - -1999-06-19 Stefan Monnier <monnier@cs.yale.edu> - - * Release version 3.9.2 - - * sml-proc.el (sml-error-regexp-alist): Fix the pathological - font-locking on long lines. - - * sml-move.el (sml-forward-sexp): Slightly improved. - -1999-06-17 Stefan Monnier <monnier@cs.yale.edu> - - * sml-mode.el (sml-insert-form): Only add a space if needed. - (sml-electric-space): New command bound to M-SPC. - - * sml-defs.el (sml-close-paren): Add a second field that specifies when - not to delegate. Only used for `else'. - -1999-06-16 Stefan Monnier <monnier@cs.yale.edu> - - * sml-move.el (sml-(for|back)ward-sym): Distinguish between - operator "=" and syntax for definitions "d=". - - * sml-defs.el (sml-indent-starters, sml-delegate): Simplify. - (sml-symbol-indent): Add outdentation for `fn' and generalize it to - also work for `of' and `in' and `end'. - - * sml-mode.el (sml-nested-if-indent): Reintroduce as well as the - special casing code for it. - (sml-indent-relative): Generalize treatment of `of', `in', `end', ... - (sml-electric-pipe): Remove the slow behavior and add smarts for the - never-used type-variable arguments for function definitions. - -1999-06-15 Stefan Monnier <monnier@cs.yale.edu> - - * sml-defs.el (sml-mode-menu), sml-mode.el (sml-forms-menu): - Make the menu dynamically. - - * sml-mode.el (sml-form-<foo>): Use skeletons. - (sml-calculate-indentation): Add `with' indentation. - -1999-06-14 Stefan Monnier <monnier@cs.yale.edu> - - * sml-move.el (sml-(for|back)ward-sym): Now also return the string - if any and take care of the "op" special keyword. - (sml-op-prec): Setup an alist for the infix operators. - - * version 3.9.1: sent to Roland McGrath. - -1999-06-13 Stefan Monnier <monnier@cs.yale.edu> - - * sml-smlnj.el, sml-mosml.el, sml-poly-ml.el: Remove. - - * sml-proc.el (...): Get rid of sml-next-error by spicing up the - interface with compile.el so that intervals can be displayed. - `sml-overlay' is kept (and moved from sml-mode to sml-proc where it - belongs) but is made redundant in the case of transient-mark-mode. - -1999-06-12 Stefan Monnier <monnier@cs.yale.edu> - - * sml-proc.el (sml-prompt-regexp): More general regexp to catch mosml, - smlnj as well as polyml prompts. - (sml-update-cursor, sml-send-command, inferior-sml-mode): - Make it work with compile.el's `next-error'. - (sml-temp-threshold): Drop: always use a temp file. - -1999-06-10 Stefan Monnier <monnier@cs.yale.edu> - - * sml-move.el (sml-op-prec): Update the list of default infix ops - based on sml/nj's source files. - -1999-06-08 Stefan Monnier <monnier@cs.yale.edu> - - * sml-proc.el (sml-run): Remove dubious code to take care of a - supposedly special case in order not to send "" when args=nil. - -1999-06-07 Stefan Monnier <monnier@cs.yale.edu> - - * sml-mode.el (sml-font-lock-syntactic-keywords): Add syntactic - fontification for the ' \"' case (exhibited by lexgen.sml). - -1999-06-07 Stefan Monnier <monnier@cs.yale.edu> - - * ALL: The new indentation begins to work. v3_9_0 - -1999-05-29 Stefan Monnier <monnier@cs.yale.edu> - - * sml-defs.el (sml-mode-syntax-table): Add ~ of prefix-syntax. - - * sml-mode.el (sml-find-match-indent): (nilp sml-type-of-indent) is - only applied if the `let' is alone at the end of the line. - (sml-type-of-indent): Default changed to `nil'. - -1999-05-28 Stefan Monnier <monnier@cs.yale.edu> - - * sml-mode.el (sml-font-lock-keywords): Change _ and ' back to word - syntax for font-locking. - -1999-05-27 Stefan Monnier <monnier@cs.yale.edu> - - * sml-mode.el (sml-font-lock-syntactic-keywords): Finally got the - matching of let...end working. - (sml-electric-pipe): Take a fun sexp (symbol) rather than a fun word. - -1998-10-26 Stefan Monnier <monnier@cs.yale.edu> - - * sml-mode.el (sml-font-lock-syntactic-keywords): - Add syntactic-keywords to support nested comments. - diff --git a/emacs/emacs.d/sml-mode-5.0/INSTALL b/emacs/emacs.d/sml-mode-5.0/INSTALL @@ -1,39 +0,0 @@ -SML-MODE shouldn't require any special external support package, -as far as I can rememebr. Just a recent copy of Emacs or XEmacs. - -Installation of the program -=================================== - - 1. Edit the file `Makefile' to reflect the situation at your site. - The only things you have to change is the definition of `lispdir' - and `infodir'. The elisp files will be copied to `lispdir', and - the info file to `infodir'. - - 2. Have some sorbet. - - 3. Type `make install' in the source directory. This will byte-compile - all `.el' files and copy all into the directory you specified in step - 1. It will also copy the info files (and add a corresponding entry to - the info-dir file if install-info can be found). - - If you only want to create the compiled elisp files, you can just type - `make elcfiles' instead. - - 4. Edit the file `site-start.el' in your emacs lisp directory (usually - `/usr/local/share/emacs/site-lisp' or something similar) and make it - load the file `sml-mode-startup.el'. It contains a couple of - `auto-load's that facilitates the use of sml-mode. Alternatively, you - can just use `make install_startup'. If you're only installing it for - yourself rather than for the whole system, then use something like - `make install_startup startupfile=$HOME/.emacs'. - - 5. If you had copied the contents of a previous sml-mode-startup.el file to - your site-start.el (or .emacs), you might want to remove that. - - -How to make typeset documentation from the TeXinfo manual -========================================================= - - If you have TeX installed at your site, you can make a typeset version of -the manual typing ``make dvi''. If you prefer a postscript version of this -file, just use ``make postscript''. diff --git a/emacs/emacs.d/sml-mode-5.0/Makefile b/emacs/emacs.d/sml-mode-5.0/Makefile @@ -1,176 +0,0 @@ -# Makefile for emacs-lisp package - -# Copyright (C) 1998, 1999, 2004, 2007, 2010 Stefan Monnier <monnier@gnu.org> - -# This file is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License as published by the -# Free Software Foundation; either version 3, or (at your option) any -# later version. - -# This file is distributed in the hope that it will be useful, but WITHOUT -# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License -# for more details. - -# You should have received a copy of the GNU General Public License -# along with GNU Emacs; see the file COPYING. If not, write to -# the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. - -# load the package-specific settings -include makefile.pkg - -# set up the usual installation paths -prefix = /usr/local -datadir = $(prefix)/share - -# the directory where you install third-party emacs packges -lispdir = $(datadir)/emacs/site-lisp - -# the directory where the .elc files will be installed -elcdir = $(lispdir)/$(PACKAGE) -# the directory where the .el files will be installed -eldir = $(elcdir) - -# the file where the initialization goes. -#startupfile = $(HOME/.emacs -startupfile = $(lispdir)/site-start.el - -# the directory where you installed the elib .elc files. -# This is only needed if your site-start.el (or default.el) does not -# set up elib correctly. -elibdir = $(lispdir)/elib - -# the directory where you install the info doc -infodir = $(prefix)/info -docdir = $(prefix)/doc - -EMACS = emacs -MAKEINFO= makeinfo -TEXI2DVI= texi2dvi -SHELL = /bin/sh -DVIPS = dvips -CP = cp -RM = rm -f -MKDIR = mkdir -p -ETAGS = etags - -###################################################################### -### No changes below this line should be necessary ### -###################################################################### - -ELFLAGS = --eval '(setq load-path (append (list "." "$(elibdir)" "$(lispdir)") load-path))' -ELC = $(EMACS) -batch $(ELFLAGS) -f batch-byte-compile - -ELCFILES = $(ELFILES:.el=.elc) - -TEXEXTS = *.cps *.fns *.kys *.vr *.tp *.pg *.log *.aux *.toc *.cp *.ky *.fn - -.SUFFIXES: .elc .el .info .ps .dvi .texi -.PHONY: elcfiles info clean distclean default -.PHONY: install_startup install_elc install install_el install_info -.PHONY: dvi postscript - -.el.elc: - $(ELC) $< - -.texi.info: - $(MAKEINFO) $< - -.texi.dvi: - $(TEXI2DVI) $< - -.dvi.ps: - $(DVIPS) -f $< >$@ - -###################################################################### - -default: elcfiles - -elcfiles: $(ELCFILES) -info: $(PACKAGE).info - -install_elc: $(ELCFILES) $(PACKAGE)-startup.el - $(MKDIR) $(elcdir) - for f in $(ELCFILES) $(PACKAGE)-startup.el; do \ - $(CP) $$f $(elcdir)/$$f ;\ - done - -install_el: - $(MKDIR) $(eldir) - for f in $(ELFILES); do \ - $(CP) $$f $(eldir)/$$f ;\ - done - -install_info: $(PACKAGE).info - $(MKDIR) $(infodir) - $(CP) *.info* $(infodir)/ - -[ ! -w $(infodir)/dir ] \ - || install-info --info-dir=$(infodir)/dir $(PACKAGE).info - -install_startup: - $(MKDIR) $(lispdir) - @if grep $(PACKAGE) $(lispdir)/site-start.el >/dev/null 2>&1 || \ - grep $(PACKAGE) $(startupfile) >/dev/null 2>&1 || \ - grep $(PACKAGE) $(lispdir)/default.el >/dev/null 2>&1; \ - then \ - echo "**********************************************************" ;\ - echo "*** It seems you already have some setup code" ;\ - echo "*** for $(PACKAGE) in your startup files." ;\ - echo "*** Check that it properly loads \"$(PACKAGE)-startup\"" ;\ - echo "**********************************************************" ;\ - else \ - echo 'echo ";; load $(PACKAGE) setup code" >>$(startupfile)' ;\ - echo ";; load $(PACKAGE) setup code" >>$(startupfile) ;\ - echo 'echo "(load \"$(elcdir)/$(PACKAGE)-startup\")" >>$(startupfile)' ;\ - echo "(load \"$(elcdir)/$(PACKAGE)-startup\")" >>$(startupfile) ;\ - fi - -postscript: $(PACKAGE).ps -dvi: $(PACKAGE).dvi -install_dvi: dvi - $(MKDIR) $(docdir) - $(CP) `find . -type f -name '*.dvi' -print` $(docdir)/ - -install: install_elc install_info install_startup install_el - -clean: - $(RM) *~ core .\#* $(TEXEXTS) - -TAGS tags: - $(ETAGS) $(ELFILES) - -distclean: clean - $(RM) *.elc *.dvi *.info* *.ps - -###################################################################### -### don't look below ### -###################################################################### - -$(PACKAGE)-startup.el: $(ELFILES) - echo "\ - ;;; $@ --- automatically extracted autoloads\n\ - ;;; Code:\n\ - (add-to-list 'load-path\n\ - (or (file-name-directory load-file-name) (car load-path)))\n\ - " >$@ - $(EMACS) --batch --eval '(setq generated-autoload-file "'`pwd`'/$@")' -f batch-update-autoloads "." - -## - -#TAG = $(shell echo v$(VERSION) | tr '.' '_') -URL=$(shell sed -n -e '5p' .svn/entries) -TAG=$(shell dirname "$(URL)")/releases/$(PACKAGE)-$(VERSION) -ftpdir=/u/monnier/html/elisp/ -cvsmodule=$(shell cat CVS/Repository) -cvsroot=$(shell cat CVS/Root) - -dist: - svn cp . "$(TAG)" &&\ - svn export "$(TAG)" "$(TMP)/$(PACKAGE)-$(VERSION)" &&\ - cd "$(TMP)/$(PACKAGE)-$(VERSION)" &&\ - $(MAKE) info $(PACKAGE)-startup.el &&\ - cd .. &&\ - ztar $(PACKAGE)-$(VERSION) &&\ - rm -rf $(PACKAGE)-$(VERSION) - mv $(TMP)/$(PACKAGE)-$(VERSION).tar.gz $(ftpdir)/ - ln -sf $(PACKAGE)-$(VERSION).tar.gz $(ftpdir)/$(PACKAGE).tar.gz diff --git a/emacs/emacs.d/sml-mode-5.0/NEWS b/emacs/emacs.d/sml-mode-5.0/NEWS @@ -1,137 +0,0 @@ -Changes since 4.1: - -* New indentation code using SMIE when available. - -* `sml-back-to-outer-indent' is now on S-tab (aka `backtab') rather than M-tab. - -* Support for electric-layout-mode and electric-indent-mode. - -* `sml-mark-defun' tries to be more clever. - -* A single file (sml-mode.el) is needed unless you want to use an interactive - process like SML/NJ, or if your Emacs does not provide SMIE. - -Changes since 4.0: - -* Switch to GPLv3+. - -* When possible (i.e. running under Emacs>=23), be case-sensitive when - expanding abbreviations, and don't expand them in comments and strings. - -* When you `next-error' to a type error, highlight the actual parts of the - types that differ. - -* Flush the recorded errors not only upon sml-compile and friends, but also - when typing commands directly at the prompt. - -* New command sml-mlton-typecheck. - -* Simple support to parse errors and warnings in MLton's output. - -* Simple support for MLton's def-use files. - -Changes since 3.9.5: - -* No need to add the dir to your load-path any more. - The sml-mode-startup.el file does it for you. - -* Symbols like -> can be displayed as real arrows. See sml-font-lock-symbols. - -* Fix some incompatibilities with the upcoming Emacs-21.4. - -* Indentation rules improved. New customizable variable - `sml-rightalign-and'. Also `sml-symbol-indent' is now customizable. - -Changes since 3.9.3: - -* New add-log support (try C-x 4 a from within an SML function). - -* Imenu support - -* sml-bindings has disappeared. - -* The code skeletons are now abbrevs as well. - -* A new *sml* process is sent the content of sml-config-file (~/.sml-proc.sml) - if it exists. - -* `sml-compile' works yet a bit differently. The command can begin - with `cd "path";' and it will be replaced by OS.FileSys.chDir. - -* run-sml now pops up the new buffer. It can also run the command on another - machine. And it always prompts for the command name. Use a prefix - argument if you want to give args or to specify a host on which - to run the command. - -* mouse-2 to yank in *sml* should work again (but won't work for next-error - any more). - -* New major-modes sml-cm-mode, sml-lex-mode and sml-yacc-mode. - -* sml-load-hook has disappeared as has inferior-sml-load-hook. - -* sml-mode-startup.el is now automatically generated and you're supposed to - `load' it from .emacs or site-start.el. - -* Minor bug fixes. - -Changes since 3.3: - -* the sml-drag-* commands have disappeared. - -* added a little bit of `customize' support. Many of the customization - variables for indentation are still in flux, so they are not customize'd. - -* proformas have been replaced by skeletons. it's mostly the same as - before (the layout has slightly changed, tho). The main difference - is that the indentation relies on the major-mode indentation so it - is implicitly customized, which makes more sense to me. - Also I added an electric space M-SPC that will call the corresponding - skeleton if any matches the immediately preceding symbol. Basically - that allows you to type `l e t M-SPC' to call the `let' skeleton. - -* M-C-f and M-C-b try to be smart and jump around let..end and such blocks. - It's probably either too smart or not smart enough, tho. - -* there is no more sml-<compiler>.el since the code should work for "all" - known compilers. If your favorite compiler doesn't seem to work right - send me a sample session. - -* hilite support has disappeared and font-lock and menu support is now built-in. - -* the indentation algorithm is inherently much slower. I've tried to ensure - the slowness never manifests itself in practice, but if you find a case - where the indentation doesn't feel instantaneous, tell me. - -* function arguments get properly indented (yes, madam). - -* the indentation has been majorly reworked. The list of changes is too long. - Many customizations have disappeared, some may reappear depending on the - feedback I get. The indentation should now "always" work right, so - tell me when it doesn't. - -* nested comments are only properly handled if you have a nested-comments - aware Emacs (I don't know of any yet) or if you turn on font-lock. - -* provide `sml-compile' which does something similat to `compile' except it - passes the command to an inferior-sml process. Also it has an additional - hack to look for sml-make-file-name in parent directories and cd to it - before sending the command (handy for CM.make() when the sources.cm file - is not in the current directory). This hack is very ad-hoc and quite - misleading for people who don't use CM. I.e. the default is not safe. - -* sml-send-region and friends now always use a temp file. The temp file - management has been made a little more secure. - -* the overlay is now turned off by default. Instead the region is activated, - so that transient-mark-mode will end up highlighting the error just like - the overlay used to do. - -* sml-proc uses compile.el for error parsing. This mostly means that instead - of C-c ` you want to use the standard C-x `. It also means that error - formats for any compiler can be added more easily. - -* The special frame handling has been thrown out because it doesn't interact - well with Emacs' own similar feature. I believe XEmacs still doesn't provide - such a feature, so if you miss it, either switch to Emacs or (convince - someone else to) add it to XEmacs. diff --git a/emacs/emacs.d/sml-mode-5.0/README b/emacs/emacs.d/sml-mode-5.0/README @@ -1,19 +0,0 @@ -SML-MODE is a major Emacs mode for editing Standard ML. -It provides syntax highlighting and automatic indentation and -comes with sml-proc which allows interaction with an inferior SML -interactive loop. - -This release should work on any recent version of Emacs or XEmacs. -If it doesn't: complain. - -Some more or less out of date documentation can be found in TeXinfo format. - -Check the INSTALL file for installation instructions. -Check the NEWS file for a list of changes in this version. -Check the BUGS and TODO file before sending me bug reports and requests for -enhancements. - -Send any complaint/question/praise/ice-cream to me, - - - Stefan Monnier <monnier@iro.umontreal.ca> diff --git a/emacs/emacs.d/sml-mode-5.0/TODO b/emacs/emacs.d/sml-mode-5.0/TODO @@ -1,46 +0,0 @@ -* file-name completion in sml-cm-mode. - -* Don't always jump to the *sml* buffer when you send a snippet of code. - -* Fix inferior-sml-mode's TAB completion of filenames so it doesn't append - a space. - -* Improve support for MLton's def-use info (see http://mlton.org/Emacs) - -* Add an sml-mlb-mode for ML Basis files (see http://mlton.org/Emacs) - -* make `M-x sml-compile' more generic. - -* allow specifying indentation of dependent keywords (how to indent `in' - relative to `let', for example). - -* recognize irrefutable patterns (with "Capital"-heuristics, for example: - a regexp like "\\([(),]\\|[_a-z][_a-z0-9]*\\)+"). - This can then be used to allow indenting like - - (fn x => - some expressions) - -* take advantage of text after-the-line (when available) for indentation. - -* obey fixity directives. - -* dangling `case e' in stuff like - - fun myfunction x = case x - of bla => - | bli => - -* deal with CPS kind of code ??? - - function1 (arg1, arg2, fn v1 => - function2 (arg2, fn v2 => - function3 (arg5, arg3, arg8, fn v3 => - function4 (v1, v2, v3)))) - - or even just - - F.LET (v1, foo, - F.LET (v2, bar, - F.LET (v3, baz, - F.RET [v1, v2, v3]))) diff --git a/emacs/emacs.d/sml-mode-5.0/makefile.pkg b/emacs/emacs.d/sml-mode-5.0/makefile.pkg @@ -1,15 +0,0 @@ -PACKAGE = sml-mode -ELFILES = sml-mode.el sml-proc.el sml-oldindent.el - -default: elcfiles - -TESTCASE = testcases.sml - -test: - $(RM) $(TESTCASE).new - $(EMACS) --batch \ - --eval "(load \"$$(pwd)/sml-mode-startup\")" \ - $(TESTCASE) \ - --eval '(indent-region (point-min) (point-max) nil)' \ - --eval '(write-region (point-min) (point-max) "$(TESTCASE).new")' - diff -u -B $(TESTCASE) $(TESTCASE).new diff --git a/emacs/emacs.d/sml-mode-5.0/sml-mode-startup.el b/emacs/emacs.d/sml-mode-5.0/sml-mode-startup.el @@ -1,59 +0,0 @@ -;;; sml-mode-startup.el --- automatically extracted autoloads -;;; Code: -(add-to-list 'load-path - (or (file-name-directory load-file-name) (car load-path))) - -;;;### (autoloads (sml-yacc-mode sml-lex-mode sml-cm-mode sml-mode) -;;;;;; "sml-mode" "sml-mode.el" (20358 8148)) -;;; Generated autoloads from sml-mode.el - -(add-to-list 'auto-mode-alist '("\\.s\\(ml\\|ig\\)\\'" . sml-mode)) - -(autoload 'sml-mode "sml-mode" "\ -\\<sml-mode-map>Major mode for editing ML code. -This mode runs `sml-mode-hook' just before exiting. -\\{sml-mode-map} - -\(fn)" t nil) - -(add-to-list 'completion-ignored-extensions ".cm/") - -(add-to-list 'auto-mode-alist '("\\.cm\\'" . sml-cm-mode)) - -(autoload 'sml-cm-mode "sml-mode" "\ -Major mode for SML/NJ's Compilation Manager configuration files. - -\(fn)" t nil) - -(autoload 'sml-lex-mode "sml-mode" "\ -Major Mode for editing ML-Lex files. - -\(fn)" t nil) - -(add-to-list 'auto-mode-alist '("\\.grm\\'" . sml-yacc-mode)) - -(autoload 'sml-yacc-mode "sml-mode" "\ -Major Mode for editing ML-Yacc files. - -\(fn)" t nil) - -(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "sml-mode" '("font-lock-type-def-face" "font-lock-module-def-face" "font-lock-interface-def-face"))) - -;;;*** - -;;;### (autoloads nil "sml-oldindent" "sml-oldindent.el" (20358 8148)) -;;; Generated autoloads from sml-oldindent.el - -(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "sml-oldindent" '("sml-"))) - -;;;*** - -;;;### (autoloads nil "sml-proc" "sml-proc.el" (20358 8148)) -;;; Generated autoloads from sml-proc.el - -(autoload 'run-sml "sml-proc" nil t) - -(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "sml-proc" '("sml-" "inferior-sml-" "font-lock-" "run-sml" "switch-to-sml"))) - -;;;*** - diff --git a/emacs/emacs.d/sml-mode-5.0/sml-mode.el b/emacs/emacs.d/sml-mode-5.0/sml-mode.el @@ -1,1436 +0,0 @@ -;;; sml-mode.el --- Major mode for editing (Standard) ML - -;; Copyright (C) 1999,2000,2004,2007,2010-2012 Stefan Monnier -;; Copyright (C) 1994-1997 Matthew J. Morley -;; Copyright (C) 1989 Lars Bo Nielsen - -;; Author: Lars Bo Nielsen -;; Olin Shivers -;; Fritz Knabe (?) -;; Steven Gilmore (?) -;; Matthew Morley <mjm@scs.leeds.ac.uk> (aka <matthew@verisity.com>) -;; Matthias Blume <blume@cs.princeton.edu> (aka <blume@kurims.kyoto-u.ac.jp>) -;; (Stefan Monnier) <monnier@iro.umontreal.ca> -;; Maintainer: (Stefan Monnier) <monnier@iro.umontreal.ca> -;; Keywords: SML - -;; This file is not part of GNU Emacs, but it is distributed under the -;; same conditions. - -;; This program is free software; you can redistribute it and/or -;; modify it under the terms of the GNU General Public License as -;; published by the Free Software Foundation; either version 3, or (at -;; your option) any later version. - -;; This program is distributed in the hope that it will be useful, but -;; WITHOUT ANY WARRANTY; without even the implied warranty of -;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -;; General Public License for more details. - -;; You should have received a copy of the GNU General Public License -;; along with GNU Emacs; see the file COPYING. If not, write to the -;; Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. - -;;; Commentary: - -;;; HISTORY - -;; Still under construction: History obscure, needs a biographer as -;; well as a M-x doctor. Change Log on request. - -;; Hacked by Olin Shivers for comint from Lars Bo Nielsen's sml.el. - -;; Hacked by Matthew Morley to incorporate Fritz Knabe's hilite and -;; font-lock patterns, some of Steven Gilmore's (reduced) easy-menus, -;; and numerous bugs and bug-fixes. - -;;; DESCRIPTION - -;; See accompanying info file: sml-mode.info - -;;; FOR YOUR .EMACS FILE - -;; If sml-mode.el lives in some non-standard directory, you must tell -;; emacs where to get it. This may or may not be necessary: - -;; (add-to-list 'load-path "~jones/lib/emacs/") - -;; Then to access the commands autoload sml-mode with that command: - -;; (load "sml-mode-startup") - -;; sml-mode-hook is run whenever a new sml-mode buffer is created. - -;; Finally, there are inferior-sml-{mode,load}-hooks -- see comments -;; in sml-proc.el. For much more information consult the mode's *info* -;; tree. - -;;; Code: - -(eval-when-compile (require 'cl)) -(require 'smie nil 'noerror) - -(condition-case nil (require 'skeleton) (error nil)) - -(defgroup sml () - "Editing SML code." - :group 'languages) - -;;; VARIABLES CONTROLLING INDENTATION - -(defcustom sml-indent-level 4 - "Indentation of blocks in ML (see also `sml-indent-rule')." - :type '(integer)) - -(defcustom sml-indent-args sml-indent-level - "Indentation of args placed on a separate line." - :type '(integer)) - -;; (defvar sml-indent-align-args t -;; "*Whether the arguments should be aligned.") - -;; (defvar sml-case-indent nil -;; "*How to indent case-of expressions. -;; If t: case expr If nil: case expr of -;; of exp1 => ... exp1 => ... -;; | exp2 => ... | exp2 => ... - -;; The first seems to be the standard in SML/NJ, but the second -;; seems nicer...") - -(defcustom sml-electric-semi-mode nil - "If non-nil, `\;' will self insert, reindent the line, and do a newline. -If nil, just insert a `\;'. (To insert while t, do: \\[quoted-insert] \;)." - :type 'boolean) -(when (fboundp 'electric-layout-mode) - (make-obsolete-variable 'sml-electric-semi-mode - 'electric-layout-mode "Emacs-24")) - -(defcustom sml-rightalign-and t - "If non-nil, right-align `and' with its leader. -If nil: If t: - datatype a = A datatype a = A - and b = B and b = B" - :type 'boolean) - -;;; OTHER GENERIC MODE VARIABLES - -(defvar sml-mode-info "sml-mode" - "*Where to find Info file for `sml-mode'. -The default assumes the info file \"sml-mode.info\" is on Emacs' info -directory path. If it is not, either put the file on the standard path -or set the variable `sml-mode-info' to the exact location of this file - - (setq sml-mode-info \"/usr/me/lib/info/sml-mode\") - -in your .emacs file. You can always set it interactively with the -set-variable command.") - -(defvar sml-mode-hook nil - "*Run upon entering `sml-mode'. -This is a good place to put your preferred key bindings.") - -;;; CODE FOR SML-MODE - -(defun sml-mode-info () - "Command to access the TeXinfo documentation for `sml-mode'. -See doc for the variable `sml-mode-info'." - (interactive) - (require 'info) - (condition-case nil - (info sml-mode-info) - (error (progn - (describe-variable 'sml-mode-info) - (message "Can't find it... set this variable first!"))))) - - -;;; Autoload functions -- no-doc is another idea cribbed from AucTeX! - -(let ((sml-no-doc - "This function is part of sml-proc, and has not yet been loaded. -Full documentation will be available after autoloading the function.")) - - (autoload 'sml-compile "sml-proc" sml-no-doc t) - (autoload 'sml-load-file "sml-proc" sml-no-doc t) - (autoload 'switch-to-sml "sml-proc" sml-no-doc t) - (autoload 'sml-send-region "sml-proc" sml-no-doc t) - (autoload 'sml-send-buffer "sml-proc" sml-no-doc t)) - -;; font-lock setup - -(defvar sml-outline-regexp - ;; `st' and `si' are to match structure and signature. - " \\|s[ti]\\|[ \t]*\\(let[ \t]+\\)?\\(fun\\|and\\)\\>" - "Regexp matching a major heading. -This actually can't work without extending `outline-minor-mode' with the -notion of \"the end of an outline\".") - -;; -;; Internal defines -;; - -(defvar sml-mode-map - (let ((map (make-sparse-keymap))) - ;; Smarter cursor movement. - ;; (define-key map [remap forward-sexp] 'sml-user-forward-sexp) - ;; (define-key map [remap backward-sexp] 'sml-user-backward-sexp) - ;; Text-formatting commands: - (define-key map "\C-c\C-m" 'sml-insert-form) - (define-key map "\C-c\C-i" 'sml-mode-info) - (define-key map "\M-|" 'sml-electric-pipe) - (define-key map "\M-\ " 'sml-electric-space) - (define-key map "\;" 'sml-electric-semi) - (define-key map [backtab] 'sml-back-to-outer-indent) - ;; Process commands added to sml-mode-map -- these should autoload. - (define-key map "\C-c\C-l" 'sml-load-file) - (define-key map "\C-c\C-c" 'sml-compile) - (define-key map "\C-c\C-s" 'switch-to-sml) - (define-key map "\C-c\C-r" 'sml-send-region) - (define-key map "\C-c\C-b" 'sml-send-buffer) - map) - "The keymap used in `sml-mode'.") - -(defconst sml-builtin-nested-comments-flag - (ignore-errors - (not (equal (let ((st (make-syntax-table))) - (modify-syntax-entry ?\* ". 23n" st) st) - (let ((st (make-syntax-table))) - (modify-syntax-entry ?\* ". 23" st) st)))) - "Non-nil means this Emacs understands the `n' in syntax entries.") - -(defvar sml-mode-syntax-table - (let ((st (make-syntax-table))) - (modify-syntax-entry ?\* (if sml-builtin-nested-comments-flag - ". 23n" ". 23") st) - (modify-syntax-entry ?\( "()1" st) - (modify-syntax-entry ?\) ")(4" st) - (mapc (lambda (c) (modify-syntax-entry c "_" st)) "._'") - (mapc (lambda (c) (modify-syntax-entry c "." st)) ",;") - ;; `!' is not really a prefix-char, oh well! - (mapc (lambda (c) (modify-syntax-entry c "'" st)) "~#!") - (mapc (lambda (c) (modify-syntax-entry c "." st)) "%&$+-/:<=>?@`^|") - st) - "The syntax table used in `sml-mode'.") - - -(easy-menu-define sml-mode-menu sml-mode-map "Menu used in `sml-mode'." - '("SML" - ("Process" - ["Start default ML compiler" run-sml t] - ["-" nil nil] - ["run CM.make" sml-compile t] - ["load ML source file" sml-load-file t] - ["switch to ML buffer" switch-to-sml t] - ["--" nil nil] - ["send buffer contents" sml-send-buffer t] - ["send region" sml-send-region t] - ["send paragraph" sml-send-function t] - ["goto next error" next-error (featurep 'sml-proc)] - ["---" nil nil] - ;; ["Standard ML of New Jersey" sml-smlnj (fboundp 'sml-smlnj)] - ;; ["Poly/ML" sml-poly-ml (fboundp 'sml-poly-ml)] - ;; ["Moscow ML" sml-mosml (fboundp 'sml-mosml)] - ["Help for Inferior ML" (describe-function 'inferior-sml-mode) - :active (featurep 'sml-proc)]) - ["electric pipe" sml-electric-pipe t] - ["insert SML form" sml-insert-form t] - ("Forms" :filter sml-forms-menu) - ("Format/Mode Variables" - ["indent region" indent-region t] - ["outdent" sml-back-to-outer-indent t] - ;; ["-" nil nil] - ;; ["set indent-level" sml-indent-level t] - ;; ["set pipe-indent" sml-pipe-indent t] - ;; ["--" nil nil] - ;; ["toggle type-of-indent" sml-type-of-indent t] - ;; ["toggle nested-if-indent" sml-nested-if-indent t] - ;; ["toggle electric-semi-mode" sml-electric-semi-mode t] - ) - ["-----" nil nil] - ["SML mode help (brief)" describe-mode t] - ["SML mode *info*" sml-mode-info t] - ["Remove overlay" (sml-error-overlay 'undo) - :visible (or (and (boundp 'sml-error-overlay) - sml-error-overlay) - (not (fboundp 'compilation-fake-loc))) - :active (and (boundp 'sml-error-overlay) - (overlayp sml-error-overlay) - (overlay-start sml-error-overlay)) - ])) - -;; Make's sure they appear in the menu bar when sml-mode-map is active. -;; On the hook for XEmacs only -- see easy-menu-add in auc-menu.el. -;; (defun sml-mode-menu-bar () -;; "Make sure menus appear in the menu bar as well as under mouse 3." -;; (and (eq major-mode 'sml-mode) -;; (easy-menu-add sml-mode-menu sml-mode-map))) -;; (add-hook 'sml-mode-hook 'sml-mode-menu-bar) - -;; -;; regexps -;; - -(defun sml-syms-re (syms) - (concat "\\<" (regexp-opt syms t) "\\>")) - -;; - -(defconst sml-module-head-syms - '("signature" "structure" "functor" "abstraction")) - - -(defconst sml-=-starter-syms - (list* "|" "val" "fun" "and" "datatype" "type" "abstype" "eqtype" - sml-module-head-syms) - "Symbols that can be followed by a `='.") -(defconst sml-=-starter-re - (concat "\\S.|\\S.\\|" (sml-syms-re (cdr sml-=-starter-syms))) - "Symbols that can be followed by a `='.") - -(defconst sml-non-nested-of-starter-re - (sml-syms-re '("datatype" "abstype" "exception")) - "Symbols that can introduce an `of' that shouldn't behave like a paren.") - -(defconst sml-starters-syms - (append sml-module-head-syms - '("abstype" "datatype" "exception" "fun" - "local" "infix" "infixr" "sharing" "nonfix" - "open" "type" "val" "and" - "withtype" "with")) - "The starters of new expressions.") - -(defconst sml-pipeheads - '("|" "of" "fun" "fn" "and" "handle" "datatype" "abstype") - "A `|' corresponds to one of these.") - -(defconst sml-keywords-regexp - (sml-syms-re '("abstraction" "abstype" "and" "andalso" "as" "before" "case" - "datatype" "else" "end" "eqtype" "exception" "do" "fn" - "fun" "functor" "handle" "if" "in" "include" "infix" - "infixr" "let" "local" "nonfix" "of" "op" "open" "orelse" - "overload" "raise" "rec" "sharing" "sig" "signature" - "struct" "structure" "then" "type" "val" "where" "while" - "with" "withtype" "o")) - "A regexp that matches any and all keywords of SML.") - -(defconst sml-tyvarseq-re - "\\(\\('+\\(\\sw\\|\\s_\\)+\\|(\\([,']\\|\\sw\\|\\s_\\|\\s-\\)+)\\)\\s-+\\)?") - -;;; Font-lock settings ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - -(defcustom sml-font-lock-symbols nil - "Display \\ and -> and such using symbols in fonts. -This may sound like a neat trick, but be extra careful: it changes the -alignment and can thus lead to nasty surprises w.r.t layout. -If t, try to use whichever font is available. Otherwise you can -set it to a particular font of your preference among `japanese-jisx0208' -and `unicode'." - :type '(choice (const nil) - (const t) - (const unicode) - (const japanese-jisx0208))) - -(defconst sml-font-lock-symbols-alist - (append - ;; The symbols can come from a JIS0208 font. - (and (fboundp 'make-char) (charsetp 'japanese-jisx0208) - (memq sml-font-lock-symbols '(t japanese-jisx0208)) - (list (cons "fn" (make-char 'japanese-jisx0208 38 75)) - (cons "andalso" (make-char 'japanese-jisx0208 34 74)) - (cons "orelse" (make-char 'japanese-jisx0208 34 75)) - ;; (cons "as" (make-char 'japanese-jisx0208 34 97)) - (cons "not" (make-char 'japanese-jisx0208 34 76)) - (cons "div" (make-char 'japanese-jisx0208 33 96)) - ;; (cons "*" (make-char 'japanese-jisx0208 33 95)) - (cons "->" (make-char 'japanese-jisx0208 34 42)) - (cons "=>" (make-char 'japanese-jisx0208 34 77)) - (cons "<-" (make-char 'japanese-jisx0208 34 43)) - (cons "<>" (make-char 'japanese-jisx0208 33 98)) - (cons ">=" (make-char 'japanese-jisx0208 33 102)) - (cons "<=" (make-char 'japanese-jisx0208 33 101)) - (cons "..." (make-char 'japanese-jisx0208 33 68)) - ;; Some greek letters for type parameters. - (cons "'a" (make-char 'japanese-jisx0208 38 65)) - (cons "'b" (make-char 'japanese-jisx0208 38 66)) - (cons "'c" (make-char 'japanese-jisx0208 38 67)) - (cons "'d" (make-char 'japanese-jisx0208 38 68)) - )) - ;; Or a unicode font. - (and (fboundp 'decode-char) - (memq sml-font-lock-symbols '(t unicode)) - (list (cons "fn" (decode-char 'ucs 955)) - (cons "andalso" (decode-char 'ucs 8896)) - (cons "orelse" (decode-char 'ucs 8897)) - ;; (cons "as" (decode-char 'ucs 8801)) - (cons "not" (decode-char 'ucs 172)) - (cons "div" (decode-char 'ucs 247)) - (cons "*" (decode-char 'ucs 215)) - (cons "o" (decode-char 'ucs 9675)) - (cons "->" (decode-char 'ucs 8594)) - (cons "=>" (decode-char 'ucs 8658)) - (cons "<-" (decode-char 'ucs 8592)) - (cons "<>" (decode-char 'ucs 8800)) - (cons ">=" (decode-char 'ucs 8805)) - (cons "<=" (decode-char 'ucs 8804)) - (cons "..." (decode-char 'ucs 8943)) - ;; (cons "::" (decode-char 'ucs 8759)) - ;; Some greek letters for type parameters. - (cons "'a" (decode-char 'ucs 945)) - (cons "'b" (decode-char 'ucs 946)) - (cons "'c" (decode-char 'ucs 947)) - (cons "'d" (decode-char 'ucs 948)) - )))) - -(defun sml-font-lock-compose-symbol (alist) - "Compose a sequence of ascii chars into a symbol. -Regexp match data 0 points to the chars." - ;; Check that the chars should really be composed into a symbol. - (let* ((start (match-beginning 0)) - (end (match-end 0)) - (syntaxes (if (eq (char-syntax (char-after start)) ?w) - '(?w) '(?. ?\\)))) - (if (or (memq (char-syntax (or (char-before start) ?\ )) syntaxes) - (memq (char-syntax (or (char-after end) ?\ )) syntaxes) - (memq (get-text-property start 'face) - '(font-lock-doc-face font-lock-string-face - font-lock-comment-face))) - ;; No composition for you. Let's actually remove any composition - ;; we may have added earlier and which is now incorrect. - (remove-text-properties start end '(composition)) - ;; That's a symbol alright, so add the composition. - (compose-region start end (cdr (assoc (match-string 0) alist))))) - ;; Return nil because we're not adding any face property. - nil) - -(defun sml-font-lock-symbols-keywords () - (when (fboundp 'compose-region) - (let ((alist nil)) - (dolist (x sml-font-lock-symbols-alist) - (when (and (if (fboundp 'char-displayable-p) - (char-displayable-p (cdr x)) - t) - (not (assoc (car x) alist))) ;Not yet in alist. - (push x alist))) - (when alist - `((,(regexp-opt (mapcar 'car alist) t) - (0 (sml-font-lock-compose-symbol ',alist)))))))) - -;; The font lock regular expressions. - -(defconst sml-font-lock-keywords - `(;;(sml-font-comments-and-strings) - (,(concat "\\<\\(fun\\|and\\)\\s-+" sml-tyvarseq-re "\\(\\sw+\\)\\s-+[^ \t\n=]") - (1 font-lock-keyword-face) - (6 font-lock-function-name-face)) - (,(concat "\\<\\(\\(data\\|abs\\|with\\|eq\\)?type\\)\\s-+" sml-tyvarseq-re "\\(\\sw+\\)") - (1 font-lock-keyword-face) - (7 font-lock-type-def-face)) - ("\\<\\(val\\)\\s-+\\(\\sw+\\>\\s-*\\)?\\(\\sw+\\)\\s-*[=:]" - (1 font-lock-keyword-face) - ;;(6 font-lock-variable-def-face nil t) - (3 font-lock-variable-name-face)) - ("\\<\\(structure\\|functor\\|abstraction\\)\\s-+\\(\\sw+\\)" - (1 font-lock-keyword-face) - (2 font-lock-module-def-face)) - ("\\<\\(signature\\)\\s-+\\(\\sw+\\)" - (1 font-lock-keyword-face) - (2 font-lock-interface-def-face)) - - (,sml-keywords-regexp . font-lock-keyword-face) - ,@(sml-font-lock-symbols-keywords)) - "Regexps matching standard SML keywords.") - -(defface font-lock-type-def-face - '((t (:bold t))) - "Font Lock mode face used to highlight type definitions." - :group 'font-lock-highlighting-faces) -(defvar font-lock-type-def-face 'font-lock-type-def-face - "Face name to use for type definitions.") - -(defface font-lock-module-def-face - '((t (:bold t))) - "Font Lock mode face used to highlight module definitions." - :group 'font-lock-highlighting-faces) -(defvar font-lock-module-def-face 'font-lock-module-def-face - "Face name to use for module definitions.") - -(defface font-lock-interface-def-face - '((t (:bold t))) - "Font Lock mode face used to highlight interface definitions." - :group 'font-lock-highlighting-faces) -(defvar font-lock-interface-def-face 'font-lock-interface-def-face - "Face name to use for interface definitions.") - -;; -;; Code to handle nested comments and unusual string escape sequences -;; - -(defvar sml-syntax-prop-table - (let ((st (make-syntax-table))) - (modify-syntax-entry ?\\ "." st) - (modify-syntax-entry ?* "." st) - st) - "Syntax table for text-properties") - -;; For Emacsen that have no built-in support for nested comments -(defun sml-get-depth-st () - (save-excursion - (let* ((disp (if (eq (char-before) ?\)) (progn (backward-char) -1) nil)) - (_ (backward-char)) - (disp (if (eq (char-before) ?\() (progn (backward-char) 0) disp)) - (pt (point))) - (when disp - (let* ((depth - (save-match-data - (if (re-search-backward "\\*)\\|(\\*" nil t) - (+ (or (get-char-property (point) 'comment-depth) 0) - (case (char-after) (?\( 1) (?* 0)) - disp) - 0))) - (depth (if (> depth 0) depth))) - (put-text-property pt (1+ pt) 'comment-depth depth) - (when depth sml-syntax-prop-table)))))) - -(defconst sml-font-lock-syntactic-keywords - `(("^\\s-*\\(\\\\\\)" (1 ',sml-syntax-prop-table)) - ,@(unless sml-builtin-nested-comments-flag - '(("(?\\(\\*\\))?" (1 (sml-get-depth-st))))))) - -(defconst sml-font-lock-defaults - '(sml-font-lock-keywords nil nil ((?_ . "w") (?' . "w")) nil - (font-lock-syntactic-keywords . sml-font-lock-syntactic-keywords))) - - -;;; Indentation with SMIE - -(defvar sml-use-smie t) - -(defconst sml-smie-grammar - (when (fboundp 'smie-prec2->grammar) - ;; We have several problem areas where SML's syntax can't be handled by an - ;; operator precedence grammar: - ;; - ;; "= A before B" is "= A) before B" if this is the - ;; `boolean-=' but it is "= (A before B)" if it's the `definitional-='. - ;; We can work around the problem by tweaking the lexer to return two - ;; different tokens for the two different kinds of `='. - ;; "of A | B" in a "case" we want "of (A | B, but in a `datatype' - ;; we want "of A) | B". - ;; "= A | B" can be "= A ) | B" if the = is from a "fun" definition, - ;; but it is "= (A | B" if it is a `datatype' definition (of course, if - ;; the previous token introducing the = is `and', deciding whether - ;; it's a datatype or a function requires looking even further back). - ;; "functor foo (...) where type a = b = ..." the first `=' looks very much - ;; like a `definitional-=' even tho it's just an equality constraint. - ;; Currently I don't even try to handle `where' at all. - (smie-prec2->grammar - (smie-merge-prec2s - (smie-bnf->prec2 - '((exp ("if" exp "then" exp "else" exp) - ("case" exp "of" branches) - ("let" decls "in" cmds "end") - ("struct" decls "end") - ("sig" decls "end") - (sexp) - (sexp "handle" branches) - ("fn" sexp "=>" exp)) - ;; "simple exp"s are the ones that can appear to the left of `handle'. - (sexp (sexp ":" type) ("(" exps ")") - (sexp "orelse" sexp) - (marg ":>" type) - (sexp "andalso" sexp)) - (cmds (cmds ";" cmds) (exp)) - (exps (exps "," exps) (exp)) ; (exps ";" exps) - (branches (sexp "=>" exp) (branches "|" branches)) - ;; Operator precedence grammars handle separators much better then - ;; starters/terminators, so let's pretend that let/fun are separators. - (decls (sexp "d=" exp) - (sexp "d=" databranches) - (funbranches "|" funbranches) - (sexp "=of" type) ;After "exception". - ;; FIXME: Just like PROCEDURE in Pascal and Modula-2, this - ;; interacts poorly with the other constructs since I - ;; can't make "local" a separator like fun/val/type/... - ("local" decls "in" decls "end") - ;; (decls "local" decls "in" decls "end") - (decls "functor" decls) - (decls "signature" decls) - (decls "structure" decls) - (decls "type" decls) - (decls "open" decls) - (decls "and" decls) - (decls "infix" decls) - (decls "infixr" decls) - (decls "nonfix" decls) - (decls "abstype" decls) - (decls "datatype" decls) - (decls "exception" decls) - (decls "fun" decls) - (decls "val" decls)) - (type (type "->" type) - (type "*" type)) - (funbranches (sexp "d=" exp)) - (databranches (sexp "=of" type) (databranches "d|" databranches)) - ;; Module language. - ;; (mexp ("functor" marg "d=" mexp) - ;; ("structure" marg "d=" mexp) - ;; ("signature" marg "d=" mexp)) - (marg (marg ":" type) (marg ":>" type)) - (toplevel (decls) (exp) (toplevel ";" toplevel))) - ;; '(("local" . opener)) - ;; '((nonassoc "else") (right "handle")) - '((nonassoc "of") (assoc "|")) ; "case a of b => case c of d => e | f" - '((nonassoc "handle") (assoc "|")) ; Idem for "handle". - '((assoc "->") (assoc "*")) - '((assoc "val" "fun" "type" "datatype" "abstype" "open" "infix" "infixr" - "nonfix" "functor" "signature" "structure" "exception" - ;; "local" - ) - (assoc "and")) - '((assoc "orelse") (assoc "andalso") (nonassoc ":")) - '((assoc ";")) '((assoc ",")) '((assoc "d|"))) - - (smie-precs->prec2 - '((nonassoc "andalso") ;To anchor the prec-table. - (assoc "before") ;0 - (assoc ":=" "o") ;3 - (nonassoc ">" ">=" "<>" "<" "<=" "=") ;4 - (assoc "::" "@") ;5 - (assoc "+" "-" "^") ;6 - (assoc "/" "*" "quot" "rem" "div" "mod") ;7 - (nonassoc " -dummy- "))) ;Bogus anchor at the end. - )))) - -(defvar sml-indent-separator-outdent 2) - -(defun sml-smie-rules (kind token) - ;; I much preferred the pcase version of the code, especially while - ;; edebugging the code. But that will have to wait until we get rid of - ;; support for Emacs-23. - (case kind - (:elem (case token - (basic sml-indent-level) - (args sml-indent-args))) - (:list-intro (member token '("fn"))) - (:after - (cond - ((equal token "struct") 0) - ((equal token "=>") (if (smie-rule-hanging-p) 0 2)) - ((equal token "in") (if (smie-rule-parent-p "local") 0)) - ((equal token "of") 3) - ((member token '("(" "{" "[")) (if (not (smie-rule-hanging-p)) 2)) - ((equal token "else") (if (smie-rule-hanging-p) 0)) ;; (:next "if" 0) - ((member token '("|" "d|" ";" ",")) (smie-rule-separator kind)) - ((equal token "d=") - (if (and (smie-rule-parent-p "val") (smie-rule-next-p "fn")) -3)))) - (:before - (cond - ((equal token "=>") (if (smie-rule-parent-p "fn") 3)) - ((equal token "of") 1) - ;; In case the language is extended to allow a | directly after of. - ((and (equal token "|") (smie-rule-prev-p "of")) 1) - ((member token '("|" "d|" ";" ",")) (smie-rule-separator kind)) - ;; Treat purely syntactic block-constructs as being part of their parent, - ;; when the opening statement is hanging. - ((member token '("let" "(" "[" "{")) - (if (smie-rule-hanging-p) (smie-rule-parent))) - ;; Treat if ... else if ... as a single long syntactic construct. - ;; Similarly, treat fn a => fn b => ... as a single construct. - ((member token '("if" "fn")) - (and (not (smie-rule-bolp)) - (smie-rule-prev-p (if (equal token "if") "else" "=>")) - (smie-rule-parent))) - ((equal token "and") - ;; FIXME: maybe "and" (c|sh)ould be handled as an smie-separator. - (cond - ((smie-rule-parent-p "datatype") (if sml-rightalign-and 5 0)) - ((smie-rule-parent-p "fun" "val") 0))) - ((equal token "d=") - (cond - ((smie-rule-parent-p "datatype") (if (smie-rule-bolp) 2)) - ((smie-rule-parent-p "structure" "signature") 0))) - ;; Indent an expression starting with "local" as if it were starting - ;; with "fun". - ((equal token "local") (smie-indent-keyword "fun")) - ;; FIXME: type/val/fun/... are separators but "local" is not, even though - ;; it appears in the same list. Try to fix up the problem by hand. - ;; ((or (equal token "local") - ;; (equal (cdr (assoc token smie-grammar)) - ;; (cdr (assoc "fun" smie-grammar)))) - ;; (let ((parent (save-excursion (smie-backward-sexp)))) - ;; (when (or (and (equal (nth 2 parent) "local") - ;; (null (car parent))) - ;; (progn - ;; (setq parent (save-excursion (smie-backward-sexp "fun"))) - ;; (eq (car parent) (nth 1 (assoc "fun" smie-grammar))))) - ;; (goto-char (nth 1 parent)) - ;; (cons 'column (smie-indent-virtual))))) - )))) - -(defun sml-smie-definitional-equal-p () - "Figure out which kind of \"=\" this is. -Assumes point is right before the = sign." - ;; The idea is to look backward for the first occurrence of a token that - ;; requires a definitional "=" and then see if there's such a definitional - ;; equal between that token and ourselves (in which case we're not - ;; a definitional = ourselves). - ;; The "search for =" is naive and will match "=>" and "<=", but it turns - ;; out to be OK in practice because such tokens very rarely (if ever) appear - ;; between the =-starter and the corresponding definitional equal. - ;; One known problem case is code like: - ;; "functor foo (structure s : S) where type t = s.t =" - ;; where the "type t = s.t" is mistaken for a type definition. - (let ((re (concat "\\(" sml-=-starter-re "\\)\\|="))) - (save-excursion - (and (re-search-backward re nil t) - (or (match-beginning 1) - ;; If we first hit a "=", then that = is probably definitional - ;; and we're an equality, but not necessarily. One known - ;; problem case is code like: - ;; "functor foo (structure s : S) where type t = s.t =" - ;; where the first = is more like an equality (tho it doesn't - ;; matter much) and the second is definitional. - ;; - ;; FIXME: The test below could be used to recognize that the - ;; second = is not a mere equality, but that's not enough to - ;; parse the construct properly: we'd need something - ;; like a third kind of = token for structure definitions, in - ;; order for the parser to be able to skip the "type t = s.t" - ;; as a sub-expression. - ;; - ;; (and (not (looking-at "=>")) - ;; (not (eq ?< (char-before))) ;Not a <= - ;; (re-search-backward re nil t) - ;; (match-beginning 1) - ;; (equal "type" (buffer-substring (- (match-end 1) 4) - ;; (match-end 1)))) - ))))) - -(defun sml-smie-non-nested-of-p () - ;; FIXME: Maybe datatype-|-p makes this nested-of business unnecessary. - "Figure out which kind of \"of\" this is. -Assumes point is right before the \"of\" symbol." - (save-excursion - (and (re-search-backward (concat "\\(" sml-non-nested-of-starter-re - "\\)\\|\\<case\\>") nil t) - (match-beginning 1)))) - -(defun sml-smie-datatype-|-p () - "Figure out which kind of \"|\" this is. -Assumes point is right before the | symbol." - (save-excursion - (forward-char 1) ;Skip the |. - (let ((after-type-def - '("|" "of" "in" "datatype" "and" "exception" "abstype" "infix" - "infixr" "nonfix" "local" "val" "fun" "structure" "functor" - "signature"))) - (or (member (sml-smie-forward-token-1) after-type-def) ;Skip the tag. - (member (sml-smie-forward-token-1) after-type-def))))) - -(defun sml-smie-forward-token-1 () - (forward-comment (point-max)) - (buffer-substring-no-properties - (point) - (progn - (or (/= 0 (skip-syntax-forward "'w_")) - (skip-syntax-forward ".'")) - (point)))) - -(defun sml-smie-forward-token () - (let ((sym (sml-smie-forward-token-1))) - (cond - ((equal "op" sym) - (concat "op " (sml-smie-forward-token-1))) - ((member sym '("|" "of" "=")) - ;; The important lexer for indentation's performance is the backward - ;; lexer, so for the forward lexer we delegate to the backward one. - (save-excursion (sml-smie-backward-token))) - (t sym)))) - -(defun sml-smie-backward-token-1 () - (forward-comment (- (point))) - (buffer-substring-no-properties - (point) - (progn - (or (/= 0 (skip-syntax-backward ".'")) - (skip-syntax-backward "'w_")) - (point)))) - -(defun sml-smie-backward-token () - (let ((sym (sml-smie-backward-token-1))) - (unless (zerop (length sym)) - ;; FIXME: what should we do if `sym' = "op" ? - (let ((point (point))) - (if (equal "op" (sml-smie-backward-token-1)) - (concat "op " sym) - (goto-char point) - (cond - ((string= sym "=") (if (sml-smie-definitional-equal-p) "d=" "=")) - ((string= sym "of") (if (sml-smie-non-nested-of-p) "=of" "of")) - ((string= sym "|") (if (sml-smie-datatype-|-p) "d|" "|")) - (t sym))))))) - -;;;; -;;;; Imenu support -;;;; - -(defvar sml-imenu-regexp - (concat "^[ \t]*\\(let[ \t]+\\)?" - (regexp-opt (append sml-module-head-syms - '("and" "fun" "datatype" "abstype" "type")) t) - "\\>")) - -(defun sml-imenu-create-index () - (let (alist) - (goto-char (point-max)) - (while (re-search-backward sml-imenu-regexp nil t) - (save-excursion - (let ((kind (match-string 2)) - (column (progn (goto-char (match-beginning 2)) (current-column))) - (location - (progn (goto-char (match-end 0)) - (forward-comment (point-max)) - (when (looking-at sml-tyvarseq-re) - (goto-char (match-end 0))) - (point))) - (name (sml-smie-forward-token))) - ;; Eliminate trivial renamings. - (when (or (not (member kind '("structure" "signature"))) - (progn (search-forward "=") - (forward-comment (point-max)) - (looking-at "sig\\|struct"))) - (push (cons (concat (make-string (/ column 2) ?\ ) name) location) - alist))))) - alist)) - -;;; MORE CODE FOR SML-MODE - -;;;###autoload -(add-to-list 'auto-mode-alist '("\\.s\\(ml\\|ig\\)\\'" . sml-mode)) - -(unless (fboundp 'prog-mode) (defalias 'prog-mode 'fundamental-mode)) -(defvar comment-quote-nested) -(defvar electric-indent-chars) -(defvar electric-layout-rules) - -;;;###autoload -(define-derived-mode sml-mode prog-mode "SML" - "\\<sml-mode-map>Major mode for editing ML code. -This mode runs `sml-mode-hook' just before exiting. -\\{sml-mode-map}" - (set (make-local-variable 'font-lock-defaults) sml-font-lock-defaults) - (set (make-local-variable 'outline-regexp) sml-outline-regexp) - (set (make-local-variable 'imenu-create-index-function) - 'sml-imenu-create-index) - (set (make-local-variable 'add-log-current-defun-function) - 'sml-current-fun-name) - ;; Treat paragraph-separators in comments as paragraph-separators. - (set (make-local-variable 'paragraph-separate) - (concat "\\([ \t]*\\*)?\\)?\\(" paragraph-separate "\\)")) - (set (make-local-variable 'require-final-newline) t) - (set (make-local-variable 'electric-indent-chars) - (cons ?\; (if (boundp 'electric-indent-chars) - electric-indent-chars '(?\n)))) - (set (make-local-variable 'electric-layout-rules) - `((?\; . ,(lambda () - (save-excursion - (skip-chars-backward " \t;") - (unless (or (bolp) - (progn (skip-chars-forward " \t;") - (eolp))) - 'after)))))) - ;; For XEmacs - (easy-menu-add sml-mode-menu) - ;; Compatibility. FIXME: we should use `-' in Emacs-CVS. - (unless (boundp 'skeleton-positions) (set (make-local-variable '@) nil)) - (sml-mode-variables)) - -(defun sml-mode-variables () - (set-syntax-table sml-mode-syntax-table) - (setq local-abbrev-table sml-mode-abbrev-table) - ;; Setup indentation and sexp-navigation. - (when (fboundp 'smie-setup) - (smie-setup sml-smie-grammar #'sml-smie-rules - :backward-token #'sml-smie-backward-token - :forward-token #'sml-smie-forward-token)) - (unless (and sml-use-smie (fboundp 'smie-setup)) - (set (make-local-variable 'forward-sexp-function) 'sml-user-forward-sexp) - (set (make-local-variable 'indent-line-function) 'sml-indent-line)) - (set (make-local-variable 'parse-sexp-ignore-comments) t) - (set (make-local-variable 'comment-start) "(* ") - (set (make-local-variable 'comment-end) " *)") - (set (make-local-variable 'comment-start-skip) "(\\*+\\s-*") - (set (make-local-variable 'comment-end-skip) "\\s-*\\*+)") - ;; No need to quote nested comments markers. - (set (make-local-variable 'comment-quote-nested) nil)) - -(defun sml-funname-of-and () - "Name of the function this `and' defines, or nil if not a function. -Point has to be right after the `and' symbol and is not preserved." - (forward-comment (point-max)) - (if (looking-at sml-tyvarseq-re) (goto-char (match-end 0))) - (let ((sym (sml-smie-forward-token))) - (forward-comment (point-max)) - (unless (or (member sym '(nil "d=")) - (member (sml-smie-forward-token) '("d="))) - sym))) - -(defun sml-find-forward (re) - (while (progn (forward-comment (point-max)) - (not (looking-at re))) - (or (ignore-errors (forward-sexp 1) t) (forward-char 1)))) - -(defun sml-electric-pipe () - "Insert a \"|\". -Depending on the context insert the name of function, a \"=>\" etc." - ;; FIXME: Make it a skeleton. - (interactive) - (unless (save-excursion (skip-chars-backward "\t ") (bolp)) (insert "\n")) - (insert "| ") - (let ((text - (save-excursion - (backward-char 2) ;back over the just inserted "| " - (let ((sym (sml-find-matching-starter sml-pipeheads - ;; (sml-op-prec "|" 'back) - ))) - (sml-smie-forward-token) - (forward-comment (point-max)) - (cond - ((string= sym "|") - (let ((f (sml-smie-forward-token))) - (sml-find-forward "\\(=>\\|=\\||\\)\\S.") - (cond - ((looking-at "|") "") ;probably a datatype - ((looking-at "=>") " => ") ;`case', or `fn' or `handle' - ((looking-at "=") (concat f " = "))))) ;a function - ((string= sym "and") - ;; could be a datatype or a function - (setq sym (sml-funname-of-and)) - (if sym (concat sym " = ") "")) - ;; trivial cases - ((string= sym "fun") - (while (and (setq sym (sml-smie-forward-token)) - (string-match "^'" sym)) - (forward-comment (point-max))) - (concat sym " = ")) - ((member sym '("case" "handle" "fn" "of")) " => ") - ;;((member sym '("abstype" "datatype")) "") - (t "")))))) - - (insert text) - (indent-according-to-mode) - (beginning-of-line) - (skip-chars-forward "\t |") - (skip-syntax-forward "w") - (skip-chars-forward "\t ") - (when (eq ?= (char-after)) (backward-char)))) - -(defun sml-electric-semi () - "Insert a \;. -If variable `sml-electric-semi-mode' is t, indent the current line, insert -a newline, and indent." - (interactive) - (self-insert-command 1) - (if sml-electric-semi-mode - (reindent-then-newline-and-indent))) - -;;; Misc - -(defun sml-mark-function () - "Mark the surrounding function. Or try to at least." - (interactive) - (if (not (fboundp 'smie-setup)) - (mark-paragraph) - ;; FIXME: Provide beginning-of-defun-function so mark-defun "just works". - (let ((start (point))) - (sml-beginning-of-defun) - (let ((beg (point))) - (smie-forward-sexp 'halfsexp) - (if (or (< start beg) (> start (point))) - (progn - (goto-char start) - (mark-paragraph)) - (push-mark nil t t) - (goto-char beg)))))) - -(defun sml-back-to-outer-indent () - "Unindents to the next outer level of indentation." - (interactive) - (save-excursion - (beginning-of-line) - (skip-chars-forward "\t ") - (let ((start-column (current-column)) - (indent (current-column))) - (if (> start-column 0) - (progn - (save-excursion - (while (>= indent start-column) - (if (re-search-backward "^[^\n]" nil t) - (setq indent (current-indentation)) - (setq indent 0)))) - (backward-delete-char-untabify (- start-column indent))))))) - -(defun sml-smie-find-matching-starter (syms) - (let ((halfsexp nil) - tok) - ;;(sml-smie-forward-token) - (while (not (or (bobp) - (member (nth 2 (setq tok (smie-backward-sexp halfsexp))) - syms))) - (cond - ((null (car tok)) nil) - ((numberp (car tok)) (setq halfsexp 'half)) - (t (goto-char (cadr tok))))) - (if (nth 2 tok) (goto-char (cadr tok))) - (nth 2 tok))) - -(defun sml-find-matching-starter (syms) - (cond - ((and sml-use-smie (fboundp 'smie-backward-sexp)) - (sml-smie-find-matching-starter syms)) - ((fboundp 'sml-old-find-matching-starter) - (sml-old-find-matching-starter syms)))) - -(defun sml-smie-skip-siblings () - (let (tok) - (while (and (not (bobp)) - (progn (setq tok (smie-backward-sexp 'half)) - (cond - ((null (car tok)) t) - ((numberp (car tok)) t) - (t nil))))) - (if (nth 2 tok) (goto-char (cadr tok))) - (nth 2 tok))) - -(defun sml-skip-siblings () - (cond - ((and sml-use-smie (fboundp 'smie-backward-sexp)) - (sml-smie-skip-siblings)) - ((fboundp 'sml-old-skip-siblings) - (sml-old-skip-siblings)) - (t (up-list -1)))) - -(defun sml-beginning-of-defun () - (let ((sym (sml-find-matching-starter sml-starters-syms))) - (if (member sym '("fun" "and" "functor" "signature" "structure" - "abstraction" "datatype" "abstype")) - (save-excursion (sml-smie-forward-token) (forward-comment (point-max)) - (sml-smie-forward-token)) - ;; We're inside a "non function declaration": let's skip all other - ;; declarations that we find at the same level and try again. - (sml-skip-siblings) - ;; Obviously, let's not try again if we're at bobp. - (unless (bobp) (sml-beginning-of-defun))))) - -(defcustom sml-max-name-components 3 - "Maximum number of components to use for the current function name." - :type 'integer) - -(defun sml-current-fun-name () - (save-excursion - (let ((count sml-max-name-components) - fullname name) - (end-of-line) - (while (and (> count 0) - (setq name (sml-beginning-of-defun))) - (decf count) - (setq fullname (if fullname (concat name "." fullname) name)) - ;; Skip all other declarations that we find at the same level. - (sml-skip-siblings)) - fullname))) - - -;;; INSERTING PROFORMAS (COMMON SML-FORMS) - -(defvar sml-forms-alist nil - "*Alist of code templates. -You can extend this alist to your heart's content. For each additional -template NAME in the list, declare a keyboard macro or function (or -interactive command) called 'sml-form-NAME'. -If 'sml-form-NAME' is a function it takes no arguments and should -insert the template at point\; if this is a command it may accept any -sensible interactive call arguments\; keyboard macros can't take -arguments at all. Apropos keyboard macros, see `name-last-kbd-macro' -and `sml-addto-forms-alist'. -`sml-forms-alist' understands let, local, case, abstype, datatype, -signature, structure, and functor by default.") - -(defmacro sml-def-skeleton (name interactor &rest elements) - (when (fboundp 'define-skeleton) - (let ((fsym (intern (concat "sml-form-" name)))) - ;; TODO: don't do the expansion in comments and strings. - `(progn - (add-to-list 'sml-forms-alist ',(cons name fsym)) - (condition-case err - ;; Try to use the new `system' flag. - (define-abbrev sml-mode-abbrev-table ,name "" ',fsym nil 'system) - (wrong-number-of-arguments - (define-abbrev sml-mode-abbrev-table ,name "" ',fsym))) - (when (fboundp 'abbrev-put) - (let ((abbrev (abbrev-symbol ,name sml-mode-abbrev-table))) - (abbrev-put abbrev :case-fixed t) - (abbrev-put abbrev :enable-function - (lambda () (not (nth 8 (syntax-ppss))))))) - (define-skeleton ,fsym - ,(format "SML-mode skeleton for `%s..' expressions" name) - ,interactor - ,(concat name " ") > - ,@elements))))) -(put 'sml-def-skeleton 'lisp-indent-function 2) - -(sml-def-skeleton "let" nil - @ "\nin " > _ "\nend" >) - -(sml-def-skeleton "if" nil - @ " then " > _ "\nelse " > _) - -(sml-def-skeleton "local" nil - @ "\nin" > _ "\nend" >) - -(sml-def-skeleton "case" "Case expr: " - str "\nof " > _ " => ") - -(sml-def-skeleton "signature" "Signature name: " - str " =\nsig" > "\n" > _ "\nend" >) - -(sml-def-skeleton "structure" "Structure name: " - str " =\nstruct" > "\n" > _ "\nend" >) - -(sml-def-skeleton "functor" "Functor name: " - str " () : =\nstruct" > "\n" > _ "\nend" >) - -(sml-def-skeleton "datatype" "Datatype name and type params: " - str " =" \n) - -(sml-def-skeleton "abstype" "Abstype name and type params: " - str " =" \n _ "\nwith" > "\nend" >) - -;; - -(sml-def-skeleton "struct" nil - _ "\nend" >) - -(sml-def-skeleton "sig" nil - _ "\nend" >) - -(sml-def-skeleton "val" nil - @ " = " > _) - -(sml-def-skeleton "fn" nil - @ " =>" > _) - -(sml-def-skeleton "fun" nil - @ " =" > _) - -;; - -(defun sml-forms-menu (menu) - (mapcar (lambda (x) (vector (car x) (cdr x) t)) - sml-forms-alist)) - -(defvar sml-last-form "let") - -(defun sml-electric-space () - "Expand a symbol into an SML form, or just insert a space. -If the point directly precedes a symbol for which an SML form exists, -the corresponding form is inserted." - (interactive) - (let ((abbrev-mode (not abbrev-mode)) - (last-command-event ?\ ) - ;; Bind `this-command' to fool skeleton's special abbrev handling. - (this-command 'self-insert-command)) - (call-interactively 'self-insert-command))) - -(defun sml-insert-form (name newline) - "Interactive short-cut to insert the NAME common ML form. -If a prefix argument is given insert a NEWLINE and indent first, or -just move to the proper indentation if the line is blank\; otherwise -insert at point (which forces indentation to current column). - -The default form to insert is 'whatever you inserted last time' -\(just hit return when prompted\)\; otherwise the command reads with -completion from `sml-forms-alist'." - (interactive - (list (completing-read - (format "Form to insert: (default %s) " sml-last-form) - sml-forms-alist nil t nil) - current-prefix-arg)) - ;; default is whatever the last insert was... - (if (string= name "") (setq name sml-last-form) (setq sml-last-form name)) - (unless (or (not newline) - (save-excursion (beginning-of-line) (looking-at "\\s-*$"))) - (insert "\n")) - (unless (/= ?w (char-syntax (preceding-char))) (insert " ")) - (let ((f (cdr (assoc name sml-forms-alist)))) - (cond - ((commandp f) (command-execute f)) - (f (funcall f)) - (t (error "Undefined form: %s" name))))) - -;; See also macros.el in emacs lisp dir. - -(defun sml-addto-forms-alist (name) - "Assign a name to the last keyboard macro defined. -Argument NAME is transmogrified to sml-form-NAME which is the symbol -actually defined. - -The symbol's function definition becomes the keyboard macro string. - -If that works, NAME is added to `sml-forms-alist' so you'll be able to -reinvoke the macro through \\[sml-insert-form]. You might want to save -the macro to use in a later editing session -- see `insert-kbd-macro' -and add these macros to your .emacs file. - -See also `edit-kbd-macro' which is bound to \\[edit-kbd-macro]." - (interactive "sName for last kbd macro (\"sml-form-\" will be added): ") - (when (string= name "") (error "No command name given")) - (let ((fsym (intern (concat "sml-form-" name)))) - (name-last-kbd-macro fsym) - (message "Macro bound to %s" fsym) - (add-to-list 'sml-forms-alist (cons name fsym)))) - -;;; -;;; MLton support -;;; - -(defvar sml-mlton-command "mlton" - "Command to run MLton. Can include arguments.") - -(defvar sml-mlton-mainfile nil) - -(defconst sml-mlton-error-regexp-alist - ;; I wish they just changed MLton to use one of the standard - ;; error formats. - `(("^\\(?:Error\\|\\(Warning\\)\\): \\(.+\\) \\([0-9]+\\)\\.\\([0-9]+\\)\\.$" - 2 3 4 - ;; If subgroup 1 matched, then it's a warning, otherwise it's an error. - ,@(if (fboundp 'compilation-fake-loc) '((1)))))) - -(defvar compilation-error-regexp-alist) -(eval-after-load "compile" - '(dolist (x sml-mlton-error-regexp-alist) - (add-to-list 'compilation-error-regexp-alist x))) - -(defun sml-mlton-typecheck (mainfile) - "typecheck using MLton." - (interactive - (list (if (and mainfile (not current-prefix-arg)) - mainfile - (read-file-name "Main file: ")))) - (save-some-buffers) - (require 'compile) - (dolist (x sml-mlton-error-regexp-alist) - (add-to-list 'compilation-error-regexp-alist x)) - (with-current-buffer (find-file-noselect mainfile) - (compile (concat sml-mlton-command - " -stop tc " ;Stop right after type checking. - (shell-quote-argument - (file-relative-name buffer-file-name)))))) - -;;; -;;; MLton's def-use info. -;;; - -(defvar sml-defuse-file nil) - -(defun sml-defuse-file () - (or sml-defuse-file (sml-defuse-set-file))) - -(defun sml-defuse-set-file () - "Specify the def-use file to use." - (interactive) - (setq sml-defuse-file (read-file-name "Def-use file: "))) - -(defun sml-defuse-symdata-at-point () - (save-excursion - (sml-smie-forward-token) - (let ((symname (sml-smie-backward-token))) - (if (equal symname "op") - (save-excursion (setq symname (sml-smie-forward-token)))) - (when (string-match "op " symname) - (setq symname (substring symname (match-end 0))) - (forward-word) - (forward-comment (point-max))) - (list symname - ;; Def-use files seem to count chars, not columns. - ;; We hope here that they don't actually count bytes. - ;; Also they seem to start counting at 1. - (1+ (- (point) (progn (beginning-of-line) (point)))) - (save-restriction - (widen) (1+ (count-lines (point-min) (point)))) - buffer-file-name)))) - -(defconst sml-defuse-def-regexp - "^[[:alpha:]]+ \\([^ \n]+\\) \\(.+\\) \\([0-9]+\\)\\.\\([0-9]+\\)$") -(defconst sml-defuse-use-regexp-format "^ %s %d\\.%d $") - -(defun sml-defuse-jump-to-def () - "Jump to the definition corresponding to the symbol at point." - (interactive) - (let ((symdata (sml-defuse-symdata-at-point))) - (if (null (car symdata)) - (error "Not on a symbol") - (with-current-buffer (find-file-noselect (sml-defuse-file)) - (goto-char (point-min)) - (unless (re-search-forward - (format sml-defuse-use-regexp-format - (concat "\\(?:" - ;; May be an absolute file name. - (regexp-quote (nth 3 symdata)) - "\\|" - ;; Or a relative file name. - (regexp-quote (file-relative-name - (nth 3 symdata))) - "\\)") - (nth 2 symdata) - (nth 1 symdata)) - nil t) - ;; FIXME: This is typically due to editing: any minor editing will - ;; mess everything up. We should try to fail more gracefully. - (error "Def-use info not found")) - (unless (re-search-backward sml-defuse-def-regexp nil t) - ;; This indicates a bug in this code. - (error "Internal failure while looking up def-use")) - (unless (equal (match-string 1) (nth 0 symdata)) - ;; FIXME: This again is most likely due to editing. - (error "Incoherence in the def-use info found")) - (let ((line (string-to-number (match-string 3))) - (char (string-to-number (match-string 4)))) - (pop-to-buffer (find-file-noselect (match-string 2))) - (goto-char (point-min)) - (forward-line (1- line)) - (forward-char (1- char))))))) - -;;; -;;; SML/NJ's Compilation Manager support -;;; - -(defvar sml-cm-mode-syntax-table sml-mode-syntax-table) -(defvar sml-cm-font-lock-keywords - `(,(concat "\\<" (regexp-opt '("library" "group" "is" "structure" - "functor" "signature" "funsig") t) - "\\>"))) -;;;###autoload -(add-to-list 'completion-ignored-extensions ".cm/") -;; This was used with the old compilation manager. -(add-to-list 'completion-ignored-extensions "CM/") -;;;###autoload -(add-to-list 'auto-mode-alist '("\\.cm\\'" . sml-cm-mode)) -;;;###autoload -(define-derived-mode sml-cm-mode fundamental-mode "SML-CM" - "Major mode for SML/NJ's Compilation Manager configuration files." - (local-set-key "\C-c\C-c" 'sml-compile) - (set (make-local-variable 'font-lock-defaults) - '(sml-cm-font-lock-keywords nil t nil nil))) - -;;; -;;; ML-Lex support -;;; - -(defvar sml-lex-font-lock-keywords - (append - '(("^%\\sw+" . font-lock-builtin-face) - ("^%%" . font-lock-module-def-face)) - sml-font-lock-keywords)) -(defconst sml-lex-font-lock-defaults - (cons 'sml-lex-font-lock-keywords (cdr sml-font-lock-defaults))) - -;;;###autoload -(define-derived-mode sml-lex-mode sml-mode "SML-Lex" - "Major Mode for editing ML-Lex files." - (set (make-local-variable 'font-lock-defaults) sml-lex-font-lock-defaults)) - -;;; -;;; ML-Yacc support -;;; - -(defface sml-yacc-bnf-face - '((t (:foreground "darkgreen"))) - "Face used to highlight (non)terminals in `sml-yacc-mode'.") -(defvar sml-yacc-bnf-face 'sml-yacc-bnf-face) - -(defcustom sml-yacc-indent-action 16 - "Indentation column of the opening paren of actions." - :type 'integer) - -(defcustom sml-yacc-indent-pipe nil - "Indentation column of the pipe char in the BNF. -If nil, align it with `:' or with previous cases." - :type 'integer) - -(defcustom sml-yacc-indent-term nil - "Indentation column of the (non)term part. -If nil, align it with previous cases." - :type 'integer) - -(defvar sml-yacc-font-lock-keywords - (cons '("^\\(\\sw+\\s-*:\\|\\s-*|\\)\\(\\s-*\\sw+\\)*\\s-*\\(\\(%\\sw+\\)\\s-+\\sw+\\|\\)" - (0 (save-excursion - (save-match-data - (goto-char (match-beginning 0)) - (unless (or (re-search-forward "\\<of\\>" (match-end 0) 'move) - (progn (forward-comment (point-max)) - (not (looking-at "(")))) - sml-yacc-bnf-face)))) - (4 font-lock-builtin-face t t)) - sml-lex-font-lock-keywords)) -(defconst sml-yacc-font-lock-defaults - (cons 'sml-yacc-font-lock-keywords (cdr sml-font-lock-defaults))) - -(defun sml-yacc-indent-line () - "Indent current line of ML-Yacc code." - (let ((savep (> (current-column) (current-indentation))) - (indent (max (or (ignore-errors (sml-yacc-indentation)) 0) 0))) - (if savep - (save-excursion (indent-line-to indent)) - (indent-line-to indent)))) - -(defun sml-yacc-indentation () - (save-excursion - (back-to-indentation) - (or (and (looking-at "%\\|\\(\\sw\\|\\s_\\)+\\s-*:") 0) - (when (save-excursion - (condition-case nil (progn (up-list -1) nil) (scan-error t))) - ;; We're outside an action. - (cond - ;; Special handling of indentation inside %term and %nonterm - ((save-excursion - (and (re-search-backward "^%\\(\\sw+\\)" nil t) - (member (match-string 1) '("term" "nonterm")))) - (if (numberp sml-yacc-indent-term) sml-yacc-indent-term - (let ((offset (if (looking-at "|") -2 0))) - (forward-line -1) - (looking-at "\\s-*\\(%\\sw*\\||\\)?\\s-*") - (goto-char (match-end 0)) - (+ offset (current-column))))) - ((looking-at "(") sml-yacc-indent-action) - ((looking-at "|") - (if (numberp sml-yacc-indent-pipe) sml-yacc-indent-pipe - (backward-sexp 1) - (while (progn (forward-comment (- (point))) - (/= 0 (skip-syntax-backward "w_")))) - (forward-comment (- (point))) - (if (not (looking-at "\\s-$")) - (1- (current-column)) - (skip-syntax-forward " ") - (- (current-column) 2)))))) - ;; default to SML rules - (cond - ((and sml-use-smie (fboundp 'smie-indent-calculate)) - (smie-indent-calculate)) - ((fboundp 'sml-calculate-indentation) (sml-calculate-indentation)))))) - -;;;###autoload -(add-to-list 'auto-mode-alist '("\\.grm\\'" . sml-yacc-mode)) -;;;###autoload -(define-derived-mode sml-yacc-mode sml-mode "SML-Yacc" - "Major Mode for editing ML-Yacc files." - (set (make-local-variable 'indent-line-function) 'sml-yacc-indent-line) - (set (make-local-variable 'font-lock-defaults) sml-yacc-font-lock-defaults)) - -(provide 'sml-mode) - -(unless (and sml-use-smie (fboundp 'smie-setup)) - (require 'sml-oldindent)) - -;;; sml-mode.el ends here diff --git a/emacs/emacs.d/sml-mode-5.0/sml-mode.info b/emacs/emacs.d/sml-mode-5.0/sml-mode.info @@ -1,908 +0,0 @@ -This is sml-mode.info, produced by makeinfo version 4.13 from -sml-mode.texi. - -INFO-DIR-SECTION Emacs -START-INFO-DIR-ENTRY -* sml:(sml-mode). Emacs mode for editing SML -END-INFO-DIR-ENTRY - - -File: sml-mode.info, Node: Top, Next: Copying, Prev: (dir), Up: (dir) - -1 SML Mode Info -*************** - -You are looking at the top node of the Info tree documenting SML-MODE -(Version $Name$). Not all functions are documented here, but those that -aren't you probably won't miss. All commands and settable variables -have built-in documentation, as per usual Emacs conventions. - -* Menu: - -* Copying:: You can copy SML mode -* Introduction:: Setting things up -* SML Mode:: Editing SML source -* Interaction Mode:: Running ML processes -* Configuration:: Menus, highlighting, setting defaults - -Indexes -* Command Index:: Commands you can invoke -* Variable Index:: Variables you can set -* Key Index:: Default keybindings - -Introduction -* Contributors:: Who did what -* Getting Started:: What to tell Emacs -* Getting Help:: How Emacs can help - -SML Mode -* Basics:: On entering SML mode -* Indentation:: Prettying SML text -* Magic Insertion:: Templates and electric keys -* SML Mode Defaults:: Variables controlling indentation - -Interaction Mode -* Running ML:: Commands to run the ML compiler in a buffer -* ML Interaction:: Sending program fragments to the compiler -* Tracking Errors:: Finding reported syntax errors -* Process Defaults:: Setting defaults for process interaction - -Configuration -* Hooks:: Creating hooks -* Key Bindings:: Binding commands to keys -* Highlighting:: Syntax colouring -* Advanced Topics:: You may need to speak Emacs Lisp - - -File: sml-mode.info, Node: Copying, Next: Introduction, Prev: Top, Up: Top - -2 Copying -********* - -You can freely copy, modify and redistribute SML mode because it's made -available under the liberal terms of the GNU General Public License. - - GNU General Public License as published by the Free Software -Foundation; either version 3, or (at your option) any later version. - - SML mode is distributed in the hope that it will be useful, but -WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General -Public License for more details. - - You should have received a copy of the GNU General Public License -along with GNU Emacs; see the file COPYING. If not, write to the Free -Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. - - -File: sml-mode.info, Node: Introduction, Next: SML Mode, Prev: Copying, Up: Top - -3 Introduction -************** - -SML mode is a major mode for Emacs for editing Standard ML. It has some -novel bugs, and some nice features: - - * Automatic indentation of sml code--a number of variables to - customise the indentation. - - * Easy insertion for commonly used templates like let, local, - signature, and structure declarations, with minibuffer prompting - for types and expressions. - - * Magic pipe insertion: `|' automatically determines if it is used - in a case or fun construct, and indents the next line as - appropriate, inserting `=>' or the name of the function. - - * Inferior shell for running ML. There's no need to leave Emacs, - just keep on editing while the compiler runs in another window. - - * Automatic "use file" in the inferior shell--you can send files, - buffers, or regions of code to the ML subprocess. - - * Menus, and syntax and keyword highlighting supported for Emacs 19 - and derivatives. - - * Parsing errors from the inferior shell, and repositioning the - source with next-error--just like in c-mode. - - * SML mode can be easily configured to work with a number of Standard - ML compilers, and other SML based tools. - -* Menu: - -* Contributors:: Who did what -* Getting Started:: What to tell Emacs -* Getting Help:: How Emacs can help - - -File: sml-mode.info, Node: Contributors, Next: Getting Started, Prev: Introduction, Up: Introduction - -3.1 Contributors to the SML mode -================================ - -Contributions to the package are welcome. I have limited time to work -on this project, but I will gladly add any code that you contribute to -me to this package. - - Although the history of sml-mode is obscure, it seems that the -following persons have made contributions to sml-mode: - - * Lars Bo Nielsen wrote the original version of the code, providing - the sml editing mode and the inferior-sml support. - - * Olin Shivers (`shivers@ai.mit.edu') hacked the inferior-sml support - to use comint and call the whole thing ml-mode. - - * Steven Gilmore supposedly provided some early attempt at menubar - support. - - * Matthew J. Morley (`matthew@verisity.com') was maintainer for a - long time (until version 3.4) and provided many additions and - fixes in all areas. - - * Frederick Knabe (`knabe@ecrc.de') provided the original code for - font-lock and hilite support as well as for proper handling of - nested comments and of all the string escape sequences. - - * Matthias Blume (`blume@kurims.kyoto-u.ac.jp') provided a sml-make - which was replaced by sml-compile. - - * Monnier Stefan (`monnier@iro.umontreal.ca') completely reworked the - indentation engine as well as most of the rest of the code and is - the current maintainer since after version 3.4. - - - -File: sml-mode.info, Node: Getting Started, Next: Getting Help, Prev: Contributors, Up: Introduction - -3.2 Getting started -=================== - -With luck your system administrator will have installed SML mode -somewhere convenient, so it will just magically all work--you can skip -the rest of this getting started section. Otherwise you will need to -tell Emacs where to find all the SML mode `.el' files, and when to use -them. The where is addressed by locating the Lisp code on your Emacs -Lisp load path--you may have to create a directory for this, say -`/home/mjm/elisp', and then insert the following lines in your -`/home/mjm/.emacs' file: - - (add-to-list 'load-path "/home/mjm/elisp") - (autoload 'sml-mode "sml-mode" "Major mode for editing SML." t) - (autoload 'run-sml "sml-proc" "Run an inferior SML process." t) - -The first line adjusts Emacs' internal search path so it can locate the -Lisp source you have copied to that directory; the second and third -lines tell Emacs to load the code automatically when it is needed. You -can then switch any Emacs buffer into SML mode by entering the command - - M-x sml-mode - -It is usually more convenient to have Emacs automatically place the -buffer in SML mode whenever you visit a file containing ML programs. -The simplest way of achieving this is to put something like - - (add-to-list 'auto-mode-alist '("\\.\\(sml\\|sig\\)\\'" . sml-mode)) - -also in your `.emacs' file. Subsequently (after a restart), any files -with these extensions will be placed in SML mode buffers when you visit -them. - - You may want to pre-compile the `sml-*.el' files (`M-x -byte-compile-file') for greater speed--byte compiled code loads and -runs somewhat faster. - - -File: sml-mode.info, Node: Getting Help, Prev: Getting Started, Up: Introduction - -3.3 Help! -========= - -You're reading it. Apart from the on-line info tree (`C-h i' is the -Emacs key to enter the `info' system--you should follow the brief -tutorial if this is unfamiliar), there are further details on specific -commands in their documentation strings. Only the most useful SML mode -commands are documented in the info tree: to find out more use Emacs' -help facilities. - - Briefly, to get help on a specific function use `C-h f' and enter -the command name. All (almost all, then) SML mode commands begin with -`sml-', so if you type this and press <TAB> (for completion) you will -get a list of all commands. Another way is to use `C-h a' and enter the -string `sml'. This is command apropos; it will list all commands with -that sub-string in their names, and any key binding they may have in -the current buffer. Command apropos gives a one-line synopsis of what -each command does. - - Some commands are also variables--such things are allowed in Lisp, if -not in ML! *Note Command Index::, for a list of (info) documented -functions. *Note Variable Index::, for a list of user settable variables -to control the behaviour of SML mode. - - Before accessing this information on-line from within Emacs you may -have to set the variable `sml-mode-info'. Put in your `.emacs' file -something like: - - (setq sml-mode-info "/home/mjm/info/sml-mode.info") - -When different from the default this variable should be a string giving -the absolute name of the `.info' file. Then `C-c C-i' in SML mode -(i.e., the command `M-x sml-mode-info') will bring up the manual. This -help is also accessible from the menu. (Resetting this variable will -not be necessary if your site administrator has been kind enough to -install SML mode and its attendant documentation in the Emacs -hierarchy.) - - -File: sml-mode.info, Node: SML Mode, Next: Interaction Mode, Prev: Introduction, Up: Top - -4 Editing with SML Mode -*********************** - -Now SML mode provides just a few additional editing commands. Most of -the work has gone into implementing the indentation algorithm which, if -you think about it, has to be complicated for a language like ML. *Note -Indentation Defaults: SML Mode Defaults, for details on how to control -some of the behaviour of the indentation algorithm. Principal goodies -are the `electric pipe' feature, and the ability to insert common SML -forms (macros or templates). - -* Menu: - -* Basics:: On entering SML mode -* Indentation:: Prettying SML text -* Magic Insertion:: Templates and electric keys -* SML Mode Defaults:: Variables controlling indentation - - -File: sml-mode.info, Node: Basics, Next: Indentation, Prev: SML Mode, Up: SML Mode - -4.1 On entering SML mode -======================== - - - - -- Command: sml-mode - This switches a buffer into SML mode. This is a _major mode_ in - Emacs. To get out of SML mode the buffer's major mode must be set - to something else, like text-mode. *Note Getting Started::, for - details on how to set this up automatically when visiting an SML - file. - - Emacs is all hooks of course. A hook is a variable: if the variable -is non-nil it binds a list of Emacs Lisp functions to be run in some -order (usually left to right). You can customise SML mode with these -hooks: - - -- Hook: sml-mode-hook - Default: `nil' - - This is run every time a new SML mode buffer is created (or if you - type `M-x sml-mode'). This is one place to put your preferred key - bindings. *Note Configuration::, for some examples. - - -File: sml-mode.info, Node: Indentation, Next: Magic Insertion, Prev: Basics, Up: SML Mode - -4.2 Automatic indentation -========================= - -ML is a complicated language to parse, let alone compile. The -indentation algorithm is a little wooden (for some tastes), and the best -advice is not to fight it! There are several variables that can be -adjusted to control the indentation algorithm (*note Customising SML -Mode: SML Mode Defaults, below). - - -- Command: indent-for-tab-command - Key: <TAB> - - This command indents the current line. If you set the indentation - of the previous line by hand, `indent-for-tab-command' will indent - relative to this setting. - - -- Command: indent-region - Key: `C-M-\' - - Indent the current region. Be patient if the region is large (like - the whole buffer). - - -- Command: sml-back-to-outer-indent - Key: `M-<TAB>' - - Unindents the line to the next outer level of indentation. - - Further indentation commands that Emacs provides (generically, for -all modes) that you may like to recall: - - - `M-x newline-and-indent' - - On <LFD> by default. Insert a newline, then indent according to - the major mode. *Note Indentation for Programs: (emacs)Program - Indent, for details. - - - `M-x indent-rigidly' - - On `C-x <TAB>' by default. Moves all lines in the region right by - its argument (left, for negative arguments). *Note Indentation: - (emacs)Indentation. - - - `M-x indent-for-comment' - - On `M-;' by default. Indent this line's comment to comment - column, or insert an empty comment. *Note Comment Commands: - (emacs)Comment Commands. - - - `M-x indent-new-comment-line' - - On `M-<LFD>' by default. Break line at point and indent, - continuing comment if within one. *Note Multi-Line Comments: - (emacs)Multi-Line Comments. - - As with other language modes, `M-;' gives you a comment at the end -of the current line. The column where the comment starts is determined -by the variable `comment-column'--default is 40, but it can be changed -with `set-comment-column' (on `C-x ;' by default). - - -File: sml-mode.info, Node: Magic Insertion, Next: SML Mode Defaults, Prev: Indentation, Up: SML Mode - -4.3 Electric features -===================== - -Electric keys are generally pretty irritating, so those provided by SML -mode are fairly muted. The only truly electric key is `;', and this has -to be enabled to take effect. - - -- Command: sml-electric-pipe - Key: `M-|' - - When the point is in a `case' statement this opens a new line, - indents and inserts `| =>' leaving point just before the double - arrow; if the enclosing construct is a `fun' declaration, the - newline is indented and the function name copied at the - appropriate column. Generally, try it whenever a `|' is - wanted--you'll like it! - - -- Command: sml-electric-space - Key: `M-SPC' - - When the point is after a keyword like `let', this inserts the - corresponding predefined skeleton if one exists. Else it just - inserts a space. Another way to insert those skeletons is to use - `sml-insert-form', described below. - - -- Command: sml-electric-semi - Key: `;' - - Just inserts a semi-colon, usually. The behaviour of this command - is governed by the variable `sml-electric-semi-mode'. - - -- Variable: sml-electric-semi-mode - Default: `nil' - - If this variable is `nil', `sml-electric-semi' just inserts a - semi-colon, otherwise it inserts a semi-colon and a newline, and - indents the newline for SML. - - -- Command: sml-insert-form - Key: `C-c <RET>' - - Interactive short-cut to insert common ML forms (a.k.a. macros, or - templates). Recognised forms are `let', `local', `case', `abstype', - `datatype', `signature', `structure', and `functor'. Except for - `let' and `local', these will prompt for appropriate parameters - like functor name and signature, etc.. This command prompts in the - mini-buffer, with completion. - - By default `C-c <RET>' will insert at point, with the indentation - of the current column; if you give a prefix argument (i.e., `C-u - C-c <RET>') the command will insert a newline first, indent, and - then insert the template. - - `sml-insert-form' is also extensible: see *note Configuration:: for -further details. - - -File: sml-mode.info, Node: SML Mode Defaults, Prev: Magic Insertion, Up: SML Mode - -4.4 Indentation defaults -======================== - -Several variables try to control the indentation algorithm and other -features of SML mode. Most of them are still in flux so they are not -described here yet. If the default values are not acceptable you can -set these variables permanently in your `.emacs' file. *Note -Configuration::, for details and examples. - - -- Variable: sml-indent-level - Default: `4' - - This variable controls the block indentation level. - - -File: sml-mode.info, Node: Interaction Mode, Next: Configuration, Prev: SML Mode, Up: Top - -5 Running ML under Emacs -************************ - -The most useful feature of SML mode is that it provides a convenient -interface to the compiler. How serious users of ML put up with a -teletype interface to the compiler is beyond me... but perhaps there -are other interfaces to compilers that require one to part with serious -money. Such remarks can quickly become dated--in this case, let's hope -so! - - Anyway, SML mode provides an interaction mode, `inferior-sml-mode', -where the compiler runs in a separate buffer in a window or frame of -its own. You can use this buffer just like a terminal, but it's usually -more convenient to mark some text in the SML mode buffer and have Emacs -communicate with the sub-process. The features discussed below are -syntax-independent, so they should work with a wide range of ML-like -tools and compilers. *Note Process Defaults::, for some hints. - - `inferior-sml-mode' is a specialisation of the `comint' package that -comes with Emacs and XEmacs. - -* Menu: - -* Running ML:: Commands to run the ML compiler in a buffer -* ML Interaction:: Sending program fragments to the compiler -* Tracking Errors:: Finding reported syntax errors -* Process Defaults:: Setting defaults for process interaction - - -File: sml-mode.info, Node: Running ML, Next: ML Interaction, Prev: Interaction Mode, Up: Interaction Mode - -5.1 Starting the compiler -========================= - -Start your favourite ML compiler with the command - - M-x run-sml - -This creates a process interaction buffer that inherits some key -bindings from SML mode and from `comint' (*note Shell Mode: -(emacs)Shell Mode.). Starting the ML compiler adds some functions to -SML mode buffers so that program text can be communicated between -editor and compiler (*note ML Interaction::). - - The name of the ML compiler is the first thing you should know how to -specify: - - -- Variable: sml-program-name - Default: `"sml"' - - The program to run as ML. You might need to specify the full path - name of the program. - - -- Variable: sml-default-arg - Default: `""' - - Useful for Poly/ML users who may supply a database file, or others - who have wrappers for setting various options around the command - to run the compiler. Moscow ML people might set this to `"-P - full"', etc.. - - The variable `sml-program-name' is a string holding the name of the -program _as you would type it at the shell_. You can always choose a -program different to the default by invoking - - C-u M-x run-sml - -With the prefix argument Emacs will prompt for the command name and any -command line arguments to pass to the compiler. Thereafter Emacs will -use this new name as the default, but for a permanent change you should -set this in your `.emacs' with, e.g.: - - (setq sml-program-name "nj-sml") - - -- Command: run-sml - Launches ML as an inferior process in another buffer; if an ML - process already exists, just switch to the process buffer. A - prefix argument allows you to edit the command line to specify the - program, and any command line options. - - -- Hook: inferior-sml-mode-hook - Default: `nil' - - `M-x run-sml' runs `comint-mode-hook' and `inferior-sml-mode-hook' - hooks in that order, but _after_ the compiler is started. Use - `inferior-sml-mode-hook' to set any `comint' buffer-local - configurations for SML mode you like. - - -- Command: switch-to-sml - Key: `C-c C-s' - - Switch from the SML buffer to the interaction buffer. By default - point will be placed at the end of the process buffer, but a - prefix argument will leave point wherever it was before. If you - try `C-c C-s' before an ML process has been started, you'll just - get an error message to the effect that there's no current process - buffer. - - -- Command: sml-cd - When started, the ML compiler's default working directory is the - current buffer's default directory. This command allows the working - directory to be changed, if the compiler can do this. The variable - `sml-cd-command' specifies the compiler command to invoke (*note - Process Defaults::). - - -File: sml-mode.info, Node: ML Interaction, Next: Tracking Errors, Prev: Running ML, Up: Interaction Mode - -5.2 Speaking to the compiler -============================ - -Several commands are defined for sending program fragments to the -running compiler. Each of the following commands takes a prefix argument -that will switch the input focus to the process buffer afterwards -(leaving point at the end of the buffer): - - -- Command: sml-load-file - Key: `C-c C-l' - - Send a `use file' command to the current ML process. The variable - `sml-use-command' is used to define the correct template for the - command to invoke (*note Process Defaults::). The default file is - the file associated with the current buffer, or the last file - loaded if you are in the interaction buffer. - - -- Command: sml-send-region - Key: `C-c C-r' - - Send the current region of text in the SML buffer. - `sml-send-region-and-go' is a similar command for you to bind in - SML mode if you wish: it'll send the region and then switch-to-sml. - - -- Command: sml-send-buffer - Key: `C-c C-b' - - Send the contents of the current buffer to ML. - - -File: sml-mode.info, Node: Tracking Errors, Next: Process Defaults, Prev: ML Interaction, Up: Interaction Mode - -5.3 Finding errors -================== - -SML mode provides one customisable function for locating the source -position of errors reported by the compiler. This should work whether -you type `use "puzzle.sml";' into the interaction buffer, or use one of -the mechanisms provided for sending programs directly to the -compiler--*note ML Interaction::. - - -- Command: next-error - Key: `C-x`' - - Jump to the source location of the next error reported by the - compiler. All the usual error-navigation commands are available, - see *note Compilation Mode: (emacs)Compilation Mode. - - -File: sml-mode.info, Node: Process Defaults, Prev: Tracking Errors, Up: Interaction Mode - -5.4 Process defaults -==================== - -The process interaction code is independent of the compiler used, -deliberately, so SML mode will work with a variety of ML compilers and -ML-based tools. There are therefore a number of variables that may need -to be set correctly before SML mode can speak to the compiler. Things -are by default set up for Standard ML of New Jersey, but switching to a -new system is quite easy. - - -- Variable: sml-use-command - Default: `"use \"%s\""' - - Use file command template. Emacs will replace the `%s' with a file - name. Note that Emacs requires double quote characters inside - strings to be quoted with a backslash. - - -- Variable: sml-cd-command - Default: `"OS.FileSys.chDir \"%s\""' - - Compiler command to change the working directory. Not all ML - systems support this feature (well, Edinburgh (core) ML didn't), - but they should. - - -- Variable: sml-prompt-regexp - Default: `"^[-=>#] *"' - - Matches the ML compiler's prompt: `comint' uses this for various - purposes. - - To customise error reportage for different ML compilers you need to -set two further variables before `next-error' can be useful: - - -- Variable: sml-error-regexp-alist - Alist that specifies how to match errors in compiler output. Each - elt has the form (REGEXP FILE-IDX LINE-IDX [COLUMN-IDX - FILE-FORMAT...]) If REGEXP matches, the FILE-IDX'th subexpression - gives the file name, and the LINE-IDX'th subexpression gives the - line number. If COLUMN-IDX is given, the COLUMN-IDX'th - subexpression gives the column number on that line. If any - FILE-FORMAT is given, each is a format string to produce a file - name to try; %s in the string is replaced by the text matching the - FILE-IDX'th subexpression. - - -File: sml-mode.info, Node: Configuration, Prev: Interaction Mode, Up: Top - -6 Configuration Summary -*********************** - -This (sort of pedagogic) section gives more information on how to -configure SML mode: menus, key bindings, hooks and highlighting are -discussed, along with a few other random topics. - -* Menu: - -* Hooks:: Creating them -* Key Bindings:: Binding commands to keys -* Highlighting:: Syntax colouring -* Advanced Topics:: You may need to speak Emacs Lisp - - -File: sml-mode.info, Node: Hooks, Next: Key Bindings, Prev: Configuration, Up: Configuration - -6.1 Hooks -========= - -One way to set SML mode variables (*note Indentation Defaults: SML Mode -Defaults.), and other defaults, is through the `sml-mode-hook' in your -`.emacs'. A simple example: - - (defun my-sml-mode-hook () "Local defaults for SML mode" - (setq sml-indent-level 2) ; conserve on horizontal space - (setq words-include-escape t) ; \ loses word break status - (setq indent-tabs-mode nil)) ; never ever indent with tabs - (add-hook 'sml-mode-hook 'my-sml-mode-hook) - The body of `my-sml-mode-hook' is a sequence of assignments. In this -case it is not really necessary to set `sml-indent-level' in a hook -because this variable is global (most SML mode variables are). With -similar effect: - - (setq sml-indent-level 2) - anywhere in your `.emacs' file. The variable `indent-tabs-mode' is -automatically made local to the current buffer whenever it is set -explicitly, so it _must_ be set in a hook if you always want SML mode -to behave like this. - - Another hook is `inferior-sml-mode-hook'. This can be used to -control the behaviour of the interaction buffer through various -variables meaningful to `comint'-based packages: - - (defun my-inf-sml-mode-hook () "Local defaults for inferior SML mode" - (add-hook 'comint-output-filter-functions 'comint-truncate-buffer) - (setq comint-scroll-show-maximum-output t) - (setq comint-input-autoexpand nil)) - (add-hook 'inferior-sml-mode-hook 'my-inf-sml-mode-hook) - Again, the body is a sequence of assignments. Unless you run several -ML compilers simultaneously under one Emacs, this hook will normally -only get run once. You might want to look up the documentation (`C-h v' -and `C-h f') for these buffer-local `comint' things. - - -File: sml-mode.info, Node: Key Bindings, Next: Highlighting, Prev: Hooks, Up: Configuration - -6.2 Key bindings -================ - -Customisation (in Emacs) usually entails putting favourite commands on -easily remembered keys. Two `keymaps' are defined in SML mode: one is -effective in program text buffers (`sml-mode-map') and the other is -effective in interaction buffers (`inferior-sml-mode-map'). The -initial design ensures that (many of) the default key bindings from the -former keymap will also be available in the latter (e.g., `C-c`'). - - Type `C-h m' in an SML mode buffer to find the default key bindings -(and similarly in an ML interaction buffer), and use the hooks provided -to install your preferred key bindings. Given that the keymaps are -global (variables): - - (defun my-sml-mode-hook () "Global defaults for SML mode" - (define-key sml-mode-map "\C-cd" 'sml-cd)) - (add-hook 'sml-mode-hook 'my-sml-mode-hook) - This has the effect of binding `sml-cd' to the key `C-c d'. If you -want the same behaviour from `C-c d' in the ML buffer: - - (defun my-inf-sml-mode-hook () "Global defaults for inferior SML mode" - (define-key inferior-sml-mode-map "\C-cd" 'sml-cd) - ;; NB. for SML/NJ '96 - (setq sml-cd-command "OS.FileSys.chDir \"%s\"")) - (add-hook 'inferior-sml-mode-hook 'my-inf-sml-mode-hook) - - There is nothing to stop you rebuilding the entire keymap for SML -mode and the ML interaction buffer in your `.emacs' of course: SML mode -won't define `sml-mode-map' or `inferior-sml-mode-map' if you have -already done so. - - -File: sml-mode.info, Node: Highlighting, Next: Advanced Topics, Prev: Key Bindings, Up: Configuration - -6.3 Syntax colouring -==================== - -Highlighting is very handy for picking out keywords in the program text, -spotting misspelled kewyords, and, if you have Emacs' `ps-print' -package installed (you usually do these days), obtaining pretty, even -colourful code listings--quite properly for your colourful ML programs. - - The indentation scheme (strangely enough) also relies on the -highlighting code to properly handle nested comments, which is yet -another reason to turn on highlighting. To turn on highlighting, use -either of: - - M-x font-lock-mode - (add-hook 'sml-mode-hook 'turn-on-font-lock) - (global-font-lock-mode 1) - - The first will turn it on in the current buffer. The second will -turn it on in all sml-mode buffers. The last will turn it on -everywhere. This is valid for Emacs but maybe not for XEmacs. Check -font-lock documentation if you encounter problems. - - -File: sml-mode.info, Node: Advanced Topics, Prev: Highlighting, Up: Configuration - -6.4 Advanced Topics -=================== - - _These forms are bloody useless; can't we have better ones?_ - - -You can indeed. `sml-insert-form' is extensible so all you need to do -is create the macros yourself. Define a _keybord macro_ (`C-x (' -<something> `C-x )') and give it a suitable name: -`sml-addto-forms-alist' prompts for a name, say `NAME', and binds the -macro `sml-form-NAME'. Thereafter `C-c <RET> NAME' will insert the -macro at point, and `C-u C-c <RET> NAME' will insert the macro after a -`newline-and-indent'. If you want to keep your macros from one editing -session to the next, go to your `.emacs' file and call -`insert-kbd-macro'; you'll need to add `NAME' to `sml-forms-alist' -permanently yourself: - - (defun my-sml-mode-hook () "Global defaults for SML mode" - ;; whatever else you do - (add-to-list 'sml-forms-alist '("NAME" . FUNCTION))) - - If you want to create templates like `case' that prompt for -parameters you'll have to do some Lisp programming. The `skeleton' -package is a good stating point. Better yet, you can reuse the -wrappers used by sml-mode itself in your sml-mode-hook: - - (add-hook 'sml-mode-hook - (lambda () - (sml-def-skeleton "case" "Case expr: " - str " of" \n _ " => "))) - - This will redefine `case' in order to leave the `of' on the first -line. See the documentation of `skeleton-insert' to get a better -understanding of how this works. - - -_I hate that indentation algorithm; can't I tweak it?_ - - -Ah, yes, of course, but this manual will not tell you how. - - -_Can SML mode handle more than one compiler running at once?_ - - Sure, just rename the `*sml*' buffer and then use `run-sml' as usual. - - -_What needs to be done to support other ML compilers?_ - - -Not much really. Just add the right regular expressions to -`sml-error-regexp-alist' and that should be all. - - -File: sml-mode.info, Node: Command Index, Next: Variable Index, Up: Top - -Command Index -************* - --* Menu: - -* indent-for-tab-command: Indentation. (line 13) -* indent-region: Indentation. (line 20) -* inferior-sml-mode: Interaction Mode. (line 21) -* next-error: Tracking Errors. (line 13) -* run-sml: Running ML. (line 47) -* sml-back-to-outer-indent: Indentation. (line 26) -* sml-cd: Running ML. (line 71) -* sml-electric-pipe: Magic Insertion. (line 11) -* sml-electric-semi: Magic Insertion. (line 29) -* sml-electric-space: Magic Insertion. (line 21) -* sml-indent-level: SML Mode Defaults. (line 13) -* sml-insert-form: Magic Insertion. (line 42) -* sml-load-file: ML Interaction. (line 12) -* sml-mode: Basics. (line 9) -* sml-mode-info: Getting Help. (line 31) -* sml-send-buffer: ML Interaction. (line 28) -* sml-send-region: ML Interaction. (line 21) -* sml-send-region-and-go: ML Interaction. (line 21) -* switch-to-sml: Running ML. (line 61) - - -File: sml-mode.info, Node: Variable Index, Next: Key Index, Prev: Command Index, Up: Top - -Variable Index -************** - --* Menu: - -* inferior-sml-mode-hook: Running ML. (line 53) -* sml-cd-command: Process Defaults. (line 21) -* sml-default-arg: Running ML. (line 26) -* sml-electric-semi-mode: Magic Insertion. (line 35) -* sml-error-regexp-alist: Process Defaults. (line 37) -* sml-indent-level: SML Mode Defaults. (line 13) -* sml-mode-hook: Basics. (line 21) -* sml-mode-info: Getting Help. (line 31) -* sml-program-name: Running ML. (line 20) -* sml-prompt-regexp: Process Defaults. (line 28) -* sml-use-command: Process Defaults. (line 14) - - -File: sml-mode.info, Node: Key Index, Prev: Variable Index, Up: Top - -Key Index -********* - --* Menu: - -* ;: Magic Insertion. (line 29) -* <LFD>: Indentation. (line 35) -* <TAB>: Indentation. (line 13) -* C-c <RET>: Magic Insertion. (line 42) -* C-c C-b: ML Interaction. (line 28) -* C-c C-i: Getting Help. (line 31) -* C-c C-l: ML Interaction. (line 12) -* C-c C-r: ML Interaction. (line 21) -* C-c C-s: Running ML. (line 61) -* C-M-\: Indentation. (line 20) -* C-x ;: Indentation. (line 57) -* C-x <TAB>: Indentation. (line 41) -* C-x`: Tracking Errors. (line 13) -* M-;: Indentation. (line 47) -* M-<LFD>: Indentation. (line 53) -* M-<TAB>: Indentation. (line 26) -* M-SPC: Magic Insertion. (line 21) -* M-|: Magic Insertion. (line 11) - - - -Tag Table: -Node: Top187 -Node: Copying1782 -Node: Introduction2595 -Node: Contributors4011 -Node: Getting Started5484 -Node: Getting Help7192 -Node: SML Mode9060 -Node: Basics9868 -Node: Indentation10787 -Node: Magic Insertion12897 -Node: SML Mode Defaults15115 -Node: Interaction Mode15676 -Node: Running ML17025 -Node: ML Interaction19894 -Node: Tracking Errors21047 -Node: Process Defaults21750 -Node: Configuration23633 -Node: Hooks24141 -Node: Key Bindings25998 -Node: Highlighting27574 -Node: Advanced Topics28579 -Node: Command Index30523 -Node: Variable Index32039 -Node: Key Index32991 - -End Tag Table diff --git a/emacs/emacs.d/sml-mode-5.0/sml-mode.spec b/emacs/emacs.d/sml-mode-5.0/sml-mode.spec @@ -1,67 +0,0 @@ -%define lispdir %{_datadir}/emacs/site-lisp -%define startupfile %{lispdir}/site-start.el - -Summary: Emacs mode for editing Standard ML source code -Name: sml-mode -Version: $Name$ -Release: 0.1 -Group: Applications/Editors -Copyright: GPL -Packager: Stefan Monnier -Source: http://iro.umontreal.ca/~monnier/elisp/%{name}.tar.gz -Buildroot: %{_tmppath}/%{name}-buildroot -BuildPreReq: emacs >= 20 xemacs >= 21 -BuildArch: noarch - -%description -SML-MODE is a major Emacs mode for editing Standard ML. It provides -syntax highlighting and automatic indentation and comes with sml-proc -which allows interaction with an inferior SML interactive loop. - -%prep -%setup -q -n %{name} - -%install -make install \ - prefix=%{buildroot}%{_prefix} \ - infodir=%{buildroot}%{_infodir} \ - lispdir=%{buildroot}%{lispdir} -gzip -9f %{buildroot}%{lispdir}/sml-mode/*.el - -texi2pdf sml-mode.texi - -%post -cat >> %{lispdir}/site-start.el <<EOF -;; sml-mode-start -;; This section was automatically generated by rpm -(load "sml-mode-startup") -;; End of automatically generated section -;; sml-mode-end -EOF - -/sbin/install-info %{_infodir}/sml-mode.info.gz %{_infodir}/dir - -%postun -ed -s %{lispdir}/site-start.el <<EOF -/^;; sml-mode-start$/,/^;; sml-mode-end$/d -wq -EOF - -/sbin/install-info --delete %{_infodir}/sml-mode.info.gz %{_infodir}/dir \ - --section=Emacs \ - --entry="* SML: (sml-mode). Editing & Running Standard ML from Emacs" - -%clean -rm -rf %{buildroot} - -%files -%defattr(-,root,root) -%doc BUGS ChangeLog INSTALL NEWS README TODO -%doc sml-mode.texi sml-mode.pdf -%doc %{_infodir}/*.info* -%dir %{lispdir}/%{name} -%{lispdir}/%{name}/*.elc -%{lispdir}/%{name}/*.el -%{lispdir}/%{name}/*.el.* - -%changelog diff --git a/emacs/emacs.d/sml-mode-5.0/sml-mode.texi b/emacs/emacs.d/sml-mode-5.0/sml-mode.texi @@ -1,1161 +0,0 @@ -\input texinfo @c -*-texinfo-*- - -@comment "@(#)$Name$:$Id$" - -@comment Documentation for the GNU Emacs SML mode. -@comment Copyright (C) 1997-1999 Matthew J.@: Morley - -@comment This file is part of the sml-mode distribution. - -@comment sml-mode is free software; you can redistribute it and/or modify -@comment it under the terms of the GNU General Public License as published by -@comment the Free Software Foundation; either version 3 of the License, -@comment or (at your option) any later version. - -@comment sml-mode is distributed in the hope that it will be useful, -@comment but WITHOUT ANY WARRANTY; without even the implied warranty of -@comment MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -@comment GNU General Public License for more details. - -@comment You should have received a copy of the GNU General Public License -@comment along with sml-mode; see the file COPYING. If not, write to -@comment the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. - -@setfilename sml-mode.info -@settitle SML mode - The Emacs SML editing mode -@dircategory Emacs -@direntry -* sml:(sml-mode). Emacs mode for editing SML -@end direntry -@setchapternewpage on - -@titlepage -@sp 5 -@center @titlefont{Editing and Running Standard ML} -@center @titlefont{under GNU Emacs} -@sp 5 -@center {SML mode, Version $Name$} -@center {August 1999} -@sp 2 -@author Authors: Matthew J.@: Morley and Stefan Monnier - -@page -@vskip 0pt plus 1filll -Copyright @copyright{} (Anon) - -@sp 1 -@noindent -GNU General Public License as published by the Free Software Foundation; -either version 3, or (at your option) any later version. - -@sp 1 -@noindent -SML mode is distributed in the hope that it will be useful, but -WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General -Public License for more details. - -@sp 1 -@noindent -You should have received a copy of the GNU General Public License along -with GNU Emacs; see the file COPYING. If not, write to the Free Software -Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. - -@end titlepage - -@setchapternewpage off -@headings double - -@c ============================================================ TOP NODE - -@node Top, Copying, (dir), (dir) - -@ifinfo -@chapter SML Mode Info - -@c == Top, Copying, (dir), (dir) ======================================= - -@noindent -You are looking at the top node of the Info tree documenting -@sc{sml-mode} (Version $Name$). Not all functions are documented here, but -those that aren't you probably won't miss. All commands and settable -variables have built-in documentation, as per usual Emacs conventions. -@end ifinfo - -@menu -* Copying:: You can copy SML mode -* Introduction:: Setting things up -* SML Mode:: Editing SML source -* Interaction Mode:: Running ML processes -* Configuration:: Menus, highlighting, setting defaults - -Indexes -* Command Index:: Commands you can invoke -* Variable Index:: Variables you can set -* Key Index:: Default keybindings - -Introduction -* Contributors:: Who did what -* Getting Started:: What to tell Emacs -* Getting Help:: How Emacs can help - -SML Mode -* Basics:: On entering SML mode -* Indentation:: Prettying SML text -* Magic Insertion:: Templates and electric keys -* SML Mode Defaults:: Variables controlling indentation - -Interaction Mode -* Running ML:: Commands to run the ML compiler in a buffer -* ML Interaction:: Sending program fragments to the compiler -* Tracking Errors:: Finding reported syntax errors -* Process Defaults:: Setting defaults for process interaction - -Configuration -* Hooks:: Creating hooks -* Key Bindings:: Binding commands to keys -* Highlighting:: Syntax colouring -* Advanced Topics:: You may need to speak Emacs Lisp -@end menu - - -@c ============================================================= COPYING - -@node Copying, Introduction, Top, Top - -@ifinfo -@chapter Copying - -@c == Copying, Introduction, Top, Top ================================== - -@noindent -You can freely copy, modify and redistribute SML mode because it's -made available under the liberal terms of the GNU General Public -License. - -GNU General Public License as published by the Free Software Foundation; -either version 3, or (at your option) any later version. - -SML mode is distributed in the hope that it will be useful, but -WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General -Public License for more details. - -You should have received a copy of the GNU General Public License along -with GNU Emacs; see the file COPYING. If not, write to the Free Software -Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. - -@end ifinfo - - - - -@c ======================================================== INTRODUCTION - -@node Introduction, SML Mode, Copying, Top - -@chapter Introduction - -@c == Introduction, SML Mode, Copying, Top ============================= - - -@noindent -SML mode is a major mode for Emacs for editing Standard ML. It has -some novel bugs, and some nice features: - -@itemize @bullet -@item -Automatic indentation of sml code---a number of variables to customise -the indentation. -@item -Easy insertion for commonly used templates like let, local, signature, -and structure declarations, with minibuffer prompting for types and -expressions. -@item -Magic pipe insertion: @code{|} automatically determines if it is used -in a case or fun construct, and indents the next line as appropriate, -inserting @code{=>} or the name of the function. -@item -Inferior shell for running ML. There's no need to leave Emacs, just keep -on editing while the compiler runs in another window. -@item -Automatic ``use file'' in the inferior shell---you can send files, -buffers, or regions of code to the ML subprocess. -@item -Menus, and syntax and keyword highlighting supported for Emacs 19 and -derivatives. -@item -Parsing errors from the inferior shell, and repositioning the -source with next-error---just like in c-mode. -@item -SML mode can be easily configured to work with a number of Standard -ML compilers, and other SML based tools. -@end itemize - -@menu -* Contributors:: Who did what -* Getting Started:: What to tell Emacs -* Getting Help:: How Emacs can help -@end menu - - - -@c ======================================================== CONTRIBUTORS - -@node Contributors, Getting Started, Introduction, Introduction - -@section Contributors to the SML mode -@cindex Contributors -@cindex Authors - -Contributions to the package are welcome. I have limited time to work -on this project, but I will gladly add any code that you contribute to -me to this package. - -Although the history of sml-mode is obscure, it seems that -the following persons have made contributions to sml-mode: - -@itemize @bullet -@item -Lars Bo Nielsen wrote the original version of the code, providing the -sml editing mode and the inferior-sml support. - -@item -Olin Shivers (@samp{shivers@@ai.mit.edu}) hacked the inferior-sml support -to use comint and call the whole thing ml-mode. - -@item -Steven Gilmore supposedly provided some early attempt at menubar support. - -@item -Matthew J. Morley (@samp{matthew@@verisity.com}) was maintainer for -a long time (until version 3.4) and provided many additions and fixes in -all areas. - -@item -Frederick Knabe (@samp{knabe@@ecrc.de}) provided the original code for -font-lock and hilite support as well as for proper handling of nested -comments and of all the string escape sequences. - -@item -Matthias Blume (@samp{blume@@kurims.kyoto-u.ac.jp}) provided a sml-make -which was replaced by sml-compile. - -@item -Monnier Stefan (@samp{monnier@@iro.umontreal.ca}) completely reworked the -indentation engine as well as most of the rest of the code and is -the current maintainer since after version 3.4. - -@end itemize - - -@c ===================================================== GETTING STARTED - -@node Getting Started, Getting Help, Contributors, Introduction - -@section Getting started - -@c == Getting Started, Getting Help, Contributors, Introduction ======== - - -@noindent -With luck your system administrator will have installed SML mode -somewhere convenient, so it will just magically all work---you can -skip the rest of this getting started section. Otherwise you will need -to tell Emacs where to find all the SML mode @file{.el} files, and -when to use them. The where is addressed by locating the Lisp code on -your Emacs Lisp load path---you may have to create a directory for this, -say @file{/home/mjm/elisp}, and then insert the following lines in your -@file{/home/mjm/.emacs} file: - -@lisp -(add-to-list 'load-path "/home/mjm/elisp") -(autoload 'sml-mode "sml-mode" "Major mode for editing SML." t) -(autoload 'run-sml "sml-proc" "Run an inferior SML process." t) -@end lisp - -@noindent -The first line adjusts Emacs' internal search path so it can locate the -Lisp source you have copied to that directory; the second and third -lines tell Emacs to load the code automatically when it is needed. You -can then switch any Emacs buffer into SML mode by entering the command - -@example -M-x sml-mode -@end example - -@noindent -It is usually more convenient to have Emacs automatically place the -buffer in SML mode whenever you visit a file containing ML -programs. The simplest way of achieving this is to put something like - -@lisp -(add-to-list 'auto-mode-alist '("\\.\\(sml\\|sig\\)\\'" . sml-mode)) -@end lisp - -@noindent -also in your @file{.emacs} file. Subsequently (after a restart), any -files with these extensions will be placed in SML mode buffers when -you visit them. - - -You may want to pre-compile the @file{sml-*.el} files (@kbd{M-x -byte-compile-file}) for greater speed---byte compiled code loads and -runs somewhat faster. - - -@c ======================================================== GETTING HELP - -@node Getting Help, , Getting Started, Introduction - -@section Help! - -@c == Getting Help, , Getting Started, Introduction ==================== - - -@noindent -You're reading it. Apart from the on-line info tree (@kbd{C-h i} is the -Emacs key to enter the @code{info} system---you should follow the brief -tutorial if this is unfamiliar), there are further details on specific -commands in their documentation strings. Only the most useful -SML mode commands are documented in the info tree: to find out more -use Emacs' help facilities. - -Briefly, to get help on a specific function use @kbd{C-h f} and enter -the command name. All (almost all, then) SML mode commands begin -with @code{sml-}, so if you type this and press @key{TAB} (for -completion) you will get a list of all commands. Another way is to use -@kbd{C-h a} and enter the string @code{sml}. This is command apropos; it -will list all commands with that sub-string in their names, and any key -binding they may have in the current buffer. Command apropos gives a -one-line synopsis of what each command does. - -Some commands are also variables---such things are allowed in Lisp, if -not in ML! @xref{Command Index}, for a list of (info) documented -functions. @xref{Variable Index}, for a list of user settable variables -to control the behaviour of SML mode. - -Before accessing this information on-line from within Emacs you may have -to set the variable @code{sml-mode-info}. Put in your @file{.emacs} file -something like: - -@vindex sml-mode-info -@findex sml-mode-info -@kindex @kbd{C-c C-i} -@lisp -(setq sml-mode-info "/home/mjm/info/sml-mode.info") -@end lisp - -@noindent -When different from the default this variable should be a string giving -the absolute name of the @file{.info} file. Then @kbd{C-c C-i} in -SML mode (i.e., the command @kbd{M-x sml-mode-info}) will bring up -the manual. This help is also accessible from the menu. (Resetting this -variable will not be necessary if your site administrator has been kind -enough to install SML mode and its attendant documentation in the -Emacs hierarchy.) - - -@c ============================================================ SML MODE - -@node SML Mode, Interaction Mode, Introduction, Top - -@chapter Editing with SML Mode - -@c == SML Mode, Interaction Mode, Introduction, Top ==================== - - -@noindent -Now SML mode provides just a few additional editing commands. Most of -the work has gone into implementing the indentation algorithm which, if -you think about it, has to be complicated for a language like -ML. @xref{SML Mode Defaults,,Indentation Defaults}, for details on how -to control some of the behaviour of the indentation algorithm. Principal -goodies are the `electric pipe' feature, and the ability to insert -common SML forms (macros or templates). - -@menu -* Basics:: On entering SML mode -* Indentation:: Prettying SML text -* Magic Insertion:: Templates and electric keys -* SML Mode Defaults:: Variables controlling indentation -@end menu - - -@c ============================================================== BASICS - -@node Basics, Indentation, SML Mode, SML Mode - -@section On entering SML mode - -@c == Basics, Indentation, SML Mode, SML Mode ========================== - -@noindent - - -@deffn Command sml-mode -This switches a buffer into SML mode. This is a @emph{major mode} in -Emacs. To get out of SML mode the buffer's major mode must be set to -something else, like @t{text-mode}. @xref{Getting Started}, for details -on how to set this up automatically when visiting an SML file. -@end deffn - -Emacs is all hooks of course. A hook is a variable: if the variable is -non-nil it binds a list of Emacs Lisp functions to be run in some order -(usually left to right). You can customise SML mode with these -hooks: - - -@defvr Hook sml-mode-hook -Default: @code{nil} - -This is run every time a new SML mode buffer is created (or if you -type @kbd{M-x sml-mode}). This is one place to put your preferred key -bindings. @xref{Configuration}, for some examples. -@end defvr - - -@c ========================================================= INDENTATION - -@node Indentation, Magic Insertion, Basics, SML Mode - -@section Automatic indentation - -@c == Indentation, Magic Insertion, Basics, SML Mode =================== - - -@noindent -ML is a complicated language to parse, let alone compile. The -indentation algorithm is a little wooden (for some tastes), and the best -advice is not to fight it! There are several variables that can be -adjusted to control the indentation algorithm (@pxref{SML Mode -Defaults,,Customising SML Mode}, below). - - -@deffn Command indent-for-tab-command -Key: @key{TAB} -@kindex @key{TAB} - -This command indents the current line. If you set the indentation of the -previous line by hand, @code{indent-for-tab-command} will indent relative to -this setting. -@end deffn - - -@deffn Command indent-region -Key: @kbd{C-M-\} -@kindex @kbd{C-M-\} - -Indent the current region. Be patient if the region is large (like the -whole buffer). -@end deffn - - -@deffn Command sml-back-to-outer-indent -Key: @kbd{M-@key{TAB}} -@kindex @kbd{M-@key{TAB}} - -Unindents the line to the next outer level of indentation. -@end deffn - - - -Further indentation commands that Emacs provides (generically, for all -modes) that you may like to recall: - -@itemize @minus -@item -@kbd{M-x newline-and-indent} - -On @key{LFD} by default. -@kindex @key{LFD} -Insert a newline, then indent according to the major mode. @xref{Program -Indent,,Indentation for Programs,emacs,The Emacs Editor Manual}, for -details. - -@item -@kbd{M-x indent-rigidly} - -On @kbd{C-x @key{TAB}} by default. -@kindex @kbd{C-x @key{TAB}} -Moves all lines in the region right by its argument (left, for negative -arguments). @xref{Indentation,,,emacs,The Emacs Editor Manual}. - -@item -@kbd{M-x indent-for-comment} - -On @kbd{M-;} by default. -@kindex @kbd{M-;} -Indent this line's comment to comment column, or insert an empty -comment. @xref{Comment Commands,,,emacs,The Emacs Editor -Manual}. - -@item -@kbd{M-x indent-new-comment-line} - -On @kbd{M-@key{LFD}} by default. -@kindex @kbd{M-@key{LFD}} -Break line at point and indent, continuing comment if within one. -@xref{Multi-Line Comments,,,emacs,The Emacs Editor Manual}. -@end itemize - -@kindex @kbd{C-x ;} -As with other language modes, @kbd{M-;} gives you a comment at the end -of the current line. The column where the comment starts is determined -by the variable @code{comment-column}---default is 40, but it can be -changed with @code{set-comment-column} (on @kbd{C-x ;} by default). - - -@c ===================================================== MAGIC INSERTION - -@node Magic Insertion, SML Mode Defaults, Indentation, SML Mode - -@section Electric features - -@c == Magic Insertion, SML Mode Defaults, Indentation, SML Mode ======== - - -@noindent -Electric keys are generally pretty irritating, so those provided by -SML mode are fairly muted. The only truly electric key is @kbd{;}, -and this has to be enabled to take effect. - - -@deffn Command sml-electric-pipe -Key: @kbd{M-|} -@kindex @kbd{M-|} - -When the point is in a `case' statement this opens a new line, indents -and inserts @code{| =>} leaving point just before the double arrow; if -the enclosing construct is a `fun' declaration, the newline is indented -and the function name copied at the appropriate column. Generally, try -it whenever a @code{|} is wanted---you'll like it! -@end deffn - -@deffn Command sml-electric-space -Key: @kbd{M-SPC} -@kindex @kbd{M-SPC} - -When the point is after a keyword like `let', this inserts the -corresponding predefined skeleton if one exists. Else it just inserts a -space. Another way to insert those skeletons is to use -@code{sml-insert-form}, described below. -@end deffn - -@deffn Command sml-electric-semi -Key: @kbd{;} -@kindex @kbd{;} - -Just inserts a semi-colon, usually. The behaviour of this command is -governed by the variable @code{sml-electric-semi-mode}. -@end deffn - - -@defvr Variable sml-electric-semi-mode -Default: @code{nil} - -If this variable is @code{nil}, @code{sml-electric-semi} just inserts a -semi-colon, otherwise it inserts a semi-colon and a newline, and indents -the newline for SML. -@end defvr - - -@deffn Command sml-insert-form -Key: @kbd{C-c @key{RET}} -@kindex @kbd{C-c @key{RET}} - -Interactive short-cut to insert common ML forms (a.k.a.@: macros, or -templates). Recognised forms are `let', `local', `case', `abstype', -`datatype', `signature', `structure', and `functor'. Except for `let' -and `local', these will prompt for appropriate parameters like functor -name and signature, etc.. This command prompts in the mini-buffer, with -completion. - -By default @kbd{C-c @key{RET}} will insert at point, with the -indentation of the current column; if you give a prefix argument (i.e., -@kbd{C-u C-c @key{RET}}) the command will insert a newline first, -indent, and then insert the template. -@end deffn - -@code{sml-insert-form} is also extensible: see @ref{Configuration} for -further details. - - - -@c ======================================================= MODE DEFAULTS - -@node SML Mode Defaults, , Magic Insertion, SML Mode - -@section Indentation defaults - -@c == SML Mode Defaults, , Magic Insertion, SML Mode =================== - - -@noindent -Several variables try to control the indentation algorithm and other -features of SML mode. Most of them are still in flux so they are not -described here yet. -If the default values are not acceptable you can set these variables -permanently in your @file{.emacs} file. @xref{Configuration}, for -details and examples. - - -@defvr Variable sml-indent-level -@findex sml-indent-level -Default: @code{4} - -This variable controls the block indentation level. -@end defvr - -@c end vtable - - -@c ========================================================= INTERACTION - -@node Interaction Mode, Configuration, SML Mode, Top - -@chapter Running ML under Emacs - -@c == Interaction Mode, Configuration, SML Mode, Top =================== - - -@noindent -The most useful feature of SML mode is that it provides a convenient -interface to the compiler. How serious users of ML put up with a -teletype interface to the compiler is beyond me@.@.@. but perhaps there -are other interfaces to compilers that require one to part with serious -money. Such remarks can quickly become dated---in this case, let's hope -so! - -Anyway, SML mode provides an interaction mode, -@code{inferior-sml-mode}, where the compiler runs in a separate buffer -in a window or frame of its own. You can use this buffer just like a -terminal, but it's usually more convenient to mark some text in the -SML mode buffer and have Emacs communicate with the sub-process. The -features discussed below are syntax-independent, so they should work -with a wide range of ML-like tools and compilers. @xref{Process -Defaults}, for some hints. - -@findex inferior-sml-mode -@code{inferior-sml-mode} is a specialisation of the @file{comint} -package that comes with Emacs and XEmacs. - - -@menu -* Running ML:: Commands to run the ML compiler in a buffer -* ML Interaction:: Sending program fragments to the compiler -* Tracking Errors:: Finding reported syntax errors -* Process Defaults:: Setting defaults for process interaction -@end menu - - - -@c ========================================================== RUNNING ML - -@node Running ML, ML Interaction, Interaction Mode, Interaction Mode - -@section Starting the compiler - -@c == Running ML, ML Interaction, Interaction Mode, Interaction Mode == - -@noindent -Start your favourite ML compiler with the command - -@example -@kbd{M-x run-sml} -@end example - -@noindent -This creates a process interaction buffer that inherits some key -bindings from SML mode and from @file{comint} (@pxref{Shell Mode, , -, emacs, The Emacs Editor Manual}). Starting the ML compiler adds some -functions to SML mode buffers so that program text can be -communicated between editor and compiler (@pxref{ML Interaction}). - -The name of the ML compiler is the first thing you should know how to -specify: - - -@defvar sml-program-name -Default: @code{"sml"} - -The program to run as ML. You might need to specify the full path name -of the program. -@end defvar - - -@defvar sml-default-arg -Default: @code{""} - -Useful for Poly/ML users who may supply a database file, or others who -have wrappers for setting various options around the command to run the -compiler. Moscow ML people might set this to @code{"-P full"}, etc.. -@end defvar - -The variable @code{sml-program-name} is a string holding the name -of the program @emph{as you would type it at the shell}. You -can always choose a program different to the default by invoking - -@example -@kbd{C-u M-x run-sml} -@end example - -@noindent -With the prefix argument Emacs will prompt for the command name and any -command line arguments to pass to the compiler. Thereafter Emacs will -use this new name as the default, but for a permanent change you should -set this in your @file{.emacs} with, e.g.: - -@lisp -(setq sml-program-name "nj-sml") -@end lisp - - -@deffn Command run-sml -Launches ML as an inferior process in another buffer; if an ML process -already exists, just switch to the process buffer. A prefix argument -allows you to edit the command line to specify the program, and any -command line options. -@end deffn - - -@defvr Hook inferior-sml-mode-hook -Default: @code{nil} - -@kbd{M-x run-sml} runs @code{comint-mode-hook} and -@code{inferior-sml-mode-hook} hooks in that order, but @emph{after} the -compiler is started. Use @code{inferior-sml-mode-hook} to set any -@code{comint} buffer-local configurations for SML mode you like. -@end defvr - - -@deffn Command switch-to-sml -Key: @kbd{C-c C-s} -@kindex @kbd{C-c C-s} - -Switch from the SML buffer to the interaction buffer. By default point -will be placed at the end of the process buffer, but a prefix argument -will leave point wherever it was before. If you try @kbd{C-c C-s} before -an ML process has been started, you'll just get an error message to the -effect that there's no current process buffer. -@end deffn - - -@deffn Command sml-cd -When started, the ML compiler's default working directory is the -current buffer's default directory. This command allows the working -directory to be changed, if the compiler can do this. The variable -@code{sml-cd-command} specifies the compiler command to invoke -(@pxref{Process Defaults}). -@end deffn - - -@c ======================================================== SENDING TEXT - -@node ML Interaction, Tracking Errors, Running ML, Interaction Mode - -@section Speaking to the compiler - -@c == ML Interaction, Tracking Errors, Running ML, Interaction Mode ==== - - -@noindent -Several commands are defined for sending program fragments to the -running compiler. Each of the following commands takes a prefix argument -that will switch the input focus to the process buffer afterwards -(leaving point at the end of the buffer): - - -@deffn Command sml-load-file -Key: @kbd{C-c C-l} -@kindex @kbd{C-c C-l} - -Send a `use file' command to the current ML process. The variable -@code{sml-use-command} is used to define the correct template for the -command to invoke (@pxref{Process Defaults}). The default file is the -file associated with the current buffer, or the last file loaded if you -are in the interaction buffer. -@end deffn - - - -@deffn Command sml-send-region -@findex sml-send-region-and-go -Key: @kbd{C-c C-r} -@kindex @kbd{C-c C-r} - -Send the current region of text in the SML buffer. -@code{sml-send-region-and-go} is a similar command for you to bind in -SML mode if you wish: it'll send the region and then switch-to-sml. -@end deffn - -@c @deffn Command sml-send-function -@c @findex sml-send-function-and-go - -@c Send the enclosing `function' definition. Contrary to the suggestive -@c name, this command @emph{does not} try to determine the extent of the -@c function definition because that is too difficult with ML. Instead -@c this just sends the enclosing @emph{paragraph} (delimited by blank -@c lines or form-feed characters). -@c @end deffn - -@deffn Command sml-send-buffer -Key: @kbd{C-c C-b} -@kindex @kbd{C-c C-b} - -Send the contents of the current buffer to ML. -@end deffn - -@c ===================================================== TRACKING ERRORS - -@node Tracking Errors, Process Defaults, ML Interaction, Interaction Mode - -@section Finding errors - -@c == Tracking Errors, Process Defaults, ML Interaction, Interaction Mode - - -@noindent -SML mode provides one customisable function for locating the source -position of errors reported by the compiler. This should work whether -you type @code{use "puzzle.sml";} into the interaction buffer, or use -one of the mechanisms provided for sending programs directly to the -compiler---@pxref{ML Interaction}. - - -@deffn Command next-error -@findex next-error -Key: @kbd{C-x`} -@kindex @kbd{C-x`} - -Jump to the source location of the next error reported by the compiler. -All the usual error-navigation commands are available, see -@pxref{Compilation Mode, , , emacs, The Emacs Editor Manual}. -@end deffn - - -@c ==================================================== PROCESS DEFAULTS - -@node Process Defaults, , Tracking Errors, Interaction Mode - -@section Process defaults - -@c == Process Defaults, , Tracking Errors, Interaction Mode ============ - -@noindent -The process interaction code is independent of the compiler used, -deliberately, so SML mode will work with a variety of ML compilers -and ML-based tools. There are therefore a number of variables that may -need to be set correctly before SML mode can speak to the compiler. -Things are by default set up for Standard ML of New Jersey, but -switching to a new system is quite easy. - - - -@defvar sml-use-command -Default: @code{"use \"%s\""} - -Use file command template. Emacs will replace the @code{%s} with a file -name. Note that Emacs requires double quote characters inside strings -to be quoted with a backslash. -@end defvar - - -@defvar sml-cd-command -Default: @code{"OS.FileSys.chDir \"%s\""} - -Compiler command to change the working directory. Not all ML systems -support this feature (well, Edinburgh (core) ML didn't), but they -should. -@end defvar - - -@defvar sml-prompt-regexp -Default: @code{"^[-=>#] *"} - -Matches the ML compiler's prompt: @file{comint} uses this for various -purposes. -@end defvar - - -To customise error reportage for different ML compilers you need to set -two further variables before @code{next-error} can be useful: - - -@defvar sml-error-regexp-alist - -Alist that specifies how to match errors in compiler output. -Each elt has the form (REGEXP FILE-IDX LINE-IDX [COLUMN-IDX FILE-FORMAT...]) -If REGEXP matches, the FILE-IDX'th subexpression gives the file name, and -the LINE-IDX'th subexpression gives the line number. If COLUMN-IDX is -given, the COLUMN-IDX'th subexpression gives the column number on that line. -If any FILE-FORMAT is given, each is a format string to produce a file name to -try; %s in the string is replaced by the text matching the FILE-IDX'th -subexpression. -@end defvar - - -@c A typical way of (re)setting these variables correctly is to put -@c something in your @file{.emacs} file that resembles - -@c @example -@c (setq sml-use-command "PolyML.use \"%s\"") -@c (setq sml-prompt-regexp "^[>#] *") -@c @end example - -@c ======================================================= CONFIGURATION - -@node Configuration, , Interaction Mode, Top - -@chapter Configuration Summary - -@c @footnote{@url{http://www.ahl.co.uk/}} -@c @footnote{@url{http://www.dina.kvl.dk/~sestoft/mosml.html}} - -@noindent -This (sort of pedagogic) section gives more information on how to -configure SML mode: menus, key bindings, hooks and highlighting are -discussed, along with a few other random topics. - -@menu -* Hooks:: Creating them -* Key Bindings:: Binding commands to keys -* Highlighting:: Syntax colouring -* Advanced Topics:: You may need to speak Emacs Lisp -@end menu - - -@c =============================================================== HOOKS - -@node Hooks, Key Bindings, Configuration, Configuration - -@section Hooks - -@c == Hooks, Key Bindings, Configuration, Configuration ================ - - -@noindent -One way to set SML mode variables (@pxref{SML Mode -Defaults,,Indentation Defaults}), and other defaults, is through the -@code{sml-mode-hook} in your @file{.emacs}. A simple example: - -@lisp -(defun my-sml-mode-hook () "Local defaults for SML mode" - (setq sml-indent-level 2) ; conserve on horizontal space - (setq words-include-escape t) ; \ loses word break status - (setq indent-tabs-mode nil)) ; never ever indent with tabs -(add-hook 'sml-mode-hook 'my-sml-mode-hook) -@end lisp -@noindent -The body of @code{my-sml-mode-hook} is a sequence of assignments. In this -case it is not really necessary to set @code{sml-indent-level} in a hook -because this variable is global (most SML mode variables are). With -similar effect: - -@lisp -(setq sml-indent-level 2) -@end lisp -@noindent -anywhere in your @file{.emacs} file. The variable @code{indent-tabs-mode} is -automatically made local to the current buffer whenever it is set -explicitly, so it @emph{must} be set in a hook if you always want -SML mode to behave like this. - -Another hook is @code{inferior-sml-mode-hook}. This can be used to -control the behaviour of the interaction buffer through various -variables meaningful to @file{comint}-based packages: - -@lisp -(defun my-inf-sml-mode-hook () "Local defaults for inferior SML mode" - (add-hook 'comint-output-filter-functions 'comint-truncate-buffer) - (setq comint-scroll-show-maximum-output t) - (setq comint-input-autoexpand nil)) -(add-hook 'inferior-sml-mode-hook 'my-inf-sml-mode-hook) -@end lisp -@noindent -Again, the body is a sequence of assignments. Unless you run several ML -compilers simultaneously under one Emacs, this hook will normally only -get run once. You might want to look up the documentation (@kbd{C-h v} -and @kbd{C-h f}) for these buffer-local @code{comint} things. - - -@c ======================================================== Key Bindings - -@node Key Bindings, Highlighting, Hooks, Configuration - -@section Key bindings - -@noindent -Customisation (in Emacs) usually entails putting favourite commands on -easily remembered keys. Two `keymaps' are defined in SML mode: one -is effective in program text buffers (@code{sml-mode-map}) and the other -is effective in interaction buffers (@code{inferior-sml-mode-map}). -The initial design ensures that (many of) the default key bindings from -the former keymap will also be available in the latter (e.g., -@kbd{C-c`}). - -Type @kbd{C-h m} in an SML mode buffer to find the default key -bindings (and similarly in an ML interaction buffer), and use the hooks -provided to install your preferred key bindings. Given that the keymaps -are global (variables): - -@lisp -(defun my-sml-mode-hook () "Global defaults for SML mode" - (define-key sml-mode-map "\C-cd" 'sml-cd)) -(add-hook 'sml-mode-hook 'my-sml-mode-hook) -@end lisp -@noindent -This has the effect of binding @code{sml-cd} to the key @kbd{C-c d}. -If you want the same behaviour from @kbd{C-c d} in the ML buffer: - -@lisp -(defun my-inf-sml-mode-hook () "Global defaults for inferior SML mode" - (define-key inferior-sml-mode-map "\C-cd" 'sml-cd) - ;; NB. for SML/NJ '96 - (setq sml-cd-command "OS.FileSys.chDir \"%s\"")) -(add-hook 'inferior-sml-mode-hook 'my-inf-sml-mode-hook) -@end lisp - -There is nothing to stop you rebuilding the entire keymap for -SML mode and the ML interaction buffer in your @file{.emacs} of -course: SML mode won't define @code{sml-mode-map} or -@code{inferior-sml-mode-map} if you have already done so. - - -@c ======================================================== Highlighting - -@node Highlighting, Advanced Topics, Key Bindings, Configuration - -@section Syntax colouring - - -@noindent -Highlighting is very handy for picking out keywords in the program text, -spotting misspelled kewyords, and, if you have Emacs' @file{ps-print} -package installed (you usually do these days), obtaining pretty, even -colourful code listings---quite properly for your colourful ML programs. - -The indentation scheme (strangely enough) also relies on the -highlighting code to properly handle nested comments, which is yet -another reason to turn on highlighting. To turn on highlighting, -use either of: - -@lisp -M-x font-lock-mode -(add-hook 'sml-mode-hook 'turn-on-font-lock) -(global-font-lock-mode 1) -@end lisp - -The first will turn it on in the current buffer. -The second will turn it on in all sml-mode buffers. -The last will turn it on everywhere. -This is valid for Emacs but maybe not for XEmacs. Check font-lock -documentation if you encounter problems. - -@c ===================================================== ADVANCED TOPICS - -@node Advanced Topics, , Highlighting, Configuration - -@section Advanced Topics - -@flushright -@emph{These forms are bloody useless; can't we have better ones?} -@end flushright - -@sp 1 -@noindent -You can indeed. @code{sml-insert-form} is extensible so all you need to -do is create the macros yourself. Define a @emph{keybord macro} -(@kbd{C-x (} <something> @kbd{C-x )}) and give it a suitable name: -@code{sml-addto-forms-alist} prompts for a name, say @code{NAME}, and -binds the macro @code{sml-form-NAME}. Thereafter @kbd{C-c @key{RET} -NAME} will insert the macro at point, and @kbd{C-u C-c @key{RET} NAME} -will insert the macro after a @code{newline-and-indent}. If you want to -keep your macros from one editing session to the next, go to your -@file{.emacs} file and call @code{insert-kbd-macro}; you'll need -to add @code{NAME} to @code{sml-forms-alist} permanently yourself: - -@lisp -(defun my-sml-mode-hook () "Global defaults for SML mode" - ;; whatever else you do - (add-to-list 'sml-forms-alist '("NAME" . FUNCTION))) -@end lisp - -If you want to create templates like `case' that prompt for parameters -you'll have to do some Lisp programming. The @code{skeleton} package is -a good stating point. Better yet, you can reuse the wrappers used by -sml-mode itself in your sml-mode-hook: - -@lisp -(add-hook 'sml-mode-hook - (lambda () - (sml-def-skeleton "case" "Case expr: " - str " of" \n _ " => "))) -@end lisp - -This will redefine `case' in order to leave the `of' on the first line. -See the documentation of @code{skeleton-insert} to get a better -understanding of how this works. - -@sp 1 -@flushright -@emph{I hate that indentation algorithm; can't I tweak it?} -@end flushright - -@sp 1 -@noindent -Ah, yes, of course, but this manual will not tell you how. - - -@sp 1 -@flushright -@emph{Can SML mode handle more than one compiler running at once?} -@end flushright - -Sure, just rename the @samp{*sml*} buffer and then use @code{run-sml} -as usual. - -@sp 1 -@flushright -@emph{What needs to be done to support other ML compilers?} -@end flushright - -@sp 1 -@noindent -Not much really. Just add the right regular expressions to -@code{sml-error-regexp-alist} and that should be all. - - -@c ======================================================= COMMAND INDEX - -@headings singleafter - -@node Command Index, Variable Index, , Top - -@unnumbered Command Index - -@printindex fn - -@c ====================================================== VARIABLE INDEX - -@c node Variable Index, , Command Index, Top -@node Variable Index, Key Index, Command Index, Top - -@unnumbered Variable Index - -@c == Variable Index, Key Index, Command Index, Top ==================== - -@printindex vr - -@c =========================================================== KEY INDEX - -@node Key Index, , Variable Index, Top - -@unnumbered Key Index - -@c == Key Index, , Variable Index, Top ================================= - -@printindex ky - -@contents -@bye diff --git a/emacs/emacs.d/sml-mode-5.0/sml-oldindent.el b/emacs/emacs.d/sml-mode-5.0/sml-oldindent.el @@ -1,713 +0,0 @@ -;;; sml-oldindent.el --- Navigation and indentation for SML without SMIE - -;; Copyright (C) 1999,2000,2004,2007,2012 Stefan Monnier <monnier@gnu.org> -;; -;; This program is free software; you can redistribute it and/or modify -;; it under the terms of the GNU General Public License as published by -;; the Free Software Foundation; either version 3 of the License, or -;; (at your option) any later version. -;; -;; This program is distributed in the hope that it will be useful, -;; but WITHOUT ANY WARRANTY; without even the implied warranty of -;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -;; GNU General Public License for more details. -;; -;; You should have received a copy of the GNU General Public License -;; along with this program; if not, write to the Free Software -;; Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - - -;;; Commentary: - - -;;; Code: - -(eval-when-compile (require 'cl)) -(require 'sml-mode) - -(defun sml-preproc-alist (al) - "Expand an alist AL where keys can be lists of keys into a normal one." - (apply #'nconc - (mapcar (lambda (x) - (let ((k (car x)) - (v (cdr x))) - (if (consp k) - (mapcar (lambda (y) (cons y v)) k) - (list x)))) - al))) - -(defconst sml-begin-syms - '("let" "abstype" "local" "struct" "sig") - "Symbols matching the `end' symbol.") - -(defconst sml-begin-syms-re - (sml-syms-re sml-begin-syms) - "Symbols matching the `end' symbol.") - -;; (defconst sml-user-begin-symbols-re -;; (sml-syms-re '("let" "abstype" "local" "struct" "sig" "in" "with")) -;; "Symbols matching (loosely) the `end' symbol.") - -(defconst sml-sexp-head-symbols-re - (sml-syms-re `("let" "abstype" "local" "struct" "sig" "in" "with" - "if" "then" "else" "case" "of" "fn" "fun" "val" "and" - "datatype" "type" "exception" "open" "infix" "infixr" "nonfix" - ,@sml-module-head-syms - "handle" "raise")) - "Symbols starting an sexp.") - -;; (defconst sml-not-arg-start-re -;; (sml-syms-re '("in" "of" "end" "andalso")) -;; "Symbols that can't be found at the head of an arg.") - -;; (defconst sml-not-arg-re -;; (sml-syms-re '("in" "of" "end" "andalso")) -;; "Symbols that should not be confused with an arg.") - -(defconst sml-indent-rule - (sml-preproc-alist - `(("struct" . 0) - (,sml-module-head-syms "d=" 0) - ("local" "in" 0) - ;;("of" . (3 nil)) - ;;("else" . (sml-indent-level 0)) - ;;(("in" "fun" "and" "of") . (sml-indent-level nil)) - ("if" "else" 0) - (,sml-=-starter-syms nil) - (("abstype" "case" "datatype" "if" "then" "else" "sharing" "infix" "infixr" - "let" "local" "nonfix" "open" "raise" "sig" "struct" "type" "val" "while" - "do" "with" "withtype"))))) - -(defconst sml-delegate - (sml-preproc-alist - `((("of" "else" "then" "d=") . (not (sml-bolp))) - ("in" . t))) - "Words which might delegate indentation to their parent.") - -(defcustom sml-symbol-indent - '(("fn" . -3) - ("of" . 1) - ("|" . -2) - ("," . -2) - (";" . -2) - ;;("in" . 1) - ("d=" . 2)) - "Special indentation alist for some symbols. -An entry like (\"in\" . 1) indicates that a line starting with the -symbol `in' should be indented one char further to the right. -This is only used in a few specific cases, so it does not work -for all symbols and in all lines starting with the given symbol." - :group 'sml - :type '(repeat (cons string integer))) - -(defconst sml-open-paren - (sml-preproc-alist - `((,(list* "with" "in" sml-begin-syms) ,sml-begin-syms-re "\\<end\\>"))) - "Symbols that should behave somewhat like opening parens.") - -(defconst sml-close-paren - `(("in" "\\<l\\(ocal\\|et\\)\\>") - ("with" "\\<abstype\\>") - ("withtype" "\\<\\(abs\\|data\\)type\\>") - ("end" ,sml-begin-syms-re) - ("then" "\\<if\\>") - ("else" "\\<if\\>" (sml-bolp)) - ("of" "\\<case\\>") - ("d=" nil)) - "Symbols that should behave somewhat like close parens.") - -(defconst sml-agglomerate-re "\\<else[ \t]+if\\>" - "Regexp of compound symbols (pairs of symbols to be considered as one).") - -(defvar sml-internal-syntax-table - (let ((st (make-syntax-table sml-mode-syntax-table))) - (modify-syntax-entry ?_ "w" st) - (modify-syntax-entry ?' "w" st) - (modify-syntax-entry ?. "w" st) - ;; Treating `~' as a word constituent is not quite right, but - ;; close enough. Think about 12.3E~2 for example. Also `~' on its - ;; own *is* a nonfix symbol. - (modify-syntax-entry ?~ "w" st) - st) - "Syntax table used for internal sml-mode operation.") - -;;; -;;; various macros -;;; - -(defmacro sml-with-ist (&rest r) - (let ((ost-sym (make-symbol "oldtable"))) - `(let ((,ost-sym (syntax-table)) - (case-fold-search nil) - (parse-sexp-lookup-properties t) - (parse-sexp-ignore-comments t)) - (unwind-protect - (progn (set-syntax-table sml-internal-syntax-table) . ,r) - (set-syntax-table ,ost-sym))))) -(def-edebug-spec sml-with-ist t) - -(defmacro sml-move-if (&rest body) - (let ((pt-sym (make-symbol "point")) - (res-sym (make-symbol "result"))) - `(let ((,pt-sym (point)) - (,res-sym ,(cons 'progn body))) - (unless ,res-sym (goto-char ,pt-sym)) - ,res-sym))) -(def-edebug-spec sml-move-if t) - -(defmacro sml-point-after (&rest body) - `(save-excursion - ,@body - (point))) -(def-edebug-spec sml-point-after t) - -;; - -(defvar sml-op-prec - (sml-preproc-alist - '(("before" . 0) - ((":=" "o") . 3) - ((">" ">=" "<>" "<" "<=" "=") . 4) - (("::" "@") . 5) - (("+" "-" "^") . 6) - (("/" "*" "quot" "rem" "div" "mod") . 7))) - "Alist of SML infix operators and their precedence.") - -(defconst sml-syntax-prec - (sml-preproc-alist - `((("in" "with") . 10) - ((";" ",") . 20) - (("=>" "d=" "=of") . (65 . 40)) - ("|" . (47 . 30)) - (("case" "of" "fn") . 45) - (("if" "then" "else" "while" "do" "raise") . 50) - ("handle" . 60) - ("orelse" . 70) - ("andalso" . 80) - ((":" ":>") . 90) - ("->" . 95) - (,(cons "end" sml-begin-syms) . 10000))) - "Alist of pseudo-precedence of syntactic elements.") - -(defun sml-op-prec (op dir) - "Return the precedence of OP or nil if it's not an infix. -DIR should be set to BACK if you want to precedence w.r.t the left side - and to FORW for the precedence w.r.t the right side. -This assumes that we are `looking-at' the OP." - (when op - (let ((sprec (cdr (assoc op sml-syntax-prec)))) - (cond - ((consp sprec) (if (eq dir 'back) (car sprec) (cdr sprec))) - (sprec sprec) - (t - (let ((prec (cdr (assoc op sml-op-prec)))) - (when prec (+ prec 100)))))))) - -;; - -(defun sml-forward-spaces () (forward-comment 100000)) -(defun sml-backward-spaces () (forward-comment -100000)) - - -;; -;; moving forward around matching symbols -;; - -(defun sml-looking-back-at (re) - (save-excursion - (when (= 0 (skip-syntax-backward "w_")) (backward-char)) - (looking-at re))) - -(defun sml-find-match-forward (this match) - "Only works for word matches." - (let ((level 1) - (forward-sexp-function nil) - (either (concat this "\\|" match))) - (while (and (not (eobp)) (> level 0)) - (forward-sexp 1) - (while (not (or (eobp) (sml-looking-back-at either))) - (condition-case () (forward-sexp 1) (error (forward-char 1)))) - (setq level - (cond - ((sml-looking-back-at this) (1+ level)) - ((sml-looking-back-at match) (1- level)) - (t (error "Unbalanced"))))) - t)) - -(defun sml-find-match-backward (this match) - (let ((level 1) - (forward-sexp-function nil) - (either (concat this "\\|" match))) - (while (> level 0) - (backward-sexp 1) - (while (not (or (bobp) (looking-at either))) - (condition-case () (backward-sexp 1) (error (backward-char 1)))) - (setq level - (cond - ((looking-at this) (1+ level)) - ((looking-at match) (1- level)) - (t (error "Unbalanced"))))) - t)) - -;;; -;;; Read a symbol, including the special "op <sym>" case -;;; - -(defmacro sml-move-read (&rest body) - (let ((pt-sym (make-symbol "point"))) - `(let ((,pt-sym (point))) - ,@body - (when (/= (point) ,pt-sym) - (buffer-substring-no-properties (point) ,pt-sym))))) -(def-edebug-spec sml-move-read t) - -(defun sml-poly-equal-p () - (< (sml-point-after (re-search-backward sml-=-starter-re nil 'move)) - (sml-point-after (re-search-backward "=" nil 'move)))) - -(defun sml-nested-of-p () - (< (sml-point-after - (re-search-backward sml-non-nested-of-starter-re nil 'move)) - (sml-point-after (re-search-backward "\\<case\\>" nil 'move)))) - -(defun sml-forward-sym-1 () - (or (/= 0 (skip-syntax-forward "'w_")) - (/= 0 (skip-syntax-forward ".'")))) -(defun sml-forward-sym () - (let ((sym (sml-move-read (sml-forward-sym-1)))) - (cond - ((equal "op" sym) - (sml-forward-spaces) - (concat "op " (or (sml-move-read (sml-forward-sym-1)) ""))) - ((equal sym "=") - (save-excursion - (sml-backward-sym-1) - (if (sml-poly-equal-p) "=" "d="))) - ((equal sym "of") - (save-excursion - (sml-backward-sym-1) - (if (sml-nested-of-p) "of" "=of"))) - ;; ((equal sym "datatype") - ;; (save-excursion - ;; (sml-backward-sym-1) - ;; (sml-backward-spaces) - ;; (if (eq (preceding-char) ?=) "=datatype" sym))) - (t sym)))) - -(defun sml-backward-sym-1 () - (or (/= 0 (skip-syntax-backward ".'")) - (/= 0 (skip-syntax-backward "'w_")))) -(defun sml-backward-sym () - (let ((sym (sml-move-read (sml-backward-sym-1)))) - (when sym - ;; FIXME: what should we do if `sym' = "op" ? - (let ((point (point))) - (sml-backward-spaces) - (if (equal "op" (sml-move-read (sml-backward-sym-1))) - (concat "op " sym) - (goto-char point) - (cond - ((string= sym "=") (if (sml-poly-equal-p) "=" "d=")) - ((string= sym "of") (if (sml-nested-of-p) "of" "=of")) - ;; ((string= sym "datatype") - ;; (save-excursion (sml-backward-spaces) - ;; (if (eq (preceding-char) ?=) "=datatype" sym))) - (t sym))))))) - - -(defun sml-backward-sexp (prec) - "Move one sexp backward if possible, or one char else. -Returns t if the move indeed moved through one sexp and nil if not. -PREC is the precedence currently looked for." - (let ((parse-sexp-lookup-properties t) - (parse-sexp-ignore-comments t)) - (sml-backward-spaces) - (let* ((op (sml-backward-sym)) - (op-prec (sml-op-prec op 'back)) - match) - (cond - ((not op) - (let ((point (point))) - (ignore-errors (let ((forward-sexp-function nil)) (backward-sexp 1))) - (if (/= point (point)) t (ignore-errors (backward-char 1)) nil))) - ;; stop as soon as precedence is smaller than `prec' - ((and prec op-prec (>= prec op-prec)) nil) - ;; special rules for nested constructs like if..then..else - ((and (or (not prec) (and prec op-prec)) - (setq match (second (assoc op sml-close-paren)))) - (sml-find-match-backward (concat "\\<" op "\\>") match)) - ;; don't back over open-parens - ((assoc op sml-open-paren) nil) - ;; infix ops precedence - ((and prec op-prec) (< prec op-prec)) - ;; [ prec = nil ] a new operator, let's skip the sexps until the next - (op-prec (while (sml-move-if (sml-backward-sexp op-prec))) t) - ;; special symbols indicating we're getting out of a nesting level - ((string-match sml-sexp-head-symbols-re op) nil) - ;; if the op was not alphanum, then we still have to do the backward-sexp - ;; this reproduces the usual backward-sexp, but it might be bogus - ;; in this case since !@$% is a perfectly fine symbol - (t t))))) ;(or (string-match "\\sw" op) (sml-backward-sexp prec)) - -(defun sml-forward-sexp (prec) - "Moves one sexp forward if possible, or one char else. -Returns T if the move indeed moved through one sexp and NIL if not." - (let ((parse-sexp-lookup-properties t) - (parse-sexp-ignore-comments t)) - (sml-forward-spaces) - (let* ((op (sml-forward-sym)) - (op-prec (sml-op-prec op 'forw)) - match) - (cond - ((not op) - (let ((point (point))) - (ignore-errors (let ((forward-sexp-function nil)) (forward-sexp 1))) - (if (/= point (point)) t (forward-char 1) nil))) - ;; stop as soon as precedence is smaller than `prec' - ((and prec op-prec (>= prec op-prec)) nil) - ;; special rules for nested constructs like if..then..else - ((and (or (not prec) (and prec op-prec)) - (setq match (cdr (assoc op sml-open-paren)))) - (sml-find-match-forward (first match) (second match))) - ;; don't forw over close-parens - ((assoc op sml-close-paren) nil) - ;; infix ops precedence - ((and prec op-prec) (< prec op-prec)) - ;; [ prec = nil ] a new operator, let's skip the sexps until the next - (op-prec (while (sml-move-if (sml-forward-sexp op-prec))) t) - ;; special symbols indicating we're getting out of a nesting level - ((string-match sml-sexp-head-symbols-re op) nil) - ;; if the op was not alphanum, then we still have to do the backward-sexp - ;; this reproduces the usual backward-sexp, but it might be bogus - ;; in this case since !@$% is a perfectly fine symbol - (t t))))) ;(or (string-match "\\sw" op) (sml-backward-sexp prec)) - -(defun sml-in-word-p () - (and (eq ?w (char-syntax (or (char-before) ? ))) - (eq ?w (char-syntax (or (char-after) ? ))))) - -(defun sml-user-backward-sexp (&optional count) - "Like `backward-sexp' but tailored to the SML syntax." - (interactive "p") - (unless count (setq count 1)) - (sml-with-ist - (let ((point (point))) - (if (< count 0) (sml-user-forward-sexp (- count)) - (when (sml-in-word-p) (forward-word 1)) - (dotimes (i count) - (unless (sml-backward-sexp nil) - (goto-char point) - (error "Containing expression ends prematurely"))))))) - -(defun sml-user-forward-sexp (&optional count) - "Like `forward-sexp' but tailored to the SML syntax." - (interactive "p") - (unless count (setq count 1)) - (sml-with-ist - (let ((point (point))) - (if (< count 0) (sml-user-backward-sexp (- count)) - (when (sml-in-word-p) (backward-word 1)) - (dotimes (i count) - (unless (sml-forward-sexp nil) - (goto-char point) - (error "Containing expression ends prematurely"))))))) - -;;(defun sml-forward-thing () -;; (if (= ?w (char-syntax (char-after))) (forward-word 1) (forward-char 1))) - -(defun sml-backward-arg () (sml-backward-sexp 1000)) -(defun sml-forward-arg () (sml-forward-sexp 1000)) - -(provide 'sml-move) - -(defvar sml-rightalign-and) -(defvar sml-indent-args) -(defvar sml-indent-level) - -(defun sml-indent-line () - "Indent current line of ML code." - (interactive) - (let ((savep (> (current-column) (current-indentation))) - (indent (max (or (ignore-errors (sml-calculate-indentation)) 0) 0))) - (if savep - (save-excursion (indent-line-to indent)) - (indent-line-to indent)))) - -(defun sml-find-comment-indent () - (save-excursion - (let ((depth 1)) - (while (> depth 0) - (if (re-search-backward "(\\*\\|\\*)" nil t) - (cond - ;; FIXME: That's just a stop-gap. - ((eq (get-text-property (point) 'face) 'font-lock-string-face)) - ((looking-at "*)") (incf depth)) - ((looking-at comment-start-skip) (decf depth))) - (setq depth -1))) - (if (= depth 0) - (1+ (current-column)) - nil)))) - -(defun sml-calculate-indentation () - (save-excursion - (beginning-of-line) (skip-chars-forward "\t ") - (sml-with-ist - ;; Indentation for comments alone on a line, matches the - ;; proper indentation of the next line. - (when (looking-at "(\\*") (sml-forward-spaces)) - (let (data - (sym (save-excursion (sml-forward-sym)))) - (or - ;; Allow the user to override the indentation. - (when (looking-at (concat ".*" (regexp-quote comment-start) - "[ \t]*fixindent[ \t]*" - (regexp-quote comment-end))) - (current-indentation)) - - ;; Continued comment. - (and (looking-at "\\*") (sml-find-comment-indent)) - - ;; Continued string ? (Added 890113 lbn) - (and (looking-at "\\\\") - (or (save-excursion (forward-line -1) - (if (looking-at "[\t ]*\\\\") - (current-indentation))) - (save-excursion - (if (re-search-backward "[^\\\\]\"" nil t) - (1+ (current-column)) - 0)))) - - ;; Closing parens. Could be handled below with `sml-indent-relative'? - (and (looking-at "\\s)") - (save-excursion - (skip-syntax-forward ")") - (backward-sexp 1) - (if (sml-dangling-sym) - (sml-indent-default 'noindent) - (current-column)))) - - (and (setq data (assoc sym sml-close-paren)) - (sml-indent-relative sym data)) - - (and (member sym sml-starters-syms) - (sml-indent-starter sym)) - - (and (string= sym "|") (sml-indent-pipe)) - - (sml-indent-arg) - (sml-indent-default)))))) - -(defsubst sml-bolp () - (save-excursion (skip-chars-backward " \t|") (bolp))) - -(defun sml-first-starter-p () - "Non-nil if starter at point is immediately preceded by let/local/in/..." - (save-excursion - (let ((sym (unless (save-excursion (sml-backward-arg)) - (sml-backward-spaces) - (sml-backward-sym)))) - (if (member sym '(";" "d=")) (setq sym nil)) - sym))) - -(defun sml-indent-starter (orig-sym) - "Return the indentation to use for a symbol in `sml-starters-syms'. -Point should be just before the symbol ORIG-SYM and is not preserved." - (let ((sym (unless (save-excursion (sml-backward-arg)) - (sml-backward-spaces) - (sml-backward-sym)))) - (if (member sym '(";" "d=")) (setq sym nil)) - (if sym (sml-get-sym-indent sym) - ;; FIXME: this can take a *long* time !! - (setq sym (sml-old-find-matching-starter sml-starters-syms)) - (if (or (sml-first-starter-p) - ;; Don't align with `and' because it might be specially indented. - (and (or (equal orig-sym "and") (not (equal sym "and"))) - (sml-bolp))) - (+ (current-column) - (if (and sml-rightalign-and (equal orig-sym "and")) - (- (length sym) 3) 0)) - (sml-indent-starter orig-sym))))) - -(defun sml-indent-relative (sym data) - (save-excursion - (sml-forward-sym) (sml-backward-sexp nil) - (unless (second data) (sml-backward-spaces) (sml-backward-sym)) - (+ (or (cdr (assoc sym sml-symbol-indent)) 0) - (sml-delegated-indent)))) - -(defun sml-indent-pipe () - (let ((sym (sml-old-find-matching-starter sml-pipeheads - (sml-op-prec "|" 'back)))) - (when sym - (if (string= sym "|") - (if (sml-bolp) (current-column) (sml-indent-pipe)) - (let ((pipe-indent (or (cdr (assoc "|" sml-symbol-indent)) -2))) - (when (or (member sym '("datatype" "abstype")) - (and (equal sym "and") - (save-excursion - (forward-word 1) - (not (sml-funname-of-and))))) - (re-search-forward "=")) - (sml-forward-sym) - (sml-forward-spaces) - (+ pipe-indent (current-column))))))) - -(defun sml-indent-arg () - (and (save-excursion (ignore-errors (sml-forward-arg))) - ;;(not (looking-at sml-not-arg-re)) - ;; looks like a function or an argument - (sml-move-if (sml-backward-arg)) - ;; an argument - (if (save-excursion (not (sml-backward-arg))) - ;; a first argument - (+ (current-column) sml-indent-args) - ;; not a first arg - (while (and (/= (current-column) (current-indentation)) - (sml-move-if (sml-backward-arg)))) - (unless (save-excursion (sml-backward-arg)) - ;; all earlier args are on the same line - (sml-forward-arg) (sml-forward-spaces)) - (current-column)))) - -(defun sml-get-indent (data sym) - (let (d) - (cond - ((not (listp data)) data) - ((setq d (member sym data)) (cadr d)) - ((and (consp data) (not (stringp (car data)))) (car data)) - (t sml-indent-level)))) - -(defun sml-dangling-sym () - "Non-nil if the symbol after point is dangling. -The symbol can be an SML symbol or an open-paren. \"Dangling\" means that -it is not on its own line but is the last element on that line." - (save-excursion - (and (not (sml-bolp)) - (< (sml-point-after (end-of-line)) - (sml-point-after (or (sml-forward-sym) (skip-syntax-forward "(")) - (sml-forward-spaces)))))) - -(defun sml-delegated-indent () - (if (sml-dangling-sym) - (sml-indent-default 'noindent) - (sml-move-if (backward-word 1) - (looking-at sml-agglomerate-re)) - (current-column))) - -(defun sml-get-sym-indent (sym &optional style) - "Find the indentation for the SYM we're `looking-at'. -If indentation is delegated, point will move to the start of the parent. -Optional argument STYLE is currently ignored." - (assert (equal sym (save-excursion (sml-forward-sym)))) - (save-excursion - (let ((delegate (and (not (equal sym "end")) (assoc sym sml-close-paren))) - (head-sym sym)) - (when (and delegate (not (eval (third delegate)))) - ;;(sml-find-match-backward sym delegate) - (sml-forward-sym) (sml-backward-sexp nil) - (setq head-sym - (if (second delegate) - (save-excursion (sml-forward-sym)) - (sml-backward-spaces) (sml-backward-sym)))) - - (let ((idata (assoc head-sym sml-indent-rule))) - (when idata - ;;(if (or style (not delegate)) - ;; normal indentation - (let ((indent (sml-get-indent (cdr idata) sym))) - (when indent (+ (sml-delegated-indent) indent))) - ;; delgate indentation to the parent - ;;(sml-forward-sym) (sml-backward-sexp nil) - ;;(let* ((parent-sym (save-excursion (sml-forward-sym))) - ;; (parent-indent (cdr (assoc parent-sym sml-indent-starters)))) - ;; check the special rules - ;;(+ (sml-delegated-indent) - ;; (or (sml-get-indent (cdr indent-data) 1 'strict) - ;; (sml-get-indent (cdr parent-indent) 1 'strict) - ;; (sml-get-indent (cdr indent-data) 0) - ;; (sml-get-indent (cdr parent-indent) 0)))))))) - ))))) - -(defun sml-indent-default (&optional noindent) - (let* ((sym-after (save-excursion (sml-forward-sym))) - (_ (sml-backward-spaces)) - (sym-before (sml-backward-sym)) - (sym-indent (and sym-before (sml-get-sym-indent sym-before))) - (indent-after (or (cdr (assoc sym-after sml-symbol-indent)) 0))) - (when (equal sym-before "end") - ;; I don't understand what's really happening here, but when - ;; it's `end' clearly, we need to do something special. - (forward-word 1) - (setq sym-before nil sym-indent nil)) - (cond - (sym-indent - ;; the previous sym is an indentation introducer: follow the rule - (if noindent - ;;(current-column) - sym-indent - (+ sym-indent indent-after))) - ;; If we're just after a hanging open paren. - ((and (eq (char-syntax (preceding-char)) ?\() - (save-excursion (backward-char) (sml-dangling-sym))) - (backward-char) - (sml-indent-default)) - (t - ;; default-default - (let* ((prec-after (sml-op-prec sym-after 'back)) - (prec (or (sml-op-prec sym-before 'back) prec-after 100))) - ;; go back until you hit a symbol that has a lower prec than the - ;; "current one", or until you backed over a sym that has the same prec - ;; but is at the beginning of a line. - (while (and (not (sml-bolp)) - (while (sml-move-if (sml-backward-sexp (1- prec)))) - (not (sml-bolp))) - (while (sml-move-if (sml-backward-sexp prec)))) - (if noindent - ;; the `noindent' case does back over an introductory symbol - ;; such as `fun', ... - (progn - (sml-move-if - (sml-backward-spaces) - (member (sml-backward-sym) sml-starters-syms)) - (current-column)) - ;; Use `indent-after' for cases such as when , or ; should be - ;; outdented so that their following terms are aligned. - (+ (if (progn - (if (equal sym-after ";") - (sml-move-if - (sml-backward-spaces) - (member (sml-backward-sym) sml-starters-syms))) - (and sym-after (not (looking-at sym-after)))) - indent-after 0) - (current-column)))))))) - - -;; maybe `|' should be set to word-syntax in our temp syntax table ? -(defun sml-current-indentation () - (save-excursion - (beginning-of-line) - (skip-chars-forward " \t|") - (current-column))) - - -(defun sml-old-find-matching-starter (syms &optional prec) - (let (sym) - (ignore-errors - (while - (progn (sml-backward-sexp prec) - (setq sym (save-excursion (sml-forward-sym))) - (not (or (member sym syms) (bobp))))) - (if (member sym syms) sym)))) - -(defun sml-old-skip-siblings () - (while (and (not (bobp)) (sml-backward-arg)) - (sml-old-find-matching-starter sml-starters-syms)) - (when (looking-at "in\\>\\|local\\>") - ;; Skip over `local...in' and continue. - (forward-word 1) - (sml-backward-sexp nil) - (sml-old-skip-siblings))) - -(provide 'sml-oldindent) - -;;; sml-oldindent.el ends here diff --git a/emacs/emacs.d/sml-mode-5.0/sml-proc.el b/emacs/emacs.d/sml-mode-5.0/sml-proc.el @@ -1,784 +0,0 @@ -;;; sml-proc.el --- Comint based interaction mode for Standard ML. - -;; Copyright (C) 1999,2000,2003,2004,2005,2007,2012 Stefan Monnier -;; Copyright (C) 1994-1997 Matthew J. Morley -;; Copyright (C) 1989 Lars Bo Nielsen - -;; ==================================================================== - -;; This file is not part of GNU Emacs, but it is distributed under the -;; same conditions. - -;; This program is free software; you can redistribute it and/or -;; modify it under the terms of the GNU General Public License as -;; published by the Free Software Foundation; either version 3, or (at -;; your option) any later version. - -;; This program is distributed in the hope that it will be useful, but -;; WITHOUT ANY WARRANTY; without even the implied warranty of -;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -;; General Public License for more details. - -;; You should have received a copy of the GNU General Public License -;; along with GNU Emacs; see the file COPYING. If not, write to the -;; Free Software Foundation, 675 Mass Ave, Cambridge, MA 0139, USA. -;; (See sml-mode.el for HISTORY.) - -;; ==================================================================== - -;; [MJM 10/94] Separating this from sml-mode means sml-mode will run -;; under 18.59 (or anywhere without comint, if there are such places). -;; See sml-mode.el for further information. - -;;; Commentary: - -;; Inferior-sml-mode is for interacting with an ML process run under -;; emacs. This uses the comint package so you get history, expansion, -;; backup and all the other benefits of comint. Interaction is -;; achieved by M-x run-sml which starts a sub-process under emacs. You may -;; need to set this up for autoloading in your .emacs: - -;; (autoload 'run-sml "sml-proc" "Run an inferior ML process." t) - -;; Exactly what process is governed by the variable sml-program-name -;; -- just "sml" by default. If you give a prefix argument (C-u M-x -;; run-sml) you will be prompted for a different program to execute from -;; the default -- if you just hit RETURN you get the default anyway -- -;; along with the option to specify any command line arguments. Once -;; you select the ML program name in this manner, it remains the -;; default (unless you set in a hook, or otherwise). - -;; NOTE: inferior-sml-mode-hook is run AFTER the ML program has been -;; launched. inferior-sml-load-hook is run only when sml-proc.el is -;; loaded into Emacs. - -;; When running an ML process some further key-bindings are effective -;; in sml-mode buffer(s). C-c C-s (switch-to-sml) will split the -;; screen into two windows if necessary and place you in the ML -;; process buffer. In the interaction buffer, C-c C-s is bound to the -;; `sml' command by default (in case you need to restart). - -;; C-c C-l (sml-load-file) will load an SML source file into the -;; inferior process, C-c C-r (sml-send-region) will send the current -;; region of text to the ML process, etc. Given a prefix argument to -;; these commands will switch you from the SML buffer to the ML -;; process buffer as well as sending the text. If you get errors -;; reported by the compiler, C-x ` (next-error) will step through -;; the errors with you. - -;; NOTE. There is only limited support for this as it obviously -;; depends on the compiler's error messages being recognised by the -;; mode. Error reporting is currently only geared up for SML/NJ, -;; Moscow ML, and Poly/ML. For other compilers, add the relevant -;; regexp to sml-error-regexp-alist and send it to me. - -;; To send pieces of code to the underlying compiler, we never send the text -;; directly but use a temporary file instead. This breaks if the compiler -;; does not understand `use', but has the benefit of allowing better error -;; reporting. - -;; Bugs: - -;; Todo: - -;; - Keep improving `sml-compile'. -;; - ignore warnings (if requested) for next-error - -;;; Code: - -(eval-when-compile (require 'cl)) -(require 'sml-mode) -(require 'comint) -(require 'compile) - -(defgroup sml-proc () - "Interacting with an SML process." - :group 'sml) - -(defcustom sml-program-name "sml" - "Program to run as ML." - :type '(string)) - -(defcustom sml-default-arg "" - "Default command line option to pass, if any." - :type '(string)) - -(defcustom sml-host-name "" - "Host on which to run ML." - :type '(string)) - -(defcustom sml-config-file "~/.smlproc.sml" - "File that should be fed to the ML process when started." - :type '(string)) - -(defcustom sml-compile-command "CM.make()" - "The command used by default by `sml-compile'. -See also `sml-compile-commands-alist'.") - -(defcustom sml-compile-commands-alist - '(("CMB.make()" . "all-files.cm") - ("CMB.make()" . "pathconfig") - ("CM.make()" . "sources.cm") - ("use \"load-all\"" . "load-all")) - "Commands used by default by `sml-compile'. -Each command is associated with its \"main\" file. -It is perfectly OK to associate several files with a command or several -commands with the same file.") - -(defvar inferior-sml-mode-hook nil - "*This hook is run when the inferior ML process is started. -All buffer local customisations for the interaction buffers go here.") - -(defvar sml-error-overlay nil - "*Non-nil means use an overlay to highlight errorful code in the buffer. -The actual value is the name of a face to use for the overlay. -Instead of setting this variable to 'region, you can also simply keep -it NIL and use (transient-mark-mode) which will provide similar -benefits (but with several side effects).") - -(defvar sml-buffer nil - "*The current ML process buffer. - -MULTIPLE PROCESS SUPPORT (Whoever wants multi-process support anyway?) -===================================================================== -`sml-mode' supports, in a fairly simple fashion, running multiple ML -processes. To run multiple ML processes, you start the first up with -\\[sml]. It will be in a buffer named *sml*. Rename this buffer with -\\[rename-buffer]. You may now start up a new process with another -\\[sml]. It will be in a new buffer, named *sml*. You can switch -between the different process buffers with \\[switch-to-buffer]. - -NB *sml* is just the default name for the buffer. It actually gets -it's name from the value of `sml-program-name' -- *poly*, *smld*,... - -If you have more than one ML process around, commands that send text -from source buffers to ML processes -- like `sml-send-function' or -`sml-send-region' -- have to choose a process to send it to. This is -determined by the global variable `sml-buffer'. Suppose you have three -inferior ML's running: - Buffer Process - sml #<process sml> - mosml #<process mosml> - *sml* #<process sml<2>> -If you do a \\[sml-send-function] command on some ML source code, -what process do you send it to? - -- If you're in a process buffer (sml, mosml, or *sml*), you send it to - that process (usually makes sense only to `sml-load-file'). -- If you're in some other buffer (e.g., a source file), you send it to - the process attached to buffer `sml-buffer'. - -This process selection is performed by function `sml-proc' which looks -at the value of `sml-buffer' -- which must be a Lisp buffer object, or -a string \(or nil\). - -Whenever \\[sml] fires up a new process, it resets `sml-buffer' to be -the new process's buffer. If you only run one process, this will do -the right thing. If you run multiple processes, you can change -`sml-buffer' to another process buffer with \\[set-variable], or -use the command \\[sml-buffer] in the interaction buffer of choice.") - - -;;; ALL STUFF THAT DEFAULTS TO THE SML/NJ COMPILER (0.93) - -(defvar sml-use-command "use \"%s\"" - "*Template for loading a file into the inferior ML process. -Set to \"use \\\"%s\\\"\" for SML/NJ or Edinburgh ML; -set to \"PolyML.use \\\"%s\\\"\" for Poly/ML, etc.") - -(defvar sml-cd-command "OS.FileSys.chDir \"%s\"" - "*Command template for changing working directories under ML. -Set this to nil if your compiler can't change directories. - -The format specifier \"%s\" will be converted into the directory name -specified when running the command \\[sml-cd].") - -(defcustom sml-prompt-regexp "^[-=>#] *" - "Regexp used to recognise prompts in the inferior ML process." - :type '(regexp)) - -(defvar sml-error-regexp-alist - `( ;; Poly/ML messages - ("^\\(Error\\|Warning:\\) in '\\(.+\\)', line \\([0-9]+\\)" 2 3) - ;; Moscow ML - ("^File \"\\([^\"]+\\)\", line \\([0-9]+\\)\\(-\\([0-9]+\\)\\)?, characters \\([0-9]+\\)-\\([0-9]+\\):" 1 2 5) - ;; SML/NJ: the file-pattern is anchored to avoid - ;; pathological behavior with very long lines. - ("^[-= ]*\\(.*[^\n)]\\)\\( (.*)\\)?:\\([0-9]+\\)\\.\\([0-9]+\\)\\(-\\([0-9]+\\)\\.\\([0-9]+\\)\\)? \\(Error\\|Warnin\\(g\\)\\): .*" 1 - ,@(if (fboundp 'compilation-fake-loc) ;New compile.el. - '((3 . 6) (4 . 7) (9)) - '(sml-make-error 3 4 6 7))) - ;; SML/NJ's exceptions: see above. - ("^ +\\(raised at: \\)?\\(.+\\):\\([0-9]+\\)\\.\\([0-9]+\\)\\(-\\([0-9]+\\)\\.\\([0-9]+\\)\\)" 2 - ,@(if (fboundp 'compilation-fake-loc) ;New compile.el. - '((3 . 6) (4 . 7)) - '(sml-make-error 3 4 6 7)))) - "Alist that specifies how to match errors in compiler output. -See `compilation-error-regexp-alist' for a description of the format.") - -;; font-lock support -(defconst inferior-sml-font-lock-keywords - `(;; prompt and following interactive command - ;; FIXME: Actually, this should already be taken care of by comint. - (,(concat "\\(" sml-prompt-regexp "\\)\\(.*\\)") - (1 font-lock-prompt-face) - (2 font-lock-command-face keep)) - ;; CM's messages - ("^\\[\\(.*GC #.*\n\\)*.*\\]" . font-lock-comment-face) - ;; SML/NJ's irritating GC messages - ("^GC #.*" . font-lock-comment-face) - ;; error messages - ,@(unless (fboundp 'compilation-fake-loc) - (mapcar (lambda (ra) (cons (car ra) 'font-lock-warning-face)) - sml-error-regexp-alist))) - "Font-locking specification for inferior SML mode.") - -(defface font-lock-prompt-face - '((t (:bold t))) - "Font Lock mode face used to highlight prompts." - :group 'font-lock-highlighting-faces) -(defvar font-lock-prompt-face 'font-lock-prompt-face - "Face name to use for prompts.") - -(defface font-lock-command-face - '((t (:bold t))) - "Font Lock mode face used to highlight interactive commands." - :group 'font-lock-highlighting-faces) -(defvar font-lock-command-face 'font-lock-command-face - "Face name to use for interactive commands.") - -(defconst inferior-sml-font-lock-defaults - '(inferior-sml-font-lock-keywords nil nil nil nil)) - - -;;; CODE - -(defvar inferior-sml-mode-map - (let ((map (make-sparse-keymap))) - (set-keymap-parent map comint-mode-map) - (define-key map "\C-c\C-s" 'run-sml) - (define-key map "\C-c\C-l" 'sml-load-file) - (define-key map "\t" - (if (fboundp 'completion-at-point) - 'completion-at-point 'comint-dynamic-complete)) - map) - "Keymap for inferior-sml mode") - -;; buffer-local - -(defvar sml-temp-file nil) -;;(defvar sml-error-file nil) ; file from which the last error came -(defvar sml-error-cursor nil) ; ditto - -(defun sml-proc-buffer () - "Return the current ML process buffer. -or the current buffer if it is in `inferior-sml-mode'. Raises an error -if the variable `sml-buffer' does not appear to point to an existing -buffer." - (or (and (eq major-mode 'inferior-sml-mode) (current-buffer)) - (and sml-buffer - (let ((buf (get-buffer sml-buffer))) - ;; buffer-name returns nil if the buffer has been killed - (and buf (buffer-name buf) buf))) - ;; no buffer found, make a new one - (save-excursion (call-interactively 'run-sml)))) - -(defun sml-buffer (echo) - "Make the current buffer the current `sml-buffer' if that is sensible. -Lookup variable `sml-buffer' to see why this might be useful. -If prefix argument ECHO is set, then it only reports on the current state." - (interactive "P") - (when (not echo) - (setq sml-buffer - (if (eq major-mode 'inferior-sml-mode) (current-buffer) - (read-buffer "Set ML process buffer to: " nil t)))) - (message "ML process buffer is now %s." - (or (ignore-errors (buffer-name (get-buffer sml-buffer))) - "undefined"))) - -(defun sml-proc () - "Return the current ML process. See variable `sml-buffer'." - (assert (eq major-mode 'inferior-sml-mode)) - (or (get-buffer-process (current-buffer)) - (progn (call-interactively 'run-sml) - (get-buffer-process (current-buffer))))) - -(defun sml-proc-comint-input-filter-function (str) - ;; `compile.el' in Emacs-22 fails to notice that file location info from - ;; errors should be recomputed afresh (without using stale info from - ;; earlier compilations). We used to cause a refresh in sml-send-string, - ;; but this doesn't catch the case when the user types commands directly - ;; at the prompt. - (compilation-forget-errors) ;Has to run before compilation-fake-loc. - (if (and (fboundp 'compilation-fake-loc) sml-temp-file) - (compilation-fake-loc (cdr sml-temp-file) (car sml-temp-file))) - str) - -(defun inferior-sml-next-error-hook () - ;; Try to recognize SML/NJ type error message and to highlight finely the - ;; difference between the two types (in case they're large, it's not - ;; always obvious to spot it). - ;; - ;; Sample messages: - ;; - ;; Data.sml:31.9-33.33 Error: right-hand-side of clause doesn't agree with function result type [tycon mismatch] - ;; expression: Hstring - ;; result type: Hstring * int - ;; in declaration: - ;; des2hs = (fn SYM_ID hs => hs - ;; | SYM_OP hs => hs - ;; | SYM_CHR hs => hs) - ;; Data.sml:35.44-35.63 Error: operator and operand don't agree [tycon mismatch] - ;; operator domain: Hstring * Hstring - ;; operand: (Hstring * int) * (Hstring * int) - ;; in expression: - ;; HSTRING.ieq (h1,h2) - ;; vparse.sml:1861.6-1922.14 Error: case object and rules don't agree [tycon mismatch] - ;; rule domain: STConstraints list list option - ;; object: STConstraints list option - ;; in expression: - (save-current-buffer - (when (and (derived-mode-p 'sml-mode 'inferior-sml-mode) - (boundp 'next-error-last-buffer) - (bufferp next-error-last-buffer) - (set-buffer next-error-last-buffer) - (derived-mode-p 'inferior-sml-mode) - ;; The position of `point' is not guaranteed :-( - (looking-at (concat ".*\\[tycon mismatch\\]\n" - " \\(operator domain\\|expression\\|rule domain\\): +"))) - (ignore-errors (require 'smerge-mode)) - (if (not (fboundp 'smerge-refine-subst)) - (remove-hook 'next-error-hook 'inferior-sml-next-error-hook) - (save-excursion - (let ((b1 (match-end 0)) - e1 b2 e2) - (when (re-search-forward "\n in \\(expression\\|declaration\\):\n" - nil t) - (setq e2 (match-beginning 0)) - (when (re-search-backward - "\n \\(operand\\|result type\\|object\\): +" - b1 t) - (setq e1 (match-beginning 0)) - (setq b2 (match-end 0)) - (smerge-refine-subst b1 e1 b2 e2 - '((face . smerge-refined-change))))))))))) - -(define-derived-mode inferior-sml-mode comint-mode "Inferior-SML" - "Major mode for interacting with an inferior ML process. - -The following commands are available: -\\{inferior-sml-mode-map} - -An ML process can be fired up (again) with \\[sml]. - -Customisation: Entry to this mode runs the hooks on `comint-mode-hook' -and `inferior-sml-mode-hook' (in that order). - -Variables controlling behaviour of this mode are - -`sml-program-name' (default \"sml\") - Program to run as ML. - -`sml-use-command' (default \"use \\\"%s\\\"\") - Template for loading a file into the inferior ML process. - -`sml-cd-command' (default \"System.Directory.cd \\\"%s\\\"\") - ML command for changing directories in ML process (if possible). - -`sml-prompt-regexp' (default \"^[\\-=] *\") - Regexp used to recognise prompts in the inferior ML process. - -You can send text to the inferior ML process from other buffers containing -ML source. - `switch-to-sml' switches the current buffer to the ML process buffer. - `sml-send-function' sends the current *paragraph* to the ML process. - `sml-send-region' sends the current region to the ML process. - - Prefixing the sml-send-<whatever> commands with \\[universal-argument] - causes a switch to the ML process buffer after sending the text. - -For information on running multiple processes in multiple buffers, see -documentation for variable `sml-buffer'. - -Commands: -RET after the end of the process' output sends the text from the - end of process to point. -RET before the end of the process' output copies the current line - to the end of the process' output, and sends it. -DEL converts tabs to spaces as it moves back. -TAB file name completion, as in shell-mode, etc.." - (setq comint-prompt-regexp sml-prompt-regexp) - (sml-mode-variables) - - ;; We have to install it globally, 'cause it's run in the *source* buffer :-( - (add-hook 'next-error-hook 'inferior-sml-next-error-hook) - - ;; Make TAB add a " rather than a space at the end of a file name. - (set (make-local-variable 'comint-completion-addsuffix) '(?/ . ?\")) - (add-hook 'comint-input-filter-functions - 'sml-proc-comint-input-filter-function nil t) - - (set (make-local-variable 'font-lock-defaults) - inferior-sml-font-lock-defaults) - ;; For sequencing through error messages: - (set (make-local-variable 'sml-error-cursor) (point-max-marker)) - (set-marker-insertion-type sml-error-cursor nil) - - ;; Compilation support (used for `next-error'). - ;; The keymap of compilation-minor-mode is too unbearable, so we - ;; just can't use the minor-mode if we can't override the map. - (when (boundp 'minor-mode-overriding-map-alist) - (set (make-local-variable 'compilation-error-regexp-alist) - sml-error-regexp-alist) - (compilation-minor-mode 1) - ;; Eliminate compilation-minor-mode's map. - (let ((map (make-sparse-keymap))) - (dolist (keys '([menu-bar] [follow-link])) - ;; Preserve some of the bindings. - (define-key map keys (lookup-key compilation-minor-mode-map keys))) - (add-to-list 'minor-mode-overriding-map-alist - (cons 'compilation-minor-mode map))) - ;; I'm sure people might kill me for that - (setq compilation-error-screen-columns nil) - (make-local-variable 'sml-endof-error-alist)) - ;;(make-local-variable 'sml-error-overlay) - - (setq mode-line-process '(": %s"))) - -;;; FOR RUNNING ML FROM EMACS - -;;;###autoload -(autoload 'run-sml "sml-proc" nil t) -(defalias 'run-sml 'sml-run) -(defun sml-run (cmd arg &optional host) - "Run the program CMD with given arguments ARG. -The command is run in buffer *CMD* using mode `inferior-sml-mode'. -If the buffer already exists and has a running process, then -just go to this buffer. - -This updates `sml-buffer' to the new buffer. -You can have several inferior M(or L process running, but only one (> s -current one -- given by `sml-buffer' (qv). - -If a prefix argument is used, the user is also prompted for a HOST -on which to run CMD using `remote-shell-program'. - -\(Type \\[describe-mode] in the process buffer for a list of commands.)" - (interactive - (list - (read-string "ML command: " sml-program-name) - (if (or current-prefix-arg (> (length sml-default-arg) 0)) - (read-string "Any args: " sml-default-arg) - sml-default-arg) - (if (or current-prefix-arg (> (length sml-host-name) 0)) - (read-string "On host: " sml-host-name) - sml-host-name))) - (let* ((pname (file-name-nondirectory cmd)) - (args (if (equal arg "") () (split-string arg))) - (file (when (and sml-config-file (file-exists-p sml-config-file)) - sml-config-file))) - ;; and this -- to keep these as defaults even if - ;; they're set in the mode hooks. - (setq sml-program-name cmd) - (setq sml-default-arg arg) - (setq sml-host-name host) - ;; For remote execution, use `remote-shell-program' - (when (> (length host) 0) - (setq args (list* host "cd" default-directory ";" cmd args)) - (setq cmd remote-shell-program)) - ;; go for it - (let ((exec-path (if (file-name-directory cmd) - ;; If the command has slashes, make sure we - ;; first look relative to the current directory. - ;; Emacs-21 does it for us, but not Emacs-20. - (cons default-directory exec-path) exec-path))) - (setq sml-buffer (apply 'make-comint pname cmd file args))) - - (pop-to-buffer sml-buffer) - ;;(message (format "Starting \"%s\" in background." pname)) - (inferior-sml-mode) - (goto-char (point-max)) - sml-buffer)) - -(defun switch-to-sml (eobp) - "Switch to the ML process buffer. -Move point to the end of buffer unless prefix argument EOBP is set." - (interactive "P") - (pop-to-buffer (sml-proc-buffer)) - (unless eobp - (push-mark (point) t) - (goto-char (point-max)))) - -;; Fakes it with a "use <temp-file>;" if necessary. - -(defun sml-send-region (start end &optional and-go) - "Send current region START..END to the inferior ML process. -Prefix AND-GO argument means switch-to-sml afterwards. - -The region is written out to a temporary file and a \"use <temp-file>\" command -is sent to the compiler. -See variables `sml-use-command'." - (interactive "r\nP") - (if (= start end) - (message "The region is zero (ignored)") - (let* ((buf (sml-proc-buffer)) - (marker (copy-marker start)) - (tmp (make-temp-file "sml"))) - (write-region start end tmp nil 'silently) - (with-current-buffer buf - (when sml-temp-file - (ignore-errors (delete-file (car sml-temp-file))) - (set-marker (cdr sml-temp-file) nil)) - (setq sml-temp-file (cons tmp marker)) - (sml-send-string (format sml-use-command tmp) nil and-go))))) - -;; This is quite bogus, so it isn't bound to a key by default. -;; Anyone coming up with an algorithm to recognise fun & local -;; declarations surrounding point will do everyone a favour! - -(defun sml-send-function (&optional and-go) - "Send current paragraph to the inferior ML process. -With a prefix argument AND-GO switch to the sml buffer as well -\(cf. `sml-send-region'\)." - (interactive "P") - (save-excursion - (sml-mark-function) - (sml-send-region (point) (mark))) - (if and-go (switch-to-sml nil))) - -(defvar sml-source-modes '(sml-mode) - "*Used to determine if a buffer contains ML source code. -If it's loaded into a buffer that is in one of these major modes, it's -considered an ML source file by `sml-load-file'. Used by these commands -to determine defaults.") - -(defun sml-send-buffer (&optional and-go) - "Send buffer to inferior shell running ML process. -With a prefix argument AND-GO switch to the sml buffer as well -\(cf. `sml-send-region'\)." - (interactive "P") - (if (memq major-mode sml-source-modes) - (sml-send-region (point-min) (point-max) and-go))) - -;; Since sml-send-function/region take an optional prefix arg, these -;; commands are redundant. But they are kept around for the user to -;; bind if she wishes, since its easier to type C-c r than C-u C-c C-r. - -(defun sml-send-region-and-go (start end) - "Send current region START..END to the inferior ML process, and go there." - (interactive "r") - (sml-send-region start end t)) - -(defun sml-send-function-and-go () - "Send current paragraph to the inferior ML process, and go there." - (interactive) - (sml-send-function t)) - -;;; LOADING AND IMPORTING SOURCE FILES: - -(defvar sml-prev-dir/file nil - "Cache for (DIRECTORY . FILE) pair last. -Set in `sml-load-file' and `sml-cd' commands. -Used to determine the default in the next `ml-load-file'.") - -(defun sml-load-file (&optional and-go) - "Load an ML file into the current inferior ML process. -With a prefix argument AND-GO switch to sml buffer as well. - -This command uses the ML command template `sml-use-command' to construct -the command to send to the ML process\; a trailing \"\;\\n\" will be added -automatically." - (interactive "P") - (let ((file (car (comint-get-source - "Load ML file: " sml-prev-dir/file sml-source-modes t)))) - (with-current-buffer (sml-proc-buffer) - ;; Check if buffer needs saved. Should (save-some-buffers) instead? - (comint-check-source file) - (setq sml-prev-dir/file - (cons (file-name-directory file) (file-name-nondirectory file))) - (sml-send-string (format sml-use-command file) nil and-go)))) - -(defun sml-cd (dir) - "Change the working directory of the inferior ML process. -The default directory of the process buffer is changed to DIR. If the -variable `sml-cd-command' is non-nil it should be an ML command that will -be executed to change the compiler's working directory\; a trailing -\"\;\\n\" will be added automatically." - (interactive "DSML Directory: ") - (let ((dir (expand-file-name dir))) - (with-current-buffer (sml-proc-buffer) - (sml-send-string (format sml-cd-command dir) t) - (setq default-directory dir)) - (setq sml-prev-dir/file (cons dir nil)))) - -(defun sml-send-string (str &optional print and-go) - (let ((proc (sml-proc)) - (str (concat str ";\n")) - (win (get-buffer-window (current-buffer) 'visible))) - (when win (select-window win)) - (goto-char (point-max)) - (when print (insert str)) - (sml-update-cursor) - (set-marker (process-mark proc) (point-max)) - (setq compilation-last-buffer (current-buffer)) - (comint-send-string proc str) - (when and-go (switch-to-sml nil)))) - -(defun sml-compile (command &optional and-go) - "Pass a COMMAND to the SML process to compile the current program. - -You can then use the command \\[next-error] to find the next error message -and move to the source code that caused it. - -Interactively, prompts for the command if `compilation-read-command' is -non-nil. With prefix arg, always prompts. - -Prefix arg AND-GO also means to `switch-to-sml' afterwards." - (interactive - (let* ((dir default-directory) - (cmd "cd \".")) - ;; look for files to determine the default command - (while (and (stringp dir) - (dolist (cf sml-compile-commands-alist 1) - (when (file-exists-p (expand-file-name (cdr cf) dir)) - (setq cmd (concat cmd "\"; " (car cf))) (return nil)))) - (let ((newdir (file-name-directory (directory-file-name dir)))) - (setq dir (unless (equal newdir dir) newdir)) - (setq cmd (concat cmd "/..")))) - (setq cmd - (cond - ((local-variable-p 'sml-compile-command) sml-compile-command) - ((string-match "^\\s-*cd\\s-+\"\\.\"\\s-*;\\s-*" cmd) - (substring cmd (match-end 0))) - ((string-match "^\\s-*cd\\s-+\"\\(\\./\\)" cmd) - (replace-match "" t t cmd 1)) - ((string-match ";" cmd) cmd) - (t sml-compile-command))) - ;; code taken from compile.el - (if (or compilation-read-command current-prefix-arg) - (list (read-from-minibuffer "Compile command: " - cmd nil nil '(compile-history . 1))) - (list cmd)))) - ;; ;; now look for command's file to determine the directory - ;; (setq dir default-directory) - ;; (while (and (stringp dir) - ;; (dolist (cf sml-compile-commands-alist t) - ;; (when (and (equal cmd (car cf)) - ;; (file-exists-p (expand-file-name (cdr cf) dir))) - ;; (return nil)))) - ;; (let ((newdir (file-name-directory (directory-file-name dir)))) - ;; (setq dir (unless (equal newdir dir) newdir)))) - ;; (setq dir (or dir default-directory)) - ;; (list cmd dir))) - (set (make-local-variable 'sml-compile-command) command) - (save-some-buffers (not compilation-ask-about-save) nil) - (let ((dir default-directory)) - (when (string-match "^\\s-*cd\\s-+\"\\([^\"]+\\)\"\\s-*;" command) - (setq dir (match-string 1 command)) - (setq command (replace-match "" t t command))) - (setq dir (expand-file-name dir)) - (with-current-buffer (sml-proc-buffer) - (setq default-directory dir) - (sml-send-string (concat (format sml-cd-command dir) "; " command) - t and-go)))) - -;;; PARSING ERROR MESSAGES - -;; This should need no modification to support other compilers. - -;; Update the buffer-local error-cursor in proc-buffer to be its -;; current proc mark. - -(defvar sml-endof-error-alist nil) - -(defun sml-update-cursor () - ;; Update buffer local variable. - (set-marker sml-error-cursor (1- (process-mark (sml-proc)))) - (setq sml-endof-error-alist nil) - ;; This is now done in comint-input-filter-functions. - ;; (compilation-forget-errors) ;Has to run before compilation-fake-loc. - ;; (if (and (fboundp 'compilation-fake-loc) sml-temp-file) - ;; (compilation-fake-loc (cdr sml-temp-file) (car sml-temp-file))) - (if (markerp compilation-parsing-end) - (set-marker compilation-parsing-end sml-error-cursor) - (setq compilation-parsing-end sml-error-cursor))) - -(defun sml-make-error (f c) - (let ((err (point-marker)) - (linenum (string-to-number c)) - (filename (list (first f) (second f))) - (column (string-to-number (match-string (third f))))) - ;; record the end of error, if any - (when (fourth f) - (let ((endlinestr (match-string (fourth f)))) - (when endlinestr - (let* ((endline (string-to-number endlinestr)) - (endcol (string-to-number - (or (match-string (fifth f)) "0"))) - (linediff (- endline linenum))) - (push (list err linediff (if (= 0 linediff) (- endcol column) endcol)) - sml-endof-error-alist))))) - ;; build the error descriptor - (if (string= (car sml-temp-file) (first f)) - ;; special case for code sent via sml-send-region - (let ((marker (cdr sml-temp-file))) - (with-current-buffer (marker-buffer marker) - (goto-char marker) - (forward-line (1- linenum)) - (forward-char (1- column)) - ;; A pair of markers is the right thing to return, but some - ;; code in compile.el doesn't like it (when we reach the end - ;; of the errors). So we could try to avoid it, but we don't - ;; because that doesn't work correctly if the current buffer - ;; has unsaved modifications. And it's fixed in Emacs-21. - ;; (if buffer-file-name - ;; (list err buffer-file-name - ;; (count-lines (point-min) (point)) (current-column)) - (cons err (point-marker)))) ;; ) - ;; taken from compile.el - (list err filename linenum column)))) - -(unless (fboundp 'compilation-fake-loc) -(defadvice compilation-goto-locus (after sml-endof-error activate) - (let* ((next-error (ad-get-arg 0)) - (err (car next-error)) - (pos (cdr next-error)) - (endof (with-current-buffer (marker-buffer err) - (assq err sml-endof-error-alist)))) - (if (not endof) (sml-error-overlay 'undo) - (with-current-buffer (marker-buffer pos) - (goto-char pos) - (let ((linediff (second endof)) - (coldiff (third endof))) - (when (> 0 linediff) (forward-line linediff)) - (forward-char coldiff)) - (sml-error-overlay nil pos (point)) - (push-mark nil t (not sml-error-overlay)) - (goto-char pos)))))) - -(defun sml-error-overlay (undo &optional beg end) - "Move `sml-error-overlay' to the text region in the current buffer. -If the buffer-local variable `sml-error-overlay' is -non-nil it should be an overlay \(or extent, in XEmacs speak\)\; this -function moves the overlay over the current region. If the optional -BUFFER argument is given, move the overlay in that buffer instead of -the current buffer. - -Called interactively, the optional prefix argument UNDO indicates that -the overlay should simply be removed: \\[universal-argument] \ -\\[sml-error-overlay]." - (interactive "P") - (when sml-error-overlay - (unless (overlayp sml-error-overlay) - (let ((ol sml-error-overlay)) - (setq sml-error-overlay (make-overlay (point) (point))) - (overlay-put sml-error-overlay 'face (if (symbolp ol) ol 'region)))) - (if undo (delete-overlay sml-error-overlay) - ;; If active regions, signals mark not active if no region set. - (move-overlay sml-error-overlay - (or beg (region-beginning)) (or end (region-end)) - (current-buffer))))) - -(provide 'sml-proc) - -;;; sml-proc.el ends here diff --git a/emacs/emacs.d/sml-mode-5.0/testcases.sml b/emacs/emacs.d/sml-mode-5.0/testcases.sml @@ -1,563 +0,0 @@ -(* Copyright 1999,2004,2007,2010-2012 Stefan Monnier <monnier@gnu.org> *) - -(* sml-mode here treats the second `=' as an equal op because it - * thinks it's seeing something like "... type t = (s.t = ...)". FIXME! *) -functor foo (structure s : S) where type t = s.t = -struct (* fixindent *) -val bar = fn a1 a2 a3 - a5 a6 - a4 => 1 -val rec bar = - fn a1 a2 a3 - a5 a6 a4 => 1 -val bar = - fn a1 a2 a3 - a5 a6 - a4 => (1 - ;( - w - , - s - , - s - , s , a , - a - , s , a , - a - ) - ;( - w - ,s - ,a - ) - ;( - w - , s - , a - ) - ;( w - , s - , a - ) - ;( w - ,s - ,a - ) - ;3 - + a - * 4 - + let val x = 3 - in toto - end - + if a then - b - else - c - ;4) - -val ber = 1; -val sdfg = 1 -val tut = fn (x,y) z y e r => - body -val tut = fn (x,y) => fn z y => fn e r => - body -val tut = fn (x,y) - z - y e - r => - body -val tut = - (let - local - val x = 1 in val x = x end - val a = 1 val b = 2 - local val x = 1 in val x = x end - local val x = 1 in val x = x end - local val x = 1 in val x = x end (* fixindent *) - local val x = 1 in val x = x end - val c = 3 - in - let - val x = 3 - in - x + a * b - * c - end - end) - -val x = - (* From "Christopher Dutchyn" <cdutchyn@cs.ubc.ca> *) - (case foo of - (* This is actually not valid SML anyway. *) - | BAR => baz - | BAR => baz) - - -val x = - (x := 1; - x := 2; - (* Testing obedience to user overrides: *) - x := 3; (* fixindent *) - case x of - FOO => 1 - | BAR => - 2; - case x of - FOO => 1 - | BAR => - case y of - FAR => 2 - | FRA => 3; - hello); - -datatype foobar - = FooB of int - | FooA of bool * int -datatype foo = FOO | BAR of baz - and baz = BAZ | QUUX of foo - -fun toto = if a - then - b - else c - -datatype foo = FOO - | BAR of baz - and baz = BAZ (* fixindent *) - | QUUX of foo - and b = g - -datatype foo = datatype M.foo -val _ = 42 val x = 5 - -signature S = S' where type foo = int -val _ = 42 - -val foo = [ - "blah" - , let val x = f 42 in g (x,x,44) end -] - -val foo = [ - "blah", - let val x = f 42 in g (x,x,44) end -] - -val foo = - [ - "blah", - let val x = f 42 in g (x,x,44) end - ] - -val foo = [ "blah" - , let val x = f 42 in g (x,x,44) end - , foldl (fn ((p,q),s) => g (p,q,Vector.length q) ^ ":" ^ s) - "" (Beeblebrox.masterCountList mlist2) - , if null mlist2 then ";" else "" - ] - -fun foo (true::rest) = 1 + 2 * foo rest - | foo (false::rest) - = let val _ = 1 in 2 end - + 2 - * foo rest - -val x = if foo then - 1 - else if bar then - 2 - else - 3 -val y = if foo - then 1 - else if foo - then 2 (* Could also be indented by a basic offset. *) - else 3 - -val yt = 4 - -val x = - (if a then b else c; - case M.find(m,f) - of SOME(fl, filt) => - F.APP(F.VAR fl, OU.filter filt vs) - | NONE - => le - | NONE => - le - | NONE => le; - x := x + 1; - (case foo - of a => f - )) - -val y = ( - let fun f1 = - let fun g1 x = 2 - fun g2 y = 4 - local fun toto y = 1 - (* val x = 5 *) - in - fun g3 z = z - end - in toto - end - in a;( ( let - val f =1 - in - toto - end - ) - ) - foo("(*") - * 2; - end; - - let - in a - ; b - end; - - let - in - a + - b + - c - ; b - end; - - let - in if a then - b - else - c - end; - - let - in case a of - F => 1 - | D => 2 - end; - - let - in case a - of F => 1 - | D => 2 - end; - - let - in if a then b else - c - end; - - let - in if a then b - else - c - end) -end; - -structure Foo = struct -val x = 1 -end - -structure Foo = struct val x = 1 - end - -signature FSPLIT = -sig - type flint = FLINT.prog - val split: flint -> flint * flint option -end - -structure FSplit :> FSPLIT = -struct - -local - structure F = FLINT - structure S = IntRedBlackSet - structure M = FLINTIntMap - structure O = Option - structure OU = OptUtils - structure FU = FlintUtil - structure LT = LtyExtern - structure PO = PrimOp - structure PP = PPFlint - structure CTRL = FLINT_Control -in - -val say = Control_Print.say -fun bug msg = ErrorMsg.impossible ("FSplit: "^msg) -fun buglexp (msg,le) = (say "\n"; PP.printLexp le; say " "; bug msg) -fun bugval (msg,v) = (say "\n"; PP.printSval v; say " "; bug msg) -fun assert p = if p then () else bug ("assertion failed") - -type flint = F.prog -val mklv = LambdaVar.mkLvar -val cplv = LambdaVar.dupLvar - -fun S_rmv(x, s) = S.delete(s, x) handle NotFound => s - -fun addv (s,F.VAR lv) = S.add(s, lv) - | addv (s,_) = s -fun addvs (s,vs) = foldl (fn (v,s) => addv(s, v)) s vs -fun rmvs (s,lvs) = foldl (fn (l,s) => S_rmv(l, s)) s lvs - -exception Unknown - -fun split (fdec as (fk,f,args,body)) = let - val {getLty,addLty,...} = Recover.recover (fdec, false) - - val m = Intmap.new(64, Unknown) - fun addpurefun f = Intmap.add m (f, false) - fun funeffect f = (Intmap.map m f) handle Uknown => true - -(* sexp: env -> lexp -> (leE, leI, fvI, leRet) - * - env: IntSetF.set current environment - * - lexp: lexp expression to split - * - leRet: lexp the core return expression of lexp - * - leE: lexp -> lexp recursively split lexp: leE leRet == lexp - * - leI: lexp option inlinable part of lexp (if any) - * - fvI: IntSetF.set free variables of leI: FU.freevars leI == fvI - * - * sexp splits the lexp into an expansive part and an inlinable part. - * The inlinable part is guaranteed to be side-effect free. - * The expansive part doesn't bother to eliminate unused copies of - * elements copied to the inlinable part. - * If the inlinable part cannot be constructed, leI is set to F.RET[]. - * This implies that fvI == S.empty, which in turn prevents us from - * mistakenly adding anything to leI. - *) -fun sexp env lexp = (* fixindent *) - let - (* non-side effecting binds are copied to leI if exported *) - fun let1 (le,lewrap,lv,vs,effect) = - let val (leE,leI,fvI,leRet) = sexp (S.add(env, lv)) le - val leE = lewrap o leE - in if effect orelse not (S.member(fvI, lv)) - then (leE, leI, fvI, leRet) - else (leE, lewrap leI, addvs(S_rmv(lv, fvI), vs), leRet) - end - - in case lexp - (* we can completely move both RET and TAPP to the I part *) - of F.RECORD (rk,vs,lv,le as F.RET [F.VAR lv']) => - if lv' = lv - then (fn e => e, lexp, addvs(S.empty, vs), lexp) - else (fn e => e, le, S.singleton lv', le) - | F.RET vs => - (fn e => e, lexp, addvs(S.empty, vs), lexp) - | F.TAPP (F.VAR tf,tycs) => - (fn e => e, lexp, S.singleton tf, lexp) - - (* recursive splittable lexps *) - | F.FIX (fdecs,le) => sfix env (fdecs, le) - | F.TFN (tfdec,le) => stfn env (tfdec, le) - - (* binding-lexps *) - | F.CON (dc,tycs,v,lv,le) => - let1(le, fn e => F.CON(dc, tycs, v, lv, e), lv, [v], false) - | F.RECORD (rk,vs,lv,le) => - let1(le, fn e => F.RECORD(rk, vs, lv, e), lv, vs, false) - | F.SELECT (v,i,lv,le) => - let1(le, fn e => F.SELECT(v, i, lv, e), lv, [v], false) - | F.PRIMOP (po,vs,lv,le) => - let1(le, fn e => F.PRIMOP(po, vs, lv, e), lv, vs, PO.effect(#2 po)) - - (* IMPROVEME: lvs should not be restricted to [lv] *) - | F.LET(lvs as [lv],body as F.TAPP (v,tycs),le) => - let1(le, fn e => F.LET(lvs, body, e), lv, [v], false) - | F.LET (lvs as [lv],body as F.APP (v as F.VAR f,vs),le) => - let1(le, fn e => F.LET(lvs, body, e), lv, v::vs, funeffect f) - - | F.SWITCH (v,ac,[(dc as F.DATAcon(_,_,lv),le)],NONE) => - let1(le, fn e => F.SWITCH(v, ac, [(dc, e)], NONE), lv, [v], false) - - | F.LET (lvs,body,le) => - let val (leE,leI,fvI,leRet) = sexp (S.union(S.addList(S.empty, lvs), env)) le - in (fn e => F.LET(lvs, body, leE e), leI, fvI, leRet) - end - - (* useless sophistication *) - | F.APP (F.VAR f,args) => - if funeffect f - then (fn e => e, F.RET[], S.empty, lexp) - else (fn e => e, lexp, addvs(S.singleton f, args), lexp) - - (* other non-binding lexps result in unsplittable functions *) - | (F.APP _ | F.TAPP _) => bug "strange (T)APP" - | (F.SWITCH _ | F.RAISE _ | F.BRANCH _ | F.HANDLE _) => - (fn e => e, F.RET[], S.empty, lexp) - end - -(* Functions definitions fall into the following categories: - * - inlinable: if exported, copy to leI - * - (mutually) recursive: don't bother - * - non-inlinable non-recursive: split recursively *) -and sfix env (fdecs,le) = - let val nenv = S.union(S.addList(S.empty, map #2 fdecs), env) - val (leE,leI,fvI,leRet) = sexp nenv le - val nleE = fn e => F.FIX(fdecs, leE e) - in case fdecs - of [({inline=inl as (F.IH_ALWAYS | F.IH_MAYBE _),...},f,args,body)] => - let val min = case inl of F.IH_MAYBE(n,_) => n | _ => 0 - in if not(S.member(fvI, f)) orelse min > !CTRL.splitThreshold - then (nleE, leI, fvI, leRet) - else (nleE, F.FIX(fdecs, leI), - rmvs(S.union(fvI, FU.freevars body), - f::(map #1 args)), - leRet) - end - | [fdec as (fk as {cconv=F.CC_FCT,...},_,_,_)] => - sfdec env (leE,leI,fvI,leRet) fdec - - | _ => (nleE, leI, fvI, leRet) - end - -and sfdec env (leE,leI,fvI,leRet) (fk,f,args,body) = - let val benv = S.union(S.addList(S.empty, map #1 args), env) - val (bodyE,bodyI,fvbI,bodyRet) = sexp benv body - in case bodyI - of F.RET[] => - (fn e => F.FIX([(fk, f, args, bodyE bodyRet)], e), - leI, fvI, leRet) - | _ => - let val fvbIs = S.listItems(S.difference(fvbI, benv)) - val (nfk,fkE) = OU.fk_wrap(fk, NONE) - - (* fdecE *) - val fE = cplv f - val fErets = (map F.VAR fvbIs) - val bodyE = bodyE(F.RET fErets) - (* val tmp = mklv() - val bodyE = bodyE(F.RECORD(F.RK_STRUCT, map F.VAR fvbIs, - tmp, F.RET[F.VAR tmp])) *) - val fdecE = (fkE, fE, args, bodyE) - val fElty = LT.ltc_fct(map #2 args, map getLty fErets) - val _ = addLty(fE, fElty) - - (* fdecI *) - val fkI = {inline=F.IH_ALWAYS, cconv=F.CC_FCT, - known=true, isrec=NONE} - val argsI = - (map (fn lv => (lv, getLty(F.VAR lv))) fvbIs) @ args - val fdecI as (_,fI,_,_) = FU.copyfdec(fkI,f,argsI,bodyI) - val _ = addpurefun fI - - (* nfdec *) - val nargs = map (fn (v,t) => (cplv v, t)) args - val argsv = map (fn (v,t) => F.VAR v) nargs - val nbody = - let val lvs = map cplv fvbIs - in F.LET(lvs, F.APP(F.VAR fE, argsv), - F.APP(F.VAR fI, (map F.VAR lvs)@argsv)) - end - (* let val lv = mklv() - in F.LET([lv], F.APP(F.VAR fE, argsv), - F.APP(F.VAR fI, (F.VAR lv)::argsv)) - end *) - val nfdec = (nfk, f, nargs, nbody) - - (* and now, for the whole F.FIX *) - fun nleE e = - F.FIX([fdecE], F.FIX([fdecI], F.FIX([nfdec], leE e))) - - in if not(S.member(fvI, f)) then (nleE, leI, fvI, leRet) - else (nleE, - F.FIX([fdecI], F.FIX([nfdec], leI)), - S.add(S.union(S_rmv(f, fvI), S.intersection(env, fvbI)), fE), - leRet) - end - end - -(* TFNs are kinda like FIX except there's no recursion *) -and stfn env (tfdec as (tfk,tf,args,body),le) = - let val (bodyE,bodyI,fvbI,bodyRet) = - if #inline tfk = F.IH_ALWAYS - then (fn e => body, body, FU.freevars body, body) - else sexp env body - val nenv = S.add(env, tf) - val (leE,leI,fvI,leRet) = sexp nenv le - in case (bodyI, S.listItems(S.difference(fvbI, env))) - of ((F.RET _ | F.RECORD(_,_,_,F.RET _)),_) => - (* split failed *) - (fn e => F.TFN((tfk, tf, args, bodyE bodyRet), leE e), - leI, fvI, leRet) - | (_,[]) => - (* everything was split out *) - let val ntfdec = ({inline=F.IH_ALWAYS}, tf, args, bodyE bodyRet) - val nlE = fn e => F.TFN(ntfdec, leE e) - in if not(S.member(fvI, tf)) then (nlE, leI, fvI, leRet) - else (nlE, F.TFN(ntfdec, leI), - S_rmv(tf, S.union(fvI, fvbI)), leRet) - end - | (_,fvbIs) => - let (* tfdecE *) - val tfE = cplv tf - val tfEvs = map F.VAR fvbIs - val bodyE = bodyE(F.RET tfEvs) - val tfElty = LT.lt_nvpoly(args, map getLty tfEvs) - val _ = addLty(tfE, tfElty) - - (* tfdecI *) - val tfkI = {inline=F.IH_ALWAYS} - val argsI = map (fn (v,k) => (cplv v, k)) args - (* val tmap = ListPair.map (fn (a1,a2) => - * (#1 a1, LT.tcc_nvar(#1 a2))) - * (args, argsI) *) - val bodyI = FU.copy tmap M.empty - (F.LET(fvbIs, F.TAPP(F.VAR tfE, map #2 tmap), - bodyI)) - (* F.TFN *) - fun nleE e = - F.TFN((tfk, tfE, args, bodyE), - F.TFN((tfkI, tf, argsI, bodyI), leE e)) - - in if not(S.member(fvI, tf)) then (nleE, leI, fvI, leRet) - else (nleE, - F.TFN((tfkI, tf, argsI, bodyI), leI), - S.add(S.union(S_rmv(tf, fvI), S.intersection(env, fvbI)), tfE), - leRet) - end - end - -(* here, we use B-decomposition, so the args should not be - * considered as being in scope *) -val (bodyE,bodyI,fvbI,bodyRet) = sexp S.empty body -in case (bodyI, bodyRet) - of (F.RET _,_) => ((fk, f, args, bodyE bodyRet), NONE) - | (_,F.RECORD (rk,vs,lv,F.RET[lv'])) => - let val fvbIs = S.listItems fvbI - - (* fdecE *) - val bodyE = bodyE(F.RECORD(rk, vs@(map F.VAR fvbIs), lv, F.RET[lv'])) - val fdecE as (_,fE,_,_) = (fk, cplv f, args, bodyE) - - (* fdecI *) - val argI = mklv() - val argLtys = (map getLty vs) @ (map (getLty o F.VAR) fvbIs) - val argsI = [(argI, LT.ltc_str argLtys)] - val (_,bodyI) = foldl (fn (lv,(n,le)) => - (n+1, F.SELECT(F.VAR argI, n, lv, le))) - (length vs, bodyI) fvbIs - val fdecI as (_,fI,_,_) = FU.copyfdec (fk, f, argsI, bodyI) - - val nargs = map (fn (v,t) => (cplv v, t)) args - in - (fdecE, SOME fdecI) - (* ((fk, f, nargs, - F.FIX([fdecE], - F.FIX([fdecI], - F.LET([argI], - F.APP(F.VAR fE, map (F.VAR o #1) nargs), - F.APP(F.VAR fI, [F.VAR argI]))))), - NONE) *) - end - - | _ => (fdec, NONE) (* sorry, can't do that *) -(* (PPFlint.printLexp bodyRet; bug "couldn't find the returned record") *) - -end - -end -end