55; ; URL: https://github.com/ocaml-community/utop
66; ; Licence: BSD3
77; ; Version: 1.11
8- ; ; Package-Requires: ((emacs "26") (tuareg "2.2.0") )
8+ ; ; Package-Requires: ((emacs "26"))
99; ; Keywords: ocaml languages
1010
1111; ; This file is a part of utop.
1616; ;
1717; ; utop.el has two components - a nice OCaml REPL with auto-completion and a
1818; ; minor mode (`utop-minor-mode' ), which extends OCaml major modes
19- ; ; (e.g. `caml -mode' and `tuareg -mode' ) with commands to evaluate forms directly
20- ; ; in the REPL.
19+ ; ; (e.g. `tuareg -mode' , `caml -mode' ) with commands to evaluate forms directly
20+ ; ; in the REPL. Other modes can integrate via `utop-mode-compat-alist' .
2121; ;
2222; ; See the "Integration with Emacs" section of the README for more info.
2323
2727(require 'pcase )
2828(require 'seq )
2929(require 'tabulated-list )
30- (require 'tuareg )
30+ (declare-function tuareg-discover-phrase " tuareg" (&optional pos))
31+ (declare-function tuareg-skip-blank-and-comments " tuareg" ())
3132
3233; ; +-----------------------------------------------------------------+
3334; ; | License |
@@ -247,26 +248,31 @@ backend")
247248; ; | Compatibility with different ocaml major modes |
248249; ; +-----------------------------------------------------------------+
249250
250- (defun utop-compat-resolve (choices )
251- " Resolve a symbol based on the current major mode. CHOICES is a
252- list of 3 function symbols: (tuareg-symbol typerex-symbol caml-symbol)."
253- (nth
254- (pcase major-mode
255- ('tuareg-mode 0 )
256- ('typerex-mode 1 )
257- ('caml-mode 2 )
258- ('reason-mode 3 )
259- (major-mode (error (format " utop doesn't support the major mode \" %s \" . It
260- supports caml, tuareg, typerex and reason modes by default. For other
261- modes you need to set these variables:
262-
263- - `utop-next-phrase-beginning'
264- - `utop-discover-phrase'
265- " major-mode))))
266- choices))
251+ (defvar utop-mode-compat-alist
252+ '((tuareg-mode :next-phrase utop-tuareg-next-phrase
253+ :discover-phrase utop-tuareg-discover-phrase)
254+ (typerex-mode :next-phrase typerex-skip-to-end-of-phrase
255+ :discover-phrase typerex-discover-phrase)
256+ (caml-mode :next-phrase caml-skip-to-end-of-phrase
257+ :discover-phrase caml-find-phrase)
258+ (reason-mode :next-phrase reason-next-phrase
259+ :discover-phrase reason-discover-phrase))
260+ " Alist mapping major modes to their phrase navigation functions.
261+ Each entry is (MODE :next-phrase FN :discover-phrase FN).
262+
263+ :next-phrase FN should move point to the beginning of the next phrase.
264+ :discover-phrase FN should return a triple
265+ \( begin-pos end-pos end-pos-with-comments).
266+
267+ To add support for a new OCaml major mode, add an entry to this alist:
268+
269+ (add-to-list \\= 'utop-mode-compat-alist
270+ \\= '(my-ocaml-mode :next-phrase my-next-phrase
271+ :discover-phrase my-discover-phrase))" )
267272
268273(defun utop-tuareg-next-phrase ()
269274 " Move to the next phrase after point."
275+ (require 'tuareg )
270276 (let* ((pos (save-excursion
271277 (when (looking-at-p " [;[:blank:]]*$" )
272278 (skip-chars-backward " ;[:blank:]" )
@@ -281,19 +287,34 @@ modes you need to set these variables:
281287 (goto-char (match-end 0 )))
282288 (tuareg-skip-blank-and-comments))))
283289
290+ (defun utop-tuareg-discover-phrase ()
291+ " Discover the phrase at point using tuareg."
292+ (require 'tuareg )
293+ (tuareg-discover-phrase))
294+
295+ (defun utop-compat-lookup (prop )
296+ " Look up a phrase function for the current major mode.
297+ PROP should be a keyword like :next-phrase or :discover-phrase.
298+ Also checks parent modes via `derived-mode-parent' ."
299+ (let ((mode major-mode)
300+ entry)
301+ (while (and mode (not entry))
302+ (setq entry (assq mode utop-mode-compat-alist))
303+ (setq mode (get mode 'derived-mode-parent )))
304+ (if entry
305+ (or (plist-get (cdr entry) prop)
306+ (error " utop mode compat entry for \" %s \" is missing %s "
307+ (car entry) prop))
308+ (error " utop doesn't support the major mode \" %s \" .
309+ To add support, either customize `utop-mode-compat-alist' or
310+ set `utop-next-phrase-beginning' and `utop-discover-phrase'
311+ as buffer-local variables " major-mode))))
312+
284313(defun utop-compat-next-phrase-beginning ()
285- (funcall
286- (utop-compat-resolve '(utop-tuareg-next-phrase
287- typerex-skip-to-end-of-phrase
288- caml-skip-to-end-of-phrase
289- reason-next-phrase))))
314+ (funcall (utop-compat-lookup :next-phrase )))
290315
291316(defun utop-compat-discover-phrase ()
292- (funcall
293- (utop-compat-resolve '(tuareg-discover-phrase
294- typerex-discover-phrase
295- caml-find-phrase
296- reason-discover-phrase))))
317+ (funcall (utop-compat-lookup :discover-phrase )))
297318
298319; ; +-----------------------------------------------------------------+
299320; ; | Utils |
0 commit comments