Tooling and Editor Integration

mino's tooling is three independent, composable pieces. Each speaks a standard protocol. Each works standalone. Use any combination.

ToolWhatProtocol
tree-sitter-minoSyntax highlighting, brackets, foldingtree-sitter
mino-lspDiagnostics, completion, hoverLSP (JSON-RPC over stdio)
mino-nreplInteractive eval, REPLnREPL (bencode over TCP)

No mino-specific client code is needed. Any editor that supports tree-sitter, LSP, or nREPL can use the corresponding tool directly.

Syntax Highlighting

tree-sitter-mino is a tree-sitter grammar for mino. It provides syntax highlighting, bracket matching, structural navigation, and code folding in any editor that supports tree-sitter.

Neovim

Add mino to your nvim-treesitter configuration:

local parser_config = require("nvim-treesitter.parsers").get_parser_configs()
parser_config.mino = {
  install_info = {
    url = "https://github.com/leifericf/tree-sitter-mino",
    files = { "src/parser.c" },
    branch = "main",
  },
  filetype = "mino",
}

vim.filetype.add({ extension = { mino = "mino" } })

Then run :TSInstall mino.

Helix

Add to ~/.config/helix/languages.toml:

[[language]]
name = "mino"
scope = "source.mino"
file-types = ["mino"]
comment-token = ";"
indent = { tab-width = 2, unit = "  " }

[[grammar]]
name = "mino"
source = { git = "https://github.com/leifericf/tree-sitter-mino", rev = "main" }

Then run hx --grammar fetch && hx --grammar build.

Emacs (29+)

