Skip to content
Commits on Source (2)
*.elc
*.test
*-autoloads.el
*-pkg.el
*~
*.tar.gz
tuareg.*/
packages
/tuareg.*/
ChangeLog
# Inspired by http://sachachua.com/blog/2015/02/continuous-integration-code-coverage-emacs-packages-travis-coveralls/
language: emacs-lisp
sudo: false
env:
matrix:
- EVM_EMACS=emacs-24.3
- EVM_EMACS=emacs-24.4
- EVM_EMACS=emacs-24.5
- EVM_EMACS=emacs-25.1
before_install:
- export PATH="$HOME/.evm/bin:$PATH"
- git clone https://github.com/rejeep/evm.git $HOME/.evm
- evm config path /tmp
- evm install ${EVM_EMACS}-travis --use --skip
script:
- emacs --version
- make elc
- make indent-test
notifications:
email: true
2.0.9 (master):
* Do not activate Tuareg for .mll and .mly files.
* Toplevel prompt is readonly.
* Font-lock code completely rewritten (avoids several hangs). New faces
`tuareg-font-lock-module-face', `tuareg-font-lock-constructor-face',
and `tuareg-font-lock-line-number-face'.
* Non-closed comment does not cause M-q to hang.
* New variables `caml-types-build-dirs' and `caml-types-annot-dir' for
a more versatile specification of .annot files. (Submitted back to
caml-mode.)
* Fix toplevel highlighting of output and errors.
2.1.0 2017-11-10
----------------
* Let <kbd>M-q</kbd> reformat strings (and use only SMIE).
* Do not indent an expression after `;;` (issue #106).
* New face `tuareg-font-double-colon-face` to highlight `;;`.
* For `type … and …`, left-align `and` with `type`.
* Fix indentation of some GADT type definitions.
* Use `prettify-symbols-mode` to turn `+.` into `∔`,… and add a menu
entry to toggle it.
* Properly indent `type 'a foo = 'a bla = …` (issue #98).
* Properly indent (issue #7):
module … with module X = Z
and type t := C.t
* Support `let exception E in expr` (issue #102).
* Improved highlighting of `val` and `module` in first class module
expressions.
* Warn if a file inside a `_build` is edited and propose to switch.
* Add a custom face `tuareg-font-lock-label-face` for labels.
* Add option `tuareg-match-patterns-aligned` to allow to choose
between the two styles:
function v.s. function
| A | A
| B -> ... | B -> ...
| C -> ... | C -> ... "
* Highlight attributes and extension nodes.
* Disable by default and improve the compilation advice—see the new
variable `tuareg-opam-insinuate` (issue #97).
* New keybinding <kbd>C-cC-w</kbd> and function `tuareg-opam-update-env`
to update the environment to an opam switch (offering completion).
* Improved highlighting of quoted strings `{|…|}` (issue #89).
* Move after `;;` when evaluating a phrase in the toploop (issue #96).
* ocamldebug:
- Add support for `completion-at-point`.
- Highlight the right location even in presence of non-ascii chars
(issue #80).
- Make possible to pass argument to ocamldebug (say, paths with `-I`).
- Make possible to pass argument to the program being debugged (issue #66).
- Warn if SMIE is disabled.
* New modes `tuareg-jbuild` and `tuareg-opam` with syntax
highlighting, indentation, and skeletons.
2.0.10
------
* New indentation config var for SMIE: tuareg-indent-align-with-first-arg.
* Many indentation improvements.
* Fixed point jumping in ocamldebug completion (by Darius Foo).
* Improved (var: t) syntax highlighting.
* Color all predefined exceptions with font-lock-builtin-face
* Syntax highlight cppo preprocessor directives.
2.0.9
-----
* Do not activate Tuareg for .mll and .mly files.
* Toplevel prompt is readonly.
* Font-lock code completely rewritten (avoids several hangs). New faces
`tuareg-font-lock-module-face', `tuareg-font-lock-constructor-face',
and `tuareg-font-lock-line-number-face'.
* Non-closed comment does not cause M-q to hang.
* New variables `caml-types-build-dirs' and `caml-types-annot-dir' for
a more versatile specification of .annot files. (Submitted back to
caml-mode.)
* Fix toplevel highlighting of output and errors.
......@@ -6,23 +6,31 @@ 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)
OPAM_DIR = packages/tuareg/tuareg.$(VERSION)
SOURCES = tuareg.el tuareg_indent.el ocamldebug.el
SOURCES = tuareg.el ocamldebug.el tuareg-opam.el \
tuareg-jbuild.el
ELS = $(SOURCES) tuareg-site-file.el
ELC = $(ELS:.el=.elc)
INSTALL_FILES = $(ELS) $(ELC)
INSTALL_DIR ?= $(shell opam config var share)/emacs/site-lisp
DIST_FILES += $(ELS) Makefile README.md
DIST_FILES += $(ELS) Makefile README.md tuareg.install
EMACSFORMACOSX = /Applications/Emacs.app/Contents/MacOS/Emacs
AQUAMACS = $(shell test -d /Applications \
&& find /Applications -type f | grep 'Aquamacs$$')
ifeq ($(wildcard $(EMACSFORMACOSX)),$(EMACSFORMACOSX))
EMACS ?= $(EMACSFORMACOSX)
else
EMACS ?= emacs
ifneq ($(strip $(AQUAMACS)),)
ifeq ($(wildcard $(AQUAMACS)),$(AQUAMACS))
EMACS ?= $(AQUAMACS)
endif
endif
endif
EMACS ?= emacs
#ENABLE_SMIE = --eval '(setq tuareg-use-smie t)'
RM ?= rm -f
......@@ -34,12 +42,13 @@ INSTALL_RM_R = $(RM) -r
INSTALL_MKDIR = mkdir -p
INSTALL_CP = $(CP)
all : elc tuareg-site-file.el
all : tuareg-site-file.el
elc : $(ELC)
%.elc : %.el
$(EMACS) --batch -L . --no-init-file -f batch-byte-compile $<
@echo "Files byte-compiled using $(EMACS)"
install : $(INSTALL_FILES)
$(INSTALL_MKDIR) $(INSTALL_DIR)
......@@ -59,7 +68,7 @@ check : sample.ml.test
@echo ====Indent $*====
-$(RM) $@
$(EMACS) --batch -q --no-site-file $(ENABLE_SMIE) \
--load tuareg.elc $< \
--load tuareg-site-file.el $< \
--eval '(setq indent-tabs-mode nil)' \
--eval '(defun ask-user-about-lock (file opponent) nil)' \
--eval '(indent-region (point-min) (point-max) nil)' \
......@@ -67,6 +76,8 @@ check : sample.ml.test
--eval '(write-region (point-min) (point-max) "$@")'
$(DIFF) $< $@ || true
indent-test: indent-test.ml.test
tuareg-site-file.el: $(SOURCES)
(echo ";;; $@ --- Automatically extracted autoloads.";\
echo ";;; Code:";\
......@@ -87,7 +98,7 @@ $(TARBALL): $(DIST_FILES)
opam: $(TARBALL)
$(INSTALL_MKDIR) $(OPAM_DIR)
$(CP) -a $(filter-out %~, $(wildcard opam/*)) $(OPAM_DIR)
echo "archive: \"`pwd`/$(TARBALL)\"" > $(OPAM_DIR)/url
echo "archive: \"https://github.com/ocaml/tuareg/releases/download/$(VERSION)/$(TARBALL)\"" > $(OPAM_DIR)/url
echo "checksum: \"`md5sum $(TARBALL) | cut -d ' ' -f 1`\"" \
>> $(OPAM_DIR)/url
......
[![MELPA](https://melpa.org/packages/tuareg-badge.svg)](https://melpa.org/#/tuareg)
[![LGPL v2](https://img.shields.io/badge/licence-lgpl2-blue.svg)](COPYING)
[![Build Status](https://travis-ci.org/ocaml/tuareg.svg?branch=master)](https://travis-ci.org/ocaml/tuareg)
Tuareg: an Emacs OCaml mode
===========================
This archive contains files to help editing [OCaml](http://ocaml.org/)
code, to highlight important parts of the code, to run an OCaml
toplevel, and to run the OCaml debugger within Emacs.
[REPL](https://en.wikipedia.org/wiki/Read%E2%80%93eval%E2%80%93print_loop)
(also called *toplevel*),
and to run the OCaml debugger within Emacs.
Contents
--------
`README` — This file.
`README.md` — This file.
`HISTORY` — Differences with previous versions.
`tuareg.el` — A major mode for editing OCaml code in Emacs.
`ocamldebug.el` — To run the OCaml debugger under Emacs.
......@@ -17,36 +23,130 @@ Contents
Install
-------
See `tuareg.el`.
The easier way to install Tuareg is though
[`opam`](http://opam.ocaml.org/):
opam install tuareg
and follow the instructions given at the end of the `opam`
installation.
There are versions of Tuareg in [Melpa](https://melpa.org/) and
in [Marmalade](https://marmalade-repo.org/) but they may be older.
If you want to install from the Git checkout, just add to your
[Init File][]the line:
Configuration
-------------
(load "path-to-git-checkout-dir/tuareg-site-file")
Add the following line near the beginning of your ~/.emacs file:
If you want to byte compile the files, issue `make elc`. If you do
this in Darwin, make sure that the version of Emacs displayed at the
end of `make elc` is the sole that you use (the `.elc` files may not
be compatible with other versions of Emacs installed on your system).
(load "/where/ever/you/put/tuareg-mode/tuareg-site-file")
Usage & Configuration
---------------------
The Tuareg major mode is triggered by visiting a file with extension
.ml, .mli, .mly, .mll, and .mlp or manually by M-x tuareg-mode. It
gives you the correct syntax table for the OCaml language.
`.ml`, `.mli`, `.mly`, `.mll`, and `.mlp` or manually by
<kbd>M-x tuareg-mode</kbd>.
Start the OCaml REPL with <kbd>M-x run-ocaml</kbd>.
To evaluate a
phrase, simply type <kbd>S-⟨return⟩</kbd> (<kbd>shift</kbd> and
<kbd>return</kbd>). You can also evaluate a
phrase in a different buffer by typing <kbd>C-c C-e</kbd> when the
cursor is on it (it
will start the OCaml REPL if needed).
Run the OCaml debugger with <kbd>M-x ocamldebug FILE</kbd>.
Tips & customization
--------------------
- You can comment/uncomment a single line with <kbd>M-;</kbd>.
- By default, Tuareg will align the arguments of functions as follows:
function_name arg1
arg2
This is what most OCaml programmers expect and is convenient if you
use the following style:
function_name (fun x ->
do_something
)
arg2
If you prefer the “lisp style” indentation in which arguments on the
second line are aligned with the arguments on the first line as in
function_name arg1
arg2
put `(setq tuareg-indent-align-with-first-arg t)` in your [Init File][].
Thanks to the work of Stefan Monnier, a new indentation engine based
on SMIE was written. To deactivate it, add (setq tuareg-use-smie nil)
to the top-level of your `.emacs` file.
In both cases, if there are no argument on the line following the
function name, the indentation will be:
Usage
-----
function_name
arg1
arg2
See `tuareg.el`.
- To make easier to distinguish pattern-match cases containing several
patterns, sub-patterns are slightly indented as in
Customization
-------------
match x with
| A
| B -> ...
| C -> ...
The standard Emacs customization tool can be used to configure
Tuareg options. It is available from the Options menu and Tuareg's
Customize sub-menu.
If you prefer all pipes to be aligned as
match x with
| A
| B -> ...
| C -> ...
use `(setq tuareg-match-patterns-aligned t)`.
- Emacs ≥ 24.4 turned on [electric-indent-mode][] mode by default. If
you do not like it, call `(electric-indent-mode 0)` in
`tuareg-mode-hook`.
[electric-indent-mode]: https://www.gnu.org/software/emacs/manual/html_node/emacs/Indent-Convenience.html
- You can turn on and off the rendering of certain sequences of
characters as symbols (such as `∔` and `∧` instead of `+.`and `&&`),
use `prettify-symbols-mode` or use the check box in the _Tuareg
Options_ menu. To enable it by default when you start Tuareg, add
the following to your [Init File][]:
(add-hook 'tuareg-mode-hook
(lambda()
(when (functionp 'prettify-symbols-mode)
(prettify-symbols-mode))))
If you want more symbols to be prettified (such as `->` being
displayed as `→`) at the expense of modifying the indentation in
incompatible ways with those not using that option, add `(setq
tuareg-prettify-symbols-full t)` to your [Init File][].
Thanks to the work of Stefan Monnier, a new indentation engine based on
[SMIE](https://www.gnu.org/software/emacs/manual/html_node/elisp/SMIE.html)
was written. This changes the indentation somewhat w.r.t. the
previous versions of `tuareg`. If the indentation does not correspond
to what you expect, please submit a
[motivated issue](https://github.com/ocaml/tuareg/issues/).
The standard Emacs customization tool can be used to configure Tuareg
options. It is available from the Options menu and Tuareg's Customize
sub-menu. Note that, at the moment, both customization options
pertaining to the SMIE indentation mode and the old one are present.
You may also customize the appearance of OCaml code by twiddling the
variables listed at the start of tuareg.el (preferably using
......@@ -56,23 +156,17 @@ You should then add to your configuration file something like:
(add-hook 'tuareg-mode-hook
(lambda () ... ; your customization code ))
Sample Customizations
---------------------
Here are random examples of customization you might like to put in
your ~/.emacs file:
;; Indent `=' like a standard keyword.
(setq tuareg-lazy-= t)
;; Indent [({ like standard keywords.
(setq tuareg-lazy-paren t)
;; No indentation after `in' keywords.
(setq tuareg-in-indent 0)
For example:
(add-hook 'tuareg-mode-hook
;; Turn on auto-fill minor mode.
(lambda () (auto-fill-mode 1)))
See [dot-emacs.el](dot-emacs.el) for some examples.
[Init File]: https://www.gnu.org/software/emacs/manual/html_node/emacs/Init-File.html
Features, Known Bugs
--------------------
......@@ -118,7 +212,7 @@ Reporting
---------
The official Tuareg home page is located at:
<https://forge.ocamlcore.org/projects/tuareg/>.
<https://github.com/ocaml/tuareg>.
Bug reports & patches: use the tracker:
<https://forge.ocamlcore.org/tracker/?group_id=43>.
<https://github.com/ocaml/tuareg/issues>.
(require 'tuareg)
;; See README
(setq tuareg-indent-align-with-first-arg nil)
(add-hook
'tuareg-mode-hook
(lambda()
(setq show-trailing-whitespace t)
(setq indicate-empty-lines t)
;; Enable the representation of some keywords using fonts
(when (functionp 'prettify-symbols-mode)
(prettify-symbols-mode))
(when (functionp 'flyspell-prog-mode)
(flyspell-prog-mode))
;; See README
;;(setq tuareg-match-patterns-aligned t)
;;(electric-indent-mode 0)
))
;; Easy keys to navigate errors after compilation:
(define-key tuareg-mode-map [(f12)] 'next-error)
(define-key tuareg-mode-map [(shift f12)] 'previous-error)
;; Use Merlin if available
(when (require 'merlin nil t)
(setq merlin-command 'opam)
(add-to-list 'auto-mode-alist '("/\\.merlin\\'" . conf-mode))
(when (functionp 'merlin-document)
(define-key tuareg-mode-map (kbd "\C-c\C-h") 'merlin-document))
;; Run Merlin if a .merlin file in the parent dirs is detected
(add-hook 'tuareg-mode-hook
(lambda()
(let ((fn (buffer-file-name)))
(if (and fn (locate-dominating-file fn ".merlin"))
(merlin-mode))))))
;; Choose modes for related config. files
(setq auto-mode-alist
(append '(("_oasis\\'" . conf-mode)
("_tags\\'" . conf-mode)
("_log\\'" . conf-mode))
auto-mode-alist))
This diff is collapsed.
......@@ -80,7 +80,7 @@
(unless (face-differs-from-default-p 'ocamldebug-event)
(invert-face 'ocamldebug-event))
(unless (face-differs-from-default-p 'ocamldebug-underline)
(set-face-underline-p 'ocamldebug-underline t))
(set-face-underline 'ocamldebug-underline t))
(setq ocamldebug-overlay-event (make-overlay 1 1))
(overlay-put ocamldebug-overlay-event 'face 'ocamldebug-event)
(setq ocamldebug-overlay-under (make-overlay 1 1))
......@@ -91,8 +91,14 @@
;;; OCamldebug mode.
(defvar ocamldebug-prefix-map (make-sparse-keymap)
"Keymap bound to prefix keys in `ocamldebug-mode' and `tuareg-mode'.")
(define-key tuareg-mode-map "\C-x\C-a" ocamldebug-prefix-map)
(defvar ocamldebug-mode-map
(let ((map (make-sparse-keymap)))
(define-key map "\C-c" ocamldebug-prefix-map)
(define-key map "\C-l" 'ocamldebug-refresh)
;; This is already the default anyway!
;;(define-key map "\t" 'comint-dynamic-complete)
......@@ -127,17 +133,19 @@ Additionally we have:
\\[ocamldebug-display-frame] display frames file in other window
\\[ocamldebug-step] advance one line in program
C-x SPACE sets break point at current line."
(set (make-local-variable 'ocamldebug-last-frame) nil)
(set (make-local-variable 'ocamldebug-delete-prompt-marker) (make-marker))
(set (make-local-variable 'ocamldebug-filter-accumulator) "")
(set (make-local-variable 'ocamldebug-filter-function)
#'ocamldebug-marker-filter)
(set (make-local-variable 'comint-prompt-regexp) ocamldebug-prompt-pattern)
(set (make-local-variable 'comint-dynamic-complete-functions)
(cons #'ocamldebug-complete comint-dynamic-complete-functions))
(set (make-local-variable 'paragraph-start) comint-prompt-regexp)
(set (make-local-variable 'ocamldebug-last-frame-displayed-p) t)
(set (make-local-variable 'shell-dirtrackp) t)
(setq-local ocamldebug-last-frame nil)
(setq-local ocamldebug-delete-prompt-marker (make-marker))
(setq-local ocamldebug-filter-accumulator "")
(setq-local ocamldebug-filter-function #'ocamldebug-marker-filter)
(setq-local comint-prompt-regexp ocamldebug-prompt-pattern)
(setq-local comint-dynamic-complete-functions
(cons (if (boundp 'completion-at-point-functions)
#'ocamldebug-capf #'ocamldebug-complete)
comint-dynamic-complete-functions))
(setq-local comint-prompt-read-only t)
(setq-local paragraph-start comint-prompt-regexp)
(setq-local ocamldebug-last-frame-displayed-p t)
(setq-local shell-dirtrackp t)
(add-hook 'comint-input-filter-functions 'shell-directory-tracker nil t))
;;; Keymaps.
......@@ -176,8 +184,7 @@ representation is simply concatenated with the COMMAND."
(interactive "P")
(ocamldebug-call ,name ,args
(ocamldebug-numeric-arg arg))))
(define-key ocamldebug-mode-map ,(concat "\C-c" key) ',fun)
(define-key tuareg-mode-map ,(concat "\C-x\C-a" key) ',fun))))
(define-key ocamldebug-prefix-map ,key ',fun))))
(def-ocamldebug "step" "\C-s" "Step one source line with display.")
(def-ocamldebug "run" "\C-r" "Run the program.")
......@@ -221,7 +228,7 @@ representation is simply concatenated with the COMMAND."
(let ((ocamldebug-kill-output))
(with-current-buffer ocamldebug-current-buffer
(let ((proc (get-buffer-process (current-buffer)))
(ocamldebug-filter-function 'ocamldebug-kill-filter))
(ocamldebug-filter-function #'ocamldebug-kill-filter))
(ocamldebug-call "kill")
(while (not (and ocamldebug-kill-output
(zerop (length ocamldebug-filter-accumulator))))
......@@ -301,7 +308,7 @@ buffer, then try to obtain the time from context around point."
;get a list of all events in the current module
(with-current-buffer ocamldebug-current-buffer
(let* ((proc (get-buffer-process (current-buffer)))
(ocamldebug-filter-function 'ocamldebug-goto-filter))
(ocamldebug-filter-function #'ocamldebug-goto-filter))
(ocamldebug-call-1 (concat "info events " module))
(while (not (and ocamldebug-goto-output
(zerop (length ocamldebug-filter-accumulator))))
......@@ -311,7 +318,8 @@ buffer, then try to obtain the time from context around point."
(concat "^Time : \\([0-9]+\\) - pc : "
ocamldebug-goto-output
" - module "
module "$") nil t)
module "$")
nil t)
(match-string 1)))))
(if address (ocamldebug-call "goto" nil (string-to-number address))
(error "No time at %s at %s" module ocamldebug-goto-position))))))
......@@ -382,7 +390,7 @@ around point."
(ocamldebug-delete-position (ocamldebug-format-command "%c")))
(with-current-buffer ocamldebug-current-buffer
(let ((proc (get-buffer-process (current-buffer)))
(ocamldebug-filter-function 'ocamldebug-delete-filter)
(ocamldebug-filter-function #'ocamldebug-delete-filter)
(ocamldebug-delete-output))
(ocamldebug-call-1 "info break")
(while (not (and ocamldebug-delete-output
......@@ -418,72 +426,99 @@ around point."
"")
(defun ocamldebug-complete ()
"Perform completion on the ocamldebug command preceding point."
(interactive)
(let* ((capf-data (ocamldebug-capf))
(command-word (buffer-substring (nth 0 capf-data) (nth 1 capf-data))))
(completion-in-region (nth 0 capf-data) (nth 1 capf-data)
(sort (all-completions command-word (nth 2 capf-data))
#'string-lessp))))
(when (fboundp 'completion-at-point)
(make-obsolete 'ocamldebug-complete 'completion-at-point "24.1"))
(defun ocamldebug-capf ()
;; FIXME: Use an `end' after point when applicable.
(let* ((end (point))
(command (save-excursion
(cmd-start (save-excursion
(beginning-of-line)
(and (looking-at comint-prompt-regexp)
(goto-char (match-end 0)))
(buffer-substring (point) end)))
(ocamldebug-complete-list nil) (command-word))
;; Find the word break. This match will always succeed.
(string-match "\\(\\`\\| \\)\\([^ ]*\\)\\'" command)
(setq command-word (match-string 2 command))
;itz 04-21-96 if we are trying to complete a word of nonzero
;length, chop off the last character. This is a nasty hack, but it
;works - in general, not just for this set of words: the comint
;call below will weed out false matches - and it avoids further
;mucking with ocamldebug's lexer.
(when (> (length command-word) 0)
(setq command (substring command 0 (1- (length command)))))
(let ((ocamldebug-filter-function 'ocamldebug-complete-filter))
(ocamldebug-call-1 (concat "complete " command))
(if (looking-at comint-prompt-regexp)
(match-end 0) (point))))
(start (save-excursion
(skip-chars-backward "^ \n" cmd-start)
(point))))
`(,start ,end
,(completion-table-dynamic
(apply-partially #'ocamldebug--get-completions
(buffer-substring cmd-start start))))))
(defun ocamldebug--get-completions (command-prefix str)
;; FIXME: Add some caching?
(let ((ocamldebug-complete-list nil))
;; itz 04-21-96 If we are trying to complete a word of nonzero
;; length, chop off the last character. This is a nasty hack, but it
;; works - in general, not just for this set of words: the completion
;; code will weed out false matches - and it avoids further
;; mucking with ocamldebug's lexer.
;; FIXME: Which problem is this trying to fix/avoid/circumvent?
(when (> (length str) 0)
(setq str (substring str 0 (1- (length str)))))
(let ((ocamldebug-filter-function #'ocamldebug-complete-filter))
(ocamldebug-call-1 (concat "complete " command-prefix str))
(set-marker ocamldebug-delete-prompt-marker nil)
(while (not (and ocamldebug-complete-list
(zerop (length ocamldebug-filter-accumulator))))
(accept-process-output (get-buffer-process
(current-buffer)))))
(when (eq ocamldebug-complete-list 'fail)
(setq ocamldebug-complete-list nil))
(setq ocamldebug-complete-list
(sort ocamldebug-complete-list 'string-lessp))
(comint-dynamic-simple-complete command-word ocamldebug-complete-list)))
(if (eq ocamldebug-complete-list 'fail)
nil
ocamldebug-complete-list)))
(define-key tuareg-mode-map "\C-x " 'ocamldebug-break)
(defvar ocamldebug-command-name "ocamldebug"
"Pathname for executing the OCaml debugger.")
(defvar ocamldebug-debuggee-args ""
"Default arguments to the program being debugged (space
separated and possibly quoted as they would be passed on the
command line).")
;;;###autoload
(defun ocamldebug (path)
(defun ocamldebug (pgm-path)
"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'."
(interactive "fRun ocamldebug on file: ")
(setq path (expand-file-name path))
(let ((file (file-name-nondirectory path)))
(pop-to-buffer (concat "*ocamldebug-" file "*"))
(setq default-directory (file-name-directory path))
(message "Current directory is %s" default-directory)
(setq pgm-path (expand-file-name pgm-path))
(let* ((file (file-name-nondirectory pgm-path))
(name (concat "ocamldebug-" file))
(buffer-name (concat "*" name "*")))
(pop-to-buffer buffer-name)
(unless (comint-check-proc buffer-name)
(setq default-directory (file-name-directory pgm-path))
(setq ocamldebug-debuggee-args
(read-from-minibuffer (format "Args for %s: " file)
ocamldebug-debuggee-args))
(setq ocamldebug-command-name
(read-from-minibuffer "OCaml debugguer to run: "
(read-from-minibuffer "OCaml debugger to run: "
ocamldebug-command-name))
(make-comint (concat "ocamldebug-" file)
(substitute-in-file-name ocamldebug-command-name)
(message "Current directory is %s" default-directory)
(let* ((args (tuareg--split-args ocamldebug-debuggee-args))
(cmdlist (tuareg--split-args ocamldebug-command-name))
(cmdlist (mapcar #'substitute-in-file-name cmdlist)))
(apply #'make-comint name
(car cmdlist)
nil
"-emacs" "-cd" default-directory path)
"-emacs" "-cd" default-directory
(append (cdr cmdlist) (cons pgm-path args)))
(set-process-filter (get-buffer-process (current-buffer))
'ocamldebug-filter)
(set-process-sentinel (get-buffer-process (current-buffer))
'ocamldebug-sentinel)
(ocamldebug-mode)
(ocamldebug-mode)))
(ocamldebug-set-buffer)))
;;;###autoload
......@@ -643,8 +678,12 @@ Obeying it means displaying in another window the specified file and line."
(with-current-buffer buffer
(save-restriction
(widen)
(setq spos (+ (point-min) schar))
(setq epos (+ (point-min) echar))
(setq spos (if (fboundp 'filepos-to-bufferpos)
(filepos-to-bufferpos schar 'approximate)
(+ (point-min) schar)))
(setq epos (if (fboundp 'filepos-to-bufferpos)
(filepos-to-bufferpos echar 'approximate)
(+ (point-min) echar)))
(setq pos (if kind spos epos))
(ocamldebug-set-current-event spos epos pos (current-buffer) kind))
(cond ((or (< pos (point-min)) (> pos (point-max)))
......@@ -747,10 +786,11 @@ representation is simply concatenated with the COMMAND."
(defun ocamldebug-call-1 (command &optional fmt arg)
;; Record info on the last prompt in the buffer and its position.
(with-current-buffer ocamldebug-current-buffer
(save-excursion
(goto-char (process-mark (get-buffer-process ocamldebug-current-buffer)))
(beginning-of-line)
(when (looking-at comint-prompt-regexp)
(set-marker ocamldebug-delete-prompt-marker (point))))
(set-marker ocamldebug-delete-prompt-marker (point)))))
(let ((cmd (cond
(arg (concat command " " (int-to-string arg)))
(fmt (ocamldebug-format-command
......
......@@ -2,4 +2,4 @@ OCaml mode for GNU Emacs and XEmacs.
Tuareg handles automatic indentation of OCaml and Camllight codes.
Key parts of the code are highlighted using Font-Lock. Support to run
an interactive OCaml toplevel and debugger is provided.
an interactive OCaml REPL and debugger is provided.
opam-version: "1.2"
name: "tuareg"
version: "2.0.9"
maintainer: "Christophe.Troestler@umons.ac.be"
authors: [
"Albert Cohen <Albert.Cohen@prism.uvsq.fr>"
......@@ -8,13 +6,25 @@ authors: [
"Christophe Troestler <Christophe.Troestler@umons.ac.be>"
"Stefan Monnier <monnier@iro.umontreal.ca>"
]
homepage: "https://forge.ocamlcore.org/projects/tuareg/"
bug-reports: "https://forge.ocamlcore.org/tracker/?group_id=43"
homepage: "https://github.com/ocaml/tuareg"
bug-reports: "https://github.com/ocaml/tuareg/issues"
dev-repo: "https://github.com/ocaml/tuareg.git"
build: [make "tuareg-site-file.el"]
depends: "caml-mode"
post-messages: "
If you have not yet done so, please add in ~/.emacs.d/init.el or
in ~/.emacs to following line:
build: [
[make "tuareg-site-file.el"]
[make "elc"] { os != "darwin" }
]
depends: [
"conf-emacs"
]
depopts: [
"caml-mode" {>= "4.05"}
"merlin"
]
post-messages: [
"If you have not yet done so, please add the following line to ~/.emacs.d/init.el or ~/.emacs:
(load \"%{share}%/emacs/site-lisp/tuareg-site-file\")
" {success}
" {success & !user-setup:installed}
"You should consider installing \"merlin\" (completion, displaying types,...)
or \"caml-mode\" (displaying types). See https://github.com/ocaml/tuareg
for customization tips."
]
......@@ -18,6 +18,42 @@ let server_comments request t =
let qs1 = {| quoted string |} (* (issue #24) *)
let qs2 = {eof| other quoted string |noteof} |eof}
(* ocp-indent does it as follows:
let test1 = with_connection (fun conn ->
do_something conn x;
...
)
toto
*)
let test1 = with_connection (fun conn ->
do_something conn x;
...
)
toto
let x = match y with (* Issue #71 *)
| A | B ->
do_something ()
let x = match y, z with
| A, (B | C)
| X, Y -> do_something() (* Issue #78 *)
let x =
begin match y with
| A -> 1 (* Issue #73 *)
end
(* The two "let"s below are indented under the assumption that
tuareg-indent-align-with-first-arg is nil! *)
let x = List.map (fun x -> 5)
my list
let x =
logf `Info "User %s has %i new messages" ba
(Uid.to_string uid)
(List.length new_messages)
let x =
let open M in
let x = 5 in
......@@ -95,7 +131,7 @@ type t = [ `Foo of int
type t =
| A
| B
| B (* issue #76 *)
| C
with sexp
......@@ -116,6 +152,7 @@ type t = [ (* Comment. *)
]
type t = a
and typey = 4
and x = b
module M = struct
......@@ -149,6 +186,10 @@ type m =
| T
with sexp
let f = function
| A -> 1
| B | C -> 2
;; (* http://caml.inria.fr/mantis/view.php?id=4334 *)
type foo =
a
......@@ -343,6 +384,9 @@ let rec count_append l1 l2 count =
(if count > 1000
then slow_append tl l2
else count_append tl l2 (count + 1))
(* New in OCaml-4.02. *)
| exception Not_Found ->
l2
let x =
......@@ -515,6 +559,7 @@ let () =
in
x + 5)
let x =
let foo = 1 and bar = 2 and zot = 3 in
let quux = 4 in
foo
......@@ -774,11 +819,12 @@ let x =
@ snoo
let () =
IO.println out (tagL "ol" (List.map ~f:(tag ~a:[] "li") (
tagL "ol" (List.map ~f:(tag ~a:[] "li") (
(List.map results ~f:(fun (what,_) ->
tag "a" ~a:[("href","#" ^ what)] (what_title what)))
@ [tag "a" ~a:[("href","#" ^ message_id)] message_title;
tag "a" ~a:[("href","#" ^ legend_id)] legend_title])))
tag "a" ~a:[("href","#" ^ legend_id)] legend_title]))
|> IO.println out
let x =
let y =
......@@ -1224,6 +1270,7 @@ let subscribe_impl dir topic ~aborted =
next_argument (* should be indented correctly, given the braces *)
let _ =
List.map
(function x ->
blabla (* FIXME: indentation afer "(function" *)
......
;;; tuareg-jbuild.el --- Mode for editing jbuild files -*- coding: utf-8 -*-
;; Copyright (C) 2017- Christophe Troestler
;; This file is not part of GNU Emacs.
;; Permission to use, copy, modify, and distribute this software for
;; any purpose with or without fee is hereby granted, provided that
;; the above copyright notice and this permission notice appear in
;; all copies.
;;
;; THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
;; WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
;; WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
;; AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR
;; CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
;; LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
;; NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
;; CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
(require 'scheme)
(defvar tuareg-jbuild-mode-hook nil
"Hooks for the `tuareg-jbuild-mode'.")
(defvar tuareg-jbuild-flymake nil
"If t, check your jbuild file with flymake.")
(defvar tuareg-jbuild-temporary-file-directory
(expand-file-name "Tuareg-jbuild" temporary-file-directory)
"Directory where to duplicate the files for flymake.")
(defvar tuareg-jbuild-program
(expand-file-name "jbuilder-lint" tuareg-jbuild-temporary-file-directory)
"Script to use to check the jbuild file.")
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;; Syntax highlighting
(defconst tuareg-jbuild-keywords-regex
(regexp-opt
'("jbuild_version" "library" "executable" "executables" "rule"
"ocamllex" "ocamlyacc" "menhir" "alias" "install" "copy_files")
'symbols)
"Keywords in jbuild files.")
(defconst tuareg-jbuild-fields-regex
(regexp-opt
'("name" "public_name" "synopsis" "modules" "libraries" "wrapped"
"preprocess" "preprocessor_deps" "optional" "c_names" "cxx_names"
"install_c_headers" "modes" "no_dynlink" "kind"
"ppx_runtime_libraries" "virtual_deps" "js_of_ocaml" "flags"
"ocamlc_flags" "ocamlopt_flags" "library_flags" "c_flags"
"cxx_flags" "c_library_flags" "self_build_stubs_archive"
;; + for "executable" and "executables":
"package" "link_flags" "modes" "names" "public_names"
;; + for "rule":
"targets" "action" "deps" "fallback"
;; + for "menhir":
"merge_into"
;; + for "install"
"section" "files" "lib" "libexec" "bin" "sbin" "toplevel" "share"
"share_root" "etc" "doc" "stublibs" "man" "misc")
'symbols)
"Field names allowed in jbuild files.")
(defvar tuareg-jbuild-actions-regex
(regexp-opt
'("run" "chdir" "setenv"
"with-stdout-to" "with-stderr-to" "with-outputs-to"
"ignore-stdout" "ignore-stderr" "ignore-outputs"
"progn" "echo" "write-file" "cat" "copy" "copy#" "system" "bash")
t)
"Builtin actions in jbuilder")
(defvar tuareg-jbuild-var-kind-regex
(regexp-opt
'("path" "path-no-dep" "exe" "bin" "lib" "libexec" "lib-available"
"version" "read" "read-lines" "read-strings")
'words)
"Optional prefix to variable names.")
(defvar tuareg-jbuild-var-regex
(concat "\\(\\(?:!\\|" tuareg-jbuild-var-kind-regex
":\\)?\\)\\([a-zA-Z][a-zA-Z0-9_.]*\\|[<@^]\\)"
"\\(\\(?::[a-zA-Z][a-zA-Z0-9_.]*\\)?\\)"))
(defvar tuareg-jbuild-font-lock-keywords
`((,tuareg-jbuild-keywords-regex . font-lock-keyword-face)
(,tuareg-jbuild-fields-regex . font-lock-constant-face)
("\\(true\\|false\\)" 1 font-lock-constant-face)
(,(concat "(" tuareg-jbuild-actions-regex) 1 font-lock-builtin-face)
(,(concat "${" tuareg-jbuild-var-regex "}")
(1 font-lock-builtin-face)
(3 font-lock-variable-name-face)
(4 font-lock-variable-name-face))
(,(concat "$(" tuareg-jbuild-var-regex ")")
(1 font-lock-builtin-face)
(3 font-lock-variable-name-face)
(4 font-lock-variable-name-face))
("\\(:[a-zA-Z]+\\)\\b" 1 font-lock-builtin-face)))
(defvar tuareg-jbuild-mode-syntax-table
(let ((table (make-syntax-table)))
(modify-syntax-entry ?\; "< b" table)
(modify-syntax-entry ?\n "> b" table)
(modify-syntax-entry ?\( "()" table)
(modify-syntax-entry ?\) ")(" table)
(modify-syntax-entry ?\{ "(}" table)
(modify-syntax-entry ?\} "){" table)
(modify-syntax-entry ?\[ "(]" table)
(modify-syntax-entry ?\] ")[" table)
table)
"Tuareg-jbuild syntax table.")
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;; SMIE
(require 'smie)
(defvar tuareg-jbuild-smie-grammar
(when (fboundp 'smie-prec2->grammar)
(smie-prec2->grammar
(smie-bnf->prec2 '()))))
(defun tuareg-jbuild-smie-rules (kind token)
(cond
((eq kind :close-all) '(column . 0))
((and (eq kind :after) (equal token ")"))
(save-excursion
(goto-char (cadr (smie-indent--parent)))
(if (looking-at-p tuareg-jbuild-keywords-regex)
'(column . 0)
1)))
((eq kind :before)
(if (smie-rule-parent-p "(")
(save-excursion
(goto-char (cadr (smie-indent--parent)))
(cond
((looking-at-p tuareg-jbuild-keywords-regex) 1)
((looking-at-p tuareg-jbuild-fields-regex)
(smie-rule-parent 0))
((smie-rule-sibling-p) (cons 'column (current-column)))
(t (cons 'column (current-column)))))
'(column . 0)))
(t 1)))
(defun verbose-tuareg-jbuild-smie-rules (kind token)
(let ((value (tuareg-jbuild-smie-rules kind token)))
(message
"%s '%s'; sibling-p:%s parent:%s hanging:%s = %s"
kind token
(ignore-errors (smie-rule-sibling-p))
(ignore-errors smie--parent)
(ignore-errors (smie-rule-hanging-p))
value)
value))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;; Linting
(require 'flymake)
(defun tuareg-jbuild-create-lint-script ()
"Create the lint script if it does not exist. This is nedded as long as See https://github.com/janestreet/jbuilder/issues/241 is not fixed."
(unless (file-exists-p tuareg-jbuild-program)
(let ((dir (file-name-directory tuareg-jbuild-program))
(pgm "#!/usr/bin/env ocaml
;;
#load \"unix.cma\";;
#load \"str.cma\";;
open Printf
let filename = Sys.argv.(1)
let root = try Some(Sys.argv.(2)) with _ -> None
let read_all fh =
let buf = Buffer.create 1024 in
let b = Bytes.create 1024 in
let len = ref 0 in
while len := input fh b 0 1024; !len > 0 do
Buffer.add_subbytes buf b 0 !len
done;
Buffer.contents buf
let errors =
let root = match root with
| None | Some \"\" -> \"\"
| Some r -> \"--root=\" ^ Filename.quote r in
let cmd = sprintf \"jbuilder external-lib-deps %s %s\" root
(Filename.quote (Filename.basename filename)) in
let env = Unix.environment() in
let (_,_,fh) as p = Unix.open_process_full cmd env in
let out = read_all fh in
match Unix.close_process_full p with
| Unix.WEXITED (0|1) ->
(* jbuilder will normally exit with 1 as it will not be able to
perform the requested action. *)
out
| Unix.WEXITED 127 -> printf \"jbuilder not found in path.\\n\"; exit 1
| Unix.WEXITED n -> printf \"jbuilder exited with status %d.\\n\" n; exit 1
| Unix.WSIGNALED n -> printf \"jbuilder was killed by signal %d.\\n\" n;
exit 1
| Unix.WSTOPPED n -> printf \"jbuilder was stopped by signal %d\\n.\" n;
exit 1
let () =
let re = \"\\\\(:?\\\\)[\\r\\n]+\\\\([a-zA-Z]+\\\\)\" in
let errors = Str.global_substitute (Str.regexp re)
(fun s -> let colon = Str.matched_group 1 s = \":\" in
let f = Str.matched_group 2 s in
if f = \"File\" then \"\\n File\"
else if colon then \": \" ^ f
else \", \" ^ f)
errors in
print_string errors"))
(make-directory dir t)
(append-to-file pgm nil tuareg-jbuild-program)
(set-file-modes tuareg-jbuild-program #o777)
)))
(defun tuareg-jbuild--temp-name (absolute-path)
"Full path of the copy of the filename in `tuareg-jbuild-temporary-file-directory'."
(let ((slash-pos (string-match "/" absolute-path)))
(file-truename (expand-file-name (substring absolute-path (1+ slash-pos))
tuareg-jbuild-temporary-file-directory))))
(defun tuareg-jbuild-flymake-create-temp (filename _prefix)
;; based on `flymake-create-temp-with-folder-structure'.
(unless (stringp filename)
(error "Invalid filename"))
(tuareg-jbuild--temp-name filename))
(defun tuareg-jbuild--opam-files (dir)
"Return all opam files in the directory DIR."
(let ((files nil))
(dolist (f (directory-files-and-attributes dir t ".*\\.opam\\'"))
(when (null (cadr f))
(push (car f) files)))
files))
(defun tuareg-jbuild--root (filename)
"Return the root and copy the necessary context files for jbuilder."
;; FIXME: the root depends on jbuild-workspace. If none is found,
;; assume the commands are issued from the dir where opam files are found.
(let* ((dir (locate-dominating-file (file-name-directory filename)
#'tuareg-jbuild--opam-files)))
(when dir
(setq dir (expand-file-name dir)); In case it is ~/...
(make-directory (tuareg-jbuild--temp-name dir) t)
(dolist (f (tuareg-jbuild--opam-files dir))
(copy-file f (tuareg-jbuild--temp-name f) t)))
dir))
(defun tuareg-jbuild--delete-opam-files (dir)
"Delete all opam files in the directory DIR."
(dolist (f (tuareg-jbuild--opam-files dir))
(flymake-safe-delete-file f)))
(defun tuareg-jbuild-flymake-cleanup ()
"Attempt to delete temp dir created by `tuareg-jbuild-flymake-create-temp', do not fail on error."
(let ((dir (file-name-directory flymake-temp-source-file-name))
(temp-dir (concat (directory-file-name
tuareg-jbuild-temporary-file-directory) "/")))
(flymake-log 3 "Clean up %s" flymake-temp-source-file-name)
(flymake-safe-delete-file flymake-temp-source-file-name)
(condition-case nil
(delete-directory (expand-file-name "_build" dir) t)
(error nil))
;; Also delete parent dirs if empty or only contain opam files
(while (and (not (string-equal dir temp-dir))
(> (length dir) 0))
(condition-case nil
(progn
(tuareg-jbuild--delete-opam-files dir)
(delete-directory dir)
(setq dir (file-name-directory (directory-file-name dir))))
(error ; then top the loop
(setq dir ""))))))
(defun tuareg-jbuild-flymake-init ()
(tuareg-jbuild-create-lint-script)
(let ((fname (flymake-init-create-temp-buffer-copy
'tuareg-jbuild-flymake-create-temp))
(root (or (tuareg-jbuild--root buffer-file-name) "")))
(list tuareg-jbuild-program (list fname root))))
(defvar tuareg-jbuild--allowed-file-name-masks
'("\\(?:\\`\\|/\\)jbuild\\'" tuareg-jbuild-flymake-init
tuareg-jbuild-flymake-cleanup)
"Flymake entry for jbuild files. See `flymake-allowed-file-name-masks'.")
(defvar tuareg-jbuild--err-line-patterns
;; Beware that the path from the root will be reported by jbuilder
;; but flymake requires it to match the file name.
'(("File \"[^\"]*\\(jbuild\\)\", line \\([0-9]+\\), \
characters \\([0-9]+\\)-\\([0-9]+\\): +\\([^\n]*\\)$"
1 2 3 5))
"Value of `flymake-err-line-patterns' for jbuild files.")
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;; Skeletons
;; See Info node "Autotype".
(define-skeleton tuareg-jbuild-insert-version-form
"Insert the jbuild version."
nil
"(jbuild_version 1" _ ")" > ?\n)
(define-skeleton tuareg-jbuild-insert-library-form
"Insert a library stanza."
nil
"(library" > \n
"((name " _ ")" > \n
"(public_name " _ ")" > \n
"(synopsis \"" _ "\")" > \n
"(libraries (" _ "))))" > ?\n)
(define-skeleton tuareg-jbuild-insert-executable-form
"Insert an executable stanza."
nil
"(executable" > \n
"((name " _ ")" > \n
"(public_name " _ ")" > \n
"(modules (" _ "))" > \n
"(libraries (" _ "))))" > ?\n)
(define-skeleton tuareg-jbuild-insert-executables-form
"Insert an executables stanza."
nil
"(executables" > \n
"((names (" _ "))" > \n
"(public_names (" _ "))" > \n
"(libraries (" _ "))))" > ?\n)
(define-skeleton tuareg-jbuild-insert-rule-form
"Insert a rule stanza."
nil
"(rule" > \n
"((targets (" _ "))" > \n
"(deps (" _ "))" > \n
"(action (" _ "))))" > ?\n)
(define-skeleton tuareg-jbuild-insert-ocamllex-form
"Insert an ocamllex stanza."
nil
"(ocamllex (" _ "))" > ?\n)
(define-skeleton tuareg-jbuild-insert-ocamlyacc-form
"Insert an ocamlyacc stanza."
nil
"(ocamlyacc (" _ "))" > ?\n)
(define-skeleton tuareg-jbuild-insert-menhir-form
"Insert a menhir stanza."
nil
"(menhir" > \n
"((modules (" _ "))))" > ?\n)
(define-skeleton tuareg-jbuild-insert-alias-form
"Insert an alias stanza."
nil
"(alias" > \n
"((name " _ ")" > \n
"(deps (" _ "))))" > ?\n)
(define-skeleton tuareg-jbuild-insert-install-form
"Insert an install stanza."
nil
"(install" > \n
"((section " _ ")" > \n
"(files (" _ "))))" > ?\n)
(define-skeleton tuareg-jbuild-insert-copyfiles-form
"Insert a copy_files stanza."
nil
"(copy_files " _ ")" > ?\n)
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(defvar tuareg-jbuild-mode-map
(let ((map (make-sparse-keymap)))
(define-key map "\C-c.v" 'tuareg-jbuild-insert-version-form)
(define-key map "\C-c.l" 'tuareg-jbuild-insert-library-form)
(define-key map "\C-c.e" 'tuareg-jbuild-insert-executable-form)
(define-key map "\C-c.x" 'tuareg-jbuild-insert-executables-form)
(define-key map "\C-c.r" 'tuareg-jbuild-insert-rule-form)
(define-key map "\C-c.p" 'tuareg-jbuild-insert-ocamllex-form)
(define-key map "\C-c.y" 'tuareg-jbuild-insert-ocamlyacc-form)
(define-key map "\C-c.m" 'tuareg-jbuild-insert-menhir-form)
(define-key map "\C-c.a" 'tuareg-jbuild-insert-alias-form)
(define-key map "\C-c.i" 'tuareg-jbuild-insert-install-form)
(define-key map "\C-c.c" 'tuareg-jbuild-insert-copyfiles-form)
map)
"Keymap used in Tuareg-jbuild mode.")
(defun tuareg-jbuild-build-menu ()
(easy-menu-define
tuareg-jbuild-mode-menu (list tuareg-jbuild-mode-map)
"Tuareg-jbuild mode menu."
'("Jbuild"
("Stanzas"
["version" tuareg-jbuild-insert-version-form t]
["library" tuareg-jbuild-insert-library-form t]
["executable" tuareg-jbuild-insert-executable-form t]
["executables" tuareg-jbuild-insert-executables-form t]
["rule" tuareg-jbuild-insert-rule-form t]
["ocamllex" tuareg-jbuild-insert-ocamllex-form t]
["ocamlyacc" tuareg-jbuild-insert-ocamlyacc-form t]
["menhir" tuareg-jbuild-insert-menhir-form t]
["alias" tuareg-jbuild-insert-alias-form t]
["install" tuareg-jbuild-insert-install-form t]
["copy_files" tuareg-jbuild-insert-copyfiles-form t]
)))
(easy-menu-add tuareg-jbuild-mode-menu))
;;;###autoload
(define-derived-mode tuareg-jbuild-mode prog-mode "Tuareg-jbuild"
"Major mode to edit jbuild files."
(setq-local font-lock-defaults '(tuareg-jbuild-font-lock-keywords))
(setq-local comment-start ";")
(setq-local comment-end "")
(setq indent-tabs-mode nil)
(setq-local require-final-newline mode-require-final-newline)
(push tuareg-jbuild--allowed-file-name-masks flymake-allowed-file-name-masks)
(smie-setup tuareg-jbuild-smie-grammar #'tuareg-jbuild-smie-rules)
(setq-local flymake-err-line-patterns tuareg-jbuild--err-line-patterns)
(when (and tuareg-jbuild-flymake buffer-file-name)
(flymake-mode t))
(tuareg-jbuild-build-menu)
(run-mode-hooks 'tuareg-jbuild-mode-hook))
;;;###autoload
(add-to-list 'auto-mode-alist
'("\\(?:\\`\\|/\\)jbuild\\'" . tuareg-jbuild-mode))
(provide 'tuareg-jbuild-mode)
......@@ -3,7 +3,7 @@
;; Customize ;;
;;----------------------------------------------------------------------------;;
(require 'cl)
(eval-when-compile (require 'cl))
(require 'custom)
(defgroup tuareg2 nil
......@@ -222,11 +222,10 @@ instead of the historical `tuareg2-default-indent'."
(back-to-indentation)
(looking-at "\\*[^)]"))))))
(defun tuareg2-auto-fill-insert-leading-star (&optional leading-star)
(let ((point-leading-comment (looking-at "(\\*")) (return-leading nil))
(defun tuareg2-auto-fill-insert-leading-star (&optional _leading-star)
(save-excursion
(back-to-indentation))
return-leading))
nil)
(defun tuareg2-auto-fill-function ()
(unless (tuareg2-in-literal-p)
......@@ -429,6 +428,10 @@ Regexp match data 0 points to the chars."
(defvar tuareg2-font-lock-keywords ()
"Font-Lock patterns for Tuareg2 mode.")
(defconst tuareg2-font-lock-syntax
`((?_ . "w") (?` . "."))
"Syntax changes for Font-Lock.")
(defun tuareg2-install-font-lock ()
(setq
tuareg2-font-lock-keywords
......@@ -1186,6 +1189,8 @@ If found, return the actual text of the keyword or operator."
(defconst tuareg2-phrase-regexp-3
(tuareg2-ro "and" "end" "every" "in" "with"))
(defconst tuareg2-false-type-regexp (tuareg2-ro "and" "class" "module" "with"))
(defun tuareg2-looking-at-false-type ()
(save-excursion
(tuareg2-find-meaningful-word)
......@@ -1346,8 +1351,6 @@ Returns t iff skipped to indentation."
(tuareg2-find-module)
(looking-at "\\<module\\>\\|(")))
(defconst tuareg2-false-type-regexp (tuareg2-ro "and" "class" "module" "with"))
(defun tuareg2-looking-at-in-let ()
(save-excursion
(string= (tuareg2-find-meaningful-word) "in")))
......@@ -1484,7 +1487,7 @@ Returns t iff skipped to indentation."
(not (looking-at tuareg2-operator-regexp))))
(current-column))))))
(defun tuareg2-compute-arrow-indent (start-pos)
(defun tuareg2-compute-arrow-indent ()
(let (kwop pos)
(save-excursion (setq kwop (tuareg2-find-arrow-match) pos (point)))
(cond ((string= kwop "|")
......@@ -1509,7 +1512,7 @@ Returns t iff skipped to indentation."
(tuareg2-back-to-paren-or-indentation)
(current-column)))
((tuareg2-monadic-operator-p kwop)
(destructuring-bind (indent kwop point)
(destructuring-bind (indent kwop _point)
(tuareg2-semicolon-indent-kwop-point)
(- indent
(if (string= kwop "in")
......@@ -1684,7 +1687,7 @@ Returns t iff skipped to indentation."
(+ tuareg2-default-indent
(tuareg2-indent-from-paren leading-operator start-pos))))
((looking-at "->")
(tuareg2-compute-arrow-indent start-pos))
(tuareg2-compute-arrow-indent))
((looking-at (tuareg2-keyword-regexp))
(tuareg2-compute-keyword-indent kwop leading-operator start-pos))
((and (string= kwop "=") (not (tuareg2-false-=-p))
......@@ -1809,6 +1812,36 @@ Returns t iff skipped to indentation."
(tuareg2-skip-blank-and-comments)
(current-column))
;;----------------------------------------------------------------------------;;
;; Syntax table ;;
;;----------------------------------------------------------------------------;;
(defvar tuareg2-mode-syntax-table
(let ((st (make-syntax-table)))
(modify-syntax-entry ?_ "_" st)
(modify-syntax-entry ?? ". p" st)
(modify-syntax-entry ?~ ". p" st)
(modify-syntax-entry ?: "." st)
;; FIXME: Should be "_" rather than "w"!
(modify-syntax-entry ?' "w" st) ; ' is part of identifiers (for primes).
(modify-syntax-entry ?\" "\"" st) ; " is a string delimiter
(modify-syntax-entry ?\\ "\\" st)
(modify-syntax-entry ?* ". 23" st)
(modify-syntax-entry ?\( "()1n" st)
(modify-syntax-entry ?\) ")(4n" st)
st)
"Syntax table in use in Tuareg2 mode buffers.")
(defmacro tuareg2-with-internal-syntax (&rest body)
`(progn
;; Switch to a modified internal syntax.
(modify-syntax-entry ?. "w" tuareg2-mode-syntax-table)
(modify-syntax-entry ?_ "w" tuareg2-mode-syntax-table)
(unwind-protect (progn ,@body)
;; Switch back to the interactive syntax.
(modify-syntax-entry ?. "." tuareg2-mode-syntax-table)
(modify-syntax-entry ?_ "_" tuareg2-mode-syntax-table))))
(defun tuareg2-indent-command (&optional from-leading-star)
"Indent the current line in Tuareg2 mode.
......@@ -2240,41 +2273,6 @@ or indent all lines in the current phrase."
map)
"Keymap used in Tuareg2 mode.")
(defconst tuareg2-font-lock-syntax
`((?_ . "w") (?` . "."))
"Syntax changes for Font-Lock.")
;;----------------------------------------------------------------------------;;
;; Syntax table ;;
;;----------------------------------------------------------------------------;;
(defvar tuareg2-mode-syntax-table
(let ((st (make-syntax-table)))
(modify-syntax-entry ?_ "_" st)
(modify-syntax-entry ?? ". p" st)
(modify-syntax-entry ?~ ". p" st)
(modify-syntax-entry ?: "." st)
(modify-syntax-entry ?' "w" st) ; ' is part of words (for primes).
(modify-syntax-entry ?\" "\"" st) ; " is a string delimiter
(modify-syntax-entry ?\\ "\\" st)
(modify-syntax-entry ?* ". 23" st)
(condition-case nil
(progn
(modify-syntax-entry ?\( "()1n" st)
(modify-syntax-entry ?\) ")(4n" st)))
st)
"Syntax table in use in Tuareg2 mode buffers.")
(defmacro tuareg2-with-internal-syntax (&rest body)
`(progn
;; Switch to a modified internal syntax.
(modify-syntax-entry ?. "w" tuareg2-mode-syntax-table)
(modify-syntax-entry ?_ "w" tuareg2-mode-syntax-table)
(unwind-protect (progn ,@body)
;; Switch back to the interactive syntax.
(modify-syntax-entry ?. "." tuareg2-mode-syntax-table)
(modify-syntax-entry ?_ "_" tuareg2-mode-syntax-table))))
(defun tuareg2-complete (arg)
"Completes qualified ocaml identifiers."
(interactive "p")
......@@ -2353,7 +2351,7 @@ Known bugs:
Short cuts for the Tuareg2 mode:
\\{tuareg2-mode-map}
Short cuts for interactions with the toplevel:
Short cuts for interactions with the REPL:
\\{tuareg2-interactive-mode-map}"
(interactive)
(kill-all-local-variables)
......@@ -2367,7 +2365,7 @@ Short cuts for interactions with the toplevel:
(make-local-variable 'paragraph-separate)
(setq paragraph-separate paragraph-start)
(make-local-variable 'require-final-newline)
(setq require-final-newline t)
(setq require-final-newline mode-require-final-newline)
(make-local-variable 'comment-start)
(setq comment-start "(* ")
(make-local-variable 'comment-end)
......
;;; tuareg-opam.el --- Mode for editing opam files -*- coding: utf-8 -*-
;; Copyright (C) 2017- Christophe Troestler
;; This file is not part of GNU Emacs.
;; Permission to use, copy, modify, and distribute this software for
;; any purpose with or without fee is hereby granted, provided that
;; the above copyright notice and this permission notice appear in
;; all copies.
;;
;; THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
;; WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
;; WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
;; AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR
;; CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
;; LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
;; NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
;; CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
(defvar tuareg-opam-mode-hook nil)
(defvar tuareg-opam-indent-basic 2
"The default amount of indentation.")
(defvar tuareg-opam-flymake nil
"It t, use flymake to lint OPAM files.")
(defvar tuareg-opam-mode-map
(let ((map (make-keymap)))
(define-key map "\C-j" 'newline-and-indent)
map)
"Keymap for tuareg-opam mode")
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Syntax highlighting
(defconst tuareg-opam-keywords
'("opam-version" "name" "version" "maintainer" "authors"
"license" "homepage" "doc" "bug-reports" "dev-repo"
"tags" "patches" "substs" "build" "install" "build-test"
"build-doc" "remove" "depends" "depopts" "conflicts"
"depexts" "messages" "post-messages" "available"
"flags")
"Kewords in OPAM files.")
(defconst tuareg-opam-keywords-regex
(regexp-opt tuareg-opam-keywords 'symbols))
(defconst tuareg-opam-variables-regex
(regexp-opt '("user" "group" "make" "os" "root" "prefix" "lib"
"bin" "sbin" "doc" "stublibs" "toplevel" "man"
"share" "etc"
"name" "pinned"
"ocaml-version" "opam-version" "compiler" "preinstalled"
"switch" "jobs" "ocaml-native" "ocaml-native-tools"
"ocaml-native-dynlink" "arch")
'symbols)
"Variables declared in OPAM.")
(defconst tuareg-opam-pkg-variables-regex
(regexp-opt '("name" "version" "depends" "installed" "enable" "pinned"
"bin" "sbin" "lib" "man" "doc" "share" "etc" "build"
"hash")
'symbols)
"Package variables in OPAM.")
(defvar tuareg-opam-font-lock-keywords
`((,(concat tuareg-opam-keywords-regex ":")
1 font-lock-keyword-face)
(,(regexp-opt '("build" "test" "doc" "pinned" "true" "false") 'words)
. font-lock-constant-face)
(,tuareg-opam-variables-regex . font-lock-variable-name-face)
(,(concat "%{" tuareg-opam-variables-regex "}%")
(1 font-lock-variable-name-face t))
(,(concat "%{\\([a-zA-Z_][a-zA-Z0-9_+-]*\\):"
tuareg-opam-pkg-variables-regex "}%")
(1 font-lock-constant-face t)
(2 font-lock-variable-name-face t)))
"Highlighting for OPAM files")
(defvar tuareg-opam-prettify-symbols
`(("&" . ,(decode-char 'ucs 8743)); 'LOGICAL AND' (U+2227)
("|" . ,(decode-char 'ucs 8744)); 'LOGICAL OR' (U+2228)
("<=" . ,(decode-char 'ucs 8804))
(">=" . ,(decode-char 'ucs 8805))
("!=" . ,(decode-char 'ucs 8800)))
"Alist of symbol prettifications for OPAM files.
See `prettify-symbols-alist' for more information.")
(defvar tuareg-opam-mode-syntax-table
(let ((table (make-syntax-table)))
(modify-syntax-entry ?# "< b" table)
(modify-syntax-entry ?\n "> b" table)
(modify-syntax-entry ?\( "()" table)
(modify-syntax-entry ?\) ")(" table)
(modify-syntax-entry ?\{ "(}" table)
(modify-syntax-entry ?\} "){" table)
(modify-syntax-entry ?\[ "(]" table)
(modify-syntax-entry ?\] ")[" table)
table)
"Tuareg-opam syntax table.")
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; SMIE
(require 'smie)
(defvar tuareg-opam-smie-grammar
(let* ((decl-of-kw (lambda(kw) `(decls ,kw ":" list)))
(bnfprec2
(smie-bnf->prec2
`((decls . ,(mapcar decl-of-kw tuareg-opam-keywords) )
(list ("[" list "]")
(value))
(value (string "{" filter "}")
(string))
(string)
(filter)))))
(smie-prec2->grammar
(smie-merge-prec2s
bnfprec2
(smie-precs->prec2
'((right "&" "|")
(left "=" "!=" ">" ">=" "<" "<=")))
))))
(defun tuareg-opam-smie-rules (kind token)
(cond
((and (eq kind :before) (member token tuareg-opam-keywords))
0)
((and (eq kind :before) (equal token "[") (smie-rule-hanging-p))
0)
((and (eq kind :before) (equal token "{"))
0)
(t tuareg-opam-indent-basic)))
(defvar tuareg-opam-smie-verbose-p t
"Emit context information about the current syntax state.")
(defmacro tuareg-opam-smie-debug (message &rest format-args)
`(progn
(when tuareg-opam-smie-verbose-p
(message (format ,message ,@format-args)))
nil))
(defun verbose-tuareg-opam-smie-rules (kind token)
(let ((value (tuareg-opam-smie-rules kind token)))
(tuareg-opam-smie-debug
"%s '%s'; sibling-p:%s parent:%s prev-is-[:%s hanging:%s = %s"
kind token
(ignore-errors (smie-rule-sibling-p))
(ignore-errors smie--parent)
(ignore-errors (smie-rule-prev-p "["))
(ignore-errors (smie-rule-hanging-p))
value)
value))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;; Linting
(require 'flymake)
(defun tuareg-opam-flymake-init ()
(let ((fname (flymake-init-create-temp-buffer-copy
#'flymake-create-temp-inplace)))
(list "opam" (list "lint" fname))))
(defvar tuareg-opam--allowed-file-name-masks
'("[./]opam_?\\'" tuareg-opam-flymake-init)
"Flymake entry for OPAM files. See `flymake-allowed-file-name-masks'.")
(defvar tuareg-opam--err-line-patterns
'(("File \"\\([^\"]+\\)\", line \\([0-9]+\\), \
characters \\([0-9]+\\)-\\([0-9]+\\): +\\([^\n]*\\)$"
1 2 3 5))
"Value of `flymake-err-line-patterns' for OPAM files.")
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;; Skeleton
(define-skeleton tuareg-opam-insert-opam-form
"Insert a minimal opam file."
nil
"opam-version: \"1.2\"" > \n
"maintainer: \"" _ "\"" > \n
"authors: [" _ "]" > \n
"tags: [" _ "]" > \n
"license: \"" _ "\"" > \n
"homepage: \"" _ "\"" > \n
"dev-repo: \"" _ "\"" > \n
"bug-reports: \"" _ "\"" > \n
"doc: \"" _ "\"" > \n
"build: [" > \n
"[ \"jbuilder\" \"subst\" ] {pinned}" > \n
"[ \"jbuilder\" \"build\" \"-p\" name \"-j\" jobs ]" > \n
"]" > \n
"build-test: [[\"jbuilder\" \"runtest\" \"-p\" name \"-j\" jobs]]" > \n
"depends: [" > \n
"\"jbuilder\" {build}" > \n
"]" > ?\n)
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(defvar tuareg-opam-mode-map
(let ((map (make-sparse-keymap)))
(define-key map "\C-c.o" 'tuareg-opam-insert-opam-form)
map)
"Keymap used in Tuareg-opam mode.")
(defun tuareg-opam-build-menu ()
(easy-menu-define
tuareg-opam-mode-menu (list tuareg-opam-mode-map)
"Tuareg-opam mode menu."
'("OPAM"
["Skeleton" tuareg-opam-insert-opam-form t]))
(easy-menu-add tuareg-opam-mode-menu))
;;;###autoload
(define-derived-mode tuareg-opam-mode prog-mode "Tuareg-opam"
"Major mode to edit opam files."
(setq font-lock-defaults '(tuareg-opam-font-lock-keywords))
(setq-local comment-start "#")
(setq-local comment-end "")
(setq-local prettify-symbols-alist tuareg-opam-prettify-symbols)
(setq indent-tabs-mode nil)
(setq-local require-final-newline mode-require-final-newline)
(smie-setup tuareg-opam-smie-grammar #'tuareg-opam-smie-rules)
(push tuareg-opam--allowed-file-name-masks flymake-allowed-file-name-masks)
(setq-local flymake-err-line-patterns tuareg-opam--err-line-patterns)
(when (and tuareg-opam-flymake buffer-file-name)
(flymake-mode t))
(tuareg-opam-build-menu)
(run-mode-hooks 'tuareg-opam-mode-hook))
;;;###autoload
(add-to-list 'auto-mode-alist '("[./]opam_?\\'" . tuareg-opam-mode))
(provide 'tuareg-opam-mode)
......@@ -3,8 +3,8 @@
(add-to-list 'load-path
(or (file-name-directory load-file-name) (car load-path)))
;;;### (autoloads nil "ocamldebug" "ocamldebug.el" (21289 25149 485562
;;;;;; 840000))
;;;### (autoloads nil "ocamldebug" "ocamldebug.el" (22960 18385 186574
;;;;;; 216000))
;;; Generated autoloads from ocamldebug.el
(autoload 'ocamldebug "ocamldebug" "\
......@@ -13,15 +13,16 @@ 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)
\(fn PGM-PATH)" t nil)
(defalias 'camldebug 'ocamldebug)
;;;***
;;;### (autoloads nil "tuareg" "tuareg.el" (21767 12781 330987 783000))
;;;### (autoloads nil "tuareg" "tuareg.el" (23005 3097 903887 888000))
;;; Generated autoloads from tuareg.el
(add-to-list 'auto-mode-alist '("\\.ml[ip]?\\'" . tuareg-mode))
(add-to-list 'auto-mode-alist '("\\.eliomi?\\'" . tuareg-mode))
(dolist (ext '(".cmo" ".cmx" ".cma" ".cmxa" ".cmi"
".annot" ".cmt" ".cmti"))
(add-to-list 'completion-ignored-extensions ext))
......@@ -56,20 +57,20 @@ 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
A Tuareg Interactive Mode to evaluate expressions in a REPL (aka toplevel) is
included. Type `M-x tuareg-run-ocaml' or simply `M-x run-ocaml' or see
special-keys below.
Short cuts for the Tuareg mode:
\\{tuareg-mode-map}
Short cuts for interactions with the toplevel:
Short cuts for interactions with the REPL:
\\{tuareg-interactive-mode-map}
\(fn)" t nil)
(autoload 'tuareg-run-ocaml "tuareg" "\
Run an OCaml toplevel process. I/O via buffer `*ocaml-toplevel*'.
Run an OCaml REPL process. I/O via buffer `*OCaml*'.
\(fn)" t nil)
......@@ -81,8 +82,34 @@ Run an OCaml toplevel process. I/O via buffer `*ocaml-toplevel*'.
;;;***
;;;### (autoloads nil nil ("tuareg-light.el" "tuareg-mly.el" "tuareg_indent.el")
;;;;;; (21767 12785 775655 707000))
;;;### (autoloads nil "tuareg-jbuild" "tuareg-jbuild.el" (23040 63673
;;;;;; 915101 116000))
;;; Generated autoloads from tuareg-jbuild.el
(autoload 'tuareg-jbuild-mode "tuareg-jbuild" "\
Major mode to edit jbuild files.
\(fn)" t nil)
(add-to-list 'auto-mode-alist '("\\(?:\\`\\|/\\)jbuild\\'" . tuareg-jbuild-mode))
;;;***
;;;### (autoloads nil "tuareg-opam" "tuareg-opam.el" (23040 63783
;;;;;; 815739 961000))
;;; Generated autoloads from tuareg-opam.el
(autoload 'tuareg-opam-mode "tuareg-opam" "\
Major mode to edit opam files.
\(fn)" t nil)
(add-to-list 'auto-mode-alist '("[./]opam_?\\'" . tuareg-opam-mode))
;;;***
;;;### (autoloads nil nil ("dot-emacs.el" "tuareg-light.el" "tuareg-mly.el")
;;;;;; (22928 42647 125772 673000))
;;;***
This diff is collapsed.
share_root: [
"tuareg.el" {"emacs/site-lisp/tuareg.el"}
"tuareg_indent.el" {"emacs/site-lisp/tuareg_indent.el"}
"ocamldebug.el" {"emacs/site-lisp/ocamldebug.el"}
"tuareg-site-file.el" {"emacs/site-lisp/tuareg-site-file.el"}
"tuareg-jbuild.el" {"emacs/site-lisp/tuareg-jbuild.el"}
"tuareg-opam.el" {"emacs/site-lisp/tuareg-opam.el"}
"?tuareg.elc" {"emacs/site-lisp/tuareg.elc"}
"?ocamldebug.elc" {"emacs/site-lisp/ocamldebug.elc"}
"?tuareg-site-file.elc" {"emacs/site-lisp/tuareg-site-file.elc"}
"?tuareg-jbuild.elc" {"emacs/site-lisp/tuareg-jbuild.elc"}
"?tuareg-opam.elc" {"emacs/site-lisp/tuareg-opam.elc"}
]
This diff is collapsed.