mirror of
https://gitlab.com/dwt1/dotfiles.git
synced 2026-04-22 02:50:24 +10:00
Moving to Doom Emacs!
This commit is contained in:
93
.emacs.d/modules/lang/ocaml/README.org
Normal file
93
.emacs.d/modules/lang/ocaml/README.org
Normal file
@@ -0,0 +1,93 @@
|
||||
#+TITLE: lang/ocaml
|
||||
#+DATE: June 27, 2017
|
||||
#+SINCE: v2.0.3
|
||||
|
||||
* Table of Contents :TOC:
|
||||
- [[#description][Description]]
|
||||
- [[#module-flags][Module Flags]]
|
||||
- [[#plugins][Plugins]]
|
||||
- [[#prerequisites][Prerequisites]]
|
||||
- [[#features][Features]]
|
||||
- [[#configuration][Configuration]]
|
||||
- [[#appendix][Appendix]]
|
||||
- [[#commands][Commands]]
|
||||
- [[#hacks][Hacks]]
|
||||
|
||||
* Description
|
||||
This module adds [[https://ocaml.org/][OCaml]] support to Doom Emacs, powered by [[https://github.com/ocaml/tuareg][tuareg-mode]].
|
||||
|
||||
+ Code completion, documentation look-up, code navigation and refactoring
|
||||
([[https://github.com/ocaml/merlin/wiki/emacs-from-scratch][merlin]])
|
||||
+ Type, documentation and function argument display on idle ([[https://github.com/Khady/merlin-eldoc][merlin-eldoc]])
|
||||
+ REPL ([[https://github.com/ocaml-community/utop][utop]])
|
||||
+ Syntax-checking (~merlin~ with [[https://github.com/flycheck/flycheck-ocaml][flycheck-ocaml]])
|
||||
+ Auto-indentation ([[https://github.com/OCamlPro/ocp-indent][ocp-indent]])
|
||||
+ Code formatting ([[https://github.com/ocaml-ppx/ocamlformat][ocamlformat]])
|
||||
+ Dune file format ([[http://dune.build/][dune]])
|
||||
|
||||
** Module Flags
|
||||
This module provides no flags.
|
||||
|
||||
** Plugins
|
||||
+ [[https://github.com/ocaml/tuareg][tuareg]]
|
||||
+ [[https://github.com/ocaml/merlin][merlin]]
|
||||
+ [[https://github.com/Khady/merlin-eldoc][merlin-eldoc]]
|
||||
+ [[https://github.com/OCamlPro/ocp-indent][ocp-indent]]
|
||||
+ [[https://github.com/flycheck/flycheck-ocaml][flycheck-ocaml]]*
|
||||
+ [[https://github.com/ocaml-community/utop][utop]]*
|
||||
+ [[https://github.com/ocaml-ppx/ocamlformat][ocamlformat]]*
|
||||
+ [[https://github.com/ocaml/dune][dune]]
|
||||
|
||||
* Prerequisites
|
||||
This module has no hard dependencies, but it is recommanded that you install
|
||||
[[http://opam.ocaml.org/][opam]] and the following opam (optional) packages:
|
||||
|
||||
#+BEGIN_SRC shell
|
||||
opam install merlin utop ocp-indent dune ocamlformat
|
||||
#+END_SRC
|
||||
|
||||
* Features
|
||||
+ The following files should have syntax highlighting support: ~.ml{i,p,y,}~,
|
||||
~.eliom{i,}~, ~jbuild~, ~dune~, ~opam~
|
||||
+ =merlin-mode= is activated whenever a =.merlin= file is found (including in a
|
||||
parent directory) and =ocamlmerlin= executable is present
|
||||
+ Line-based auto-indentation is provided by =ocp-indent=, if it is available.
|
||||
|
||||
* Configuration
|
||||
+ If =:completion company= is enabled then autocomplete is provided by =merlin=
|
||||
+ When =:tools flycheck= is enabled then =flycheck-ocaml= is activated to do
|
||||
on-the-fly syntax/type checking via =merlin=, otherwise this is only done when
|
||||
the file is saved.
|
||||
+ Spell checking is activated in comments if =:tools flyspell= is active
|
||||
+ A REPL is provided if =utop= is installed and =:tools eval= is active
|
||||
+ If =:editor format= is enabled, the =ocamlformat= executable is available and
|
||||
there is an =.ocamlformat= file present then =format-all-buffer= is bound to
|
||||
=ocamlformat=, otherwise to =ocp-indent=
|
||||
+ If =:editor multiple-cursors= is enabled then identifiers can be refactored
|
||||
with =v R= and multiple cursors (this correctly matches identifier occurrences
|
||||
according to scope, it is not purely a textual match)
|
||||
+ If =:emacs imenu= is enabled then top level symbols (modules, type, functions,
|
||||
etc.) can be looked up using =SPC / i=
|
||||
|
||||
Run =bin/doom refresh= to install all packages and =make doctor= to diagnose
|
||||
missing tools.
|
||||
|
||||
* Appendix
|
||||
** Commands
|
||||
| Command | Key | Description |
|
||||
|------------------------------+-----------+-----------------------------------------------------------|
|
||||
| =merlin-type-enclosing= | =SPC m t= | display type under point |
|
||||
| =tuareg-find-alternate-file= | =SPC m a= | switch between =.ml= and =.mli= |
|
||||
| =merlin-locate= | =gd= | lookup definition |
|
||||
| =merlin-occurences= | =SPC c D= | lookup references |
|
||||
| =merlin-document= | =K= | lookup documentation |
|
||||
| =merlin-imenu= | =SPC / i= | symbol lookup in file |
|
||||
| =merlin-iedit-occurrences= | =v R= | visual refactor identifier under point (multiple cursors) |
|
||||
| =utop= | =SPC o r= | open =utop= as REPL |
|
||||
| =utop-eval-region= | =SPC c e= | evaluate selected region in =utop= |
|
||||
|
||||
** Hacks
|
||||
+ =set-pretty-symbols!= is called with the full tuareg prettify symbol list, this
|
||||
can cause columns to change as certain keywords are shortened (e.g. =fun=
|
||||
becomes \lambda.
|
||||
+ =tuareg-opam-update-env= is called the first time =tuareg= is loaded
|
||||
9
.emacs.d/modules/lang/ocaml/autoload.el
Normal file
9
.emacs.d/modules/lang/ocaml/autoload.el
Normal file
@@ -0,0 +1,9 @@
|
||||
;;; lang/ocaml/autoload.el -*- lexical-binding: t; -*-
|
||||
|
||||
;;;###autoload
|
||||
(defun +ocaml/comment-indent-new-line (&optional _)
|
||||
"Break line at point and indent, continuing comment if within one."
|
||||
(interactive)
|
||||
(comment-indent-new-line)
|
||||
(when (eq (char-before) ?*)
|
||||
(just-one-space)))
|
||||
116
.emacs.d/modules/lang/ocaml/config.el
Normal file
116
.emacs.d/modules/lang/ocaml/config.el
Normal file
@@ -0,0 +1,116 @@
|
||||
;;; lang/ocaml/config.el -*- lexical-binding: t; -*-
|
||||
|
||||
(when (featurep! +lsp)
|
||||
(add-hook! '(tuareg-mode-local-vars-hook reason-mode-local-vars-hook)
|
||||
#'lsp!))
|
||||
|
||||
|
||||
(after! tuareg
|
||||
;; tuareg-mode has the prettify symbols itself
|
||||
(set-pretty-symbols! 'tuareg-mode :alist
|
||||
(append tuareg-prettify-symbols-basic-alist
|
||||
tuareg-prettify-symbols-extra-alist))
|
||||
;; harmless if `prettify-symbols-mode' isn't active
|
||||
(setq tuareg-prettify-symbols-full t)
|
||||
|
||||
;; Use opam to set environment
|
||||
(setq tuareg-opam-insinuate t)
|
||||
(tuareg-opam-update-env (tuareg-opam-current-compiler))
|
||||
|
||||
;; Spell-check comments
|
||||
(when (featurep! :tools flyspell)
|
||||
(add-hook 'tuareg-mode-local-vars-hook #'flyspell-prog-mode))
|
||||
|
||||
;; Ensure asterixes in block comments have at least one space of indentation
|
||||
(setq-hook! 'tuareg-mode-hook
|
||||
comment-line-break-function #'+ocaml/comment-indent-new-line)
|
||||
|
||||
(map! :localleader
|
||||
:map tuareg-mode-map
|
||||
"a" #'tuareg-find-alternate-file)
|
||||
|
||||
(use-package! utop
|
||||
:when (featurep! :tools eval)
|
||||
:hook (tuareg-mode . +ocaml-init-utop-h)
|
||||
:init
|
||||
(set-repl-handler! 'tuareg-mode #'utop)
|
||||
(set-eval-handler! 'tuareg-mode #'utop-eval-region)
|
||||
(defun +ocaml-init-utop-h ()
|
||||
(when (executable-find "utop")
|
||||
(utop-minor-mode)))
|
||||
:config
|
||||
(set-popup-rule! "^\\*utop\\*" :quit nil)))
|
||||
|
||||
|
||||
(use-package! merlin
|
||||
:unless (featurep! +lsp)
|
||||
:hook (tuareg-mode . +ocaml-init-merlin-h)
|
||||
:init
|
||||
(defun +ocaml-init-merlin-h ()
|
||||
"Activate `merlin-mode' if the ocamlmerlin executable exists."
|
||||
(when (executable-find "ocamlmerlin")
|
||||
(merlin-mode)))
|
||||
|
||||
(after! tuareg
|
||||
(set-company-backend! 'tuareg-mode 'merlin-company-backend)
|
||||
(set-lookup-handlers! 'tuareg-mode
|
||||
:definition #'merlin-locate
|
||||
:references #'merlin-occurrences
|
||||
:documentation #'merlin-document))
|
||||
:config
|
||||
(setq merlin-completion-with-doc t)
|
||||
|
||||
(map! :localleader
|
||||
:map tuareg-mode-map
|
||||
"t" #'merlin-type-enclosing)
|
||||
|
||||
(use-package! flycheck-ocaml
|
||||
:when (featurep! :tools flycheck)
|
||||
:hook (merlin-mode . +ocaml-init-flycheck-h)
|
||||
:config
|
||||
(defun +ocaml-init-flycheck-h ()
|
||||
"Activate `flycheck-ocaml`"
|
||||
;; Disable Merlin's own error checking
|
||||
(setq merlin-error-after-save nil)
|
||||
;; Enable Flycheck checker
|
||||
(flycheck-ocaml-setup)))
|
||||
|
||||
(use-package! merlin-eldoc
|
||||
:hook (merlin-mode . merlin-eldoc-setup))
|
||||
|
||||
(use-package! merlin-iedit
|
||||
:when (featurep! :editor multiple-cursors)
|
||||
:defer t
|
||||
:init
|
||||
(map! :map tuareg-mode-map
|
||||
:v "R" #'merlin-iedit-occurrences))
|
||||
|
||||
(use-package! merlin-imenu
|
||||
:when (featurep! :emacs imenu)
|
||||
:hook (merlin-mode . merlin-use-merlin-imenu)))
|
||||
|
||||
|
||||
(use-package! ocp-indent
|
||||
;; must be careful to always defer this, it has autoloads that adds hooks
|
||||
;; which we do not want if the executable can't be found
|
||||
:hook (tuareg-mode . +ocaml-init-ocp-indent-h)
|
||||
:config
|
||||
(defun +ocaml-init-ocp-indent-h ()
|
||||
"Run `ocp-setup-indent', so long as the ocp-indent binary exists."
|
||||
(when (executable-find "ocp-indent")
|
||||
(ocp-setup-indent))))
|
||||
|
||||
|
||||
(use-package! ocamlformat
|
||||
:when (featurep! :editor format)
|
||||
:commands ocamlformat
|
||||
:hook (tuareg-mode . +ocaml-init-ocamlformat-h)
|
||||
:config
|
||||
(set-formatter! 'ocamlformat #'ocamlformat
|
||||
:modes '(caml-mode tuareg-mode))
|
||||
;; TODO Fix region-based formatting support
|
||||
(defun +ocaml-init-ocamlformat-h ()
|
||||
(setq +format-with 'ocp-indent)
|
||||
(when (and (executable-find "ocamlformat")
|
||||
(locate-dominating-file default-directory ".ocamlformat"))
|
||||
(setq +format-with 'ocamlformat))))
|
||||
24
.emacs.d/modules/lang/ocaml/doctor.el
Normal file
24
.emacs.d/modules/lang/ocaml/doctor.el
Normal file
@@ -0,0 +1,24 @@
|
||||
;; -*- lexical-binding: t; no-byte-compile: t; -*-
|
||||
;;; lang/ocaml/doctor.el
|
||||
|
||||
(assert! (or (not (featurep! +lsp))
|
||||
(featurep! :tools lsp))
|
||||
"This module requires (:tools lsp)")
|
||||
|
||||
(unless (executable-find "ocamlmerlin")
|
||||
(warn! "Couldn't find ocamlmerlin. Lookup, completion and syntax checking won't work"))
|
||||
|
||||
;; Tuareg can still indent
|
||||
(unless (executable-find "ocp-indent")
|
||||
(warn! "Couldn't find ocp-indent. Auto-indentation will be less precise"))
|
||||
|
||||
(when (featurep! :tools eval)
|
||||
(unless (executable-find "utop")
|
||||
(warn! "Couldn't find utop. REPL won't be available")))
|
||||
|
||||
(unless (executable-find "dune")
|
||||
(warn! "Couldn't find dune. Won't be able to highlight dune files"))
|
||||
|
||||
(when (featurep! :editor format)
|
||||
(unless (executable-find "ocamlformat")
|
||||
(warn! "Couldn't find ocamlformat. Code-formatting will be unavailable")))
|
||||
25
.emacs.d/modules/lang/ocaml/packages.el
Normal file
25
.emacs.d/modules/lang/ocaml/packages.el
Normal file
@@ -0,0 +1,25 @@
|
||||
;; -*- no-byte-compile: t; -*-
|
||||
;;; lang/ocaml/packages.el
|
||||
|
||||
(package! tuareg)
|
||||
|
||||
(unless (featurep! +lsp)
|
||||
(package! merlin)
|
||||
(package! merlin-eldoc)
|
||||
(when (featurep! :tools flycheck)
|
||||
(package! flycheck-ocaml)))
|
||||
|
||||
(package! ocp-indent)
|
||||
|
||||
(when (featurep! :tools eval)
|
||||
(package! utop))
|
||||
|
||||
(when (featurep! :editor format)
|
||||
;; by default quelpa generated a version 0pre0.20180929.192844, which got
|
||||
;; parsed into (0 -1 0 ...), which when compared with version nil (0) in
|
||||
;; package-installed-p always yielded false
|
||||
(package! ocamlformat :recipe
|
||||
(:host github :repo "ocaml-ppx/ocamlformat" :files ("emacs/*.el"))))
|
||||
|
||||
(package! dune :recipe
|
||||
(:host github :repo "ocaml/dune" :files ("editor-integration/emacs/*.el")))
|
||||
Reference in New Issue
Block a user