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.
sml-mode.cp
+sml-mode.cps
sml-mode.fn
sml-mode.fns
sml-mode.info
* 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
+ )
+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
# 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.
SHELL = /bin/sh
DVIPS = dvips
CP = cp
+RM = rm -f
MKDIR = mkdir -p
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
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)
### 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 "."
##
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$
--*- 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:
--*- 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:
--- /dev/null
+PACKAGE = sml-mode
+ELFILES = sml-compat.el sml-util.el sml-defs.el sml-move.el sml-mode.el \
+ sml-proc.el
(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)
;;("\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")
("._'" . "_")
["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.")
;;
+++ /dev/null
-;;;
-;;; 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:
-;;; 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!")))))
"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
(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))
(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
;;; 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)
(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 \"|\".
(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")
(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 "\;")
;;; 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))
;; (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"))
(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."
(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))
(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.")
(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
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.
(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
-;;; 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
;; 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.
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>
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.")
(defconst inferior-sml-font-lock-defaults
'(inferior-sml-font-lock-keywords nil nil nil nil))
+
;;; CODE
(defmap inferior-sml-mode-map
(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))
;; 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:
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.
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)
;; 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.
(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
(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)
;; 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))
(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
;;; 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
(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."
(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))))
(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
(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
;;; 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
: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)))
(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)