This is an automated email from the git hooks/post-receive script. treinen pushed a commit to branch master in repository tuareg-mode.
commit 2d99ed749cc8aa08497d11b6e15e1eabe31b6dcd Author: Ralf Treinen <trei...@free.fr> Date: Mon Jul 7 08:54:28 2014 +0200 Imported Upstream version 2.0.7 --- Makefile | 92 ++++++-------- tuareg-pkg.el | 2 +- tuareg-site-file.el | 109 ++++++++++++++++ tuareg.el | 360 +++++++++++++++++++++++++++++++++++----------------- 4 files changed, 389 insertions(+), 174 deletions(-) diff --git a/Makefile b/Makefile index cd44f40..2d3554b 100644 --- a/Makefile +++ b/Makefile @@ -1,26 +1,31 @@ VERSION = $(shell grep ';; Version:' tuareg.el \ | sed 's/;; Version: *\([0-9.]\+\).*/\1/') DESCRIPTION = $(shell grep ';;; tuareg.el ---' tuareg.el \ - | sed 's/[^-]*--- *\(.*\)/\1/') + | sed 's/[^-]*--- *\([^.]*\).*/\1/') REQUIREMENTS = $(shell grep ';; Package-Requires:' tuareg.el \ | sed 's/;; Package-Requires: *\(.\+\).*/\1/') DIST_NAME = tuareg-$(VERSION) +TARBALL = $(DIST_NAME).tar.gz +OPAM_DIR = tuareg.$(VERSION) -ELS = tuareg.el ocamldebug.el +ELS = tuareg.el ocamldebug.el tuareg-site-file.el ELC = $(ELS:.el=.elc) +# Installation directory: +INSTALL_DIR ?= $(shell opam config var prefix)/share/tuareg + DIST_FILES += $(ELS) Makefile README -EMACS = emacs +EMACS ?= emacs #ENABLE_SMIE = --eval '(setq tuareg-use-smie t)' -RM = rm -rf -CP = cp -f +RM ?= rm -f +CP ?= cp -f LN = ln DIFF = diff -u -B -INSTALL_RM_R = $(RM) -INSTALL_MKDIR = mkdir +INSTALL_RM_R = $(RM) -r +INSTALL_MKDIR = mkdir -p INSTALL_CP = $(CP) all : elc tuareg-site-file.el @@ -28,41 +33,16 @@ all : elc tuareg-site-file.el elc : $(ELC) %.elc : %.el - $(EMACS) -batch $(NOINIT) -f batch-byte-compile $< - -# ifneq ($(realpath .hg),) -# POST_INSTALL_HOOK = $(RM) $(VERSION_FILE) -# MAKE_VERSION_FILE = hg id -i | fgrep -v '+' >/dev/null || \ -# (echo 'uncommitted changes' >&2; exit 1); \ -# hg id -i --debug > $(VERSION_FILE) -# else -# ifneq ($(realpath .svn),) -# POST_INSTALL_HOOK = $(RM) $(VERSION_FILE) -# MAKE_VERSION_FILE = svn info | grep Revision: | sed 's/Revision: //' > $(VERSION_FILE) -# else -# ifneq ($(realpath .bzr),) -# POST_INSTALL_HOOK = $(RM) $(VERSION_FILE) -# MAKE_VERSION_FILE = bzr log -l -1 | grep revno: > $(VERSION_FILE) -# else -# ifneq ($(realpath $(VERSION_FILE)),) -# POST_INSTALL_HOOK = -# MAKE_VERSION_FILE = @echo "Using \"$(VERSION_FILE)\" in the distribution." -# else -# POST_INSTALL_HOOK = -# MAKE_VERSION_FILE = @(echo "missing \"$(VERSION_FILE)\" in the distribution?" >&2; exit 1) -# endif -# endif -# endif -# endif - -# install : $(ELC) $(VERSION_FILE) -# fgrep `cat $(VERSION_FILE)` tuareg.elc >/dev/null 2>&1 || \ -# ($(RM) tuareg.elc; $(MAKE) tuareg.elc) -# $(INSTALL_RM_R) ${DEST} -# $(INSTALL_MKDIR) ${DEST} -# for f in $(ELS) $(ELC) $(VERSION_FILE); do $(INSTALL_CP) $$f $(DEST)/$$f; done -# $(POST_INSTALL_HOOK) + $(EMACS) --batch --no-init-file -f batch-byte-compile $< + +install : $(ELC) + -$(INSTALL_RM_R) $(INSTALL_DIR) + $(INSTALL_MKDIR) $(INSTALL_DIR) + $(INSTALL_CP) $(ELS) $(ELC) $(INSTALL_DIR)/ + $(POST_INSTALL_HOOK) +uninstall : + -test -d $(INSTALL_DIR) && $(INSTALL_RM_R) $(INSTALL_DIR) .PHONY: refresh refresh: @@ -82,27 +62,31 @@ check : sample.ml.test $(DIFF) $< $@ || true tuareg-site-file.el: refresh - echo "\ - ;;; $@ --- Automatically extracted autoloads.\n\ - ;;; Code:\n\ - (add-to-list 'load-path\n\ - (or (file-name-directory load-file-name) (car load-path)))\n\ - " >$@ + (echo ";;; $@ --- Automatically extracted autoloads.";\ + echo ";;; Code:";\ + echo "(add-to-list 'load-path";\ + echo " (or (file-name-directory load-file-name) (car load-path)))";\ + echo "") >$@ $(EMACS) --batch --eval '(setq generated-autoload-file "'`pwd`'/$@")' -f batch-update-autoloads "." -.PHONY: dist tar -dist: $(DIST_NAME).tar.gz -tar: $(DIST_NAME).tar +dist distrib: $(TARBALL) -$(DIST_NAME).tar.gz $(DIST_NAME).tar: $(DIST_FILES) +$(TARBALL): $(DIST_FILES) mkdir -p $(DIST_NAME) for f in $(DIST_FILES); do $(LN) $$f $(DIST_NAME); done echo '(define-package "tuareg" "$(VERSION)" "$(DESCRIPTION)" ' "'"'$(REQUIREMENTS))' > $(DIST_NAME)/tuareg-pkg.el tar acvf $@ $(DIST_NAME) - $(RM) -rf $(DIST_NAME) + $(RM) -r $(DIST_NAME) + +opam: $(TARBALL) + $(INSTALL_MKDIR) $(OPAM_DIR) + $(CP) -a $(filter-out %~, $(wildcard opam/*)) $(OPAM_DIR) + echo "archive: \"`pwd`/$(TARBALL)\"" > $(OPAM_DIR)/url + echo "checksum: \"`md5sum $(TARBALL) | cut -d ' ' -f 1`\"" \ + >> $(OPAM_DIR)/url clean : $(RM) $(ELC) "$(DIST_NAME).tar.gz" "$(DIST_NAME).tar" -# $(POST_INSTALL_HOOK) + $(RM) -r tuareg.$(VERSION) -# .PHONY : all elc clean install force check distrib dist +.PHONY : all elc clean install uninstall check distrib dist opam diff --git a/tuareg-pkg.el b/tuareg-pkg.el index 552d91a..22740b5 100644 --- a/tuareg-pkg.el +++ b/tuareg-pkg.el @@ -1 +1 @@ -(define-package "tuareg" "2.0.6" "OCaml mode for Emacs. -*- coding: utf-8 -*-" '((caml "3.12.0.1"))) +(define-package "tuareg" "2.0.7" "OCaml mode for Emacs" '((caml "3.12.0.1"))) diff --git a/tuareg-site-file.el b/tuareg-site-file.el new file mode 100644 index 0000000..b7143ed --- /dev/null +++ b/tuareg-site-file.el @@ -0,0 +1,109 @@ +;;; tuareg-site-file.el --- Automatically extracted autoloads. +;;; Code: +(add-to-list 'load-path + (or (file-name-directory load-file-name) (car load-path))) + +;;;### (autoloads (ocamldebug) "ocamldebug" "ocamldebug.el" (21004 +;;;;;; 40040 237491 510000)) +;;; Generated autoloads from ocamldebug.el + +(autoload 'ocamldebug "ocamldebug" "\ +Run ocamldebug on program FILE in buffer *ocamldebug-FILE*. +The directory containing FILE becomes the initial working directory +and source-file directory for ocamldebug. If you wish to change this, use +the ocamldebug commands `cd DIR' and `directory'. + +\(fn PATH)" t nil) + +(defalias 'camldebug 'ocamldebug) + +;;;*** + +;;;### (autoloads (tuareg-run-ocaml tuareg-mode) "tuareg" "tuareg.el" +;;;;;; (21122 7932 481646 772000)) +;;; Generated autoloads from tuareg.el +(add-to-list 'auto-mode-alist '("\\.ml[iylp]?\\'" . tuareg-mode)) +(dolist (ext '(".cmo" ".cmx" ".cma" ".cmxa" ".cmi" ".annot")) + (add-to-list 'completion-ignored-extensions ext)) + +(autoload 'tuareg-mode "tuareg" "\ +Major mode for editing OCaml code. + +Dedicated to Emacs and XEmacs, version 21 and higher. Provides +automatic indentation and compilation interface. Performs font/color +highlighting using Font-Lock. It is designed for OCaml but handles +Caml Light as well. + +The Font-Lock minor-mode is used according to your customization +options. + +You have better byte-compile tuareg.el. + +For customization purposes, you should use `tuareg-mode-hook' +\(run for every file) or `tuareg-load-hook' (run once) and not patch +the mode itself. You should add to your configuration file something like: + (add-hook 'tuareg-mode-hook + (lambda () + ... ; your customization code + )) +For example you can change the indentation of some keywords, the +`electric' flags, Font-Lock colors... Every customizable variable is +documented, use `C-h-v' or look at the mode's source code. + +`dot-emacs.el' is a sample customization file for standard changes. +You can append it to your `.emacs' or use it as a tutorial. + +`M-x ocamldebug' FILE starts the OCaml debugger ocamldebug on the executable +FILE, with input and output in an Emacs buffer named *ocamldebug-FILE*. + +A Tuareg Interactive Mode to evaluate expressions in a toplevel is included. +Type `M-x tuareg-run-ocaml' or see special-keys below. + +For the best indentation experience, some elementary rules must be followed. + - Because the `function' keyword has a special indentation (to handle + case matches) use the `fun' keyword when no case match is performed. + - In OCaml, `;;' is no longer necessary for correct indentation, + except before top level phrases not introduced by `type', `val', `let' + etc. (i.e., phrases used for their side-effects or to be executed + in a top level.) + - Long sequences of `and's may slow down indentation slightly, since + some computations (few) require to go back to the beginning of the + sequence. Some very long nested blocks may also lead to slow + processing of `end's, `else's, `done's... + - Multiline strings are handled properly, but you may prefer string + concatenation `^' to break long strings (the C-j keystroke can help). + - Comment indentation is often a matter of taste and context, yet + sophisticated heuristics provide reasonable indentation in most cases. + When inserting a comment right before the code it refers to, it is + generally expected that this comment will be aligned with the folowing + code; to enforce this, leave a blank line before the comment. + +Known bugs: + - When writing a line with mixed code and comments, avoid putting + comments at the beginning or middle of the text. More precisely, + writing comments immediately after `=' or parentheses then writing + some more code on the line leads to indentation errors. You may write + `let x (* blah *) = blah' but should avoid `let x = (* blah *) blah'. + +Short cuts for the Tuareg mode: +\\{tuareg-mode-map} + +Short cuts for interactions with the toplevel: +\\{tuareg-interactive-mode-map} + +\(fn)" t nil) + +(autoload 'tuareg-run-ocaml "tuareg" "\ +Run an OCaml toplevel process. I/O via buffer `*ocaml-toplevel*'. + +\(fn)" t nil) + +(defalias 'run-ocaml 'tuareg-run-ocaml) + +;;;*** + +;;;### (autoloads nil nil ("tuareg-light.el") (21122 7940 365297 +;;;;;; 584000)) + +;;;*** + diff --git a/tuareg.el b/tuareg.el index efbfb30..be1235c 100644 --- a/tuareg.el +++ b/tuareg.el @@ -5,13 +5,13 @@ ;; Licensed under the GNU General Public License. ;; Author: Albert Cohen <albert.co...@inria.fr> -;; Sam Steingold <s...@gnu.org> -;; Christophe Troestler <christophe.troest...@umons.ac.be> -;; Till Varoquaux <t...@pps.jussieu.fr> -;; Sean McLaughlin <sean...@gmail.com> -;; Stefan Monnier <monn...@iro.umontreal.ca> +;; Sam Steingold <s...@gnu.org> +;; Christophe Troestler <christophe.troest...@umons.ac.be> +;; Till Varoquaux <t...@pps.jussieu.fr> +;; Sean McLaughlin <sean...@gmail.com> +;; Stefan Monnier <monn...@iro.umontreal.ca> ;; Created: 8 Jan 1997 -;; Version: 2.0.6 +;; Version: 2.0.7 ;; Package-Requires: ((caml "3.12.0.1")) ;; Keywords: ocaml languages ;; URL: http://forge.ocamlcore.org/projects/tuareg/ @@ -77,14 +77,18 @@ (defconst tuareg-mode-revision (eval-when-compile (with-temp-buffer - (cond ((file-directory-p ".hg") - (call-process "hg" nil t nil "id" "-i" "--debug")) - ((file-directory-p ".svn") + (cond ((file-directory-p ".git") + (progn + (insert "git: ") + (call-process "git" nil t nil "log" "--pretty=%h" "-1"))) + ((file-directory-p ".hg") + (call-process "hg" nil t nil "id" "-i" "--debug")) + ((file-directory-p ".svn") (let ((process-environment (cons "LANG=C" process-environment))) (shell-command "svn info | grep Revision: | sed 's/Revision: //'" t))) - ((file-directory-p ".bzr") - (shell-command "bzr log -l -1 | grep revno:" t))) + ((file-directory-p ".bzr") + (shell-command "bzr log -l -1 | grep revno:" t))) (unless (zerop (buffer-size)) (buffer-substring-no-properties (point-min) (1- (point-max)))))) @@ -93,7 +97,7 @@ (defconst tuareg-mode-version (let ((version "Tuareg Version 2.0.6")) (if (null tuareg-mode-revision) - version + version (concat version " (" tuareg-mode-revision ")") )) " Copyright (C) 1997-2006 Albert Cohen, all rights reserved. @@ -133,6 +137,9 @@ (read-from-minibuffer prompt initial-input nil nil (or history 'shell-command-history)))) +(unless (fboundp 'derived-mode-p) ;; in derived.el in emacs21 + (require 'derived)) + ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; Import types and help features @@ -489,8 +496,9 @@ Valid names are `browse-url', `browse-url-firefox', etc." (assq :inherit face-attribute-name-alist))) (defface tuareg-font-lock-governing-face - '((((background light)) (:foreground "blue" :bold t)) - (t (:foreground "orange" :bold t))) + '((((class color) (type tty)) (:bold t)) + (((background light)) (:foreground "black" :bold t)) + (t (:foreground "wheat" :bold t))) "Face description for governing/leading keywords." :group 'tuareg-faces) (defvar tuareg-font-lock-governing-face @@ -856,9 +864,9 @@ alignment and can thus lead to surprises." ("'s" . ,(decode-char 'ucs 963)) ("'t" . ,(decode-char 'ucs 964)) ("'x" . ,(decode-char 'ucs 958)))) - ((and (fboundp 'make-char) (fboundp 'charsetp) (charsetp 'symbol)) - `(("fun" . ,(make-char 'symbol 108)) - ("sqrt" . ,(make-char 'symbol 214)) + ((and (fboundp 'make-char) (fboundp 'charsetp) (charsetp 'symbol)) + `(("fun" . ,(make-char 'symbol 108)) + ("sqrt" . ,(make-char 'symbol 214)) ("not" . ,(make-char 'symbol 216)) ("&&" . ,(make-char 'symbol 217)) ("or" . ,(make-char 'symbol 218)) @@ -1200,9 +1208,10 @@ For use on `electric-indent-functions'." ;; - Use it by default (when possible). ;; - Move the old indentation code to a separate file. -(defvar tuareg-use-smie nil) ;Not used by default yet. +(defvar tuareg-use-smie nil) -(require 'smie nil 'noerror) +(when (require 'smie nil 'noerror) + (setq tuareg-use-smie t)) (defconst tuareg-smie-grammar ;; Problems: @@ -1250,6 +1259,7 @@ For use on `electric-indent-functions'." (decls "class" decls) (decls "val" decls) (decls "external" decls) (decls "open" decls) (decls "include" decls) + (decls "DEFINE" decls) (exception) (def) ;; Hack: at the top-level, a "let D in E" can appear in @@ -1260,7 +1270,7 @@ For use on `electric-indent-functions'." (def-in-exp (defs "in" exp)) (def (var "d=" exp) (id "d=" datatype) (id "d=" module)) (idtype (id ":" type)) - (var (id) ("m-type" var) ("rec" var) (idtype) + (var (id) ("m-type" var) ("rec" var) ("private" var) (idtype) ("l-module" var) ("l-class" var)) (exception (id "of" type)) (datatype ("{" typefields "}") (typebranches) @@ -1313,6 +1323,7 @@ For use on `electric-indent-functions'." (pattern (id) (pattern "as" id) (pattern "," pattern)) (class-body (class-body "inherit" class-body) (class-body "method" class-body) + (class-body "initializer" class-body) (class-body "val" class-body) (class-body "constraint" class-body) (class-field)) @@ -1365,9 +1376,9 @@ For use on `electric-indent-functions'." '((assoc "|") (assoc ";")) ;; Fix up associative declaration keywords. '((assoc "type" "d-let" "exception" "module" "val" "open" - "external" "include" "class" ";;") + "external" "include" "class" "DEFINE" ";;") (assoc "and")) - '((assoc "val" "method" "inherit" "constraint")) + '((assoc "val" "method" "inherit" "constraint" "initializer")) ;; Declare associativity of remaining sequence separators. '((assoc ";")) '((assoc "|")) '((assoc "m-and"))))) ;; (dolist (pair '()) ;; ("then" . "|") ("|" . "then") @@ -1392,7 +1403,7 @@ For use on `electric-indent-functions'." (reverse '((nonassoc "." "#") ;; function application, constructor application, assert, lazy - ;; - -. (prefix) – + ;; - -. (prefix) – (right "**…" "lsl" "lsr" "asr") (nonassoc "*…" "/…" "%…" "mod" "land" "lor" "lxor") (left "+…" "-…") @@ -1529,12 +1540,16 @@ For use on `electric-indent-functions'." (defun tuareg-smie--=-disambiguate () "Return which kind of \"=\" we've just found. Point is not moved and should be right in front of the equality. -Return values can be \"f=\" for field definition, \"d=\" for a normal definition, -\"c=\" for a type equality constraint, and \"=…\" for an equality test." +Return values can be + \"f=\" for field definition, + \"d=\" for a normal definition, + \"c=\" for a type equality constraint, and + \"=…\" for an equality test." (save-excursion (let* ((pos (point)) (telltale '("type" "let" "module" "class" "and" "external" - "=" "if" "then" "else" "->" ";")) + "val" "method" "DEFINE" "=" + "if" "then" "else" "->" ";" )) (nearest (tuareg-smie--search-backward telltale))) (cond ((and (member nearest '("{" ";")) @@ -1556,8 +1571,8 @@ Return values can be \"f=\" for field definition, \"d=\" for a normal definition (equal (tuareg-smie-backward-token) "t->"))) (setq nearest (tuareg-smie--search-backward telltale))) nil)) - ((not (member nearest - '("type" "let" "module" "class" "and" "external"))) + ((not (member nearest '("type" "let" "module" "class" "and" + "external" "val" "method" "DEFINE"))) "=…") ((and (member nearest '("type" "module")) (member (tuareg-smie--backward-token) '("with" "and"))) "c=") @@ -1670,18 +1685,18 @@ Return values can be \"f=\" for field definition, \"d=\" for a normal definition (:list-intro (member token '("fun"))) (:before (cond - ((equal token "d=") (smie-rule-parent 2)) - ((member token '("fun" "match")) + ((equal token "d=") (smie-rule-parent 2)) + ((member token '("fun" "match")) (if (and (not (smie-rule-bolp)) (smie-rule-prev-p "d=")) (smie-rule-parent tuareg-default-indent))) - ((equal token "then") (smie-rule-parent)) - ((equal token "if") (if (and (not (smie-rule-bolp)) - (smie-rule-prev-p "else")) - (smie-rule-parent))) - ((and (equal token "with") (smie-rule-parent-p "{")) - (smie-rule-parent)) + ((equal token "then") (smie-rule-parent)) + ((equal token "if") (if (and (not (smie-rule-bolp)) + (smie-rule-prev-p "else")) + (smie-rule-parent))) + ((and (equal token "with") (smie-rule-parent-p "{")) + (smie-rule-parent)) ;; Align the "with" of "module type A = B \n with ..." w.r.t "module". - ((and (equal token "m-with") (smie-rule-parent-p "d=")) + ((and (equal token "m-with") (smie-rule-parent-p "d=")) (save-excursion (smie-backward-sexp token) (goto-char (nth 1 (smie-backward-sexp 'halfsexp))) @@ -1702,6 +1717,10 @@ Return values can be \"f=\" for field definition, \"d=\" for a normal definition (save-excursion (smie-backward-sexp 'halfsexp) (cons 'column (smie-indent-virtual)))))) + ;; If we're looking at the first class-field-spec + ;; in a "object(type)...end", don't rely on the default behavior which + ;; will treat (type) as a previous element with which to align. + ((tuareg-smie--object-hanging-rule token)) ;; Apparently, people like their `| pattern when test -> body' to have ;; the `when' indented deeper than the body. ((equal token "when") (smie-rule-parent tuareg-match-when-indent)))) @@ -1713,30 +1732,30 @@ Return values can be \"f=\" for field definition, \"d=\" for a normal definition 2)) ((equal token "->") (cond - ((and (smie-rule-parent-p "with") - ;; Align with "with" but only if it's the only branch (often - ;; the case in try..with), since otherwise subsequent - ;; branches can't be both indented well and aligned. - (save-excursion - (and (not (equal "|" (nth 2 (smie-forward-sexp "|")))) - ;; Since we may misparse "if..then.." we need to - ;; double check that smie-forward-sexp indeed got us - ;; to the right place. - (equal (nth 2 (smie-backward-sexp "|")) "with")))) - (smie-rule-parent 2)) - ((smie-rule-parent-p "|") tuareg-match-clause-indent) - (t 0))) + ((and (smie-rule-parent-p "with") + ;; Align with "with" but only if it's the only branch (often + ;; the case in try..with), since otherwise subsequent + ;; branches can't be both indented well and aligned. + (save-excursion + (and (not (equal "|" (nth 2 (smie-forward-sexp "|")))) + ;; Since we may misparse "if..then.." we need to + ;; double check that smie-forward-sexp indeed got us + ;; to the right place. + (equal (nth 2 (smie-backward-sexp "|")) "with")))) + (smie-rule-parent 2)) + ((smie-rule-parent-p "|") tuareg-match-clause-indent) + (t 0))) ((equal token ":") (cond ((smie-rule-parent-p "val" "external") (smie-rule-parent 2)) ((smie-rule-parent-p "module") (smie-rule-parent)) (t 2))) - ((equal token "in") tuareg-in-indent) ;;(if (smie-rule-hanging-p) - ((equal token "with") - (cond - ;; ((smie-rule-next-p "|") 2) - ((smie-rule-parent-p "{") nil) - (t (+ 2 tuareg-with-indent)))) + ((equal token "in") tuareg-in-indent) ;;(if (smie-rule-hanging-p) + ((equal token "with") + (cond + ;; ((smie-rule-next-p "|") 2) + ((smie-rule-parent-p "{") nil) + (t (+ 2 tuareg-with-indent)))) ((or (member token '("." "t->" "]")) (consp (nth 2 (assoc token tuareg-smie-grammar)))) ;; Closer. nil) @@ -1780,10 +1799,29 @@ Return values can be \"f=\" for field definition, \"d=\" for a normal definition (save-excursion (let ((prev (tuareg-smie-backward-token))) ;; FIXME: Should we use the same loop as above? - (and (equal prev ">…") (looking-at ">>[>=]") + (and (equal prev ">…") (looking-at ">>[>=|]") (progn (smie-backward-sexp prev) (cons 'column (current-column))))))))) +(defun tuareg-smie--object-hanging-rule (token) + ;; If we're looking at the first class-field-spec + ;; in a "object(type)...end", don't rely on the default behavior which + ;; will treat (type) as a previous element with which to align. + (cond + ;; An important role of this first condition is to call smie-indent-virtual + ;; so that we get called back to compute the (virtual) indentation of + ;; "object", thus making sure we get called back to apply the second rule. + ((and (member token '("inherit" "val" "method" "constraint")) + (smie-rule-parent-p "object")) + (save-excursion + (forward-word 1) + (goto-char (nth 1 (smie-backward-sexp 'halfsexp))) + (let ((col (smie-indent-virtual))) + `(column . ,(+ tuareg-default-indent col))))) + ;; For "class foo = object(type)...end", align object...end with class. + ((and (equal token "object") (smie-rule-parent-p "class")) + (smie-rule-parent)))) + (defun tuareg-smie--if-then-hack (token) ;; Getting SMIE's parser to properly parse "if E1 then E2" is difficult, so ;; instead we live with a confused parser and try to work around the mess @@ -1821,7 +1859,9 @@ Return values can be \"f=\" for field definition, \"d=\" for a normal definition (smie-setup tuareg-smie-grammar #'tuareg-smie-rules :forward-token #'tuareg-smie-forward-token :backward-token #'tuareg-smie-backward-token) - (add-hook 'smie-indent-functions #'tuareg-smie--inside-string nil t)) + (add-hook 'smie-indent-functions #'tuareg-smie--inside-string nil t) + (set (make-local-variable 'add-log-current-defun-function) + 'tuareg-current-fun-name)) (set (make-local-variable 'indent-line-function) #'tuareg-indent-command)) (tuareg-install-font-lock) (set (make-local-variable 'open-paren-in-column-0-is-defun-start) nil) @@ -1922,8 +1962,8 @@ Short cuts for interactions with the toplevel: (set (make-local-variable 'comment-start) "(* ") (set (make-local-variable 'comment-end) " *)") (set (make-local-variable 'comment-start-skip) "(\\*+[ \t]*") - (set (make-local-variable 'comment-column) 40) ;FIXME: Why? - (set (make-local-variable 'comment-multi-line) t) ;FIXME: Why? + ;(set (make-local-variable 'comment-column) 40) ;FIXME: Why? + ;(set (make-local-variable 'comment-multi-line) t) ;FIXME: Why? ;; `ocamlc' counts columns from 0, contrary to other tools which start at 1. (set (make-local-variable 'compilation-first-column) 0) (set (make-local-variable 'compilation-error-screen-columns) nil) @@ -1943,7 +1983,61 @@ Short cuts for interactions with the toplevel: (abbrev-mode 1)) (message nil)) +(defconst tuareg-starters-syms + '("module" "type" "let" "d-let" "and")) + +(defun tuareg-find-matching-starter (starters) + (let (tok) + (while + (let ((td (smie-backward-sexp 'halfsexp))) + (cond + ((and (car td) + (member (nth 2 td) starters)) + (goto-char (nth 1 td)) (setq tok (nth 2 td)) nil) + ((and (car td) (not (numberp (car td)))) + (unless (bobp) (goto-char (nth 1 td)) t)) + (t t)))) + tok)) + +(defun tuareg-skip-siblings () + (while (and (not (bobp)) + (null (car (smie-backward-sexp)))) + (tuareg-find-matching-starter tuareg-starters-syms)) + (when (looking-at "in") + ;; Skip over `local...in' and continue. + (forward-word 1) + (smie-backward-sexp 'halfsexp) + (tuareg-skip-siblings))) + +(defun tuareg-beginning-of-defun () + (when (tuareg-find-matching-starter tuareg-starters-syms) + (save-excursion (tuareg-smie-forward-token) + (forward-comment (point-max)) + (let ((name (tuareg-smie-forward-token))) + (if (not (member name '("rec" "type"))) + name + (forward-comment (point-max)) + (tuareg-smie-forward-token)))))) + +(defcustom tuareg-max-name-components 3 + "Maximum number of components to use for the current function name." + :type 'integer) + +(defun tuareg-current-fun-name () + (save-excursion + (let ((count tuareg-max-name-components) + fullname name) + (end-of-line) + (while (and (> count 0) + (setq name (tuareg-beginning-of-defun))) + (decf count) + (setq fullname (if fullname (concat name "." fullname) name)) + ;; Skip all other declarations that we find at the same level. + (tuareg-skip-siblings)) + fullname))) + (defun tuareg-install-font-lock () + (let ((lid "[_[:lower:]][_'[:alnum:]]*")) (setq tuareg-font-lock-keywords `(,@(if (tuareg-editing-ls3) @@ -1956,87 +2050,105 @@ Short cuts for interactions with the toplevel: 0 tuareg-font-lock-governing-face nil nil))) (,(concat "\\<\\(" (regexp-opt '("external" "open" "include" "sig" "struct" - "module" "functor" "val" "type" "method" + "module" "functor" "type" "virtual" "constraint" "class" "in" "inherit" "initializer" "let" "rec" "object" "and" "begin" "end")) - "\\|with[ \t\n]+\\(type\\|module\\)\\)\\>") + "\\>\\|with[ \t\n]+\\(type\\|module\\)\\>" + "\\|\\(method\\|val\\)\\>!?" + "\\([ \t\n]\\(virtual\\|private\\)\\>\\)*\\)") 0 tuareg-font-lock-governing-face nil nil) + (,(concat "\\<\\(" + (regexp-opt '("DEFINE" "IFDEF" "IFNDEF" "THEN" "ENDIF" + "INCLUDE" "__FILE__" "__LOCATION__")) + "\\)\\>") + 0 font-lock-preprocessor-face nil nil) ,@(and tuareg-support-metaocaml '(("\\.<\\|>\\.\\|\\.~\\|\\.!" 0 tuareg-font-lock-multistage-face nil nil))) ("\\<\\(false\\|true\\)\\>" 0 font-lock-constant-face nil nil) (,(regexp-opt '("as" "do" "of" "done" "downto" "else" "for" "if" - "mutable" "new" "parser" "private" - "then" "to" "try" "when" "while" "match" "with" - "lazy" "exception" "raise" "failwith" "failwithf" - "exit" "assert" "fun" "function") 'words) + "mutable" "new" "private" + "then" "to" "try" "when" "while" "match" "with" + "lazy" "exception" "assert" "fun" "function") 'words) 0 font-lock-keyword-face nil nil) ,@(if (tuareg-editing-ls3) - `(("\\<\\(merge\\|when\\|emit\\|period\\)\\>" + `(("\\<\\(merge\\|emit\\|period\\)\\>" 0 font-lock-keyword-face nil nil))) + (,(regexp-opt '("failwith" "failwithf" "exit" "invalid_arg" + "parser" "raise") 'words) + 0 font-lock-builtin-face nil nil) + ("\\([?~]\\<[_[:alpha:]]\\w*\\) *[\t\n]? *:[^:>=]" + 1 font-lock-constant-face keep nil) + ;; label in a type signature + (,(concat "\\(->\\|:[^:>=]\\) *[\t\n]? *\\(" lid "\\)[ \t]*:[^:>=]") + 2 font-lock-constant-face keep nil) + (,(concat "( *\\<" lid "\\> *:>? *[\t\n]? *" + "\\(\\([[:alnum:] '*.]+\\|([[:alnum:], '*.]+)\\)+\\))") + 1 font-lock-type-face keep nil) (,(concat - "[][;,()|{}]\\|[@^!:*=<>&/%+~?#---]\\.?\\|\\.\\.\\.*\\|" + "[][;,()|{}]\\|[-@^!:*=<>&/%+~?#]\\.?\\|\\.\\.\\.*\\|" (if (tuareg-editing-ls3) (regexp-opt '("asr" "asl" "lsr" "lsl" "or" "lor" "and" "land" "lxor" "not" "lnot" "mod" "of" "ref" "fby" "pre" "last" "at") 'words) - (regexp-opt '("asr" "asl" "lsr" "lsl" "or" "lor" "and" "land" + (regexp-opt '("asr" "asl" "lsr" "lsl" "or" "lor" "land" "lxor" "not" "lnot" "mod" "of" "ref") 'words))) 0 tuareg-font-lock-operator-face nil nil) + ;; (value: type) and (value :> type) + ;; A method is considered a function ([self] is always a param) + (,(concat "\\<method\\>!?\\( *[\t\n]? *\\(private\\|virtual\\)\\>\\)*" + " *[\t\n]? *\\([_[:lower:]]\\(\\w\\|['_]\\)*\\)") + 3 font-lock-function-name-face keep nil) (,(concat - "\\<\\(\\(method\\([ \t\n]+\\(private\\|virtual\\)\\)*\\)" - "\\|val\\([ \t\n]+mutable\\)?" - "\\|external\\|and\\|class" + "\\<\\(val\\>!?\\( +\\(mutable\\|virtual\\)\\>\\)*" + "\\|external\\>\\|and\\>\\|class\\>" (if (tuareg-editing-ls3) - "\\|let\\([ \t\n]+\\(?:rec\\|clock\\|node\\|static\\)\\)?" - "\\|let\\([ \t\n]+rec\\)?") - "\\)\\>[ \t\n]*\\([_[:lower:]]\\(\\w\\|[._]\\)*\\)\\>" - "[ \t\n]*\\(\\(\\w\\|[()_?~.'*:--->]\\)+" - "\\|=[ \t\n]*fun\\(ction\\)?\\>\\)") - 7 font-lock-function-name-face keep nil) - ;; FIXME: Isn't this redundant with the previous one? - ("\\<method\\([ \t\n]+\\(private\\|virtual\\)\\)?\\>[ \t\n]*\\(\\(\\w\\|[_,?~.]\\)*\\)" - 3 font-lock-function-name-face keep nil) - ("\\<\\(fun\\(ction\\)?\\)\\>[ \t\n]*\\(\\(\\w\\|[_ \t()*,]\\)+\\)" - 3 font-lock-variable-name-face keep nil) + "\\|let\\( *[\t\n]? *\\(?:rec\\|clock\\|node\\|static\\)\\)?" + "\\|let\\( +rec\\)?\\>") + "\\) *[\t\n]? *\\([_[:lower:]]\\(\\w\\|[._]\\)*\\)\\> *[\t\n]? *" + "\\(\\(\\w\\|[->()_?~.'*:]\\)+\\|= *[\t\n]? *fun\\(ction\\)?\\>\\)") + 5 font-lock-function-name-face keep nil) + (,(concat "\\<function[ \t\n]+\\(" lid "\\)") + 1 font-lock-variable-name-face keep nil) + ;; "type lid" anywhere (e.g. "let f (type t) x =") introduces a new type + (,(concat "\\<type\\> *[\t\n]? *\\(\\<" lid "\\>\\)") + 1 font-lock-type-face keep nil) + (,(concat "\\<fun\\>\\(\\(\\w\\|[_ \t\n(),*~?:=]\\)+\\) *[\t\n]? *->") + 1 font-lock-variable-name-face keep nil) (,(concat - "\\<\\(" - (if (tuareg-editing-ls3) "reset\\|do\\|") - "val\\([ \t\n]+mutable\\)?\\|external\\|and\\|class" - "\\|let\\([ \t\n]+rec\\)?" - "\\)\\>[ \t\n]*\\(\\(\\w\\|[_,?~.]\\)*\\)") - 4 font-lock-variable-name-face keep nil) + "\\(?:" + (if (tuareg-editing-ls3) "\\<val\\> *\\w+ *[\t\n]? *:\\|") + "[^~?]\\<\\w+ *:\\) *[\t\n]? *" + "\\([^:>=]\\(['?]*\\(-> *[\t\n]? *\\|:[^:>=]\\|[_.* \t[:alnum:]]" + "\\|(['?]*[->_.,* \t:[:alnum:]]*)" + "\\|\\[[_'`<>|[:alnum:] \t]+\\]\\)\\{1,500\\}\\)\\)\\>") + 1 font-lock-type-face keep nil) (,(concat "\\<\\(" (if (tuareg-editing-ls3) "reset\\|do\\|") - "val\\([ \t\n]+mutable\\)?\\|external\\|method\\|and\\|class" - "\\|let\\([ \t\n]+" + "val\\>\\( *[\t\n]? *mutable\\)?\\|method\\|and\\|class" + "\\|let\\>\\( *[\t\n]? *" (if (tuareg-editing-ls3) "\\(?:rec\\|clock\\|node\\|static\\)" "rec") - "\\)?\\)\\>[ \t\n]*\\(\\(\\w\\|[_,?~.]\\)*\\)\\>" - "\\(\\(\\w\\|[->_ \t,?~.]\\|(\\(\\w\\|[--->_ \t,?~.=]\\)*)\\)*\\)") - 6 font-lock-variable-name-face keep nil) + "\\)?\\)\\> *[\t\n]? *\\(\\(" + lid "\\|([ \t]*" lid "[ \t]*:[->~_' \t(),.[:word:]]+)\\|\\?" lid + ;; FIXME: how to match multiple lines (until "=") efficiently? + "\\|\\?(" lid "=[->[:word:]'_. \t,.:\"]+)" + "\\|[>~_(),.[:space:]]\\)+\\)") + 4 font-lock-variable-name-face keep nil) (,(concat - "\\<\\(open\\|\\(class\\([ \t\n]+type\\)?\\)\\([ \t\n]+virtual\\)?" - "\\|inherit\\|include\\|module\\([ \t\n]+\\(type\\|rec\\)\\)?" - "\\|type\\)\\>[ \t\n]*" - "\\(['~?]*\\([_--->.* \t]\\|\\w\\|(['~?]*\\([_--->.,* \t]\\|\\w\\)*)\\)*\\)") + "\\<\\(open\\|\\(class\\>\\( *[\t\n]? *type\\)?\\)" + "\\( *[\t\n]? *\\<virtual\\)?" + "\\|inherit\\|include\\|module\\( *[\t\n]? *\\<\\(type\\|rec\\)\\)?" + "\\|type\\)\\> *[\t\n]? *" + "\\(['~?]*\\([->_.* \t]\\|\\w\\|(['~?]*\\([->_.,* \t]\\|\\w\\)*)\\)*\\)") 7 font-lock-type-face keep nil) - (,(concat - "\\(?:" - (if (tuareg-editing-ls3) - "\\<val\\>[ \t\n]*\\w*[ \t\n]*:\\|") - "[^:>=]\\):[ \t\n]*" - "\\(['~?]*\\([_--->.* \t]\\|\\w\\|(['~?]*\\([_--->.,* \t]\\|\\w\\)*)\\)*\\)") - 1 font-lock-type-face keep nil) ("\\<\\([A-Z]\\w*\\>\\)[ \t]*\\." 1 font-lock-type-face keep nil) - ("\\<\\([?~]?[_[:alpha:]]\\w*\\)[ \t\n]*:[^:>=]" - 1 font-lock-variable-name-face keep nil) - ("\\<exception\\>[ \t\n]*\\(\\<[_[:alpha:]]\\w*\\>\\)" + ("\\<exception\\> *[\t\n]? *\\(\\<[_[:alpha:]]\\w*\\>\\)" 1 font-lock-variable-name-face keep nil) ("^#\\w+\\>" 0 font-lock-preprocessor-face t nil) ,@(and tuareg-font-lock-symbols - (tuareg-font-lock-symbols-keywords)))) + (tuareg-font-lock-symbols-keywords))))) (setq font-lock-defaults `(tuareg-font-lock-keywords ,(not tuareg-use-syntax-ppss) nil @@ -2086,7 +2198,10 @@ Short cuts for interactions with the toplevel: (list tuareg-error-regexp 2 '(3 . 4) '(5 . 6) '(7 . 1)) (list tuareg-error-regexp 2 3)) - compilation-error-regexp-alist)))) + ;; Other error format used for unhandled match case. + (cons '("^Fatal error: exception [^ \n]*(\"\\([^\"]*\\)\", \\([0-9]+\\), \\([0-9]+\\))" + 1 2 3) + compilation-error-regexp-alist))))) ;; A regexp to extract the range info. @@ -2211,7 +2326,7 @@ For synchronous programming.") tuareg-match-pipe-kwop-regexp-ls3 tuareg-match-pipe-kwop-regexp)) -(defconst tuareg-operator-regexp "[---+*/=<>@^&|]\\|:>\\|::\\|\\<\\(or\\|l\\(and\\|x?or\\|s[lr]\\)\\|as[lr]\\|mod\\)\\>" +(defconst tuareg-operator-regexp "[-+*/=<>@^&|]\\|:>\\|::\\|\\<\\(or\\|l\\(and\\|x?or\\|s[lr]\\)\\|as[lr]\\|mod\\)\\>" "Regexp for all operators.") (defconst tuareg-matching-keyword-regexp @@ -2238,6 +2353,7 @@ For synchronous programming.") (defconst tuareg-matching-kwop-regexp (concat tuareg-matching-keyword-regexp "\\|\\<with\\>\\|[|>]?\\]\\|>?}\\|[|)]\\|;;") + ;; FIXME: what about \\|\\<end\\> ? "Regexp matching OCaml keywords or operators which act as end block delimiters.") @@ -4101,13 +4217,13 @@ otherwise return non-nil." (let ((name buffer-file-name)) (when (string-match "\\`\\(.*\\)\\.ml\\([il]\\)?\\'" name) (let ((mod-name (tuareg-match-string 1 name)) - (e (tuareg-match-string 2 name))) - (cond - ((string= e "i") - (unless (tuareg--try-find-alternate-file mod-name ".mll" 'no-create) - (tuareg--try-find-alternate-file mod-name ".ml"))) - (t - (tuareg--try-find-alternate-file mod-name ".mli"))))))) + (e (tuareg-match-string 2 name))) + (cond + ((string= e "i") + (unless (tuareg--try-find-alternate-file mod-name ".mll" 'no-create) + (tuareg--try-find-alternate-file mod-name ".ml"))) + (t + (tuareg--try-find-alternate-file mod-name ".mli"))))))) (define-skeleton tuareg-insert-class-form "Insert a nicely formatted class-end form, leaving a mark after end." @@ -4153,7 +4269,7 @@ otherwise return non-nil." ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; Tuareg interactive mode -;; Augment Tuareg mode with a OCaml toplevel. +;; Augment Tuareg mode with an OCaml toplevel. (require 'comint) @@ -4255,6 +4371,9 @@ Short cuts for interactions with the toplevel: (setq comint-scroll-to-bottom-on-output tuareg-interactive-scroll-to-bottom-on-output) (set-syntax-table tuareg-mode-syntax-table) + (set (make-local-variable 'comment-start) "(* ") + (set (make-local-variable 'comment-end) " *)") + (set (make-local-variable 'comment-start-skip) "(\\*+[ \t]*") (tuareg--common-mode-setup) (when (or tuareg-interactive-input-font-lock @@ -4276,6 +4395,9 @@ Short cuts for interactions with the toplevel: (tuareg-run-process-if-needed) (display-buffer tuareg-interactive-buffer-name)) +;;;###autoload +(defalias 'run-ocaml 'tuareg-run-ocaml) + (defun tuareg-run-process-if-needed (&optional cmd) "Run an OCaml toplevel process if needed, with an optional command name. I/O via buffer `*ocaml-toplevel*'." -- Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-ocaml-maint/packages/tuareg-mode.git _______________________________________________ Pkg-ocaml-maint-commits mailing list Pkg-ocaml-maint-commits@lists.alioth.debian.org http://lists.alioth.debian.org/cgi-bin/mailman/listinfo/pkg-ocaml-maint-commits