]> code.delx.au - gnu-emacs-elpa/commitdiff
First cut at support for MLton
authormonnier <>
Fri, 15 Jun 2007 00:32:05 +0000 (00:32 +0000)
committermonnier <>
Fri, 15 Jun 2007 00:32:05 +0000 (00:32 +0000)
ChangeLog
NEWS
TODO
sml-mode.el

index fbc462cddceb7d673ece3233d314bf18e094cc16..ed49fdfdcdb1542fc89ccc94082659a5bb08ecbe 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,16 @@
+2007-06-14  Stefan Monnier  <monnier@iro.umontreal.ca>
+
+       * sml-mode.el (sml-mode-variables): Set comment-quote-nested instead of
+       comment-nested.  Set comment-end-skip.
+       (sml-first-starter-p): New function.
+       (sml-indent-starter): Use it to fix an indentation bug.
+       (sml-mlton-command, sml-mlton-mainfile): New vars.
+       (sml-mlton-typecheck): New command.
+       (sml-defuse-file): New var.
+       (sml-defuse-def-regexp, sml-defuse-use-regexp-format): New consts.
+       (sml-defuse-file, sml-defuse-symdata-at-point): New functions.
+       (sml-defuse-set-file, sml-defuse-jump-to-def): New commands.
+
 2005-11-20  Stefan Monnier  <monnier@iro.umontreal.ca>
 
        * sml-move.el (sml-find-match-forward): Avoid infinite looping if the
diff --git a/NEWS b/NEWS
index 3dc7eb8267316ff1aeafb645eb56f4409685b74e..a34a30af23ff3fa15134448eccd44840f8d9f61a 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -1,3 +1,9 @@
+Changes since 4.0:
+
+* Simple support to parse errors and warnings in MLton's output.
+
+* Simple support for MLton's def-use files.
+
 Changes since 3.9.5:
 
 * No need to add the dir to your load-path any more.
