Skip to content

About

Emacs major mode for the Unison language

Topics

Resources

Stars

10 stars

Watchers

3 watching

Forks

Repository files navigation

unison-ts-mode

Emacs major mode for Unison using tree-sitter.

Status: Ready for MELPA submission. Once accepted, install with M-x package-install RET unison-ts-mode.

Quick Start

  1. Install the package (see Installation)
  2. Open a .u file - you'll be prompted to install the tree-sitter grammar
  3. (Optional) Enable LSP: M-x eglot or M-x lsp

Features

  • Syntax highlighting with tree-sitter (4 customizable levels)
  • Automatic indentation for all Unison constructs
  • imenu support for navigation (functions, types, abilities)
  • LSP integration (eglot and lsp-mode)
  • UCM REPL integration with keybindings
  • Auto-install of tree-sitter grammar

Screenshots

Syntax highlighting example 1 Syntax highlighting example 2

Requirements

Installation

Package

use-package + straight:

(use-package unison-ts-mode
  :straight (:host github :repo "fmguerreiro/unison-ts-mode")
  :mode ("\\.u\\'" "\\.unison\\'"))

straight.el:

(straight-use-package
  '(unison-ts-mode :type git :host github :repo "fmguerreiro/unison-ts-mode"))

Doom Emacs:

;; packages.el
(package! unison-ts-mode :recipe (:host github :repo "fmguerreiro/unison-ts-mode"))

Grammar

The tree-sitter grammar installs automatically when you first open a .u file. Customize behavior with unison-ts-grammar-install:

  • 'prompt (default): Ask before installing
  • 'auto: Install automatically
  • nil: Never auto-install

Manual install: M-x unison-ts-install-grammar

Custom grammar source:

(setq unison-ts-grammar-repository "https://github.com/yourname/tree-sitter-unison")
(setq unison-ts-grammar-revision "your-branch")  ; Optional

Configuration

Font-lock Levels

Customize highlighting depth via treesit-font-lock-level:

  1. comment, doc, string, declaration, preprocessor, error
  2. keyword, type, constant
  3. function-call, variable
  4. bracket, operator, delimiter

Apply changes: M-x treesit-font-lock-recompute-features

imenu Navigation

Navigate to functions, types, and abilities:

  • M-x imenu - Jump to definition
  • M-x which-function-mode - Show current function in mode line
  • Works with helm-imenu, counsel-imenu, consult-imenu
;; Auto-enable which-function-mode
(add-hook 'unison-ts-mode-hook 'which-function-mode)

LSP Support

Requires UCM. UCM auto-starts as the inferior UCM (full TUI in a comint buffer) the first time eglot, lsp-mode, or the REPL needs it. The same process serves LSP, MCP, and the user-facing TUI, so there is no codebase-lock conflict.

Eglot (built-in):

(with-eval-after-load 'unison-ts-mode
  (with-eval-after-load 'eglot
    (unison-ts-mode-setup-eglot)))
(add-hook 'unison-ts-mode-hook 'eglot-ensure)

lsp-mode:

(with-eval-after-load 'unison-ts-mode
  (with-eval-after-load 'lsp-mode
    (unison-ts-mode-setup-lsp)))
(add-hook 'unison-ts-mode-hook 'lsp-deferred)

Custom port:

export UNISON_LSP_PORT=5758

Windows: LSP is disabled by default. Enable it:

[System.Environment]::SetEnvironmentVariable('UNISON_LSP_ENABLED','true')

Manual UCM:

If you would rather manage UCM yourself, just start it before connecting (Emacs detects it on the LSP port and skips the auto-spawn):

ucm

UCM Integration

Interact with UCM directly from Emacs. Open the REPL with C-c C-u r or use these commands:

Keybinding Command Description
C-c C-u r unison-ts-repl Open UCM REPL (MCP-based)
C-c C-u i unison-ts-inferior-ucm Open the inferior UCM (full TUI)
C-c C-u a unison-ts-add Add definitions from current file
C-c C-u u unison-ts-update Update existing definitions
C-c C-u t unison-ts-test Run tests (prompts for pattern)
C-c C-u x unison-ts-run Run a term
C-c C-u w unison-ts-watch Watch current file for changes
C-c C-u l unison-ts-load Load current file
C-c C-u v unison-ts-eval Evaluate expression via MCP
C-c C-u e unison-ts-send-region Send region to UCM via MCP
C-c C-u d unison-ts-send-definition Send definition at point to UCM
C-c C-u V unison-ts-eval-and-go Evaluate expression and switch to REPL
C-c C-u E unison-ts-send-region-and-go Send region to REPL and switch to it
C-c C-u D unison-ts-send-definition-and-go Send definition to REPL and switch to it

Troubleshooting

Grammar installation fails:

Install build tools:

# macOS
xcode-select --install

# Debian/Ubuntu
sudo apt-get install build-essential git

# Fedora/RHEL
sudo dnf install gcc git

ABI version mismatch:

tree-sitter generate --abi=13

Grammar not found:

Check ~/.emacs.d/tree-sitter/ or treesit-extra-load-path contains the compiled grammar.

Highlighting is wrong after an upgrade:

The grammar is installed once and never re-checked, so a release that changes the pinned revision does not reach an existing install. Run M-x unison-ts-install-grammar to rebuild at the current pin.

LSP connection refused:

  • Verify ucm is in PATH: which ucm
  • Check port 5757: lsof -i :5757 (macOS/Linux) or netstat -an | findstr 5757 (Windows)
  • Start manually: ucm headless
  • Check logs: *EGLOT events* (eglot) or *lsp-log* (lsp-mode)

LSP features not working:

Ensure you're in a valid Unison codebase directory.

Advanced

Manual Grammar Build

If auto-install fails:

git clone https://github.com/kylegoetz/tree-sitter-unison.git
cd tree-sitter-unison
git checkout 28be881547089225cd5253ead9db0e0d0e2e7a1f

# Determine shared library extension
if [ "$(uname)" = "Darwin" ]; then soext="dylib"
elif uname | grep -q "MINGW"; then soext="dll"
else soext="so"; fi

cd src
cc -fPIC -c -I. parser.c
cc -fPIC -c -I. scanner.c
cc -fPIC -shared *.o -o "libtree-sitter-unison.${soext}"

# Copy to Emacs tree-sitter directory
mkdir -p ~/.emacs.d/tree-sitter
cp "libtree-sitter-unison.${soext}" ~/.emacs.d/tree-sitter/

Syntax Tree Inspection

Use M-x treesit-explore-mode to inspect the syntax tree while developing or debugging.

Development

Set up the pre-commit hook to run MELPA-style checks:

ln -s ../../scripts/pre-commit .git/hooks/pre-commit

Contributing

Contributions welcome via GitHub pull requests.

License

GPL-3.0 License. See LICENSE for details.

Credits

Tree-sitter grammar by @kylegoetz.

About

Emacs major mode for the Unison language

Topics

Resources

Stars

10 stars

Watchers

3 watching

Forks

Releases

Packages

Contributors

Languages