(add-to-list 'treesit-language-source-alist
             '(mino "https://github.com/leifericf/tree-sitter-mino"))
(treesit-install-language-grammar 'mino)

Zed

Create a language extension or add mino to your settings with the grammar pointed at the tree-sitter-mino repository.

Structural Editing

Paredit and parinfer work out of the box with mino files. mino uses standard balanced brackets (), [], and {}, so every editor's structural editing support applies without any additional configuration.

mino-lsp

mino-lsp is a Language Server Protocol server for mino. It provides real-time diagnostics, symbol completion, and hover documentation. It is a small C program that links against mino.c and communicates over stdin/stdout using JSON-RPC. No runtime dependencies beyond mino itself.

Features

FeatureDescription
DiagnosticsParse and eval errors shown inline as you type.
CompletionSymbol suggestions filtered by prefix.
HoverType and docstring for the symbol under the cursor.

Build

git clone --recursive https://github.com/leifericf/mino-lsp.git
cd mino-lsp
make

This produces a single mino-lsp binary.

Editor Setup

Neovim (nvim-lspconfig)

local configs = require("lspconfig.configs")
configs.mino = {
  default_config = {
    cmd = { "mino-lsp" },
    filetypes = { "mino" },
    root_dir = function(fname)
      return vim.fs.dirname(fname)
    end,
  },
}
require("lspconfig").mino.setup({})

Helix

Add to ~/.config/helix/languages.toml:

[language-server.mino-lsp]
command = "mino-lsp"

[[language]]
name = "mino"
language-servers = ["mino-lsp"]

Emacs (eglot)

(add-to-list 'eglot-server-programs '(mino-mode "mino-lsp"))

VS Code

Install a generic LSP client extension and point it at the mino-lsp binary.

Zed

Add mino-lsp as the language server in a mino language extension.

mino-nrepl

mino-nrepl is a standalone nREPL server for mino. It is a small C program that links against mino.c and implements the nREPL wire protocol (bencode over TCP). No JVM, no runtime dependencies beyond mino itself.

Build

git clone --recursive https://github.com/leifericf/mino-nrepl.git
cd mino-nrepl
make

This produces a single mino-nrepl binary.

Run

cd your-project/
mino-nrepl               # random port, written to .nrepl-port
mino-nrepl --port 7888   # fixed port

The server writes a .nrepl-port file to the current directory on startup and removes it on shutdown. Editors that support nREPL auto-detect this file.

Editor Setup

Conjure (Neovim)

Conjure auto-connects when it finds .nrepl-port in the project directory. Start mino-nrepl, open a file, and evaluate with <localleader>ee (current form) or <localleader>eb (current buffer).

vim-fireplace (Vim)

vim-fireplace reads .nrepl-port automatically. Evaluate the innermost form with cpp or a visual selection with cp.

CIDER (Emacs)

Run M-x cider-connect-clj, enter localhost and the port number. Basic eval, completion, and inline results work out of the box. Advanced features that depend on cider-nrepl middleware are not available.

Calva (VS Code)

Open the Command Palette and choose Calva: Connect to a Running REPL Server. Select Generic as the project type, then enter the host and port.

Cursive (IntelliJ)

Go to Run > Edit Configurations > + > Remote REPL. Set the host and port, then connect. Cursive will use the nREPL connection for evaluation.

Supported Operations

mino-nrepl implements the following nREPL operations:

OpDescription
cloneCreate a new session.
closeClose a session.
describeList server capabilities.
evalEvaluate code in a session.
completionsSymbol completion by prefix.
load-fileEvaluate file contents.
ls-sessionsList active sessions.

Guide for Tools Developers

If you are building editor plugins, developer tools, or integrations that work with mino, two standard protocols give you ready-made communication layers. You do not need to parse mino output or invent a custom protocol.

LSP (mino-lsp)

mino-lsp speaks standard LSP over stdin/stdout. Launch the mino-lsp binary as a subprocess, send JSON-RPC 2.0 messages with Content-Length framing, and receive responses on stdout. Any LSP client library works without modification.

Supported methods: initialize, textDocument/didOpen, textDocument/didChange, textDocument/didClose, textDocument/completion, textDocument/hover.

The server pushes textDocument/publishDiagnostics notifications whenever a document is opened or changed.

nREPL (mino-nrepl)

Connecting

Connect a TCP socket to the host and port. If .nrepl-port exists in the project directory, read it to discover the port number. The server listens on 127.0.0.1 by default.

Wire format

All messages are bencode dictionaries. Bencode is a simple binary format with four types:

TypeEncodingExample
Stringlength : data5:hello
Integeri number ei42e
Listl items el5:helloi42ee
Dictionaryd key/value pairs ed3:foo3:bare

Many languages have bencode libraries. A minimal encoder and decoder is roughly 50 lines in most languages.

Message structure

Every request is a bencode dictionary with at least an "op" field. Most ops also require "id" (for correlating responses) and "session" (from a prior clone).

Every response includes "status", a list that always contains "done" when the operation is complete.

Typical session lifecycle

1. Connect TCP socket to server
2. Send:   {"op" "clone" "id" "1"}
   Recv:   {"id" "1" "new-session" "<uuid>" "status" ["done"]}
3. Send:   {"op" "eval" "id" "2" "session" "<uuid>" "code" "(+ 1 2)"}
   Recv:   {"id" "2" "session" "<uuid>" "ns" "user" "value" "3" "status" ["done"]}
4. Send:   {"op" "close" "id" "3" "session" "<uuid>"}
   Recv:   {"id" "3" "session" "<uuid>" "status" ["done"]}
5. Disconnect

Evaluating code

Send an eval op with a "code" field containing the mino source. The server responds with:

If the evaluated code produces side-effect output (via println or prn), the server sends a separate message with an "out" field before the result message.

Completions

Send a completions op with a "prefix" field. The server returns a "completions" list of dictionaries, each with a "candidate" field:

Send: {"op" "completions" "id" "4" "prefix" "ma" "session" "<uuid>"}
Recv: {"id" "4" "completions" [{"candidate" "map"}
                                {"candidate" "map?"}
                                {"candidate" "macroexpand"}
                                {"candidate" "macroexpand-1"}]
       "status" ["done"]}

Existing nREPL client libraries

Most languages already have nREPL client libraries that handle bencode and the message protocol for you:

Using one of these libraries, connecting to mino-nrepl is identical to connecting to any other nREPL server. No mino-specific client code is needed.

Source

The full source for mino-nrepl is at github.com/leifericf/mino-nrepl. It is roughly 1,400 lines of C99 with no dependencies beyond mino itself.