142 |
"*Run upon entering `sml-mode'. |
"*Run upon entering `sml-mode'. |
143 |
This is a good place to put your preferred key bindings.") |
This is a good place to put your preferred key bindings.") |
144 |
|
|
|
(defvar sml-mode-abbrev-table nil "*Abbrev table for `sml-mode'.") |
|
|
|
|
145 |
;;; CODE FOR SML-MODE |
;;; CODE FOR SML-MODE |
146 |
|
|
147 |
(defun sml-mode-info () |
(defun sml-mode-info () |
273 |
\\{sml-mode-map}" |
\\{sml-mode-map}" |
274 |
(set (make-local-variable 'font-lock-defaults) sml-font-lock-defaults) |
(set (make-local-variable 'font-lock-defaults) sml-font-lock-defaults) |
275 |
(set (make-local-variable 'outline-regexp) sml-outline-regexp) |
(set (make-local-variable 'outline-regexp) sml-outline-regexp) |
276 |
|
(set (make-local-variable 'add-log-current-defun-function) |
277 |
|
'sml-current-fun-name) |
278 |
|
;; forward-sexp-function is an experimental variable in my hacked Emacs. |
279 |
|
(set (make-local-variable 'forward-sexp-function) 'sml-user-forward-sexp) |
280 |
(sml-mode-variables)) |
(sml-mode-variables)) |
281 |
|
|
282 |
(defun sml-mode-variables () |
(defun sml-mode-variables () |
381 |
"Indent current line of ML code." |
"Indent current line of ML code." |
382 |
(interactive) |
(interactive) |
383 |
(let ((savep (> (current-column) (current-indentation))) |
(let ((savep (> (current-column) (current-indentation))) |
384 |
(indent (or (ignore-errors (sml-calculate-indentation)) 0))) |
(indent (max (or (ignore-errors (sml-calculate-indentation)) 0) 0))) |
385 |
(if savep |
(if savep |
386 |
(save-excursion (indent-line-to indent)) |
(save-excursion (indent-line-to indent)) |
387 |
(indent-line-to indent)))) |
(indent-line-to indent)))) |
619 |
(not (or (member sym syms) (bobp))))) |
(not (or (member sym syms) (bobp))))) |
620 |
(unless (bobp) sym)))) |
(unless (bobp) sym)))) |
621 |
|
|
622 |
|
(defun sml-skip-siblings () |
623 |
|
(while (and (not (bobp)) (sml-backward-arg)) |
624 |
|
(sml-find-matching-starter sml-starters-syms)) |
625 |
|
(when (looking-at "in\\>\\|local\\>") |
626 |
|
;;skip over `local...in' and continue |
627 |
|
(forward-word 1) |
628 |
|
(sml-backward-sexp nil) |
629 |
|
(sml-skip-siblings))) |
630 |
|
|
631 |
|
(defun sml-beginning-of-defun () |
632 |
|
(let ((sym (sml-find-matching-starter sml-starters-syms))) |
633 |
|
(if (member sym '("fun" "functor" "signature" "structure" |
634 |
|
"abstraction" "datatype" "abstype")) |
635 |
|
(save-excursion (sml-forward-sym) (sml-forward-spaces) |
636 |
|
(sml-forward-sym)) |
637 |
|
;; We're inside a "non function declaration": let's skip all other |
638 |
|
;; declarations that we find at the same level and try again. |
639 |
|
(sml-skip-siblings) |
640 |
|
;; Obviously, let's not try again if we're at bobp. |
641 |
|
(unless (bobp) (sml-beginning-of-defun))))) |
642 |
|
|
643 |
|
(defcustom sml-max-name-components 3 |
644 |
|
"Maximum number of components to use for the current function name." |
645 |
|
:group 'sml |
646 |
|
:type 'integer) |
647 |
|
|
648 |
|
(defun sml-current-fun-name () |
649 |
|
(save-excursion |
650 |
|
(let ((count sml-max-name-components) |
651 |
|
fullname name) |
652 |
|
(end-of-line) |
653 |
|
(while (and (> count 0) |
654 |
|
(setq name (sml-beginning-of-defun))) |
655 |
|
(decf count) |
656 |
|
(setq fullname (if fullname (concat name "." fullname) name)) |
657 |
|
;; Skip all other declarations that we find at the same level. |
658 |
|
(sml-skip-siblings)) |
659 |
|
fullname))) |
660 |
|
|
661 |
|
|
662 |
(defun sml-comment-indent () |
(defun sml-comment-indent () |
663 |
(if (looking-at "^(\\*") ; Existing comment at beginning |
(if (looking-at "^(\\*") ; Existing comment at beginning |
664 |
0 ; of line stays there. |
0 ; of line stays there. |
665 |
(save-excursion |
comment-column)) |
|
(skip-chars-backward " \t") |
|
|
(max (1+ (current-column)) ; Else indent at comment column |
|
|
comment-column)))) ; except leave at least one space. |
|
666 |
|
|
667 |
;;; INSERTING PROFORMAS (COMMON SML-FORMS) |
;;; INSERTING PROFORMAS (COMMON SML-FORMS) |
668 |
|
|
683 |
(let ((fsym (intern (concat "sml-form-" name)))) |
(let ((fsym (intern (concat "sml-form-" name)))) |
684 |
`(progn |
`(progn |
685 |
(add-to-list 'sml-forms-alist ',(cons name fsym)) |
(add-to-list 'sml-forms-alist ',(cons name fsym)) |
686 |
|
(define-abbrev sml-mode-abbrev-table ,name "" ',fsym) |
687 |
(define-skeleton ,fsym |
(define-skeleton ,fsym |
688 |
,(format "SML-mode skeleton for `%s..' expressions" name) |
,(format "SML-mode skeleton for `%s..' expressions" name) |
689 |
,interactor |
,interactor |
712 |
(sml-def-skeleton "functor" "Functor name: " |
(sml-def-skeleton "functor" "Functor name: " |
713 |
str " () : =\nstruct" > "\n" > _ "\nend" >) |
str " () : =\nstruct" > "\n" > _ "\nend" >) |
714 |
|
|
715 |
(sml-def-skeleton "datatype" "Datatype name and type parameters: " |
(sml-def-skeleton "datatype" "Datatype name and type params: " |
716 |
str " =" \n) |
str " =" \n) |
717 |
|
|
718 |
(sml-def-skeleton "abstype" "Abstype name and type parameters: " |
(sml-def-skeleton "abstype" "Abstype name and type params: " |
719 |
str " =" \n _ "\nwith" > "\nend" >) |
str " =" \n _ "\nwith" > "\nend" >) |
720 |
|
|
721 |
;; |
;; |
722 |
|
|
723 |
|
(sml-def-skeleton "struct" nil |
724 |
|
_ "\nend" >) |
725 |
|
|
726 |
|
(sml-def-skeleton "sig" nil |
727 |
|
_ "\nend" >) |
728 |
|
|
729 |
|
(sml-def-skeleton "val" nil |
730 |
|
_ " = " >) |
731 |
|
|
732 |
|
(sml-def-skeleton "fn" nil |
733 |
|
_ " =>" >) |
734 |
|
|
735 |
|
(sml-def-skeleton "fun" nil |
736 |
|
_ " =" >) |
737 |
|
|
738 |
|
;; |
739 |
|
|
740 |
(defun sml-forms-menu (menu) |
(defun sml-forms-menu (menu) |
741 |
(easy-menu-filter-return |
(easy-menu-filter-return |
742 |
(easy-menu-create-menu "Forms" |
(easy-menu-create-menu "Forms" |
753 |
If the point directly precedes a symbol for which an SML form exists, |
If the point directly precedes a symbol for which an SML form exists, |
754 |
the corresponding form is inserted." |
the corresponding form is inserted." |
755 |
(interactive) |
(interactive) |
756 |
(let* ((point (point)) |
(let ((abbrev-mode (not abbrev-mode)) |
757 |
(sym (sml-backward-sym))) |
(last-command-char ?\ ) |
758 |
(if (not (and sym (assoc sym sml-forms-alist))) |
;; Bind `this-command' to fool skeleton's special abbrev handling. |
759 |
(progn (goto-char point) (insert " ")) |
(this-command 'self-insert-command)) |
760 |
(delete-region (point) point) |
(call-interactively 'self-insert-command))) |
|
(sml-insert-form sym nil)))) |
|
761 |
|
|
762 |
(defun sml-insert-form (name newline) |
(defun sml-insert-form (name newline) |
763 |
"Interactive short-cut to insert the NAME common ML form. |
"Interactive short-cut to insert the NAME common ML form. |