I use company mode as a completion backend
(use-package company
:ensure t
:custom
(company-quickhelp-delay 0)
(company-tooltip-align-annotations t)
:hook
((prog-mode utop-mode) . company-mode)
:config
(company-quickhelp-mode 1)
:bind
("M-o" . company-complete)
)
Popup for documentation or help
(use-package company-quickhelp
:ensure t
:bind (:map company-active-map
("M-h" . company-quickhelp-manual-begin))
)
Util function to select where to load merlin from.
(defun shell-cmd (cmd)
"Returns the stdout output of a shell command or nil if the command returned
an error"
(car (ignore-errors (apply 'process-lines (split-string cmd)))))
(setq opam-p (shell-cmd "which opam"))
(setq reason-p (shell-cmd "which refmt"))
Setup environment variables using opam.
(if opam-p
(dolist (var (car (read-from-string (shell-command-to-string "opam config env --sexp"))))
(setenv (car var) (cadr var))))
Add opam libs.
(if opam-p
(let ((opam-share (ignore-errors (car (process-lines "opam" "config" "var" "share")))))
(when (and opam-share (file-directory-p opam-share))
(add-to-list 'load-path (expand-file-name "emacs/site-lisp" opam-share)))))
caml
is required because caml-types-expr-face
is used by merlin.
(use-package caml
:ensure t)
We don’t need the tuareg package from the emacs repositories, it comes from opam.
(use-package tuareg
:if opam-p
:mode ("\\.ml[ily]?$" . tuareg-mode))
When using reason-mode
, we want to load merlin from
node_modules
rather than opam.
(use-package reason-mode
:if reason-p
:ensure t
:config
(let* ((refmt-bin (or (shell-cmd "refmt ----where")
(shell-cmd "which refmt")))
(merlin-bin (or (shell-cmd "ocamlmerlin ----where")
(shell-cmd "which ocamlmerlin")))
(merlin-base-dir (when merlin-bin
(replace-regexp-in-string "bin/ocamlmerlin$" "" merlin-bin))))
;; Add npm merlin.el to the emacs load path and tell emacs where to find ocamlmerlin
(when merlin-bin
(add-to-list 'load-path (concat merlin-base-dir "share/emacs/site-lisp/"))
(setq merlin-command merlin-bin))
(when refmt-bin
(setq refmt-command refmt-bin)))
)
Require ocp stuff first because of conflicts between shortcuts.
It is installed from opam, ensure
is not required.
(use-package ocp-indent :if opam-p)
(use-package ocp-index :if opam-p)
Configure merlin. Magical autocompletion and IDE features.
(use-package merlin
:custom
(merlin-completion-with-doc t)
:bind (:map merlin-mode-map
("M-." . merlin-locate)
("M-," . merlin-pop-stack)
("M-?" . merlin-occurrences)
("C-c C-j" . merlin-jump)
("C-c i" . merlin-locate-ident)
("C-c C-e" . merlin-iedit-occurrences)
)
:hook
;; Start merlin on ml files
((reason-mode tuareg-mode caml-mode) . merlin-mode)
)
(use-package utop
:custom
(utop-edit-command nil)
:hook
(tuareg-mode . (lambda ()
(setq utop-command "utop -emacs")
(utop-minor-mode)))
(reason-mode . (lambda ()
(setq utop-command "rtop -emacs")
(setq utop-prompt
(lambda ()
(let ((prompt (format "rtop[%d]> " utop-command-number)))
(add-text-properties 0 (length prompt) '(face utop-prompt) prompt)
prompt)))
(utop-minor-mode)))
)