21 Jul 2024

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!

Tags: emacs nix
13 Jul 2024

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

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.

Tags: haskell nix
13 Jul 2024

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:

1

This was the second time I gave up on using it instead of straight, but that's another story.

Tags: emacs org-mode
19 May 2024

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)
Tags: cabal haskell nix
04 May 2024

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)))
Tags: emacs lsp
Other posts