diff --git a/TODO b/TODO
index 19cd7516ddf100bfd8774ecc747a64d1c01b0f58..3c61a09fc098fc6b1613bc4ef0a4b3d7ad35c37a 100644 (file)
--- a/TODO
+++ b/TODO
@@ -1,3 +1,6 @@
+* Add support for MLton's def-use info (see http://mlton.org/Emacs)
+
+* Add an sml-mlb-mode for ML Basis files (see http://mlton.org/Emacs)
 
 * 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.
@@ -12,8 +15,6 @@
 
 * use symbols instead of strings for `sym'.
 
-* ignore warnings in C-x ` ????
-
 * recognize irrefutable patterns (with "Capital"-heuristics, for example:
   a regexp like "\\([(),]\\|[_a-z][_a-z0-9]*\\)+").
   This can then be used to allow indenting like
index 05485ac4107715675cf3e498c94a0c96770e7399..085d7a8acfd35d31d6519f40dd23f1f8019f2698 100644 (file)
@@ -417,16 +417,13 @@ This mode runs `sml-mode-hook' just before exiting.
 (defun sml-mode-variables ()
   (set-syntax-table sml-mode-syntax-table)
   (setq local-abbrev-table sml-mode-abbrev-table)
-  ;; A paragraph is separated by blank lines or ^L only.
-  
   (set (make-local-variable '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-start-skip) "(\\*+\\s-*")
+  (set (make-local-variable 'comment-end-skip) "\\s-*\\*+)")
+  ;; No need to quote nested comments markers.
+  (set (make-local-variable 'comment-quote-nested) nil))
 
 (defun sml-funname-of-and ()
   "Name of the function this `and' defines, or nil if not a function.
@@ -594,6 +591,16 @@ If anyone has a good algorithm for this..."
 (defsubst sml-bolp ()
   (save-excursion (skip-chars-backward " \t|") (bolp)))
 
+(defun sml-first-starter-p ()
+  "Non-nil if starter at point is immediately preceded by let/local/in/..."
+  (save-excursion
+    (let ((sym (unless (save-excursion (sml-backward-arg))
+                 (sml-backward-spaces)
+                 (sml-backward-sym))))
+      (if (member sym '(";" "d=")) (setq sym nil))
+      sym)))
+
+
 (defun sml-indent-starter (orig-sym)
   "Return the indentation to use for a symbol in `sml-starters-syms'.
 Point should be just before the symbol ORIG-SYM and is not preserved."
@@ -604,9 +611,10 @@ Point should be just before the symbol ORIG-SYM and is not preserved."
     (if sym (sml-get-sym-indent sym)
       ;; FIXME: this can take a *long* time !!
       (setq sym (sml-find-matching-starter sml-starters-syms))
-      ;; Don't align with `and' because it might be specially indented.
-      (if (and (or (equal orig-sym "and") (not (equal sym "and")))
-              (sml-bolp))
+      (if (or (sml-first-starter-p)
+              ;; Don't align with `and' because it might be specially indented.
+              (and (or (equal orig-sym "and") (not (equal sym "and")))
+                   (sml-bolp)))
          (+ (current-column)
             (if (and sml-rightalign-and (equal orig-sym "and"))
                 (- (length sym) 3) 0))
@@ -849,6 +857,7 @@ signature, structure, and functor by default.")
 (defmacro sml-def-skeleton (name interactor &rest elements)
   (when (fboundp 'define-skeleton)
     (let ((fsym (intern (concat "sml-form-" name))))
+      ;; TODO: don't do the expansion in comments and strings.
       `(progn
         (add-to-list 'sml-forms-alist ',(cons name fsym))
         (condition-case err
@@ -974,9 +983,113 @@ 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))))
 
-;;;;
-;;;;  SML/NJ's Compilation Manager support
-;;;;
+;;;
+;;; MLton support
+;;;
+
+(defvar sml-mlton-command "mlton"
+  "Command to run MLton.   Can include arguments.")
+
+(defvar sml-mlton-mainfile nil)
+
+(defun sml-mlton-typecheck (mainfile)
+  "typecheck using MLton."
+  (interactive
+   (list (if (and mainfile (not current-prefix-arg))
+             mainfile
+           (read-file-name "Main file: "))))
+  (save-some-buffers)
+  (require 'compile)
+  (add-to-list
+   'compilation-error-regexp-alist
+   ;; I wish they just changed MLton to use one of the standard
+   ;; error formats.
+   `("^\\(?:Error\\|\\(Warning\\)\\): \\(.+\\) \\([0-9]+\\)\\.\\([0-9]+\\)\\."
+     2 3 4
+     ;; If subgroup 1 matched, then it's a warning, otherwise it's an error.
+     ,@(if (fboundp 'compilation-fake-loc) '((1)))))
+  (with-current-buffer (find-file-noselect mainfile)
+    (compile (concat sml-mlton-command
+                     " -stop tc "       ;Stop right after type checking.
+                     (shell-quote-argument
+                      (file-relative-name buffer-file-name))))))
+
+;;;
+;;; MLton's def-use info.
+;;;
+
+(defvar sml-defuse-file nil)
+
+(defun sml-defuse-file ()
+  (or sml-defuse-file (sml-defuse-set-file)))
+
+(defun sml-defuse-set-file ()
+  "Specify the def-use file to use."
+  (interactive)
+  (setq sml-defuse-file (read-file-name "Def-use file: ")))
+
+(defun sml-defuse-symdata-at-point ()
+  (save-excursion
+    (sml-forward-sym)
+    (let ((symname (sml-backward-sym)))
+      (if (equal symname "op")
+          (save-excursion (setq symname (sml-forward-sym))))
+      (when (string-match "op " symname)
+        (setq symname (substring symname (match-end 0)))
+        (forward-word)
+        (sml-forward-spaces))
+      (list symname
+            ;; Def-use files seem to count chars, not columns.
+            ;; We hope here that they don't actually count bytes.
+            ;; Also they seem to start counting at 1.
+            (1+ (- (point) (progn (beginning-of-line) (point))))
+            (save-restriction
+              (widen) (1+ (count-lines (point-min) (point))))
+            buffer-file-name))))
+
+(defconst sml-defuse-def-regexp
+  "^[[:alpha:]]+ \\([^ \n]+\\) \\(.+\\) \\([0-9]+\\)\\.\\([0-9]+\\)$")
+(defconst sml-defuse-use-regexp-format "^    %s %d\\.%d $")
+
+(defun sml-defuse-jump-to-def ()
+  "Jump to the definition corresponding to the symbol at point."
+  (interactive)
+  (let ((symdata (sml-defuse-symdata-at-point)))
+    (if (null (car symdata))
+        (error "Not on a symbol")
+      (with-current-buffer (find-file-noselect (sml-defuse-file))
+        (goto-char (point-min))
+        (unless (re-search-forward
+                 (format sml-defuse-use-format
+                         (concat "\\(?:"
+                                 ;; May be an absolute file name.
+                                 (regexp-quote (nth 3 symdata))
+                                 "\\|"
+                                 ;; Or a relative file name.
+                                 (regexp-quote (file-relative-name
+                                                (nth 3 symdata)))
+                                 "\\)")
+                         (nth 2 symdata)
+                         (nth 1 symdata))
+                 nil t)
+          ;; FIXME: This is typically due to editing: any minor editing will
+          ;; mess everything up.  We should try to fail more gracefully.
+          (error "Def-use info not found"))
+        (unless (re-search-backward sml-defuse-def-regexp nil t)
+          ;; This indicates a bug in this code.
+          (error "Internal failure while looking up def-use"))
+        (unless (equal (match-string 1) (nth 0 symdata))
+          ;; FIXME: This again is most likely due to editing.
+          (error "Incoherence in the def-use info found"))
+        (let ((line (string-to-number (match-string 3)))
+              (char (string-to-number (match-string 4))))
+          (pop-to-buffer (find-file-noselect (match-string 2)))
+          (goto-line line)
+          (forward-char (1- char)))))))
+
+;;;
+;;; SML/NJ's Compilation Manager support
+;;;
 
 (defvar sml-cm-mode-syntax-table sml-mode-syntax-table)
 (defvar sml-cm-font-lock-keywords
@@ -984,8 +1097,9 @@ See also `edit-kbd-macro' which is bound to \\[edit-kbd-macro]."
                                "functor" "signature" "funsig") t)
            "\\>")))
 ;;;###autoload
-(add-to-list 'completion-ignored-extensions "CM/")
 (add-to-list 'completion-ignored-extensions ".cm/")
+;; This was used with the old compilation manager.
+(add-to-list 'completion-ignored-extensions "CM/")
 ;;;###autoload
 (add-to-list 'auto-mode-alist '("\\.cm\\'" . sml-cm-mode))
 ;;;###autoload
@@ -995,9 +1109,9 @@ See also `edit-kbd-macro' which is bound to \\[edit-kbd-macro]."
   (set (make-local-variable 'font-lock-defaults)
        '(sml-cm-font-lock-keywords nil t nil nil)))
 
-;;;;
-;;;; ML-Lex support
-;;;;
+;;;
+;;; ML-Lex support
+;;;
 
 (defvar sml-lex-font-lock-keywords
   (append
@@ -1012,9 +1126,9 @@ See also `edit-kbd-macro' which is bound to \\[edit-kbd-macro]."
   "Major Mode for editing ML-Lex files."
   (set (make-local-variable 'font-lock-defaults) sml-lex-font-lock-defaults))
 
-;;;;
-;;;; ML-Yacc support
-;;;;
+;;;
+;;; ML-Yacc support
+;;;
 
 (defface sml-yacc-bnf-face
   '((t (:foreground "darkgreen")))