]> code.delx.au - gnu-emacs-elpa/commitdiff
* sml-mode.el (sml-electric-pipe-mode): New var.
authorStefan Monnier <monnier@iro.umontreal.ca>
Fri, 19 Oct 2012 16:16:07 +0000 (12:16 -0400)
committerStefan Monnier <monnier@iro.umontreal.ca>
Fri, 19 Oct 2012 16:16:07 +0000 (12:16 -0400)
(sml-pipeheads): Add (, {, and [ to more reliably detect cases where
the pipe is not part of a case/fun/...
(sml-tyvarseq-re): Use shy groups.
(sml-font-lock-keywords): Adjust accordingly.
(sml-compile): Avoid the 3rd part of dolist's spec.
(sml-post-self-insert-pipe): New fun, extracted from sml-electric-pipe.
(sml-mode): Use it to obey sml-electric-pipe-mode.
(sml-electric-pipe): Use sml-post-self-insert-pipe.
* makefile.pkg (ELFILES): Remove sml-proc.el.
* prog-proc.el: Rename from sml-prog-proc.el.

ChangeLog
makefile.pkg
prog-proc.el [moved from sml-prog-proc.el with 62% similarity]
sml-mode.el

index c596a5340a9854ccb54738426e199300fece86f5..f7f160303ae94ee453371eeb868b7659b0a7705b 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,19 @@
+2012-10-19  Stefan Monnier  <monnier@iro.umontreal.ca>
+
+       * sml-mode.el (sml-electric-pipe-mode): New var.
+       (sml-pipeheads): Add (, {, and [ to more reliably detect cases where
+       the pipe is not part of a case/fun/...
+       (sml-tyvarseq-re): Use shy groups.
+       (sml-font-lock-keywords): Adjust accordingly.
+       (sml-compile): Avoid the 3rd part of dolist's spec.
+       (sml-post-self-insert-pipe): New fun, extracted from sml-electric-pipe.
+       (sml-mode): Use it to obey sml-electric-pipe-mode.
+       (sml-electric-pipe): Use sml-post-self-insert-pipe.
+
+       * prog-proc.el: Rename from sml-prog-proc.el.
+
+       * makefile.pkg (ELFILES): Remove sml-proc.el.
+
 2012-04-11  Stefan Monnier  <monnier@iro.umontreal.ca>
 
        Merge sml-defs.el into sml-mode.el.
index d43bf3f526e6b07f6ff6c9cbefcfb14d2d833701..2dcbd54df0a2f6a568c6d90e5f236f0d70c15a9d 100644 (file)
@@ -1,5 +1,5 @@
 PACKAGE = sml-mode
-ELFILES        = sml-mode.el sml-proc.el sml-prog-proc.el
+ELFILES        = sml-mode.el prog-proc.el
 
 default: elcfiles
 
similarity index 62%
rename from sml-prog-proc.el
rename to prog-proc.el
index 7c692bfe945b8ad34553e8f685e2f3a2e9eb2afc..0a643bca77b3b18d82890e7383aae3ab31c66c38 100644 (file)
@@ -1,4 +1,4 @@
-;;; sml-prog-proc.el --- Interacting from a source buffer with an inferior process   -*- lexical-binding: t; coding: utf-8 -*-
+;;; prog-proc.el --- Interacting from a source buffer with an inferior process   -*- lexical-binding: t; coding: utf-8 -*-
 
 ;; Copyright (C) 1999,2000,2003,2004,2005,2007,2012  Stefan Monnier
 ;; Copyright (C) 1994-1997  Matthew J. Morley
 (require 'comint)
 (require 'compile)
 
-(defvar sml-prog-proc-mode-map
+(defvar prog-proc-mode-map
   (let ((map (make-sparse-keymap)))
-    (define-key map [?\C-c ?\C-l] 'sml-prog-proc-load-file)
-    (define-key map [?\C-c ?\C-c] 'sml-prog-proc-compile)
-    (define-key map [?\C-c ?\C-z] 'sml-prog-proc-switch-to)
-    (define-key map [?\C-c ?\C-r] 'sml-prog-proc-send-region)
-    (define-key map [?\C-c ?\C-b] 'sml-prog-proc-send-buffer)
+    (define-key map [?\C-c ?\C-l] 'prog-proc-load-file)
+    (define-key map [?\C-c ?\C-c] 'prog-proc-compile)
+    (define-key map [?\C-c ?\C-z] 'prog-proc-switch-to)
+    (define-key map [?\C-c ?\C-r] 'prog-proc-send-region)
+    (define-key map [?\C-c ?\C-b] 'prog-proc-send-buffer)
     map)
-  "Keymap for `sml-prog-proc-mode'.")
+  "Keymap for `prog-proc-mode'.")
 
-(defvar sml-prog-proc--buffer nil
+(defvar prog-proc--buffer nil
   "The inferior-process buffer to which to send code.")
-(make-variable-buffer-local 'sml-prog-proc--buffer)
+(make-variable-buffer-local 'prog-proc--buffer)
 
-(defstruct (sml-prog-proc-functions
-            (:constructor sml-prog-proc-make)
+(defstruct (prog-proc-functions
+            (:constructor prog-proc-make)
             (:predicate nil)
             (:copier nil))
   (name :read-only t)
   (load-cmd :read-only t)
   (chdir-cmd :read-only t))
 
-(defvar sml-prog-proc-functions nil
+(defvar prog-proc-functions nil
   "Struct containing the various functions to create a new process, ...")
 
-(defmacro sml-prog-proc--call (method &rest args)
-  `(sml-prog-proc--funcall
-    #',(intern (format "sml-prog-proc-functions-%s" method))
+(defmacro prog-proc--call (method &rest args)
+  `(prog-proc--funcall
+    #',(intern (format "prog-proc-functions-%s" method))
     ,@args))
-(defun sml-prog-proc--funcall (selector &rest args)
-  (if (not sml-prog-proc-functions)
+(defun prog-proc--funcall (selector &rest args)
+  (if (not prog-proc-functions)
       ;; FIXME: Look for available ones and pick one.
-      (error "Not an `sml-prog-proc' buffer")
-    (apply (funcall selector sml-prog-proc-functions) args)))
+      (error "Not an `prog-proc' buffer")
+    (apply (funcall selector prog-proc-functions) args)))
 
 ;; The inferior process and his buffer are basically interchangeable.
-;; Currently the code takes sml-prog-proc--buffer as the main reference,
-;; but all users should either use sml-prog-proc-proc or sml-prog-proc-buffer
+;; Currently the code takes prog-proc--buffer as the main reference,
+;; but all users should either use prog-proc-proc or prog-proc-buffer
 ;; to find the info.
 
-(defun sml-prog-proc-proc ()
+(defun prog-proc-proc ()
   "Return the inferior process for the code in current buffer."
-  (or (and (buffer-live-p sml-prog-proc--buffer)
-           (get-buffer-process sml-prog-proc--buffer))
-      (when (derived-mode-p 'sml-prog-proc-mode 'sml-prog-proc-comint-mode)
-        (setq sml-prog-proc--buffer (current-buffer))
-        (get-buffer-process sml-prog-proc--buffer))
-      (let ((buf (sml-prog-proc--call run)))
-        (setq sml-prog-proc--buffer buf)
-        (get-buffer-process sml-prog-proc--buffer))))
-
-(defun sml-prog-proc-buffer ()
+  (or (and (buffer-live-p prog-proc--buffer)
+           (get-buffer-process prog-proc--buffer))
+      (when (derived-mode-p 'prog-proc-mode 'prog-proc-comint-mode)
+        (setq prog-proc--buffer (current-buffer))
+        (get-buffer-process prog-proc--buffer))
+      (let ((buf (prog-proc--call run)))
+        (setq prog-proc--buffer buf)
+        (get-buffer-process prog-proc--buffer))))
+
+(defun prog-proc-buffer ()
   "Return the buffer of the inferior process."
-  (process-buffer (sml-prog-proc-proc)))
+  (process-buffer (prog-proc-proc)))
 
-(defun sml-prog-proc-switch-to ()
+(defun prog-proc-switch-to ()
   "Switch to the buffer running the read-eval-print process."
-  (pop-to-buffer (sml-prog-proc-buffer)))
+  (pop-to-buffer (prog-proc-buffer)))
 
-(defun sml-prog-proc-send-string (proc str)
+(defun prog-proc-send-string (proc str)
   (with-current-buffer (process-buffer proc)
     ;; FIXME: comint-send-string does not pass the string through
     ;; comint-input-filter-function, so we have to do it by hand.
     ;; Maybe we should insert the command into the buffer and then call
     ;; comint-send-input?
-    (sml-prog-proc-comint-input-filter-function nil)
+    (prog-proc-comint-input-filter-function nil)
     (comint-send-string proc (concat str "\n"))))
     
-(defun sml-prog-proc-load-file (file &optional and-go)
+(defun prog-proc-load-file (file &optional and-go)
   "Load FILE into the read-eval-print process.
 FILE is the file visited by the current buffer.
 If prefix argument AND-GO is used, then we additionally switch
@@ -121,63 +121,63 @@ to the buffer where the process is running."
              (read-file-name "File to load: " nil nil t))
          current-prefix-arg))
   (comint-check-source file)
-  (let ((proc (sml-prog-proc-proc)))
-    (sml-prog-proc-send-string proc (sml-prog-proc--call load-cmd file))
+  (let ((proc (prog-proc-proc)))
+    (prog-proc-send-string proc (prog-proc--call load-cmd file))
     (when and-go (pop-to-buffer (process-buffer proc)))))
 
-(defvar sml-prog-proc--tmp-file nil)
+(defvar prog-proc--tmp-file nil)
 
-(defun sml-prog-proc-send-region (start end &optional and-go)
+(defun prog-proc-send-region (start end &optional and-go)
   "Send the content of the region to the read-eval-print process.
 START..END delimit the region; AND-GO if non-nil indicate to additionally
 switch to the process's buffer."
   (interactive "r\nP")
   (if (> start end) (let ((tmp end)) (setq end start) (setq start tmp))
     (if (= start end) (error "Nothing to send: the region is empty")))
-  (let ((proc (sml-prog-proc-proc))
+  (let ((proc (prog-proc-proc))
         (tmp (make-temp-file "emacs-region")))
     (write-region start end tmp nil 'silently)
-    (when sml-prog-proc--tmp-file
-      (ignore-errors (delete-file (car sml-prog-proc--tmp-file)))
-      (set-marker (cdr sml-prog-proc--tmp-file) nil))
-    (setq sml-prog-proc--tmp-file (cons tmp (copy-marker start)))
-    (sml-prog-proc-send-string proc (sml-prog-proc--call load-cmd tmp))
+    (when prog-proc--tmp-file
+      (ignore-errors (delete-file (car prog-proc--tmp-file)))
+      (set-marker (cdr prog-proc--tmp-file) nil))
+    (setq prog-proc--tmp-file (cons tmp (copy-marker start)))
+    (prog-proc-send-string proc (prog-proc--call load-cmd tmp))
     (when and-go (pop-to-buffer (process-buffer proc)))))
 
-(defun sml-prog-proc-send-buffer (&optional and-go)
+(defun prog-proc-send-buffer (&optional and-go)
   "Send the content of the current buffer to the read-eval-print process.
 AND-GO if non-nil indicate to additionally switch to the process's buffer."
   (interactive "P")
-  (sml-prog-proc-send-region (point-min) (point-max) and-go))
+  (prog-proc-send-region (point-min) (point-max) and-go))
 
 ;; FIXME: How 'bout a menu?  Now, that's trickier because keymap inheritance
 ;; doesn't play nicely with menus!
 
-(define-derived-mode sml-prog-proc-mode prog-mode "Prog-Proc"
+(define-derived-mode prog-proc-mode prog-mode "Prog-Proc"
   "Major mode for editing source code and interact with an interactive loop."
   )
 
 ;;; Extended comint-mode for Prog-Proc.
 
-(defun sml-prog-proc-chdir (dir)
+(defun prog-proc-chdir (dir)
   "Change the working directory of the inferior process."
   (interactive "DChange to directory: ")
   (let ((dir (expand-file-name dir))
-        (proc (sml-prog-proc-proc)))
+        (proc (prog-proc-proc)))
     (with-current-buffer (process-buffer proc)
-      (sml-prog-proc-send-string proc (sml-prog-proc--call chdir-cmd dir))
+      (prog-proc-send-string proc (prog-proc--call chdir-cmd dir))
       (setq default-directory (file-name-as-directory dir)))))
 
-(defun sml-prog-proc-comint-input-filter-function (str)
+(defun prog-proc-comint-input-filter-function (str)
   ;; `compile.el' doesn't know that file location info from errors should be
   ;; recomputed afresh (without using stale info from earlier compilations).
   (compilation-forget-errors)       ;Has to run before compilation-fake-loc.
-  (if sml-prog-proc--tmp-file
-      (compilation-fake-loc (cdr sml-prog-proc--tmp-file)
-                            (car sml-prog-proc--tmp-file)))
+  (if prog-proc--tmp-file
+      (compilation-fake-loc (cdr prog-proc--tmp-file)
+                            (car prog-proc--tmp-file)))
   str)
 
-(define-derived-mode sml-prog-proc-comint-mode comint-mode "Prog-Proc-Comint"
+(define-derived-mode prog-proc-comint-mode comint-mode "Prog-Proc-Comint"
   "Major mode for an inferior process used to run&compile source code."
   ;; Enable compilation-minor-mode, but only after the child mode is setup
   ;; since the child-mode might want to add rules to
@@ -194,7 +194,7 @@ AND-GO if non-nil indicate to additionally switch to the process's buffer."
                  (cons 'compilation-minor-mode map)))
 
   (add-hook 'comint-input-filter-functions
-            #'sml-prog-proc-comint-input-filter-function nil t))
+            #'prog-proc-comint-input-filter-function nil t))
 
-(provide 'sml-prog-proc)
-;;; sml-prog-proc.el ends here
+(provide 'prog-proc)
+;;; prog-proc.el ends here
index cdf7759b514ca07b4fbc305099aa66f76c6c3354..83cba3ddbe085d98a4fdae058687614a6b890825 100644 (file)
@@ -69,7 +69,8 @@
 
 (eval-when-compile (require 'cl))
 (require 'smie nil 'noerror)
-(require 'sml-prog-proc)
+(require 'electric)
+(require 'prog-proc)
 
 (defgroup sml ()
   "Editing SML code."
@@ -90,6 +91,10 @@ If nil:                                      If t:
        and b = B                                    and b = B"
   :type 'boolean)
 
+(defcustom sml-electric-pipe-mode t
+  "If non-nil, automatically insert appropriate template when hitting |."
+  :type 'boolean)
+
 (defvar sml-mode-hook nil
   "Run upon entering `sml-mode'.
 This is a good place to put your preferred key bindings.")
@@ -208,7 +213,8 @@ notion of \"the end of an outline\".")
   "The starters of new expressions.")
 
 (defconst sml-pipeheads
-   '("|" "of" "fun" "fn" "and" "handle" "datatype" "abstype")
+  '("|" "of" "fun" "fn" "and" "handle" "datatype" "abstype"
+    "(" "{" "[")
    "A `|' corresponds to one of these.")
 
 (defconst sml-keywords-regexp
@@ -225,7 +231,7 @@ notion of \"the end of an outline\".")
   (defconst sml-id-re "\\sw\\(?:\\sw\\|\\s_\\)*"))
 
 (defconst sml-tyvarseq-re
-  (concat "\\(\\('+" sml-id-re "\\|(\\([,']\\|" sml-id-re
+  (concat "\\(?:\\(?:'+" sml-id-re "\\|(\\(?:[,']\\|" sml-id-re
           "\\|\\s-\\)+)\\)\\s-+\\)?"))
 
 ;;; Font-lock settings ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
@@ -294,16 +300,15 @@ Regexp match data 0 points to the chars."
     (,(concat "\\_<\\(fun\\|and\\)\\s-+" sml-tyvarseq-re
               "\\(" sml-id-re "\\)\\s-+[^ \t\n=]")
      (1 font-lock-keyword-face)
-     (6 font-lock-function-name-face))
-    (,(concat "\\_<\\(\\(data\\|abs\\|with\\|eq\\)?type\\)\\s-+"
+     (2 font-lock-function-name-face))
+    (,(concat "\\_<\\(\\(?:data\\|abs\\|with\\|eq\\)?type\\)\\s-+"
               sml-tyvarseq-re "\\(" sml-id-re "\\)")
      (1 font-lock-keyword-face)
-     (7 font-lock-type-def-face))
-    (,(concat "\\_<\\(val\\)\\s-+\\(" sml-id-re "\\_>\\s-*\\)?\\("
+     (2 font-lock-type-def-face))
+    (,(concat "\\_<\\(val\\)\\s-+\\(?:" sml-id-re "\\_>\\s-*\\)?\\("
               sml-id-re "\\)\\s-*[=:]")
      (1 font-lock-keyword-face)
-     ;;(6 font-lock-variable-def-face nil t)
-     (3 font-lock-variable-name-face))
+     (2 font-lock-variable-name-face))
     (,(concat "\\_<\\(structure\\|functor\\|abstraction\\)\\s-+\\("
               sml-id-re "\\)")
      (1 font-lock-keyword-face)
@@ -708,16 +713,16 @@ specified when running the command \\[sml-cd].")
 See `compilation-error-regexp-alist' for a description of the format.")
 
 (defconst sml-pp-functions
-  (sml-prog-proc-make :name "SML"
-                      :run (lambda () (call-interactively #'sml-run))
-                      :load-cmd (lambda (file)
-                                  ;; `sml-use-command' was defined a long time
-                                  ;; ago not to include a final semi-colon.
-                                  (concat (format sml-use-command file) ";"))
-                      :chdir-cmd (lambda (dir)
-                                   ;; `sml-cd-command' was defined a long time
-                                   ;; ago not to include a final semi-colon.
-                                   (concat (format sml-cd-command dir) ";"))))
+  (prog-proc-make :name "SML"
+                  :run (lambda () (call-interactively #'sml-run))
+                  :load-cmd (lambda (file)
+                              ;; `sml-use-command' was defined a long time
+                              ;; ago not to include a final semi-colon.
+                              (concat (format sml-use-command file) ";"))
+                  :chdir-cmd (lambda (dir)
+                               ;; `sml-cd-command' was defined a long time
+                               ;; ago not to include a final semi-colon.
+                               (concat (format sml-cd-command dir) ";"))))
 
 ;; font-lock support
 (defconst inferior-sml-font-lock-keywords
@@ -857,7 +862,7 @@ on which to run CMD using `remote-shell-program'.
               (smerge-refine-subst b1 e1 b2 e2
                                    '((face . smerge-refined-change))))))))))
 
-(define-derived-mode inferior-sml-mode sml-prog-proc-comint-mode "Inferior-SML"
+(define-derived-mode inferior-sml-mode prog-proc-comint-mode "Inferior-SML"
   "Major mode for interacting with an inferior ML process.
 
 The following commands are available:
@@ -950,9 +955,12 @@ Prefix arg AND-GO also means to `switch-to-sml' afterwards."
          (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))))
+                 (progn
+                   (dolist (cf sml-compile-commands-alist)
+                     (when (file-exists-p (expand-file-name (cdr cf) dir))
+                       (setq cmd (concat cmd "\"; " (car cf)))
+                       (return nil)))
+                   (not cmd)))
        (let ((newdir (file-name-directory (directory-file-name dir))))
         (setq dir (unless (equal newdir dir) newdir))
         (setq cmd (concat cmd "/.."))))
@@ -999,16 +1007,14 @@ Prefix arg AND-GO also means to `switch-to-sml' afterwards."
 (add-to-list 'auto-mode-alist '("\\.s\\(ml\\|ig\\)\\'" . sml-mode))
 
 (defvar comment-quote-nested)
-(defvar electric-indent-chars)
-(defvar electric-layout-rules)
 
 ;;;###autoload
-(define-derived-mode sml-mode sml-prog-proc-mode "SML"
+(define-derived-mode sml-mode prog-proc-mode "SML"
   "\\<sml-mode-map>Major mode for editing Standard ML code.
 This mode runs `sml-mode-hook' just before exiting.
 See also (info \"(sml-mode)Top\").
 \\{sml-mode-map}"
-  (set (make-local-variable 'sml-prog-proc-functions) sml-pp-functions)
+  (set (make-local-variable 'prog-proc-functions) sml-pp-functions)
   (set (make-local-variable 'font-lock-defaults) sml-font-lock-defaults)
   (set (make-local-variable 'outline-regexp) sml-outline-regexp)
   (set (make-local-variable 'imenu-create-index-function)
@@ -1030,6 +1036,8 @@ See also (info \"(sml-mode)Top\").
                                  (progn (skip-chars-forward " \t;")
                                         (eolp)))
                        'after))))))
+  (when sml-electric-pipe-mode
+    (add-hook 'post-self-insert-hook #'sml-post-self-insert-pipe nil t))
   (sml-mode-variables))
 
 (defun sml-mode-variables ()
@@ -1063,50 +1071,63 @@ Point has to be right after the `and' symbol and is not preserved."
                 (not (looking-at re)))
     (or (ignore-errors (forward-sexp 1) t) (forward-char 1))))
 
-(defun sml-electric-pipe ()             ;FIXME: Use post-self-insert-hook?
+(defun sml-electric-pipe ()
   "Insert a \"|\".
 Depending on the context insert the name of function, a \"=>\" etc."
-  ;; FIXME: Make it a skeleton.
   (interactive)
   (unless (save-excursion (skip-chars-backward "\t ") (bolp)) (insert "\n"))
   (insert "| ")
-  (let ((text
-         (save-excursion
-           (backward-char 2)           ;back over the just inserted "| "
-           (let ((sym (sml-find-matching-starter sml-pipeheads
-                                                 ;; (sml-op-prec "|" 'back)
-                                                 )))
-             (sml-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 "=") (concat f "  = "))))) ;a function
-              ((string= sym "and")
-               ;; could be a datatype or a function
-               (setq sym (sml-funname-of-and))
-               (if sym (concat sym "  = ") ""))
-              ;; trivial cases
-              ((string= sym "fun")
-               (while (and (setq sym (sml-smie-forward-token))
-                           (string-match "^'" sym))
-                 (forward-comment (point-max)))
-               (concat sym "  = "))
-              ((member sym '("case" "handle" "fn" "of")) " => ")
-              ;;((member sym '("abstype" "datatype")) "")
-              (t ""))))))
-
-    (insert text)
-    (indent-according-to-mode)
-    (beginning-of-line)
-    (skip-chars-forward "\t |")
-    (skip-syntax-forward "w_")
-    (skip-chars-forward "\t ")
-    (when (eq ?= (char-after)) (backward-char))))
+  (unless (sml-post-self-insert-pipe (1- (point)))
+    (indent-according-to-mode)))
+
+(defun sml-post-self-insert-pipe (&optional acp)
+  (when (or acp (and (eq ?| last-command-event)
+                     (setq acp (electric--after-char-pos))))
+    (let ((text
+           (save-excursion
+             (goto-char (1- acp))       ;Jump before the "|" we 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 "|") nil)     ; A datatype or an OR pattern?
+                    ((looking-at "=>") " => ") ;`case', or `fn' or `handle'.
+                    ((looking-at "=")          ;A function.
+                     (cons (concat f " ")" = ")))))
+                ((string= sym "and")
+                 ;; Could be a datatype or a function.
+                 (let ((funname (sml-funname-of-and)))
+                   (if funname (cons (concat funname " ") " = ") nil)))
+                ((string= sym "fun")
+                 (while (and (setq sym (sml-smie-forward-token))
+                             (string-match "^'" sym))
+                   (forward-comment (point-max)))
+                 (cons (concat sym " ") " = "))
+                ((member sym '("case" "handle" "of")) " => ") ;; "fn"?
+                ;;((member sym '("abstype" "datatype")) "")
+                (t nil))))))
+      (when text
+        (save-excursion
+          (goto-char (1- acp))
+          (unless (save-excursion (skip-chars-backward "\t ") (bolp))
+            (insert "\n")))
+        (unless (memq (char-before) '(?\s ?\t)) (insert " "))
+        (let ((use-region (and (use-region-p) (< (point) (mark)))))
+          ;; (skeleton-proxy-new `(nil ,(if (consp text) (pop text)) _ ,text))
+          (when (consp text) (insert (pop text)))
+          (if (not use-region)
+              (save-excursion (insert text))
+            (goto-char (mark))
+            (insert text)))
+        (indent-according-to-mode)
+        t))))
+
 
 ;;; Misc