Emacs salmagundi, 2026-09-06
Compilation commands by project type
I while ago I added a minor mode, haskell-ng-project-mode, to my Haskell mode.
The idea I had was that I could use it to add keybindings for running various
tools (via compile), e.g. I bound cabal build and cabal test , p b and
, p t respectively. Then I hooked in the minor mode in my haskell-ng-mode.
Soon I realised it'd be nice to have those shortcuts available in dired too,
so I hooked it in there as well. When I later wanted to re-run the tests after
modifying a JSON file that was part of a golden test I realised that this wasn't
a very nice solution at all.
After looking around a bit I found emacs-multi-compile. I removed the minor mode and add this configuration instead
(add-to-list 'multi-compile-alist
'((haskell-ng-is-project) . (("cabal build" "cabal build -j --semaphore" (project-root (project-current)))
("cabal test" "cabal test" (project-root (project-current)))
("fourmolu" "fourmolu -i $(fd .hs$)" (project-root (project-current))))))
I've had some vague thoughts that it'd be rather easy to write something
slightly more custom, but emacs-multi-compile works very well for me so I'm
very happy with it.
Jumping between implementation and test, again
I wrote about this a while ago. At the time I came up with a way of bending
ff-find-other-file to my will, but soon after that I ran into a case where
there may be 2 "other files" – one of the Haskell projects at work put unit
tests in files ending in Spec.hs and property tests in filed ending with
Prop.hs. Unfortunately this is a situation that ff-find-other-file can't
handle.
I ended up hacking together consult-kith to deal with it. The configuration to
handle two kinds of test files looks like this
(setq-local consult-kith-alist `((,(rx (seq "Spec.hs" eol)) (".hs"))
(,(rx (seq "Prop.hs" eol)) (".hs"))
(,(rx (seq ".hs" eol)) ("Prop.hs" "Spec.hs")))
consult-kith-search-directories '("src" "test"))
The project has since settled on only using Spec.hs for tests, but I'm
sticking to consult-kith for now.