Skip to content
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 14 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ OCaml. It can run in a terminal or
in Emacs. It supports line editing, history, real-time and context
sensitive completion, colors, and more.

It integrates with the Tuareg, caml, ReasonML and typerex modes in Emacs.
It integrates with the Tuareg, caml, neocaml, ReasonML and typerex modes in Emacs.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If I read the code correctly, the integration with neocaml is done on the neocaml side, isn't it?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, exactly. I could have added it here, but I thought it's probably better to just provide it in neocaml. IMO that's the best for every major mode, but I didn't want to make changes that might break someone's setup.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it might then be slightly clearer to update the phrasing to

The following Emacs modes are explicitly supported: Tuareg, caml, neocaml, ReasonML and typerex .

to not give the impression that there is explicit integration for neocaml inside utop.

(Because I believe that this important for a community maintained project to be very explicit in term of the state of the code.)

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fair enough. I'll think about some updated wording for this.


![Screenshot](screenshot.png)

Expand Down Expand Up @@ -240,12 +240,20 @@ have it enabled by default with the following configuration:

If you plan to use utop with another major-mode than tuareg, replace
`tuareg-mode-hook` by the appropriate hook. The utop minor mode will work out of
the box with these modes: `tuareg-mode`, `caml-mode`, `reason-mode` and
`typerex-mode`. For other modes you will need to set the following three
variables:
the box with these modes: `tuareg-mode`, `caml-mode`, `neocaml-mode`,
`reason-mode` and `typerex-mode`. Modes derived from any of these will
also work automatically.

- `utop-skip-blank-and-comments`
- `utop-skip-to-end-of-phrase`
For other modes you can register support via `utop-mode-compat-alist`:

```elisp
(add-to-list 'utop-mode-compat-alist
'(my-ocaml-mode . (my-next-phrase . my-discover-phrase)))
```

Alternatively, you can set the following buffer-local variables:

- `utop-next-phrase-beginning`
- `utop-discover-phrase`

You can also complete text in a buffer using the environment of the
Expand Down
75 changes: 44 additions & 31 deletions src/top/utop.el
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
;; URL: https://github.com/ocaml-community/utop
;; Licence: BSD3
;; Version: 1.11
;; Package-Requires: ((emacs "26") (tuareg "2.2.0"))
;; Package-Requires: ((emacs "26"))
;; Keywords: ocaml languages

;; This file is a part of utop.
Expand All @@ -16,8 +16,8 @@
;;
;; utop.el has two components - a nice OCaml REPL with auto-completion and a
;; minor mode (`utop-minor-mode'), which extends OCaml major modes
;; (e.g. `caml-mode' and `tuareg-mode') with commands to evaluate forms directly
;; in the REPL.
;; (e.g. `tuareg-mode', `caml-mode', `neocaml-mode') with commands to evaluate
;; forms directly in the REPL.
;;
;; See the "Integration with Emacs" section of the README for more info.

Expand All @@ -27,7 +27,8 @@
(require 'pcase)
(require 'seq)
(require 'tabulated-list)
(require 'tuareg)
(declare-function tuareg-discover-phrase "tuareg" (&optional pos))
(declare-function tuareg-skip-blank-and-comments "tuareg" ())

;; +-----------------------------------------------------------------+
;; | License |
Expand Down Expand Up @@ -247,26 +248,25 @@ backend")
;; | Compatibility with different ocaml major modes |
;; +-----------------------------------------------------------------+

(defun utop-compat-resolve (choices)
"Resolve a symbol based on the current major mode. CHOICES is a
list of 3 function symbols: (tuareg-symbol typerex-symbol caml-symbol)."
(nth
(pcase major-mode
('tuareg-mode 0)
('typerex-mode 1)
('caml-mode 2)
('reason-mode 3)
(major-mode (error (format "utop doesn't support the major mode \"%s\". It
supports caml, tuareg, typerex and reason modes by default. For other
modes you need to set these variables:

- `utop-next-phrase-beginning'
- `utop-discover-phrase'
" major-mode))))
choices))
(defvar utop-mode-compat-alist
'((tuareg-mode . (utop-tuareg-next-phrase . utop-tuareg-discover-phrase))
(typerex-mode . (typerex-skip-to-end-of-phrase . typerex-discover-phrase))
(caml-mode . (caml-skip-to-end-of-phrase . caml-find-phrase))
(reason-mode . (reason-next-phrase . reason-discover-phrase)))
"Alist mapping major modes to their phrase navigation functions.
Each entry is (MODE . (NEXT-PHRASE-FN . DISCOVER-PHRASE-FN)).

NEXT-PHRASE-FN should move point to the beginning of the next phrase.
DISCOVER-PHRASE-FN should return a triple (begin-pos end-pos end-pos-with-comments).

To add support for a new OCaml major mode, add an entry to this alist:

(add-to-list \\='utop-mode-compat-alist
\\='(my-ocaml-mode . (my-next-phrase . my-discover-phrase)))")

(defun utop-tuareg-next-phrase ()
"Move to the next phrase after point."
(require 'tuareg)
(let* ((pos (save-excursion
(when (looking-at-p "[;[:blank:]]*$")
(skip-chars-backward ";[:blank:]")
Expand All @@ -281,19 +281,32 @@ modes you need to set these variables:
(goto-char (match-end 0)))
(tuareg-skip-blank-and-comments))))

(defun utop-tuareg-discover-phrase ()
"Discover the phrase at point using tuareg."
(require 'tuareg)
(tuareg-discover-phrase))

(defun utop-compat-lookup (slot)
"Look up a phrase function for the current major mode.
SLOT should be `car' for next-phrase or `cdr' for discover-phrase.
Also checks parent modes via `derived-mode-parent'."
(let ((mode major-mode)
entry)
(while (and mode (not entry))
(setq entry (assq mode utop-mode-compat-alist))
(setq mode (get mode 'derived-mode-parent)))
(if entry
(funcall slot (cdr entry))
(error "utop doesn't support the major mode \"%s\".
To add support, either customize `utop-mode-compat-alist' or
set `utop-next-phrase-beginning' and `utop-discover-phrase'
as buffer-local variables" major-mode))))

(defun utop-compat-next-phrase-beginning ()
(funcall
(utop-compat-resolve '(utop-tuareg-next-phrase
typerex-skip-to-end-of-phrase
caml-skip-to-end-of-phrase
reason-next-phrase))))
(funcall (utop-compat-lookup #'car)))

(defun utop-compat-discover-phrase ()
(funcall
(utop-compat-resolve '(tuareg-discover-phrase
typerex-discover-phrase
caml-find-phrase
reason-discover-phrase))))
(funcall (utop-compat-lookup #'cdr)))

;; +-----------------------------------------------------------------+
;; | Utils |
Expand Down
Loading