Anonymous avatar Anonymous committed 71fbc87

Imported my WIP stuff.

Comments (0)

Files changed (23)

+_pkg.el
+auto-autoloads.el
+custom-load.el
+package-info
+pdepends.mk

.cvsignore.upstream

+sml-mode-startup.el
+sml-mode.cp
+sml-mode.cps
+sml-mode.fn
+sml-mode.fns
+sml-mode.info
+sml-mode.ky
+sml-mode.kys
+sml-mode.pg
+sml-mode.tp
+sml-mode.vr
+sml-mode.vrs
+-*- text -*-
+
+Here are the current known bugs.
+If you find any other, send it to <monnier+lists.emacs.sml@flint.cs.yale.edu>.
+
+* 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
+2002-06-09  Ville Skytt�  <ville.skytta@xemacs.org>
+
+	* First cut at making an XEmacs package.
+

ChangeLog.upstream

+2000-12-24  Stefan Monnier  <monnier@cs.yale.edu>
+
+	* 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): Replaced by the make-temp-file from Emacs-21.
+	(custom-create-map): add :group arg and allow key to be a list.
+	(define-major-mode): Removed (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): Replaced by `sml-compile-commands'.
+	(sml-config-file): New var.
+	(sml-compile-commands-alist): New var.
+	(inferior-sml-load-hook): Removed.
+	(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 autogenerated.
+
+	* 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: 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: removed.
+
+	* 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): dropped: 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): added ~ 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.
+
+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 the
+     `.elc' files 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 want to install the `.el' files,
+     just type ``make install_el''.
+
+     If you only want to create the compiled elisp files, but don't
+     want to install them, you can 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 enter the
+     contents of the file `sml-mode-startup.el' into it.  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 already had copied the pcl-cvs.startup.el file to your
+     site-start.el (or .emacs), you might want to check if it is still correct
+     since autoloads might have been added/removed.
+
+
+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''.
+
+
+#ident @(#)v3_9_5:INSTALL,v 1.1 1999/08/11 20:48:16 monnier Exp
+# Makefile for sml-mode lisp code
+
+# This file is not yet part of XEmacs.
+
+VERSION = 0.01
+AUTHOR_VERSION = 3.9.5
+MAINTAINER = Ville Skytt� <ville.skytta@xemacs.org>
+PACKAGE = sml-mode
+PKG_TYPE = regular
+REQUIRES = xemacs-base edebug fsf-compat
+CATEGORY = standard
+
+ELCS = sml-compat.elc sml-defs.elc sml-mode.elc sml-move.elc sml-proc.elc \
+	sml-util.elc
+
+EXTRA_SOURCES = BUGS ChangeLog.upstream INSTALL NEWS README sml-mode.spec \
+	TODO testcases.sml
+
+INFO_FILES = $(PACKAGE).info*
+HTML_FILES = $(PACKAGE)*.html
+HTML_DEP = $(PACKAGE).html
+TEXI_FILES = $(PACKAGE).texi
+MANUAL = $(PACKAGE)
+
+PRELOADS = -l overlay -l sml-mode
+
+# XXX: This path has an extra "../" for now.
+include ../../../XEmacs.rules
+# XXX: This should be removed if this package ever becomes official.
+STAGING = `pwd`/../unsupported-site-packages
+
+GENERATED += custom-load.elc
+
+all:: $(ELCS) auto-autoloads.elc custom-load.elc $(PACKAGE).info
+
+srckit: srckit-std
+
+binkit: binkit-common

Makefile.upstream

+# Makefile for emacs-lisp package
+
+#ident "@(#)v3_9_5:Makefile,v 1.11 2000/12/24 20:06:28 monnier Exp"
+
+# Copyright (C) 1998-1999  Stefan Monnier <monnier@cs.yale.edu>
+
+# 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 2, 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 "(add-to-list '\''load-path \"$(elcdir)\")" >>$(startupfile)' ;\
+	    echo "(add-to-list 'load-path \"$(elcdir)\")" >>$(startupfile) ;\
+	    echo 'echo "(load \"$(PACKAGE)-startup\")" >>$(startupfile)' ;\
+	    echo "(load \"$(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)
+	[ -f $@ ] || echo '
+	$(EMACS) --batch --eval '(setq generated-autoload-file "'`pwd`'/$@")' -f batch-update-autoloads "."
+
+##
+
+TAG = $(shell echo v$(VERSION) | tr '.' '_')
+ftpdir=/home/ftp/pub/monnier/$(PACKAGE)
+cvsmodule=$(shell cat CVS/Repository)
+cvsroot=$(shell cat CVS/Root)
+
+dist:
+	cvs tag -F $(TAG) &&\
+	cd $(TMP) &&\
+	cvs -d $(cvsroot) export -r $(TAG) -d $(PACKAGE)-$(VERSION) $(cvsmodule) &&\
+	cd $(PACKAGE)-$(VERSION) &&\
+	gmake 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
+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.
+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+lists/emacs/sml@tequila.cs.yale.edu>
+
+* improve M-C-f and M-C-b (they too often don't do the right thing) and
+  add M-C-k and other such sexp-chunked operations.
+
+* if indentation is non-obvious, return a list of possible indentations
+  and choose the first unless the current is one of the possible choices.
+
+* make `M-x sml-compile' more generic.
+
+* allow specifying indentation of dependent keywords (how to indent `in'
+  relative to `let', for example).
+
+* use symbols instead of strings for `sym'.
+
+* ignore warnings in C-x ` ????
+
+* 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.
+
+* right-align "and" with its correspondent.
+PACKAGE = sml-mode
+ELFILES	= sml-compat.el sml-util.el sml-defs.el sml-move.el sml-mode.el \
+	sml-proc.el
+
+default: elcfiles
+
+TESTCASE = testcases.sml
+
+test:
+	$(RM) $(TESTCASE).new
+	$(EMACS) -batch $(TESTCASE) \
+	    --eval '(indent-region (point-min) (point-max) nil)' \
+	    --eval '(write-region (point-min) (point-max) "$(TESTCASE).new")'
+	diff -u $(TESTCASE) $(TESTCASE).new
+(sml-mode
+  (standards-version 1.1
+   version VERSION
+   author-version AUTHOR_VERSION
+   date DATE
+   build-date BUILD_DATE
+   maintainer MAINTAINER
+   distribution site
+   priority low
+   category CATEGORY
+   dump nil
+   description "SML editing support."
+   filename FILENAME
+   md5sum MD5SUM
+   size SIZE
+   provides (sml-compat sml-defs sml-mode sml-move sml-proc sml-util)
+   requires (REQUIRES)
+   type regular
+))
+;;; sml-compat.el --- Compatibility functions for Emacs variants for sml-mode
+
+;; Copyright (C) 1999-2000  Stefan Monnier <monnier@cs.yale.edu>
+;;
+;; 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 2 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:
+
+(unless (fboundp 'set-keymap-parents)
+  (defun set-keymap-parents (m parents)
+    (if (keymapp parents) (setq parents (list parents)))
+    (set-keymap-parent
+     m
+     (if (cdr parents)
+	 (reduce (lambda (m1 m2)
+		   (let ((m (copy-keymap m1)))
+		     (set-keymap-parent m m2) m))
+		 parents
+		 :from-end t)
+       (car parents)))))
+
+;; for XEmacs
+(when (and (not (boundp 'temporary-file-directory)) (fboundp 'temp-directory))
+  (defvar temporary-file-directory (temp-directory)))
+
+(unless (fboundp 'make-temp-file)
+  ;; Copied from Emacs-21's subr.el
+  (defun make-temp-file (prefix &optional dir-flag)
+  "Create a temporary file.
+The returned file name (created by appending some random characters at the end
+of PREFIX, and expanding against `temporary-file-directory' if necessary,
+is guaranteed to point to a newly created empty file.
+You can then use `write-region' to write new data into the file.
+
+If DIR-FLAG is non-nil, create a new empty directory instead of a file."
+  (let (file)
+    (while (condition-case ()
+	       (progn
+		 (setq file
+		       (make-temp-name
+			(expand-file-name prefix temporary-file-directory)))
+		 (if dir-flag
+		     (make-directory file)
+		   (write-region "" nil file nil 'silent nil 'excl))
+		 nil)
+	    (file-already-exists t))
+      ;; the file was somehow created by someone else between
+      ;; `make-temp-name' and `write-region', let's try again.
+      nil)
+    file)))
+
+
+(provide 'sml-compat)
+
+;;; sml-compat.el ends here
+;;; sml-defs.el --- Various definitions for sml-mode
+
+;; Copyright (C) 1999-2000  Stefan Monnier <monnier@cs.yale.edu>
+;;
+;; 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 2 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-util)
+
+
+(defgroup sml ()
+  "Editing SML code."
+  :group 'languages)
+
+(defvar sml-outline-regexp
+  ;; `st' and `si' are to match structure and signature.
+  "
+  "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
+;;; 
+
+(defmap sml-mode-map
+  ;; smarter cursor movement
+  '((forward-sexp	. sml-user-forward-sexp)
+    (backward-sexp	. sml-user-backward-sexp)
+    ;; Text-formatting commands:
+    ("\C-c\C-m"	. sml-insert-form)
+    ("\C-c\C-i"	. sml-mode-info)
+    ("\M-|"	. sml-electric-pipe)
+    ("\M-\ "	. sml-electric-space)
+    ("\;"	. sml-electric-semi)
+    ("\M-\t"	. sml-back-to-outer-indent)
+    ;; Process commands added to sml-mode-map -- these should autoload
+    ("\C-c\C-l"	. sml-load-file)
+    ("\C-c\C-c" . sml-compile)
+    ("\C-c\C-s" . switch-to-sml)
+    ("\C-c\C-r" . sml-send-region)
+    ("\C-c\C-b" . sml-send-buffer)
+    ([(meta shift down-mouse-1)] . sml-drag-region))
+  "The keymap used in `sml-mode'."
+  ;; :inherit sml-bindings
+  :group 'sml)
+
+(defsyntax sml-mode-syntax-table
+  `((?\*   . ,(if sml-builtin-nested-comments-flag ". 23n" ". 23"))
+    (?\(   . "()1")
+    (?\)   . ")(4")
+    ("._'" . "_")
+    (",;"  . ".")
+    ;; `!' is not really a prefix-char, oh well!
+    ("~#!" . "'")
+    ("%&$+-/:<=>?@`^|"	 . "."))
+  "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" sml		(fboundp 'sml)]
+     ["-" nil nil]
+     ["run CM.make"		sml-make	(featurep 'sml-proc)]
+     ["load ML source file"	sml-load-file	(featurep 'sml-proc)]
+     ["switch to ML buffer"	switch-to-sml	(featurep 'sml-proc)]
+     ["--" nil nil]
+     ["send buffer contents"	sml-send-buffer	(featurep 'sml-proc)]
+     ["send region"		sml-send-region	(featurep 'sml-proc)]
+     ["send paragraph"		sml-send-function (featurep 'sml-proc)]
+     ;;["goto next error"		sml-next-error	(featurep 'sml-proc)]
+     ["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"             sml-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 case-indent"        (sml-case-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]
+    ["-----" nil nil]
+    ["Remove overlay"    (sml-error-overlay 'undo) ;:active (sml-overlay-active-p)
+     ]))
+
+;;; 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 (&rest syms)
+  (concat "\\<" (regexp-opt (flatten syms) t) "\\>"))
+
+;;
+
+(defconst sml-module-head-syms
+  '("signature" "structure" "functor" "abstraction"))
+
+
+(defconst sml-begin-syms
+  '("let" "abstype" "local" "struct" "sig")
+  "Symbols matching the `end' symbol.")
+
+(defconst sml-begin-syms-re
+  (sml-syms-re "let" "abstype" "local" "struct" "sig")
+  "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-=-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-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-starters-indent-after
+  (sml-syms-re "let" "local" "struct" "in" "sig" "with")
+  "Indent after these.")
+
+(defconst sml-delegate
+  (sml-preproc-alist
+   `((("of" "else" "then" "d=") . (not (sml-bolp)))
+     ("in" . t)))
+  "Words which might delegate indentation to their parent.")
+
+(defconst sml-symbol-indent
+  '(("fn" . -3)
+    ("of" . 1)
+    ("|" . -2)
+    ;;("in" . 1)
+    ("d=" . 2))
+  "Special indentation alist for some symbols.")
+
+(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).")
+
+(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-exptrail-syms
+  '("if" "then" "else" "while" "withtype" "do" "case" "of" "raise" "fn"))
+
+(defconst sml-pipeheads
+   '("|" "of" "fun" "fn" "and" "handle" "datatype" "abstype")
+   "A `|' corresponds to one of these.")
+
+
+(provide 'sml-defs)
+
+;;; sml-defs.el ends here

sml-mode-startup.el

+
+;;;### (autoloads (sml-yacc-mode sml-lex-mode sml-cm-mode sml-mode)
+;;;;;;  "sml-mode" "sml-mode.el" (14918 21945))
+;;; Generated autoloads from sml-mode.el
+
+(add-to-list (quote auto-mode-alist) (quote ("\\.s\\(ml\\|ig\\)\\'" . sml-mode)))
+
+(autoload (quote 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}" t nil)
+
+(add-to-list (quote completion-ignored-extensions) "CM/")
+
+(add-to-list (quote auto-mode-alist) (quote ("\\.cm\\'" . sml-cm-mode)))
+
+(autoload (quote sml-cm-mode) "sml-mode" "\
+Major mode for SML/NJ's Compilation Manager configuration files." t nil)
+
+(autoload (quote sml-lex-mode) "sml-mode" "\
+Major Mode for editing ML-Lex files." t nil)
+
+(add-to-list (quote auto-mode-alist) (quote ("\\.grm\\'" . sml-yacc-mode)))
+
+(autoload (quote sml-yacc-mode) "sml-mode" "\
+Major Mode for editing ML-Yacc files." t nil)
+
+;;;***
+
+;;;### (autoloads nil "sml-proc" "sml-proc.el" (14918 21909))
+;;; Generated autoloads from sml-proc.el
+
+(autoload (quote run-sml) "sml-proc" nil t)
+
+;;;***
+
+;;; sml-mode.el --- Major mode for editing (Standard) ML
+
+;; Copyright (C) 1989       Lars Bo Nielsen
+;; Copyright (C) 1994-1997  Matthew J. Morley
+;; Copyright (C) 1999-2000  Stefan Monnier
+
+;; 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@cs.yale.edu
+;; Maintainer: (Stefan Monnier) monnier+lists/emacs/sml@flint.cs.yale.edu
+;; Keywords: SML
+;; 1.25
+;; 2000/12/24 19:59:53
+
+;; 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 2, 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 'sml-util)
+(require 'sml-move)
+(require 'sml-defs)
+(condition-case nil (require 'skeleton) (error nil))
+
+;;; VARIABLES CONTROLLING INDENTATION
+
+(defcustom sml-indent-level 4
+  "*Indentation of blocks in ML (see also `sml-structure-indent')."
+  :group 'sml
+  :type '(integer))
+
+(defcustom sml-indent-args sml-indent-level
+  "*Indentation of args placed on a separate line."
+  :group 'sml
+  :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] \;)."
+  :group 'sml
+  :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
+
+(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-font-lock-keywords
+  `(;;(sml-font-comments-and-strings)
+    ("\\<\\(fun\\|and\\)\\s-+\\('\\sw+\\s-+\\)*\\(\\sw+\\)"
+     (1 font-lock-keyword-face)
+     (3 font-lock-function-name-face))
+    ("\\<\\(\\(data\\|abs\\|with\\|eq\\)?type\\)\\s-+\\('\\sw+\\s-+\\)*\\(\\sw+\\)"
+     (1 font-lock-keyword-face)
+     (4 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))
+  "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
+;;;
+
+(defsyntax sml-syntax-prop-table
+  '((?\\ . ".") (?* . "."))
+  "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))
+	   (foo (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)))
+
+;;;;
+;;;; 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)) (sml-forward-spaces) (point)))
+	      (name (sml-forward-sym)))
+	  ;; Eliminate trivial renamings.
+	  (when (or (not (member kind '("structure" "signature")))
+		    (progn (search-forward "=")
+			   (sml-forward-spaces)
+			   (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))
+
+;;;###Autoload
+(define-derived-mode sml-mode fundamental-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)
+  ;; forward-sexp-function is an experimental variable in my hacked Emacs.
+  (set (make-local-variable 'forward-sexp-function) 'sml-user-forward-sexp)
+  ;; For XEmacs
+  (easy-menu-add sml-mode-menu)
+  ;; Compatibility
+  (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)
+  ;; A paragraph is separated by blank lines or ^L only.
+  
+  (set (make-local-variable 'paragraph-start)
+       (concat "^[\t ]*$\\|" page-delimiter))
+  (set (make-local-variable 'paragraph-separate) paragraph-start)
+  (set (make-local-variable 'indent-line-function) 'sml-indent-line)
+  (set (make-local-variable 'comment-start) "(* ")
+  (set (make-local-variable 'comment-end) " *)")
+  (set (make-local-variable 'comment-nested) t)
+  ;;(set (make-local-variable 'block-comment-start) "* ")
+  ;;(set (make-local-variable 'block-comment-end) "")
+  (set (make-local-variable 'comment-column) 40)
+  (set (make-local-variable 'comment-start-skip) "(\\*+\\s-*"))
+
+(defun sml-electric-pipe ()
+  "Insert a \"|\".
+Depending on the context insert the name of function, a \"=>\" etc."
+  (interactive)
+  (sml-with-ist
+   (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-forward-sym)
+	      (sml-forward-spaces)
+	      (cond
+	       ((string= sym "|")
+		(let ((f (sml-forward-sym)))
+		  (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
+		(while (and (setq sym (sml-forward-sym))
+			    (string-match "^'" sym))
+		  (sml-forward-spaces))
+		(sml-forward-spaces)
+		(if (or (not sym)
+			(equal (sml-forward-sym) "d="))
+		    ""
+		  (concat sym "  = ")))
+	       ;; trivial cases
+	       ((string= sym "fun")
+		(while (and (setq sym (sml-forward-sym))
+			    (string-match "^'" sym))
+		  (sml-forward-spaces))
+		(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 (= ?= (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)
+  (insert "\;")
+  (if sml-electric-semi-mode
+      (reindent-then-newline-and-indent)))
+
+;;; INDENTATION !!!
+
+(defun sml-mark-function ()
+  "Synonym for `mark-paragraph' -- sorry.
+If anyone has a good algorithm for this..."
+  (interactive)
+  (mark-paragraph))
+
+(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-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-find-comment-indent ()
+  (save-excursion
+    (let ((depth 1))
+      (while (> depth 0)
+	(if (re-search-backward "(\\*\\|\\*)" nil t)
+	    (cond
+	     ((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
+	   (sml-point (point))
+	   (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 "\\\\")
+	     (save-excursion
+	       (if (save-excursion (previous-line 1)
+				   (beginning-of-line)
+				   (looking-at "[\t ]*\\\\"))
+		   (progn (previous-line 1) (current-indentation))
+		 (if (re-search-backward "[^\\\\]\"" nil t)
+		     (1+ (current-column))
+		   0))))
+
+	(and (setq data (assoc sym sml-close-paren))
+	     (sml-indent-relative sym data))
+
+	(and (member (save-excursion (sml-forward-sym)) sml-starters-syms)
+	     (let ((sym (unless (save-excursion (sml-backward-arg))
+			  (sml-backward-spaces)
+			  (sml-backward-sym))))
+	       (if sym (sml-get-sym-indent sym)
+		 ;; FIXME: this can take a *long* time !!
+		 (sml-find-matching-starter sml-starters-syms)
+		 (current-column))))
+
+	(and (string= sym "|") (sml-indent-pipe))
+
+	(sml-indent-arg)
+	(sml-indent-default))))))
+
+(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-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 (member sym '("datatype" "abstype"))
+	    (re-search-forward "="))
+	  (sml-forward-sym)
+	  (sml-forward-spaces)
+	  (+ pipe-indent (current-column)))))))
+
+(defun sml-find-forward (re)
+  (sml-forward-spaces)
+  (while (and (not (looking-at re))
+	      (progn
+		(or (ignore-errors (forward-sexp 1) t) (forward-char 1))
+		(sml-forward-spaces)
+		(not (looking-at re))))))
+
+(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 ((head-sym (pop data)) d)
+    (cond
+     ((not (listp data)) data)
+     ((setq d (member sym data)) (second d))
+     ((and (consp data) (not (stringp (car data)))) (car data))
+     (t sml-indent-level))))
+
+(defun sml-dangling-sym ()
+  (save-excursion
+    (and (not (sml-bolp))
+	 (< (sml-point-after (end-of-line))
+	    (sml-point-after (sml-forward-sym)
+			     (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, the point will be at the start of
+the parent at the end of this function.
+Optional argument STYLE is currently ignored"
+  (assert (equal sym (save-excursion (sml-forward-sym))))
+  (save-excursion
+    (let ((delegate (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 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 indent-data 1 'strict)
+	  ;; (sml-get-indent parent-indent 1 'strict)
+	  ;; (sml-get-indent indent-data 0)
+	  ;; (sml-get-indent 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))))
+    (if sym-indent
+	;; the previous sym is an indentation introducer: follow the rule
+	(let ((indent-after (or (cdr (assoc sym-after sml-symbol-indent)) 0)))
+	  (if noindent
+	      ;;(current-column)
+	      sym-indent
+	    (+ sym-indent indent-after)))
+      ;; 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))
+		    (sml-move-if (sml-backward-sexp (1- prec)))
+		    (not (sml-bolp)))
+	  (while (sml-move-if (sml-backward-sexp prec))))
+	;; the `noindent' case does back over an introductory symbol
+	;; such as `fun', ...
+	(when noindent
+	  (sml-move-if
+	   (sml-backward-spaces)
+	   (member (sml-backward-sym) sml-starters-syms)))
+	(current-column)))))
+
+
+(defun sml-bolp ()
+  (save-excursion
+    (skip-chars-backward " \t|") (bolp)))
+
+
+;; 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-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)))))
+      (unless (bobp) sym))))
+
+(defun sml-skip-siblings ()
+  (while (and (not (bobp)) (sml-backward-arg))
+    (sml-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-skip-siblings)))
+
+(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-forward-sym) (sml-forward-spaces)
+			(sml-forward-sym))
+      ;; 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."
+  :group 'sml
+  :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))))
+      `(progn
+	 (add-to-list 'sml-forms-alist ',(cons name fsym))
+	 (define-abbrev sml-mode-abbrev-table ,name "" ',fsym)
+	 (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)
+	    (let ((name (car x))
+		  (fsym (cdr x)))
+	      (vector name fsym 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-char ?\ )
+	;; 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 (char-before))) (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))))
+
+;;;;
+;;;;  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/")
+;;;###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."
+  :group 'sml
+  :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."
+  :group 'sml
+  :type 'integer)
+
+(defcustom sml-yacc-indent-term nil
+  "Indentation column of the (non)term part.
+If nil, align it with previous cases."
+  :group 'sml
+  :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 (sml-forward-spaces)
+				    (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 (sml-backward-spaces)
+			    (/= 0 (skip-syntax-backward "w_"))))
+	      (sml-backward-spaces)
+	      (if (not (looking-at "\\s-$"))
+		  (1- (current-column))
+		(skip-syntax-forward " ")
+		(- (current-column) 2))))))
+	;; default to SML rules
+	(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)
+
+;;; sml-mode.el ends here
+%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:	v3_9_5
+Release:	0.1
+Group:		Applications/Editors
+Copyright:	GPL
+Packager:	Stefan Monnier
+Source:		ftp://flint.cs.yale.edu/pub/monnier/%{name}/%{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 \
+    --section=Emacs \
+    --entry="* SML: (sml-mode).    Editing & Running Standard ML from Emacs"
+
+%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
+\input texinfo @c -*-texinfo-*-
+
+@comment "@(#)v3_9_5:sml-mode.texi,v 1.5 2000/10/07 03:21:46 monnier Exp"
+
+@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 2 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 Editors
+@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 v3_9_5}
+@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 2, 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 v3_9_5). 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 2, 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 a