]> code.delx.au - gnu-emacs-elpa/blobdiff - sml-mode.el
Merge from trunk
[gnu-emacs-elpa] / sml-mode.el
index 3d42b34509e082b6d01cc299d2153147f9d4b97d..9d8698216e9fbc8bc631d4b3051d8d99b691d02b 100644 (file)
 
 (eval-when-compile (require 'cl))
 (require 'sml-defs)
-(require 'sml-oldindent)
-
-(defvar sml-use-smie t)
-
 (require 'smie nil 'noerror)
-(unless (and sml-use-smie (fboundp 'smie-setup))
-  (require 'sml-oldindent))
 
 (condition-case nil (require 'skeleton) (error nil))
 
@@ -87,7 +81,7 @@
   :type '(integer))
 
 (defcustom sml-indent-args sml-indent-level
-  "*Indentation of args placed on a separate line."
+  "Indentation of args placed on a separate line."
   :group 'sml
   :type '(integer))
 
 ;; seems nicer...")
 
 (defcustom sml-electric-semi-mode nil
-  "*If non-nil, `\;' will self insert, reindent the line, and do a newline.
+  "If non-nil, `\;' will self insert, reindent the line, and do a newline.
 If nil, just insert a `\;'.  (To insert while t, do: \\[quoted-insert] \;)."
   :group 'sml
   :type 'boolean)
+(when (fboundp 'electric-layout-mode)
+  (make-obsolete-variable 'sml-electric-semi-mode
+                          'electric-layout-mode "Emacs-24"))
 
 (defcustom sml-rightalign-and t
   "If non-nil, right-align `and' with its leader.
@@ -362,6 +359,10 @@ Regexp match data 0 points to the chars."
 
 ;;; Indentation with SMIE
 
+(defvar sml-use-smie t)
+(unless (and sml-use-smie (fboundp 'smie-setup))
+  (require 'sml-oldindent))
+
 (defconst sml-smie-grammar
   (when (fboundp 'smie-prec2->grammar)
     ;; We have several problem areas where SML's syntax can't be handled by an
@@ -577,11 +578,12 @@ Assumes point is right before the \"of\" symbol."
 Assumes point is right before the | symbol."
   (save-excursion
     (forward-char 1)                    ;Skip the |.
-    (sml-smie-forward-token-1)          ;Skip the tag.
-    (member (sml-smie-forward-token-1)
-            '("|" "of" "in" "datatype" "and" "exception" "abstype" "infix"
-              "infixr" "nonfix" "local" "val" "fun" "structure" "functor"
-              "signature"))))
+    (let ((after-type-def
+           '("|" "of" "in" "datatype" "and" "exception" "abstype" "infix"
+             "infixr" "nonfix" "local" "val" "fun" "structure" "functor"
+             "signature")))
+      (or (member (sml-smie-forward-token-1) after-type-def) ;Skip the tag.
+          (member (sml-smie-forward-token-1) after-type-def)))))
 
 (defun sml-smie-forward-token-1 ()
   (forward-comment (point-max))
@@ -664,8 +666,13 @@ Assumes point is right before the | symbol."
 ;;;###autoload
 (add-to-list 'auto-mode-alist '("\\.s\\(ml\\|ig\\)\\'" . sml-mode))
 
+(unless (fboundp 'prog-mode) (defalias 'prog-mode 'fundamental-mode))
+(defvar comment-quote-nested)
+(defvar electric-indent-chars)
+(defvar electric-layout-rules)
+
 ;;;###autoload
-(define-derived-mode sml-mode fundamental-mode "SML"
+(define-derived-mode sml-mode prog-mode "SML"
   "\\<sml-mode-map>Major mode for editing ML code.
 This mode runs `sml-mode-hook' just before exiting.
 \\{sml-mode-map}"
@@ -679,26 +686,34 @@ This mode runs `sml-mode-hook' just before exiting.
   (set (make-local-variable 'paragraph-separate)
        (concat "\\([ \t]*\\*)?\\)?\\(" paragraph-separate "\\)"))
   (set (make-local-variable 'require-final-newline) t)
+  (set (make-local-variable 'electric-indent-chars)
+       (cons ?\; (if (boundp 'electric-indent-chars)
+                     electric-indent-chars '(?\n))))
+  (set (make-local-variable 'electric-layout-rules)
+       `((?\; . ,(lambda ()
+                   (save-excursion
+                     (skip-chars-backward " \t;")
+                     (unless (or (bolp)
+                                 (progn (skip-chars-forward " \t;")
+                                        (eolp)))
+                       'after))))))
   ;; For XEmacs
   (easy-menu-add sml-mode-menu)
   ;; Compatibility.  FIXME: we should use `-' in Emacs-CVS.
   (unless (boundp 'skeleton-positions) (set (make-local-variable '@) nil))
   (sml-mode-variables))
 
-(defvar comment-quote-nested)
-
 (defun sml-mode-variables ()
   (set-syntax-table sml-mode-syntax-table)
   (setq local-abbrev-table sml-mode-abbrev-table)
   ;; Setup indentation and sexp-navigation.
-  (cond
-   ((and sml-use-smie (fboundp 'smie-setup))
+  (when (fboundp 'smie-setup)
     (smie-setup sml-smie-grammar #'sml-smie-rules
                 :backward-token #'sml-smie-backward-token
                 :forward-token #'sml-smie-forward-token))
-   (t
+  (unless (and sml-use-smie (fboundp 'smie-setup))
     (set (make-local-variable 'forward-sexp-function) 'sml-user-forward-sexp)
-    (set (make-local-variable 'indent-line-function) 'sml-indent-line)))
+    (set (make-local-variable 'indent-line-function) 'sml-indent-line))
   (set (make-local-variable 'parse-sexp-ignore-comments) t)
   (set (make-local-variable 'comment-start) "(* ")
   (set (make-local-variable 'comment-end) " *)")
@@ -732,16 +747,19 @@ Depending on the context insert the name of function, a \"=>\" etc."
   (insert "| ")
   (let ((text
          (save-excursion
-           (funcall forward-sexp-function -1)
-           (let ((sym (save-excursion (sml-smie-backward-token))))
+           (backward-char 2)           ;back over the just inserted "| "
+           (let ((sym (sml-find-matching-starter sml-pipeheads
+                                                 ;; (sml-op-prec "|" 'back)
+                                                 )))
+             (sml-smie-forward-token)
              (forward-comment (point-max))
              (cond
               ((string= sym "|")
                (let ((f (sml-smie-forward-token)))
                  (sml-find-forward "\\(=>\\|=\\||\\)\\S.")
                  (cond
-                  ((looking-at "|") "")       ;probably a datatype
-                  ((looking-at "=>") " => ")  ;`case', or `fn' or `handle'
+                  ((looking-at "|") "")      ;probably a datatype
+                  ((looking-at "=>") " => ") ;`case', or `fn' or `handle'
                   ((looking-at "=") (concat f "  = "))))) ;a function
               ((string= sym "and")
                ;; could be a datatype or a function
@@ -770,7 +788,7 @@ Depending on the context insert the name of function, a \"=>\" etc."
 If variable `sml-electric-semi-mode' is t, indent the current line, insert
 a newline, and indent."
   (interactive)
-  (insert "\;")
+  (self-insert-command 1)
   (if sml-electric-semi-mode
       (reindent-then-newline-and-indent)))
 
@@ -799,14 +817,45 @@ If anyone has a good algorithm for this..."
                   (setq indent 0))))
             (backward-delete-char-untabify (- start-column indent)))))))
 
+(defun sml-smie-find-matching-starter (syms)
+  (let ((halfsexp nil)
+        tok)
+    ;;(sml-smie-forward-token)
+    (while (not (or (bobp)
+                    (member (nth 2 (setq tok (smie-backward-sexp halfsexp)))
+                            syms)))
+      (cond
+       ((null (car tok)) nil)
+       ((numberp (car tok)) (setq halfsexp 'half))
+       (t (goto-char (cadr tok)))))
+    (if (nth 2 tok) (goto-char (cadr tok)))
+    (nth 2 tok)))
+
+(defun sml-find-matching-starter (syms)
+  (cond
+   ((and sml-use-smie (fboundp 'smie-backward-sexp))
+    (sml-smie-find-matching-starter syms))
+   ((fboundp 'sml-old-find-matching-starter)
+    (sml-old-find-matching-starter syms))))
+
+(defun sml-smie-skip-siblings ()
+  (let (tok)
+    (while (and (not (bobp))
+                (progn (setq tok (smie-backward-sexp 'half))
+                       (cond
+                        ((null (car tok)) t)
+                        ((numberp (car tok)) t)
+                        (t nil)))))
+    (if (nth 2 tok) (goto-char (cadr tok)))
+    (nth 2 tok)))
+
 (defun sml-skip-siblings ()
-  (while (and (not (bobp)) (sml-backward-arg))
-    (sml-find-matching-starter sml-starters-syms))
-  (when (looking-at "in\\>\\|local\\>")
-    ;;skip over `local...in' and continue
-    (forward-word 1)
-    (sml-backward-sexp nil)
-    (sml-skip-siblings)))
+  (cond
+   ((and sml-use-smie (fboundp 'smie-backward-sexp))
+    (sml-smie-skip-siblings))
+   ((fboundp 'sml-old-skip-siblings)
+    (sml-old-skip-siblings))
+   (t (up-list -1))))
 
 (defun sml-beginning-of-defun ()
   (let ((sym (sml-find-matching-starter sml-starters-syms)))
@@ -1043,7 +1092,7 @@ See also `edit-kbd-macro' which is bound to \\[edit-kbd-macro]."
 (defun sml-defuse-symdata-at-point ()
   (save-excursion
     (sml-smie-forward-token)
-    (let ((symname (sml-backward-sym)))
+    (let ((symname (sml-smie-backward-token)))
       (if (equal symname "op")
           (save-excursion (setq symname (sml-smie-forward-token))))
       (when (string-match "op " symname)
@@ -1217,7 +1266,10 @@ If nil, align it with previous cases."
                (skip-syntax-forward " ")
                (- (current-column) 2))))))
        ;; default to SML rules
-       (sml-calculate-indentation))))
+        (cond
+         ((and sml-use-smie (fboundp 'smie-indent-calculate))
+          (smie-indent-calculate))
+         ((fboundp 'sml-calculate-indentation) (sml-calculate-indentation))))))
 
 ;;;###autoload
 (add-to-list 'auto-mode-alist '("\\.grm\\'" . sml-yacc-mode))