]> code.delx.au - gnu-emacs-elpa/commitdiff
* sml-util.el (make-temp-dir, make-temp-file, temp-file-dir,
authormonnier <>
Fri, 18 Feb 2000 16:49:10 +0000 (16:49 +0000)
committermonnier <>
Fri, 18 Feb 2000 16:49:10 +0000 (16:49 +0000)
  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.

* 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 if it exists.  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 rhough 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.

13 files changed:
.cvsignore
BUGS
ChangeLog
Makefile
NEWS
TODO
makefile.pkg [new file with mode: 0644]
sml-compat.el
sml-defs.el
sml-mode-startup.el [deleted file]
sml-mode.el
sml-proc.el
sml-util.el

index 8acc349c3040059858e1d6affea3f013319b5847..a1614e16d189f746df19eb60a020edefee65b20f 100644 (file)
@@ -1,4 +1,5 @@
 sml-mode.cp
+sml-mode.cps
 sml-mode.fn
 sml-mode.fns
 sml-mode.info
diff --git a/BUGS b/BUGS
index 77e2bdbe6d2cf27a48f1bf79594bd995d7fa44ba..7cc9866e17cfccbe9a6f45a52ae58954e6c71dcd 100644 (file)
--- a/BUGS
+++ b/BUGS
@@ -6,3 +6,9 @@ If you find any other, send it to <monnier+lists.emacs.sml@tequila.cs.yale.edu>.
 * indentation of a declaration after a long `datatype' is slow
 
 * buggy indentation samples:  none??
+
+           (case M.find(m,f) 
+             of SOME(fl, filt) =>
+                  F.APP(F.VAR fl, OU.filter filt vs)
+               | NONE => le
+                        )
index 9c3b59f45d5c7401a7ee996128b813589f7b059e..1be1a38df98cb2d3c87af6a9e5fac8e808a34798 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,58 @@
+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.
+
+       * 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 if it exists.  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 rhough 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
index 9726421ed9f23ee9fcafb824a531ffad8a3084b5..81052eb60e57677a87d513dd4b271b52c6261915 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -1,5 +1,7 @@
 # Makefile for emacs-lisp package
 
+#ident "@(#)$Name$:$Id$"
+
 # Copyright (C) 1998-1999  Stefan Monnier <monnier@cs.yale.edu>
 
 # This file is free software; you can redistribute it and/or modify it
 # 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.
@@ -38,6 +52,7 @@ TEXI2DVI= texi2dvi
 SHELL  = /bin/sh
 DVIPS  = dvips
 CP     = cp
+RM     = rm -f
 MKDIR  = mkdir -p
 ETAGS  = etags
 
@@ -45,17 +60,9 @@ ETAGS        = etags
 ###        No changes below this line should be necessary          ###
 ######################################################################
 
-PACKAGE = sml-mode
-
-# the directory where the .elc files will be installed
-elcdir  = $(lispdir)/$(PACKAGE)
-eldir   = $(elcdir)
-
 ELFLAGS        = --eval '(setq load-path (append (list "." "$(elibdir)" "$(lispdir)") load-path))'
 ELC    = $(EMACS) -batch $(ELFLAGS) -f batch-byte-compile
 
-ELFILES        = sml-compat.el sml-util.el sml-defs.el sml-move.el sml-mode.el \
-       sml-proc.el
 ELCFILES = $(ELFILES:.el=.elc)
 
 TEXEXTS =  *.cps *.fns *.kys *.vr *.tp *.pg *.log *.aux *.toc *.cp *.ky *.fn
@@ -84,37 +91,50 @@ default: elcfiles
 elcfiles: $(ELCFILES)
 info: $(PACKAGE).info
 
-install_elc: $(ELCFILES)
+install_elc: $(ELCFILES) $(PACKAGE)-startup.el
        $(MKDIR) $(elcdir)
-       $(CP) $(ELCFILES) $(elcdir)/
+       for f in $(ELCFILES) $(PACKAGE)-startup.el; do \
+           $(CP) $$f $(elcdir)/$$f ;\
+       done
 
 install_el:
        $(MKDIR) $(eldir)
-       $(CP) $(ELFILES) $(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 $(PACKAGE).info $(infodir)/dir
+       -[ ! -w $(infodir)/dir ] \
+           || install-info --info-dir=$(infodir)/dir $(PACKAGE).info
 
 install_startup:
        $(MKDIR) $(lispdir)
-       if grep $(PACKAGE) $(startupfile) >/dev/null 2>&1 || \
+       @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 "!!! Check $(PACKAGE)-startup.el and merge it" \
-           echo "!!! into your $(startupfile) file"; \
+           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 \
-           sed 's|@elcdir@|$(elcdir)|' \
-               $(PACKAGE)-startup.el >>$(startupfile) ;\
+           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) *.dvi $(docdir)/
+       $(CP) `find . -type f -name '*.dvi' -print` $(docdir)/
 
-install: install_elc install_info # install_el
+install: install_elc install_info install_startup # install_el
 
 clean:
        $(RM) *~ core .\#* $(TEXEXTS)
@@ -129,8 +149,8 @@ distclean: clean
 ###                    don't look below                            ###
 ######################################################################
 
-$(PACKAGE)-startup.el:  $(ELFILES)
-       chmod +w $@
+$(PACKAGE)-startup.el: $(ELFILES)
+       [ -f $@ ] || echo '\f' >$@
        $(EMACS) --batch --eval '(setq generated-autoload-file "'`pwd`'/$@")' -f batch-update-autoloads "."
 
 ##
@@ -143,12 +163,9 @@ dist:
        cd $(TMP) &&\
        cvs export -r $(TAG) -d $(PACKAGE)-$(VERSION) elisp/$(PACKAGE) &&\
        cd $(PACKAGE)-$(VERSION) &&\
-       gmake info &&\
+       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
-
-
-#ident @(#)$Name$:$Id$
diff --git a/NEWS b/NEWS
index dffeed9db586e9572c6f51d3ed9af5c98e7f5fa6..c88d691c9ea4829289df8d0fd639a1af1e1ee477 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -1,4 +1,27 @@
--*- text -*-
+Changes since 3.9.3:
+
+* 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 aprefix
+  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).
+
+* Added a trivial CM major-mode.
+
+* sml-load-hook has disappeared.
+
+* sml-mode-startup.el is now automatically generated and you're supposed to
+  `load' it from .emacs or siate-start.el.
+
+* Minor bug fixes.
 
 Changes since 3.3:
 
diff --git a/TODO b/TODO
index 2800f1477b622bd3067c973b227a15d2ed1d6503..ba7642e7c77a3bbb2ae1fe5eda541ed5236b45f8 100644 (file)
--- a/TODO
+++ b/TODO
@@ -1,4 +1,3 @@
--*- text -*-
 
 * 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.
 
 * ignore warnings in C-x ` ????
 
-* recognize irrefutable patterns (with "Capital"-heuristics, 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)
 
-* find the enclosing function's name for add-change-log-entry.
+* take advantage of text after-the-line (when available) for indentation
 
 * obey fixity directives.
 
-* improve the run-sml to allow running on another machine and to take args.
-
 * right-align "and" with its correspondant.
 
+* find the enclosing function's name for add-change-log-entry.
+* add imenu support
+
 * sample indentations to be improved:
diff --git a/makefile.pkg b/makefile.pkg
new file mode 100644 (file)
index 0000000..6c187ac
--- /dev/null
@@ -0,0 +1,3 @@
+PACKAGE = sml-mode
+ELFILES        = sml-compat.el sml-util.el sml-defs.el sml-move.el sml-mode.el \
+       sml-proc.el
index eafdeb902d77b55b7f7617bf6fe93ff88a5b4cc5..d8af9dd67c6af5b7b1bc3801ae028797f5d5584d 100644 (file)
@@ -22,6 +22,7 @@
 
 (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)
                 :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)
index ef4ed3511e4b1f5ed3734bc39daa588bb5e52f30..c591e4a145501192d887fb83d66cba08c53b686f 100644 (file)
     ;;("\t"    . sml-indent-line)      ; ...except this one
     ;; Process commands added to sml-mode-map -- these should autoload
     ("\C-c\C-l"        . sml-load-file)
-    ("\C-c`"   . sml-next-error))
-  "Generic bindings used in sml-mode and sml-inferior-mode."
+    ;;("\C-c`" . sml-next-error)
+    )
+  "Generic bindings used in `sml-mode' and `inferior-sml-mode'."
   :group 'sml)
 
 (defmap sml-mode-map
   '(("\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))
-  "The keymap used in sml-mode."
+    ("\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 
-  '((?\*   . ". 23n")
+  `((?\*   . ,(if sml-builtin-nested-comments-flag ". 23n" ". 23"))
     (?\(   . "()1")
     (?\)   . ")(4")
     ("._'" . "_")
@@ -89,7 +91,8 @@
      ["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"              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)]
 (defconst sml-pipehead-re
   (concat
    "|\\S.\\|"
-   (sml-syms-re "of" "fun" "fn" "and" "handle" "datatype" "abstype"))
+   (sml-syms-re "fun" "fn" "and" "handle" "datatype" "abstype"))
   "A `|' corresponds to one of these.")
 
 ;;
diff --git a/sml-mode-startup.el b/sml-mode-startup.el
deleted file mode 100644 (file)
index 998aa56..0000000
+++ /dev/null
@@ -1,52 +0,0 @@
-;;;
-;;; sample autoload entries for your site-lisp/site-start.el file
-;;;
-
-;;#ident "@(#)$Name$:$Id$"
-
-;; don't forget to add the directory to your load-path
-(add-to-list 'load-path "@elcdir@")
-
-;; make sure the mode is loaded when necessary
-(add-to-list 'auto-mode-alist '("\\.s\\(ml\\|ig\\)\\'" . sml-mode))
-
-;; put this also if you feel like it (for SML/NJ's compilation manager)
-(add-to-list 'completion-ignored-extensions "CM/")
-
-;; the rest is the auto-generated autoloads
-\f
-;;;### (autoloads (sml-mode) "sml-mode" "sml-mode.el" (14257 57462))
-;;; Generated autoloads from sml-mode.el
-
-(autoload (quote sml-mode) "sml-mode" "\
-Major mode for editing ML code.
-Entry to this mode runs the hooks on sml-mode-hook.
-\\{sml-mode-map}" t nil)
-
-;;;***
-\f
-;;;### (autoloads (run-sml) "sml-proc" "sml-proc.el" (14257 55157))
-;;; Generated autoloads from sml-proc.el
-
-(autoload (quote run-sml) "sml-proc" "\
-Run an inferior ML process, input and output via buffer *sml*. 
-With a prefix argument, this command allows you to specify any command
-line options to pass to the complier. The command runs hook functions
-on `comint-mode-hook' and `inferior-sml-mode-hook' in that order.
-
-If there is a process already running in *sml*, just switch to that
-buffer instead. 
-
-In fact the name of the buffer created is chosen to reflect the name
-of the program name specified by `sml-program-name', or entered at the
-prompt. You can have several inferior ML process running, but only one
-current one -- given by `sml-buffer' (qv).
-
-\(Type \\[describe-mode] in the process buffer for a list of commands.)" t nil)
-
-;;;***
-\f
-;;; Local Variables:
-;;; no-byte-compile: t
-;;; no-update-autoloads: t
-;;; End:
index f28c69fda54b8800e342a5cbf84b21a2dcc0a199..268e3da9968923c40af8444a71fd54d145819479 100644 (file)
@@ -1,4 +1,4 @@
-;;; sml-mode.el. Major mode for editing (Standard) ML
+;;; sml-mode.el --- Major mode for editing (Standard) ML
 
 (defconst rcsid-sml-mode "@(#)$Name$:$Id$")
 
 
 ;; ====================================================================
 
-;;; HISTORY 
+
+;;; Commentary:
+;; 
+
+;;; HISTORY
 
 ;; Still under construction: History obscure, needs a biographer as
 ;; well as a M-x doctor. Change Log on request.
 ;; Maintainer: (Stefan Monnier) monnier+lists/emacs/sml@tequila.cs.yale.edu
 ;; Keywords: SML
 
-;;; DESCRIPTION 
+;;; 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 
+;; 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:
 
 ;; (setq load-path (cons (expand-file-name "~jones/lib/emacs") load-path))
 ;;                indent-tabs-mode nil)))    ; whatever
 
 ;; sml-mode-hook is run whenever a new sml-mode buffer is created.
-;; There is an sml-load-hook too, which is only run when this file is
-;; loaded. One use for this hook is to select your preferred
-;; highlighting scheme, like this:
-
-;; (setq sml-load-hook
-;;       '(lambda() "Highlights." (require 'sml-hilite)))
-
-;; hilit19 is the magic that actually does the highlighting. My set up
-;; for hilit19 runs something like this:
-
-;; (if window-system
-;;     (setq hilit-background-mode   t ; monochrome (alt: 'dark or 'light)
-;;           hilit-inhibit-hooks     nil
-;;           hilit-inhibit-rebinding nil
-;;           hilit-quietly           t))
-
-;; Alternatively, you can (require 'sml-font) which uses the font-lock
-;; package instead. 
 
 ;; Finally, there are inferior-sml-{mode,load}-hooks -- see comments
 ;; in sml-proc.el. For much more information consult the mode's *info*
 ;; tree.
 
-;;; VERSION STRING
-
-(defconst sml-mode-version "version $Name$")
+;;; Code:
 
 (require 'cl)
 (require 'sml-util)
 
 (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: C-q \;)."
+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.
+  "*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
-which is part of the sml-mode 3.2 (and later) distribution. E.g:  
+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\") 
+  (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
-  "*This hook is run when sml-mode is loaded, or a new sml-mode buffer created.
+  "*Run upon entering `sml-mode'.
 This is a good place to put your preferred key bindings.")
 
-(defvar sml-load-hook nil
-  "*This hook is run when sml-mode (sml-mode.el) is loaded into Emacs.")
+(defvar sml-mode-abbrev-table nil "*Abbrev table for `sml-mode'.")
 
-(defvar sml-mode-abbrev-table nil "*SML mode abbrev table (default nil)")
-
-;;; CODE FOR SML-MODE 
+;;; 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."
+  "Command to access the TeXinfo documentation for `sml-mode'.
+See doc for the variable `sml-mode-info'."
   (interactive)
   (require 'info)
   (condition-case nil
-      (Info-goto-node (concat "(" sml-mode-info ")"))
+      (info sml-mode-info)
     (error (progn
              (describe-variable 'sml-mode-info)
              (message "Can't find it... set this variable first!")))))
@@ -200,7 +180,7 @@ Full documentation will be available after autoloading the function."))
               "infixr" "let" "local" "nonfix" "of" "op" "open" "orelse"
               "overload" "raise" "rec" "sharing" "sig" "signature"
               "struct" "structure" "then" "type" "val" "where" "while"
-              "with" "withtype")
+              "with" "withtype" "o")
   "A regexp that matches any and all keywords of SML.")
 
 (defconst sml-font-lock-keywords
@@ -246,15 +226,15 @@ Full documentation will be available after autoloading the function."))
 (defvar font-lock-interface-def-face 'font-lock-interface-def-face
   "Face name to use for interface definitions.")
 
-(defvar sml-syntax-prop-table
-  (let ((st (make-syntax-table)))
-    ;;(modify-syntax-entry ?l "(d" st)
-    ;;(modify-syntax-entry ?s "(d" st)
-    ;;(modify-syntax-entry ?d ")l" st)
-    (modify-syntax-entry ?\\ "." st)
-    (modify-syntax-entry ?* "." st)
-    st))
+;;; 
+;;; 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))
@@ -274,11 +254,9 @@ Full documentation will be available after autoloading the function."))
          (when depth sml-syntax-prop-table))))))
 
 (defconst sml-font-lock-syntactic-keywords
-  `(;;("\\<\\(l\\)\\(et\\|ocal\\)\\>" (1 ',sml-syntax-prop-table))
-    ;;("\\<\\(s\\)\\(ig\\truct\\)\\>" (1 ',sml-syntax-prop-table))
-    ;;("\\<en\\(d\\)\\>" (1 ',sml-syntax-prop-table))
-    ("^\\s-*\\(\\\\\\)" (1 ',sml-syntax-prop-table))
-    ("(?\\(\\*\\))?" (1 (sml-get-depth-st)))))
+  `(("^\\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
@@ -287,25 +265,17 @@ Full documentation will be available after autoloading the function."))
 
 ;;; MORE CODE FOR SML-MODE
 
-(defun sml-mode-version ()
-  "This file's version number (sml-mode)."
-  (interactive)
-  (message sml-mode-version))
+;;;###Autoload
+(add-to-list 'auto-mode-alist '("\\.s\\(ml\\|ig\\)\\'" . sml-mode))
 
 ;;;###Autoload
-(defun sml-mode ()
-  "Major mode for editing ML code.
-Entry to this mode runs the hooks on `sml-mode-hook'.
+(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}"
-
-  (interactive)
-  (kill-all-local-variables)
-  (sml-mode-variables)
-  (use-local-map sml-mode-map)
-  (setq major-mode 'sml-mode)
-  (setq mode-name "SML")
+  (set (make-local-variable 'font-lock-defaults) sml-font-lock-defaults)
   (set (make-local-variable 'outline-regexp) sml-outline-regexp)
-  (run-hooks 'sml-mode-hook))            ; Run the hook last
+  (sml-mode-variables))
 
 (defun sml-mode-variables ()
   (set-syntax-table sml-mode-syntax-table)
@@ -318,12 +288,12 @@ Entry to this mode runs the hooks on `sml-mode-hook'.
   (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-*")
-  (set (make-local-variable 'comment-indent-function) 'sml-comment-indent)
-  (set (make-local-variable 'font-lock-defaults) sml-font-lock-defaults))
+  (set (make-local-variable 'comment-indent-function) 'sml-comment-indent))
 
 (defun sml-electric-pipe ()
   "Insert a \"|\".
@@ -368,7 +338,7 @@ Depending on the context insert the name of function, a \"=>\" etc."
               (t (error "Wow, now, there's a bug")))))))
 
      (insert text)
-     (sml-indent-line)
+     (indent-according-to-mode)
      (beginning-of-line)
      (skip-chars-forward "\t |")
      (skip-syntax-forward "w")
@@ -376,8 +346,8 @@ Depending on the context insert the name of function, a \"=>\" etc."
      (when (= ?= (char-after)) (backward-char)))))
 
 (defun sml-electric-semi ()
-  "Inserts a \;.
-If variable sml-electric-semi-mode is t, indent the current line, insert 
+  "Insert a \;.
+If variable `sml-electric-semi-mode' is t, indent the current line, insert
 a newline, and indent."
   (interactive)
   (insert "\;")
@@ -387,7 +357,7 @@ a newline, and indent."
 ;;; INDENTATION !!!
 
 (defun sml-mark-function ()
-  "Synonym for mark-paragraph -- sorry.
+  "Synonym for `mark-paragraph' -- sorry.
 If anyone has a good algorithm for this..."
   (interactive)
   (mark-paragraph))
@@ -400,7 +370,7 @@ If anyone has a good algorithm for this..."
 ;;     (goto-char end) (setq end (point-marker)) (goto-char begin)
 ;;     (while (< (point) end)
 ;;       (skip-chars-forward "\t\n ")
-;;       (sml-indent-line)
+;;       (indent-according-to-mode)
 ;;       (end-of-line))
 ;;     (move-marker end nil))
 ;;   (message "Indenting region... done"))
@@ -408,16 +378,7 @@ If anyone has a good algorithm for this..."
 (defun sml-indent-line ()
   "Indent current line of ML code."
   (interactive)
-  (let ((indent (sml-calculate-indentation)))
-    (if (/= (current-indentation) indent)
-        (save-excursion                 ;; Added 890601 (point now stays)
-          (let ((beg (progn (beginning-of-line) (point))))
-            (skip-chars-forward "\t ")
-            (delete-region beg (point))
-            (indent-to indent))))
-    ;; If point is before indentation, move point to indentation
-    (if (< (current-column) (current-indentation))
-        (skip-chars-forward "\t "))))
+  (indent-line-to (sml-calculate-indentation)))
 
 (defun sml-back-to-outer-indent ()
   "Unindents to the next outer level of indentation."
@@ -564,9 +525,10 @@ If anyone has a good algorithm for this..."
     (current-column)))
 
 (defun sml-get-sym-indent (sym &optional style)
-  "expects to be looking-at SYM.
+  "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."
+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))
@@ -653,21 +615,18 @@ the parent at the end of this function."
       (max (1+ (current-column))        ; Else indent at comment column
            comment-column))))           ; except leave at least one space.
 
-;;; INSERTING PROFORMAS (COMMON SML-FORMS) 
+;;; INSERTING PROFORMAS (COMMON SML-FORMS)
 
 (defvar sml-forms-alist nil
-  "*The alist of templates to auto-insert.
-
-You can extend this alist to your heart's content. For each additional
+  "*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'
+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.")
 
@@ -735,13 +694,13 @@ the corresponding form is inserted."
       (sml-insert-form sym nil))))
 
 (defun sml-insert-form (name newline)
-  "Interactive short-cut to insert a common ML form.
-If a perfix argument is given insert a newline and indent first, or
+  "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 
+\(just hit return when prompted\)\; otherwise the command reads with
 completion from `sml-forms-alist'."
   (interactive
    (list (completing-read
@@ -770,7 +729,7 @@ 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
+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.
 
@@ -782,13 +741,24 @@ See also `edit-kbd-macro' which is bound to \\[edit-kbd-macro]."
     (message "Macro bound to %s" fsym)
     (add-to-list 'sml-forms-alist (cons name fsym))))
 
-;; at a pinch these could be added to SML/Forms menu through the good
-;; offices of activate-menubar-hook or something... but documentation
-;; of this and/or menu-bar-update-hook is sparse in 19.33. anyway, use
-;; completing read for sml-insert-form prompt...
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;;;  SML/NJ's Compilation Manager support  ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+;;;###autoload
+(add-to-list 'completion-ignored-extensions "CM/")
+;;;###autoload
+(add-to-list 'auto-mode-alist '("\\.cm\\'" . sml-cm-mode))
+;;;###autoload
+(define-generic-mode 'sml-cm-mode
+  '(("(*" . "*)"))
+  '("library" "Library" "LIBRARY" "group" "Group" "GROUP" "is" "IS"
+    "structure" "functor" "signature" "funsig")
+  nil '("\\.cm\\'")
+  (list (lambda () (local-set-key "\C-c\C-c" 'sml-compile)))
+  "Generic mode for SML/NJ's Compilation Manager configuration files.")
 
-;;; & do the user's customisation
-(run-hooks 'sml-load-hook)
 
-;;; sml-mode.el has just finished.
 (provide 'sml-mode)
+
+;;; sml-mode.el ends here
index 0838bda2f07d45f95c52d744761dfa36f4a16510..110ba4228d796ba76f55f1af9c92a92eea176092 100644 (file)
@@ -1,6 +1,4 @@
-;;; sml-proc.el. Comint based interaction mode for Standard ML.
-
-(defconst rcsid-sml-proc "@(#)$Name$:$Id$")
+;;; sml-proc.el --- Comint based interaction mode for Standard ML.
 
 ;; Copyright (C) 1989, Lars Bo Nielsen, 1994,1997 Matthew J. Morley
 
@@ -33,7 +31,7 @@
 ;; under 18.59 (or anywhere without comint, if there are such places).
 ;; See sml-mode.el for further information.
 
-;;; DESCRIPTION
+;;; Commentary:
 
 ;; Inferior-sml-mode is for interacting with an ML process run under
 ;; emacs. This uses the comint package so you get history, expansion,
 ;; does not understand `use', but has the benefit of allowing better error
 ;; reporting.
 
-;; ===================================================================
+;; Bugs:
+
+;; Todo:
 
-;;; INFERIOR ML MODE VARIABLES
+;; - Keep improving `sml-compile'.
+;; - ignore warnings (if requested) for next-error
+
+;;; Code:
 
 (require 'sml-mode)
 (require 'sml-util)
   :group 'sml-proc
   :type '(string))
 
-(defvar sml-compile-command "CM.make()"
-  "The command used by default by `sml-make'.")
+(defcustom sml-host-name ""
+  "*Host on which to run ML."
+  :group 'sml-proc
+  :type '(string))
+
+(defcustom sml-config-file "~/.smlproc.sml"
+  "*File that should be fed to the ML process when started."
+  :group 'sml-proc
+  :type '(string))
 
-(defvar sml-make-file-name "sources.cm"
-  "The name of the makefile that `sml-make' will look for (if non-nil).")
+(defcustom sml-compile-command "CM.make()"
+  "The command used by default by `sml-compile'.
+See also `sml-compile-commands-alist'.")
 
-;;(defvar sml-raise-on-error nil
-;;  "*When non-nil, `sml-next-error' will raise the ML process's frame.")
+(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 inferior-sml-load-hook nil
-  "*Hook run when inferior-sml-mode (sml-proc.el) is loaded into Emacs.
-This is a good place to put your preferred key bindings.")
-
 (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.
@@ -132,20 +146,20 @@ benefits (but with several side effects).")
 
 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
+`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
+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
+`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>
@@ -160,12 +174,12 @@ what process do 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
+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
+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.")
 
@@ -234,6 +248,7 @@ See `compilation-error-regexp-alist' for a description of the format.")
 (defconst inferior-sml-font-lock-defaults
   '(inferior-sml-font-lock-keywords nil nil nil nil))
 
+
 ;;; CODE
 
 (defmap inferior-sml-mode-map
@@ -251,8 +266,8 @@ See `compilation-error-regexp-alist' for a description of the format.")
 (defvar sml-error-cursor nil)           ;   ditto
 
 (defun sml-proc-buffer ()
-  "Returns the current ML process buffer,
-or the current buffer if it is in `inferior-sml-mode'. Raises an error
+  "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))
@@ -261,25 +276,29 @@ buffer."
             ;; buffer-name returns nil if the buffer has been killed
             (and buf (buffer-name buf) buf)))
       ;; no buffer found, make a new one
-      (run-sml t)))
-
-(defun sml-proc ()
-  "Returns the current ML process. See variable `sml-buffer'."
-  (assert (eq major-mode 'inferior-sml-mode))
-  (or (get-buffer-process (current-buffer))
-      (progn (run-sml t) (get-buffer-process (current-buffer)))))
+      (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."
+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 (and (not echo) (eq major-mode 'inferior-sml-mode))
-    (setq sml-buffer (current-buffer)))
-  (message "ML process buffer is %s."
+  (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 inferior-sml-mode ()
+(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)))))
+
+(define-derived-mode inferior-sml-mode comint-mode "Inferior-SML"
   "Major mode for interacting with an inferior ML process.
 
 The following commands are available:
@@ -305,7 +324,7 @@ Variables controlling behaviour of this mode are
     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.  
+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.
@@ -317,15 +336,12 @@ 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 
+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.."
-  (interactive)
-  (kill-all-local-variables)
-  (comint-mode)
   (setq comint-prompt-regexp sml-prompt-regexp)
   (sml-mode-variables)
 
@@ -338,91 +354,82 @@ TAB file name completion, as in shell-mode, etc.."
   ;; compilation support (used for next-error)
   (set (make-local-variable 'compilation-error-regexp-alist)
        sml-error-regexp-alist)
-  (compilation-shell-minor-mode 1)
+  (compilation-minor-mode 1)
+  ;; eliminate compilation-minor-mode's map since its Mouse-2 binding
+  ;; is just too unbearable.
+  (add-to-list 'minor-mode-overriding-map-alist
+              (cons 'compilation-minor-mode (make-sparse-keymap)))
   ;; 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 major-mode 'inferior-sml-mode)
-  (setq mode-name "Inferior ML")
-  (setq mode-line-process '(": %s"))
-  (use-local-map inferior-sml-mode-map)
-  ;;(add-hook 'kill-emacs-hook 'sml-temp-tidy)
-
-  (run-hooks 'inferior-sml-mode-hook))
+  (setq mode-line-process '(": %s")))
 
 ;;; FOR RUNNING ML FROM EMACS
 
 ;;;###autoload
-(defun run-sml (&optional pfx)
-  "Run an inferior ML process, input and output via buffer *sml*. 
-With a prefix argument, this command allows you to specify any command
-line options to pass to the complier. The command runs hook functions
-on `comint-mode-hook' and `inferior-sml-mode-hook' in that order.
-
-If there is a process already running in *sml*, just switch to that
-buffer instead. 
-
-In fact the name of the buffer created is chosen to reflect the name
-of the program name specified by `sml-program-name', or entered at the
-prompt. You can have several inferior ML process running, but only one
+(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 "P")
-  (let ((cmd (if pfx
-                 (read-string "ML command: " sml-program-name)
-               sml-program-name))
-        (args (if pfx
-                  (read-string "Any args: " sml-default-arg)
-                sml-default-arg)))
-    (sml-run cmd args)))
-
-(defun sml-run (cmd arg)
-  "Run the ML program CMD with given arguments ARGS.
-This usually updates `sml-buffer' to a buffer named *CMD*."
+  (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 "") () (sml-args-to-list arg))))
+         (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-buffer (apply 'make-comint pname cmd nil args))
-
-    (set-buffer sml-buffer)
-    (message (format "Starting \"%s\" in background." pname))
+    (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
+    (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 sml-args-to-list (string)
-  (let ((where (string-match "[ \t]" string)))
-    (cond ((null where) (list string))
-          ((not (= where 0))
-           (cons (substring string 0 where)
-                 (sml-args-to-list (substring string (+ 1 where)
-                                              (length string)))))
-          (t (let ((pos (string-match "[^ \t]" string)))
-               (if (null pos)
-                   nil
-                   (sml-args-to-list (substring string pos
-                                                (length string)))))))))
-
-(defun switch-to-sml (eob-p)
+(defun switch-to-sml (eobp)
   "Switch to the ML process buffer.
-With prefix argument, positions cursor at point, otherwise at end of buffer."
+Move point to the end of buffer unless prefix argument EOBP is set."
   (interactive "P")
   (pop-to-buffer (sml-proc-buffer))
-  (cond ((not eob-p)
-         (push-mark (point) t)
-         (goto-char (point-max)))))
+  (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 to the inferior ML process.
-Prefix argument means switch-to-sml afterwards.
+  "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.
@@ -448,7 +455,7 @@ See variables `sml-use-command'."
 
 (defun sml-send-function (&optional and-go)
   "Send current paragraph to the inferior ML process. 
-With a prefix argument switch to the sml buffer as well 
+With a prefix argument AND-GO switch to the sml buffer as well 
 \(cf. `sml-send-region'\)."
   (interactive "P")
   (save-excursion
@@ -459,12 +466,12 @@ With a prefix argument switch to the sml buffer as well
 (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
+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 switch to the sml buffer as well
+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)
@@ -475,7 +482,7 @@ With a prefix argument switch to the sml buffer as well
 ;; 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 to the inferior ML process, and go there."
+  "Send current region START..END to the inferior ML process, and go there."
   (interactive "r")
   (sml-send-region start end t))
 
@@ -488,7 +495,7 @@ With a prefix argument switch to the sml buffer as well
 
 (defun sml-drag-region (event)
   "Highlight the text the mouse is dragged over, and send it to ML.
-This must be bound to a button-down mouse event, currently \\[sml-drag-region].
+This must be bound to a button-down mouse EVENT, currently \\[sml-drag-region].
 
 If you drag the mouse (ie, keep the mouse button depressed) the
 program text sent to the complier is delimited by where you started
@@ -523,12 +530,13 @@ undisturbed once this operation is completed."
 ;;; LOADING AND IMPORTING SOURCE FILES:
 
 (defvar sml-prev-dir/file nil
-  "Caches the (directory . file) pair used in the last `sml-load-file'
-or `sml-cd' command. Used for determining the default in the next one.")
+  "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 switch to sml buffer as well.
+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
@@ -545,7 +553,7 @@ automatically."
 
 (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
+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."
@@ -570,23 +578,55 @@ be executed to change the compiler's working directory\; a trailing
     (when and-go (switch-to-sml nil))))
 
 (defun sml-compile (command)
-  "re-make a system using (by default) CM.
-   The exact command used can be specified by providing a prefix argument."
+  "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."
   (interactive
-   ;; code taken straight from compile.el
-   (if (or compilation-read-command current-prefix-arg)
-       (list (read-from-minibuffer "Compile command: "
-                                 sml-compile-command nil nil
-                                 '(compile-history . 1)))
-     (list sml-compile-command)))
-  (setq sml-compile-command command)
+   (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)
-  ;; try to find a makefile up the directory tree
-  (let ((dir (when sml-make-file-name default-directory)))
-    (while (and dir (not (file-exists-p (concat dir sml-make-file-name))))
-      (let ((newdir (file-name-directory (directory-file-name dir))))
-       (setq dir (unless (equal newdir dir) newdir))))
-    (unless dir (setq dir default-directory))
+  (let ((dir default-directory))
+    (when (string-match "^\\s-*cd\\s-+\"\\([^\"]+\\)\"\\s-*;" command)
+      (setq dir (expand-file-name (match-string 1 command)))
+      (setq command (replace-match "" t t command)))
     (with-current-buffer (sml-proc-buffer)
       (setq default-directory dir)
       (sml-send-string (concat (format sml-cd-command dir) "; " command) t t))))
@@ -616,11 +656,14 @@ be executed to change the compiler's working directory\; a trailing
        (column (string-to-number (compile-buffer-substring (third f)))))
     ;; record the end of error, if any
     (when (fourth f)
-      (let* ((endline (string-to-number (compile-buffer-substring (fourth f))))
-            (endcol (string-to-number (compile-buffer-substring (fifth f))))
-            (linediff (- endline linenum)))
-       (push (list err linediff (if (= 0 linediff) (- endcol column) endcol))
-             sml-endof-error-alist)))
+      (let ((endlinestr (compile-buffer-substring (fourth f))))
+       (when endlinestr
+         (let* ((endline (string-to-number endlinestr))
+                (endcol (string-to-number
+                         (or (compile-buffer-substring (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
@@ -651,8 +694,8 @@ be executed to change the compiler's working directory\; a trailing
        (goto-char pos)))))
 
 (defun sml-error-overlay (undo &optional beg end)
-  "Move `sml-error-overlay' so it surrounds the text region in the
-current buffer. If the buffer-local variable `sml-error-overlay' is
+  "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
@@ -675,17 +718,8 @@ the overlay should simply be removed: \\[universal-argument] \
 
 ;;; H A C K   A T T A C K !   X E M A C S   /   E M A C S   K E Y S
 
-(if window-system
-    (cond ((string-match "\\(Lucid\\|XEmacs\\)" emacs-version)
-          ;; LUCID (19.10) or later...
-          (define-key sml-mode-map '(meta shift button1) 'sml-drag-region))
-         (t
-          ;; GNU, post circa 19.19
-          (define-key sml-mode-map [M-S-down-mouse-1] 'sml-drag-region))))
+;;(define-key sml-mode-map [(meta shift down-mouse-1)] 'sml-drag-region)
 
-;;; ...and do the user's customisations.
-
-(run-hooks 'inferior-sml-load-hook)
-
-;;; Here is where sml-proc.el ends
 (provide 'sml-proc)
+
+;;; sml-proc.el ends here
index db28f40eb0e7570500721e1c76a53f752eae3948..380316192324307f210a120b977b910fd19eaa34 100644 (file)
@@ -50,72 +50,36 @@ and is hence executed at macro-expansion-time."
          :from-end t))
 
 ;;; 
-;;; temp files
+;;; defmap
 ;;; 
 
-(defvar temp-file-dir temporary-file-directory
-  "Directory where to put temp files.")
-
-(defvar temp-directories ())
-
-(defun delete-temp-dirs ()
-  (dolist (dir temp-directories)
-    (when (file-directory-p dir)
-      (let ((default-directory dir))
-       (dolist (file (directory-files "."))
-         (ignore-errors (delete-file file))))
-      (delete-directory dir))))
-(add-hook 'kill-emacs-hook 'delete-temp-dirs)
-
-(defun make-temp-dir (s)
-  "Create a temporary directory.
-The returned dir name (created by appending some random characters at the end
-of S and prepending `temporary-file-directory' if it is not already absolute)
-is guaranteed to point to a newly created empty directory."
-  (let* ((prefix (expand-file-name s temp-file-dir))
-        (dir (make-temp-name prefix)))
-    (if (not (ignore-errors (make-directory dir t) t))
-       (make-temp-dir prefix)
-      (push dir temp-directories)
-      (file-name-as-directory dir))))
-
-(defun make-temp-file (s)
-  "Create a temporary file.
-The returned file name (created by appending some random characters at the end
-of S and prepending `temporary-file-directory' if it is not already absolute)
-is guaranteed to point to a newly created empty file."
-  (unless (file-name-absolute-p s)
-    (unless (equal (user-uid)
-                  (third (file-attributes temporary-file-directory)))
-      (setq temporary-file-directory (make-temp-dir "emacs")))
-    (setq s (expand-file-name s temporary-file-directory)))
-  (let ((file (make-temp-name s)))
-    (write-region 1 1 file nil 'silent)
-    file))
-
-;; defmap ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-
 (defun custom-create-map (m bs args)
-  (let (inherit dense)
+  (let (inherit dense suppress)
     (while args
       (let ((key (first args))
            (val (second args)))
        (cond
         ((eq key :dense) (setq dense val))
         ((eq key :inherit) (setq inherit val))
+        ((eq key :group) )
+        ;;((eq key :suppress) (setq suppress val))
         (t (message "Uknown argument %s in defmap" key))))
       (setq args (cddr args)))
     (unless (keymapp m)
       (setq bs (append m bs))
       (setq m (if dense (make-keymap) (make-sparse-keymap))))
     (dolist (b bs)
-      (let ((key (car b))
+      (let ((keys (car b))
            (binding (cdr b)))
-       (cond
-        ((symbolp key)
-         (substitute-key-definition key binding m global-map))
-        ((let ((o (lookup-key m key))) (or (null o) (numberp o)))
-         (define-key m key binding)))))
+       (dolist (key (if (consp keys) keys (list keys)))
+         (cond
+          ((symbolp key)
+           (substitute-key-definition key binding m global-map))
+          ((null binding)
+           (unless (keymapp (lookup-key m key)) (define-key m key binding)))
+          ((let ((o (lookup-key m key)))
+             (or (null o) (numberp o) (eq o 'undefined)))
+           (define-key m key binding))))))
     (cond
      ((keymapp inherit) (set-keymap-parent m inherit))
      ((consp inherit) (set-keymap-parents m inherit)))
@@ -141,5 +105,17 @@ is guaranteed to point to a newly created empty file."
 (defmacro defsyntax (st css doc &rest args)
   `(defconst ,st (custom-create-syntax ,css ,(cons 'list args)) doc))
 
+;;;; 
+;;;; Compatibility info
+;;;; 
+
+(defvar 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))))
+  "Whether this Emacs understands the `n' in syntax entries.")
+
 ;;
 (provide 'sml-util)