Glint#
A Gleam-inspired configuration language (proof of concept).
Configs are typed values — you declare shapes, then construct one root pub let config.
type Mode {
Dev
Prod
}
type Config {
Config(
name: String,
mode: Mode,
port: Int,
)
}
pub let config = Config(
name: "hello",
mode: Dev,
port: 3000,
)
Features (POC)#
- Custom types: unit variants and labeled records
let/pub letbindings- Built-ins:
String,Int,Float,Bool,List(a),Option(a) True/False,None/Some(x)//comments, trailing commas, numeric underscores (1_000)- Typecheck + evaluate → dump as Glint syntax or JSON
Not yet: imports, env helpers, floats in all edge cases, anonymous maps.
CLI#
cd glint
# Erlang target (default) if you have the BEAM installed:
gleam run -- check examples/hello.glint
gleam run -- dump examples/hello.glint
gleam run -- dump examples/hello.glint --json
# Language server (stdio JSON-RPC; Erlang target):
gleam run -- lsp
# Or JavaScript target (check/dump/library; LSP stdio needs Erlang):
gleam run --target javascript -- check examples/hello.glint
gleam test --target javascript
Language server#
glint lsp speaks the Language Server Protocol over stdio (Content-Length framing).
| Capability | Support |
|---|---|
initialize / shutdown / exit |
yes |
Full document sync (textDocumentSync: 1) |
yes |
textDocument/didOpen / didChange / didClose |
yes |
textDocument/publishDiagnostics |
yes (lex / parse / type errors) |
Editor config (generic)#
Point your editor at the glint binary with the lsp argument, and associate *.glint files.
Neovim (nvim-lspconfig style):
vim.api.nvim_create_autocmd("FileType", {
pattern = "glint",
callback = function()
vim.lsp.start({
name = "glint",
cmd = { "glint", "lsp" }, -- or: { "gleam", "run", "--", "lsp" } from the repo
root_dir = vim.fn.getcwd(),
})
end,
})
VS Code (any generic LSP client extension): command glint, args ["lsp"], language id / file glob *.glint.
Zed (extension in editors/zed/ — see that README for full detail):
The extension is Gleam (editors/zed/src/zed_glint.gleam). Zed Install Dev
Extension only knows how to run cargo build --target wasm32-wasip2, so that
directory includes a small cargo build driver (build.rs + linker script)
that runs gleam export zed-extension and installs the Gleam component as the
crate’s .wasm. There is no separate Rust implementation of the guest.
# glint LSP
cd /home/nandi/code/glint && nix build
# wasm-capable gleam: https://tangled.org/nandi.uk/gleam (branch wasm)
export GLEAM=/home/nandi/code/gleam/target/debug/gleam
# build driver (same command Zed runs)
cd /home/nandi/code/glint/editors/zed
rustup target add wasm32-wasip2 # once
cargo build --release --target wasm32-wasip2
Preferred (flake, prebuilt Gleam guest):
nix build .#zed-extension
nix run .#install-zed-extension -- ~/glint-zed-dev
# Zed → Install Dev Extension → ~/glint-zed-dev
Or point Install Dev at editors/zed after nix develop (sets GLEAM).
Optional LSP path:
{
"lsp": {
"glint": {
"binary": {
"path": "/home/nandi/code/glint/result/bin/glint",
"arguments": ["lsp"]
}
}
}
}
Library#
import glint
import glint/value
pub fn example() {
let assert Ok(checked) = glint.load(source)
value.to_json(checked.config)
}
Design#
| Idea | In Glint |
|---|---|
| Named types first | type Config { Config(...) } |
| One root export | pub let config = ... |
| No null | Option(a) with None / Some |
| Variants over string enums | Dev / Prod |
| Labeled fields | host: "localhost" |
Layout#
src/glint.gleam CLI + library entry
src/glint/
token.gleam tokens
lexer.gleam lexer (spanned tokens)
position.gleam LSP-style positions / ranges
ast.gleam AST
parser.gleam parser
check.gleam typecheck + evaluate
value.gleam runtime values + printers
pipeline.gleam source → checked config
lsp.gleam language server entry
lsp/ JSON-RPC, protocol, handlers, diagnostics
src/glint_lsp_ffi.erl stdio FFI (Erlang)
examples/
hello.glint
app.glint