1 ;; Copyright (C) 2005-2007 Vesa Karvonen
3 ;; MLton is released under a BSD-style license.
4 ;; See the file MLton-LICENSE for details.
8 ;; Emacs mode for editing ML Basis files
13 ;; - Push the path to this file (and `esml-util.el') to `load-path' and
15 ;; (require 'esml-mlb-mode)
17 ;; (autoload 'esml-mlb-mode "esml-mlb-mode")
18 ;; (add-to-list 'auto-mode-alist '("\\.mlb\\'" . esml-mlb-mode))
19 ;; in your Emacs initialization file.
21 ;; Alternatively you could use `load-file'.
23 ;; Beware that (at least) Tuareg mode may already be associated to .mlb
24 ;; files. You need to add ML Basis mode to `auto-mode-alist' after
27 ;; - Check the `esml-mlb' customization group.
29 ;; Ideas for future development
30 ;; ============================
32 ;; - customisable indentation
34 ;; - type-check / compile / compile-and-run
35 ;; - find-structure / find-signature / find-functor
36 ;; - highlight only binding occurances of basids
37 ;; - find-binding-occurance (of a basid)
38 ;; - support doc strings in mlb files
41 ;; - fix indentation bugs
42 ;; - use something more robust than `shell-command' to run shell commands
44 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
47 (defvar esml-mlb-load-time t
)
49 (defun esml-mlb-set-custom-and-update (sym val
)
50 (custom-set-default sym val
)
51 (unless esml-mlb-load-time
54 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
57 (defgroup esml-mlb nil
58 "Major mode for editing ML Basis files."
61 (defcustom esml-mlb-additional-annotations
63 "Additional annotations accepted by your compiler(s). Note that ML
64 Basis mode runs the `esml-mlb-show-annotations-command' to query available
65 annotations automatically."
66 :type
'(repeat (cons :tag
"Annotation"
68 (repeat :tag
"Values starting with the default"
70 :set
'esml-mlb-set-custom-and-update
73 (defcustom esml-mlb-additional-path-variables
75 "Additional path variables that can not be found in the path map files
76 specified by `esml-mlb-mlb-path-map-files' or by running the command
77 `esml-mlb-show-path-map-command'."
78 :type
'(repeat (cons (string :tag
"Name") (string :tag
"Value")))
79 :set
'esml-mlb-set-custom-and-update
82 (defcustom esml-mlb-completion-ignored-files-regexp
"\\.[^.].*\\|CVS/\\|.*~"
83 "Completion ignores files (and directories) whose names match this
88 (defcustom esml-mlb-indentation-offset
3
89 "Basic offset for indentation."
93 (defcustom esml-mlb-key-bindings
95 . esml-mlb-indent-line-or-complete
)
96 ("[(control c) (control f)]"
97 . esml-mlb-find-file-at-point
)
98 ("[(control c) (control s)]"
99 . esml-mlb-show-basis
))
100 "Key bindings for the ML Basis mode. The key specifications must be in a
101 format accepted by the function `define-key'. Hint: You might want to type
102 `M-x describe-function esml-mlb <TAB>' to see the available commands."
103 :type
'(repeat (cons :tag
"Key Binding"
105 (function :tag
"Command")))
108 (defcustom esml-mlb-mlb-path-map-files
109 '("~/.mlton/mlb-path-map"
110 "/usr/lib/mlton/mlb-path-map")
111 "Files to search for definitions of path variables."
113 :set
'esml-mlb-set-custom-and-update
116 (defcustom esml-mlb-path-suffix-regexp
"fun\\|mlb\\|sig\\|sml"
117 "Regexp for matching valid path name suffices. Completion only considers
118 files whose extension matches this regexp."
120 :set
'esml-mlb-set-custom-and-update
123 (defcustom esml-mlb-show-annotations-command
124 "mlton -expert true -show anns"
125 "Shell command used to query the available annotations."
127 :set
'esml-mlb-set-custom-and-update
130 (defcustom esml-mlb-show-basis-command
131 "mlton -stop tc -show-basis %t %f"
132 "Shell command used to pretty print the basis defined by an MLB file.
133 `%t' is replaced by the name of a temporary file and `%f' is replaced by
134 the name of the MLB file."
138 (defcustom esml-mlb-show-path-map-command
139 "mlton -expert true -show path-map"
140 "Shell command used to query the available path variables."
142 :set
'esml-mlb-set-custom-and-update
145 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
148 (defface font-lock-interface-def-face
150 "Font Lock mode face used to highlight interface definitions."
151 :group
'font-lock-highlighting-faces
)
153 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
156 (defvar esml-mlb-annotations nil
157 "An association list of known annotations. This variable is updated by
160 (defun esml-mlb-parse-annotations ()
161 (setq esml-mlb-annotations
164 esml-mlb-additional-annotations
165 (when (not (string= "" esml-mlb-show-annotations-command
))
168 (esml-split-string s
"[ \t]*[{}|][ \t]*")))
171 (save-window-excursion
173 esml-mlb-show-annotations-command
176 "[ \t]*\n+[ \t]*"))))
179 (string-lessp (car a
) (car b
)))))
182 (string= (car a
) (car b
)))))))
184 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
187 (defvar esml-mlb-path-variables nil
188 "An association list of known path variables. This variable is updated
189 by `esml-mlb-update'.")
191 (defun esml-mlb-parse-path-variables-from-string (path-map-string)
193 (lambda (s) (apply (function cons
) (esml-split-string s
"[ \t]+"))))
194 (esml-split-string path-map-string
"[ \t]*\n+[ \t]*")))
196 (defun esml-mlb-parse-path-variables ()
197 (setq esml-mlb-path-variables
200 esml-mlb-additional-path-variables
201 (esml-mlb-parse-path-variables-from-string
203 (save-window-excursion
205 esml-mlb-show-path-map-command
208 (loop for file in esml-mlb-mlb-path-map-files
209 append
(when (file-readable-p file
)
210 (esml-mlb-parse-path-variables-from-string
212 (insert-file-contents file
)
216 (string-lessp (car a
) (car b
)))))
219 (string= (car a
) (car b
)))))))
221 (defun esml-mlb-expand-path (path)
222 "Expands path variable references in the given path."
228 (if (looking-at "\\$(\\([^)]+\\))")
229 (let* ((name (match-string 1))
230 (name-value (assoc name esml-mlb-path-variables
)))
232 (compat-error "Unknown path variable: %s" name
))
233 (delete-char (length (match-string 0)))
234 (insert (cdr name-value
)))
236 (skip-chars-forward "^$")
237 (push (buffer-substring 1 (point))
239 (delete-char (- 1 (point))))
241 (apply (function concat
) (reverse parts
))))
243 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
244 ;; Syntax and highlighting
246 (defconst esml-mlb-string-continue-regexp
"\\(?:\\\\[ \t\n]+\\\\\\)")
247 (defconst esml-mlb-string-char-regexp
248 (concat "\\(?:" esml-mlb-string-continue-regexp
249 "*\\(?:[^\n\"\\]\\|\\\\[^ \t\n]\\)\\)"))
250 (defconst esml-mlb-inside-string-regexp
251 (concat "\"" esml-mlb-string-char-regexp
"*"
252 esml-mlb-string-continue-regexp
"*"))
253 (defconst esml-mlb-string-regexp
(concat esml-mlb-inside-string-regexp
"\""))
254 (defconst esml-mlb-inside-comment-regexp
"(\\*\\(?:[^*]\\|\\*[^)]\\)*")
255 (defconst esml-mlb-comment-regexp
256 (concat esml-mlb-inside-comment-regexp
"\\*)"))
257 (defconst esml-mlb-path-var-chars
"A-Za-z0-9_")
258 (defconst esml-mlb-unquoted-path-chars
"-A-Za-z0-9_/.")
259 (defconst esml-mlb-unquoted-path-or-ref-chars
260 (concat esml-mlb-unquoted-path-chars
"()$"))
261 (defconst esml-mlb-compiler-ann-prefix
262 (concat "\\(?:" esml-mlb-string-char-regexp
"*:[ \t]*\\)"))
264 (defun esml-mlb-<token
>-to-regexp
(<token
>)
265 (let* ((<token
>-to-regexp
266 '(("<longstrid>" .
"[A-Za-z0-9_]*")))
267 (<token
>-regexp
(assoc <token
> <token
>-to-regexp
)))
272 (defconst esml-mlb-keywords
273 '("and" "ann" "bas" "basis" "end" "functor" "in" "let" "local" "open"
274 "signature" "structure")
275 "Keywords of ML Basis syntax.")
277 (defconst esml-mlb-keywords-usually-followed-by-space
278 '("and" "functor" "open" "signature" "structure")
279 "Keywords of ML Basis syntax that are under most circumstances followed
282 (defconst esml-mlb-mode-syntax-table
283 (let ((table (make-syntax-table)))
286 (modify-syntax-entry (car char-flags
) (cdr char-flags
)
291 (?
\" .
"$") ;; not '"' to allow custom highlighting of ann
292 (?
\\ .
"/") ;; not '\' due to class of '"'
295 (?_ .
"w") ;; not "_" due to variables regexp
301 "Syntax table for ML Basis mode.")
303 (defvar esml-mlb-font-lock-table nil
)
305 (defun esml-mlb-build-font-lock-table ()
306 "Builds the font-lock table for ML Basis mode."
307 (setq esml-mlb-font-lock-table
308 `(;; quoted path names
309 (,(concat esml-mlb-inside-string-regexp
310 "\\.\\(" esml-mlb-path-suffix-regexp
"\\)\"")
311 . font-lock-constant-face
)
315 "\"[ \t]*" esml-mlb-compiler-ann-prefix
"?\\("
318 (lambda (regexps name-values
)
320 (push "\\|" regexps
))
321 (cons (if (cdr name-values
)
323 (car name-values
) "[ \t]+\\("
328 (esml-mlb-<token
>-to-regexp s
)
331 :initial-value
(concat "\\("
332 (esml-mlb-<token
>-to-regexp
339 :initial-value
'("\\)[ \t]*\"")))
340 . font-lock-string-face
)
341 (,esml-mlb-string-regexp
342 . font-lock-warning-face
)
345 (regexp-opt (mapcar 'car esml-mlb-path-variables
))
347 . font-lock-reference-face
)
349 . font-lock-warning-face
)
350 ;; unquoted path names
351 (,(concat "[-A-Za-z0-9_/.]*[.]\\("
352 esml-mlb-path-suffix-regexp
354 . font-lock-constant-face
)
355 ("[.][-A-Za-z0-9_]+[ \t\n]"
356 . font-lock-warning-face
)
357 ("[A-Za-z0-9_]*[-/.][-A-Za-z0-9_/]*"
358 . font-lock-constant-face
)
360 (,(concat "\\<\\(" (regexp-opt esml-mlb-keywords
) "\\)\\>")
361 . font-lock-keyword-face
)
363 ("[A-Za-z][A-Za-z0-9_']*"
364 . font-lock-interface-def-face
))))
366 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
369 (defconst esml-mlb-indent-sync-keywords-regexp
371 (regexp-opt '("ann" "bas" "basis" "end" "functor" "in" "let"
372 "local" "open" "signature" "structure"))
374 "Regexp for synchronizing indentation.")
376 (defun esml-mlb-previous-indentation ()
377 "Finds the previous indentation level and evidence."
381 (while (not (or (consp result
) (bobp)))
384 (skip-chars-forward " \t;")
385 (cond ((looking-at esml-mlb-indent-sync-keywords-regexp
)
386 (setq result
(let ((start (point))
387 (indentation (current-column)))
390 (intern (buffer-substring
394 (setq result
(cons (current-column) '*)))
396 (setq result
(if result
397 (min result
(current-indentation))
398 (current-indentation)))))))
399 (cond ((consp result
)
406 (defun esml-mlb-indent-line ()
407 "Indent current line as ML Basis code."
409 (let* ((indent-evidence (esml-mlb-previous-indentation))
410 (indent (car indent-evidence
))
411 (evidence (cdr indent-evidence
)))
414 (skip-chars-forward " \t")
415 (cond ((looking-at ";")
419 (max 0 (+ indent -
2 esml-mlb-indentation-offset
))))
421 (indent-line-to (max 0 (- indent
2))))))
422 ((looking-at "end[ \t\n]")
424 ((ann bas in let local
)
425 (indent-line-to indent
))
428 (max 0 (- indent esml-mlb-indentation-offset
))))))
429 ((looking-at "in[ \t\n]")
432 (indent-line-to indent
))
434 (indent-line-to (- indent esml-mlb-indentation-offset
)))))
435 ((looking-at "and[ \t\n]")
437 ((basis functor signature structure
)
438 (indent-line-to (+ indent -
3 (length (symbol-name evidence
)))))
440 (indent-line-to indent
))))
444 (indent-line-to (+ indent
1)))
446 (indent-line-to indent
))))
449 ((ann bas in let local
)
450 (indent-line-to (+ indent esml-mlb-indentation-offset
)))
452 (indent-line-to indent
))))))
453 (if (< (current-column) (current-indentation))
454 (forward-char (- (current-indentation) (current-column))))))
456 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
459 (defun esml-mlb-filter-file-completions (completions &optional allow-dots
)
460 "Removes the directories `./' and `../' as well as files whose suffix
461 does not appear in `esml-mlb-path-suffix-regexp' from the list of file
463 (let ((ignored-files-regexp
464 (concat "^\\(" esml-mlb-completion-ignored-files-regexp
"\\)$"))
465 (valid-suffices-regexp
466 (concat "^\\(" esml-mlb-path-suffix-regexp
"\\)$")))
472 (or (and (not allow-dots
)
473 (member x
'("./" "../")))
474 (string-match ignored-files-regexp x
)
475 (not (or (file-name-directory x
)
476 (let ((ext (file-name-extension x
)))
479 valid-suffices-regexp ext
)))))))))))
481 (defun esml-mlb-complete ()
482 "Performs context sensitive completion at point."
485 ;; no completion inside comments
486 ((esml-point-preceded-by esml-mlb-inside-comment-regexp
))
489 ((esml-point-preceded-by
490 (concat "\"[ \t\n]*" esml-mlb-compiler-ann-prefix
"?\\("
491 (regexp-opt (mapcar 'car esml-mlb-annotations
))
492 "\\)[ \t\n]+\\(" esml-mlb-string-char-regexp
"*\\)"))
493 (let* ((annot (assoc (match-string 1) esml-mlb-annotations
))
494 (all-values (cdr annot
))
495 (values (remove* nil all-values
498 (and (< 0 (length s
))
499 (= ?
< (aref s
0)))))))
500 (value-prefix (match-string 2))
502 (try-completion value-prefix
(mapcar 'list values
)))
503 (value (if (eq t value-completion
) value-prefix value-completion
)))
504 (message "Annotation: %s %s" (car annot
) (if all-values all-values
""))
505 (when (stringp value-completion
)
506 (esml-insert-or-skip-if-looking-at
507 (substring value
(length value-prefix
))))
509 (eq t
(try-completion value
(mapcar 'list values
))))
510 (esml-insert-or-skip-if-looking-at "\""))))
513 ((and (esml-point-preceded-by
514 (concat "\\<ann[ \t\n]+\\([ \t\n]+\\|" esml-mlb-string-regexp
515 "\\|" esml-mlb-comment-regexp
"\\)*\"[^\"]*"))
516 (esml-point-preceded-by
517 (concat "\"[ \t\n]*" esml-mlb-compiler-ann-prefix
"?\\("
518 esml-mlb-string-char-regexp
"*\\)")))
519 (let* ((name-prefix (match-string 1))
520 (name-completion (try-completion name-prefix esml-mlb-annotations
))
521 (name (if (eq t name-completion
) name-prefix name-completion
)))
522 (if (not name-completion
)
523 (message "Annotations: %s" (mapcar 'car esml-mlb-annotations
))
524 (when (stringp name-completion
)
525 (esml-insert-or-skip-if-looking-at
526 (substring name
(length name-prefix
))))
528 (eq t
(try-completion name esml-mlb-annotations
)))
529 (let ((values (cdr (assoc name esml-mlb-annotations
))))
530 (esml-insert-or-skip-if-looking-at (if values
" " "\""))
531 (message "Annotation: %s %s" name
(if values values
"")))
532 (message "Annotations: %s"
533 (all-completions name-prefix esml-mlb-annotations
))))))
536 ((esml-point-preceded-by (concat "\\$(\\([" esml-mlb-path-var-chars
"]*\\)"))
537 (let* ((name-prefix (match-string 1))
539 (try-completion name-prefix esml-mlb-path-variables
))
540 (name (if (eq t name-completion
) name-prefix name-completion
)))
541 (if (not name-completion
)
542 (message "Path variables: %s" (mapcar 'car esml-mlb-path-variables
))
543 (when (stringp name-completion
)
544 (esml-insert-or-skip-if-looking-at
545 (substring name
(length name-prefix
))))
547 (eq t
(try-completion name esml-mlb-path-variables
)))
548 (let* ((value (cdr (assoc name esml-mlb-path-variables
)))
549 (expanded (esml-mlb-expand-path value
)))
550 (esml-insert-or-skip-if-looking-at ")")
551 (if (string= value expanded
)
552 (message "Path variable: %s [%s]" name value
)
553 (message "Path variable: %s [%s ==> %s]" name value expanded
)))
554 (message "Path variables: %s"
555 (all-completions name-prefix esml-mlb-path-variables
))))))
557 ;; filenames and keywords
558 ((or (esml-point-preceded-by
559 (concat "\\(\"\\)\\(" esml-mlb-string-char-regexp
"+\\)"))
560 (esml-point-preceded-by
561 (concat "\\([ \t\n]\\|^\\)\\(["
562 esml-mlb-unquoted-path-or-ref-chars
564 ;; TBD: escape sequences in quoted pathnames
565 (let* ((quoted (string= "\"" (match-string 1)))
566 (path-prefix (match-string 2))
567 (path-expanded (esml-mlb-expand-path path-prefix
))
568 (dir (if (file-name-directory path-expanded
)
569 (file-name-directory path-expanded
)
571 (nondir-prefix (file-name-nondirectory path-expanded
))
574 (let ((files (esml-mlb-filter-file-completions
575 (file-name-all-completions nondir-prefix dir
)
580 (append (all-completions
582 (mapcar 'list esml-mlb-keywords
))
584 (esml-mlb-filter-file-completions
586 (esml-string-matches-p "\\(\.\./\\)+" dir
))))))
587 (nondir-completion (try-completion nondir-prefix nondir-completions
))
588 (nondir (if (eq t nondir-completion
)
591 (if (not nondir-completion
)
592 (if (string= path-prefix path-expanded
)
593 (message "No completions for %s" path-prefix
)
594 (message "No completions for %s ==> %s" path-prefix path-expanded
))
595 (when (stringp nondir-completion
)
596 (esml-insert-or-skip-if-looking-at
597 (substring nondir
(length nondir-prefix
))))
598 (if (eq t
(try-completion nondir nondir-completions
))
600 ((file-name-directory nondir
)
601 (message "Completions: %s"
602 (sort (let ((dir (concat dir nondir
)))
603 (esml-mlb-filter-file-completions
604 (file-name-all-completions "" dir
)
605 (esml-string-matches-p "\\(\.\./\\)+" dir
)))
607 ((member nondir esml-mlb-keywords
)
608 (esml-mlb-indent-line)
609 (message "Keyword: %s" nondir
)
610 (when (member nondir esml-mlb-keywords-usually-followed-by-space
)
611 (esml-insert-or-skip-if-looking-at " ")))
613 (message "Expanded path: %s%s" dir nondir
)))
614 (message "Completions: %s"
615 (sort (mapcar 'car nondir-completions
)
616 'string-lessp
))))))))
618 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
621 (defun esml-mlb-indent-line-or-complete ()
622 "Indents the current line. If indentation does not change, attempts to
623 perform context sensitive completion. This command is not idempotent."
625 (let ((old-indentation (current-indentation)))
626 (esml-mlb-indent-line)
627 (when (= old-indentation
(current-indentation))
628 (esml-mlb-complete))))
630 (defun esml-mlb-find-file-at-point ()
631 "Grabs the path surrounding point and attempts to find the file."
633 (let ((file (esml-mlb-expand-path
635 (if (and (not (bobp))
636 (= ?
\" (char-before)))
639 (buffer-substring (+ (point) 1) (- end
1)))
640 (skip-chars-backward esml-mlb-unquoted-path-or-ref-chars
)
641 (let ((start (point)))
642 (skip-chars-forward esml-mlb-unquoted-path-or-ref-chars
)
643 (buffer-substring start
(point))))))))
644 (if (file-readable-p file
)
646 (message (if (file-exists-p file
)
648 "Does not exists: %s")
651 (defconst esml-mlb-show-basis-process-name
"*mlb-show-basis*")
653 (defun esml-mlb-show-basis ()
654 "Shows the basis defined by the MLB file in the current buffer."
656 ;; TBD: find-error / error output mode
657 (unless (eq major-mode
'esml-mlb-mode
)
658 (compat-error "show-basis is only meaningful on MLB files"))
659 (when (get-process esml-mlb-show-basis-process-name
)
660 (compat-error "show-basis already running"))
662 (lexical-let ((tmp-file (concat
663 (file-name-directory (buffer-file-name))
664 "." (file-name-nondirectory (buffer-file-name))
666 (buffer (get-buffer-create esml-mlb-show-basis-process-name
)))
667 (when (file-exists-p tmp-file
)
668 (compat-error "Temporary basis file already exists: %s" tmp-file
))
671 (delete-region (point-min) (point-max)))
672 (let ((process (start-process-shell-command
673 esml-mlb-show-basis-process-name
675 (compat-replace-regexp-in-string
676 (compat-replace-regexp-in-string
677 esml-mlb-show-basis-command
681 (buffer-file-name)))))
682 (set-process-sentinel
685 (lambda (process event
)
686 (if (and (esml-string-matches-p "finished\n" event
)
687 (file-readable-p tmp-file
))
689 (set-buffer (find-file-other-window tmp-file
))
691 (delete-file tmp-file
))
692 (switch-to-buffer buffer
))
693 (message "%S" event
)))))
694 (message "%s" "show-basis running...")))
696 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
699 (defvar esml-mlb-mode-map
(make-sparse-keymap)
700 "Keymap for ML Basis mode. This variable is updated by
703 (defun esml-mlb-build-mode-map ()
704 "Builds the key map for ML Basis mode."
705 (let ((result (make-sparse-keymap)))
707 (lambda (key-command)
709 (read (car key-command
))
711 esml-mlb-key-bindings
)
712 (setq esml-mlb-mode-map result
)))
714 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
717 (defvar esml-mlb-mode-hook nil
718 "Hook run when entering ML Basis mode.")
720 (define-derived-mode esml-mlb-mode fundamental-mode
"MLB"
721 "Major mode for editing ML Basis files. Provides syntax highlighting,
722 indentation, and context sensitive completion.
724 See the customization group `esml-mlb'."
726 (set (make-local-variable 'font-lock-defaults
)
727 '(esml-mlb-font-lock-table))
728 (set (make-local-variable 'indent-line-function
)
729 'esml-mlb-indent-line
))
731 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
734 (setq esml-mlb-load-time nil
)
736 (defun esml-mlb-update ()
737 "Updates data based on customization variables."
739 ;; Warning: order dependencies
740 (esml-mlb-parse-path-variables)
741 (esml-mlb-parse-annotations)
742 (esml-mlb-build-font-lock-table)
743 (esml-mlb-build-mode-map))
745 ;; We are finally ready to update everything the first time.
748 (add-to-list 'auto-mode-alist
'("\\.mlb\\'" . esml-mlb-mode
))
749 (add-to-list 'auto-mode-alist
'("\\.basis\\'" . sml-mode
))
751 (provide 'esml-mlb-mode
)