Magnus web site
Random stuff
Emacs via Nix with mu4e
I've been running development versions of Emacs ever since I switched to Wayland
and needed the PGTK code. The various X-git
packages on AUR makes that easy,
as long as one doesn't mind building the packages locally, and regularly.
Building a large package like Emacs does get a bit tiring after a while though
so I started looking at the emacs overlay to see if I could keep up without
building quite that much.
The first attempt at this failed as I couldn't get my email setup working; emacs
simply refused to find the locally installed mu4e
package. I felt I didn't
have time to solve it at the time, reverted back to doing the builds myself
again. It kept irritating me though, and today I made another attempt. This time
I invested a bit more time in reading up on how to install emacs via Nix with
packages. Something that paid off.
I'm managing my packages using nix profile and a flake.nix
. To install emacs
with a working mu4e
I started with adding the emacs overlay to the inputs
inputs = { nixpkgs.url = "github:nixos/nixpkgs?ref=nixpkgs-unstable"; ... community-emacs.url = "github:nix-community/emacs-overlay"; };
and in my outputs I made sure to use the overlay on nixpkgs
outputs = inputs@{ nixpkgs, community-emacs, ... }: let system = "x86_64-linux"; pkgs = import nixpkgs { inherit system; overlays = [ community-emacs.overlays.emacs ]; }; ...
and in the list of packages passed to pkgs.buildEnv
I added
... ((emacsPackagesFor emacs-pgtk).emacsWithPackages (epkgs: [ epkgs.mu4e ])) mu ...
That's all there's to it. After running nix profile update 0
I had a build of
emacs with Wayland support that's less than a day old, all downloaded from the
community cache. Perfect!
Hoogle setup for local development
About a week ago I asked a question on the Nix Discourse about how to create a setup for Hoogle that
- includes the locally installed packages, and
- the package I'm working on, and ideally also
- have all local links, i.e. no links to Hackage.
I didn't get an answer there, but some people on the Nix Haskell channel on Matrix helped a bit, but it seems this particular use case requires a bit of manual work. The following commands get me an almost fully working setup:
cabal haddock --haddock-internal --haddock-quickjump --haddock-hoogle --haddock-html hoogle_dir=$(dirname $(dirname $(readlink -f $(which hoogle)))) hoogle generate --database=local.hoo \ $(for d in $(fd -L .txt ${hoogle_dir}); do printf "--local=%s " $(dirname $d); done) \ --local=./dist-newstyle/build/x86_64-linux/ghc-9.8.2/pkg-0.0.1/doc/html/pkg hoogle server --local --database=local.foo
What's missing is working links between the documentation of locally installed
packages. It looks like the links in the generated documention in Nix have a lot
of relative references containing ${pkgroot}/../../../../
which is what I
supect causes the broken links.
A function for jumping to a project TODO file
I've had org-projectile in my config since the beginning, and while it's worked nicely for me in my main config it gave me some grief when I played around with elpaca the other week.1
I tried to get the install instructions to work, but kept on getting errors when
loading my config. Given that I only use it for one thing, to open the file
TODO.org
in the current project's root, I decided to just write a function for
doing that instead.
(defun mep-projectile-open-todo () "Open the project's todo file." (interactive) (if-let* ((proj-dir (projectile-project-root)) (proj-todo-file (f-join proj-dir "TODO.org"))) (org-open-file proj-todo-file) (message "Not in a project")))
Footnotes:
Nix, cabal, and tests
At work I decided to attempt to change the setup of one of our projects from using
to the triplet I tend to prefer
During this I ran into two small issues relating to tests.
hspec-discover
both is, and isn't, available in the shell
I found mentions of this mentioned in an open cabal ticket and someone even made a git repo to explore it. I posted a question on the Nix discorse.
Basically, when running cabal test
in a dev shell, started with nix develop
,
the tool hspec-discover
wasn't found. At the same time the packages was
installed
(ins)$ ghc-pkg list | rg hspec hspec-2.9.7 hspec-core-2.9.7 (hspec-discover-2.9.7) hspec-expectations-0.8.2
and it was on the $PATH
(ins)$ whereis hspec-discover hspec-discover: /nix/store/vaq3gvak92whk5l169r06xrbkx6c0lqp-ghc-9.2.8-with-packages/bin/hspec-discover /nix/store/986bnyyhmi042kg4v6d918hli32lh9dw-hspec-discover-2.9.7/bin/hspec-discover
The solution, as the user julm pointed out, is to simply do what cabal
tells
you and run cabal update
first.
Dealing with tests that won't run during build
The project's tests were set up in such a way that standalone tests and
integration tests are mixed into the same test executable. As the integration
tests need the just built service to be running they can't be run during nix
build
. However, the only way of preventing that, without making code changes,
is to pass an argument to the test executable, --skip=<prefix>
, and I believe
that's not possible when using developPackage
. It's not a big deal though,
it's perfectly fine to run the tests separately using nix develop . command
...
. However, it turns out developPackage
and the underlying machinery is
smart enough to skip installing package required for testing when it's turned
off (using dontCheck
). This is the case also when returnShellEnv
is true
.
Luckily it's not too difficult to deal with it. I already had a variable
isDevShell
so I could simply reuse it and add the following expression to
modifier
(if isDevShell then hl.doCheck else hl.dontCheck)
Orderless completion in lsp-mode
If you, like me, are using corfu to get in-buffer completion and extend it with orderless to make it even more powerful, you might have noticed that you lose the orderless style as soon as you enter lsp-mode.
My setup of orderless looks like this
(use-package orderless :custom (orderless-matching-styles '(orderless-literal orderless-regexp orderless-flex)) (completion-styles '(orderless partial-completion basic)) (completion-category-defaults nil) (completion-category-overrides '((file (styles partial-completion)))))
which basically turns on orderless style for all things except when completing filenames.
It turns out that lsp-mode messes around with completion-category-defaults
and when entering lsp-mode
this code here adds a setting for 'lsp-capf
.
Unfortunately there seems to be no way to prevent lsp-mode from doing this so
the only option is to fix it up afterwards. Luckily there's a hook for running
code after the completion for lsp-mode is set up, lsp-completion-mode-hook
.
Adding the following function to it makes sure I now get to enjoy orderless
also when writing code.
(lambda () (setq-local completion-category-defaults (assoc-delete-all 'lsp-capf completion-category-defaults)))