Sharing my Gleam config for Emacs

Hey there,

since it took me a while to get it set up how I wanted I thought I’d share my Emacs config. It features language server integration via eglot, projectile integration, auto-format on save and hotkeys to insert the pipe operator:

(defun fap--pipe-operator-on-newline ()
  (insert "|> "))

(defun fap--pipe-operator ()
  (insert " |> "))

(use-package eglot
  :ensure t)

(use-package tree-sitter
  :ensure t)

(use-package tree-sitter-indent
  :ensure t)

(use-package gleam-mode
  :after (projectile eglot)
  :load-path "~/.emacs.d/lisp/gleam-mode"
  (projectile-register-project-type 'gleam '("gleam.toml")
                                    :project-file "gleam.toml"
				                    :compile "gleam build"
				                    :test "gleam test"
				                    :run "gleam run"
                                    :src-dir "src/"
                                    :test-dir "test/"
				                    :test-suffix "_test")
  (add-to-list 'eglot-server-programs
               '(gleam-mode . ("gleam" "lsp")))
  (add-hook 'gleam-mode-hook
            (lambda () (add-hook 'before-save-hook 'gleam-format nil t)))
  (define-key gleam-mode-map (kbd "<M-return>") 'fap--pipe-operator-on-newline)
  (define-key gleam-mode-map (kbd "<C-return>") 'fap--pipe-operator))

You’ll have to place gleam-mode into the specified load-path. If you’re using straight.el you could of course also directly load it from GitHub. The config also doesn’t add projectile. Check out GitHub - bbatsov/projectile: Project Interaction Library for Emacs if you’re not using it yet.

I think you need the tree-sitter dependencies also on Emacs 29 because gleam-mode is not written against the Emacs 29 treesitter API, but I might be wrong.

You’ll have to start the language server integration for each new exercise by calling eglot on the buffer with the solution file. Errors will only appear after you save the file because the LSP currently only compiles on save. The LSP doesn’t support auto completion yet.

You can jump between test and solution file with projectile-find-implementation-or-test-other-window.
You can run the tests via projectile-test-project but there is some encoding issue that makes the output hard to read and I didn’t figure out how to fix that yet. Example:

  1) leap_test.year_divisible_by_100_not_divisible_by_400_in_common_year_test
e[0;31m     Assertion pattern match failed
e[0me[0;31m        value: e[0me[0mTrue
e[0me[0;36m     location: leap_test.year_divisible_by_100_not_divisible_by_400_in_common_year_test:25
e[0me[0;36m     stacktrace:
e[0me[0;36m       leap_test.year_divisible_by_100_not_divisible_by_400_in_common_year_test
e[0me[0;36m     output: e[0m

Happy gleaming! :slight_smile:


(cc @lpil :slightly_smiling_face:)

oooh very nice! Thank you