I use Literate Haskell for some of my personal Haskell projects and for a long time I used the auto-loaded literate-haskell-mode
that comes with haskell-mode.
This past weekend, I finally buckled down and made use of mmm-mode to make the literate programming experience better.
The biggest advantage of using mmm-mode
is that you can define subregions of your file which are handled by a different major mode.
In other words, you can get proper syntax highlighting for 2, 3, or more different languages in the same file!
Setup
You’ll need to install mmm-mode along with haskell-mode. I personally use MELPA for all of my Emacs packages because once you set it up it’s really painless.
In your emacs configuration file add these lines:
; Remove the hard-coded 'literate-haskell-mode' activation for `.lhs' files that
; haskell-mode comes with. In exchange, enable LaTeX mode whenever we open up a
; `.lhs' file. Using mmm-mode, we will activate `haskell-mode' in the code
; sections.
(setq auto-mode-alist
(remove
(rassoc 'literate-haskell-mode auto-mode-alist) auto-mode-alist))
(add-to-list 'auto-mode-alist '("\\.lhs$" . latex-mode))
; Literate Haskell - mmm-mode. Adopted from
; https://wiki.haskell.org/Literate_programming#Multi-mode_support_in_Emacs
(require 'mmm-auto)
(mmm-add-classes
'((literate-haskell-latex
:submode haskell-mode
:front "^\\\\begin{code}\n"
:back "^\\\\end{code}"
)))
; Re-fontify sub-mode portions when idle. The manual command for this is
; `mmm-parse-buffer'. If you don't do this, then syntax highlighting won't work
; for new regions of Haskell code in the \begin{code}...\end{code} blocks.
(setq mmm-parse-when-idle 't)
.
Now it’s a matter of running the following commands whenever you open up a .lhs
file:
(setq mmm-global-mode 't)
(setq mmm-submode-decoration-level 1)
(mmm-ify-by-class 'literate-haskell-latex)
.
Personally I use kakapo-mode so I have a file called kakapo-project-settings
that has this snippet in it:
(defun my-kakapo-indents ()
...
; Literate Haskell
((string-match "\\.lhs$" b)
(progn
(h 'latex-mode-hook t 4)
(setq mmm-global-mode 't)
(setq mmm-submode-decoration-level 1)
(mmm-ify-by-class 'literate-haskell-latex)
)
)
...
)
.
Emacs will now automatically pick up .lhs
files and apply latex-mode
and haskell-mode
with mmm-mode
.
Happy hacking!