weir
On this page

Editor setup

Every editor talks to the same language server: weir lsp, which speaks LSP over stdio. It is a subcommand of the binary that runs your scripts, so the editor always understands exactly the version of weir you run. The setups below assume weir is on PATH.

In any editor with LSP support you get:

weir scripts often have no extension (they start with #!/usr/bin/env weir), so each setup below recognizes weir files both by the .weir extension and by the shebang line.

Neovim (0.11+)

-- filetype: .weir files, and extensionless scripts with a weir shebang
vim.filetype.add {
  extension = { weir = 'weir' },
  pattern = {
    ['.*'] = {
      function(_, bufnr)
        local first = (vim.api.nvim_buf_get_lines(bufnr, 0, 1, false)[1] or '')
        if first:match '^#!.*weir' then
          return 'weir'
        end
      end,
      { priority = -math.huge },
    },
  },
}

-- the server
vim.lsp.config('weir', {
  cmd = { 'weir', 'lsp' },
  filetypes = { 'weir' },
})
vim.lsp.enable 'weir'

-- comment + indent, matching `weir fmt`
vim.api.nvim_create_autocmd('FileType', {
  pattern = 'weir',
  callback = function()
    vim.bo.commentstring = '// %s'
    vim.bo.shiftwidth = 4
    vim.bo.expandtab = true
  end,
})

-- semantic tokens use weir's own token types; link them to see color
vim.api.nvim_set_hl(0, '@lsp.type.weirCommandHead', { link = 'Function' })
vim.api.nvim_set_hl(0, '@lsp.type.weirArgv', { link = 'String' })
vim.api.nvim_set_hl(0, '@lsp.type.weirSplice', { link = 'Special' })

On Neovim 0.10, or if you use nvim-lspconfig, add a custom server entry with the same cmd and filetypes; the filetype block stays the same.

The nvim_set_hl links at the end are what make the colors visible. weir’s semantic tokens use their own type names rather than the standard ones, so Neovim has no colors for them until you link them.

Tested with Neovim 0.11.3: the server attaches, and diagnostics, hover, colors, formatting (identical to weir fmt, whatever your tab size) and go to definition all work, as does recognizing .weir files and weir shebangs.

Helix

~/.config/helix/languages.toml:

[language-server.weir]
command = "weir"
args = ["lsp"]

[[language]]
name = "weir"
scope = "source.weir"
file-types = ["weir"]
shebangs = ["weir"]
comment-token = "//"
indent = { tab-width = 4, unit = "    " }
language-servers = ["weir"]

Helix colors code with tree-sitter, so for highlighting add the weir grammar (weir-shell/tree-sitter-weir) and build it:

# languages.toml, alongside the blocks above
[[grammar]]
name = "weir"
source = { git = "https://github.com/weir-shell/tree-sitter-weir" }

Then run hx --grammar fetch && hx --grammar build, and copy the grammar repo’s queries/highlights.scm to ~/.config/helix/runtime/queries/weir/highlights.scm. hx --health weir should now show the language server, the parser and the highlights all ✓.

Helix doesn’t support LSP semantic tokens, so the grammar is the only source of colors.

Tested with Helix 25.01.1. Diagnostics show as a gutter marker and a count in the status line, hover is space k, :format rewrites the buffer to weir fmt’s output, and gd goes to the definition. .weir files and weir shebangs are recognized. Keywords, strings, types, the names being bound, and the $/$@/! sigils each get their own color.

Emacs (eglot)

eglot attaches a server to a major mode, so Emacs needs a weir mode first. The repo ships a minimal one, editors/emacs/weir-mode.el. It sets the comment syntax, uses weir-mode for .weir files and weir shebangs (through interpreter-mode-alist), and tells eglot to run weir lsp.

(load "/path/to/weir/editors/emacs/weir-mode.el")
;; then, in a weir buffer:
;;   M-x eglot

Tested with Emacs 30.2: .weir files and #!/usr/bin/env weir scripts open in weir-mode, and M-x eglot connects to weir lsp with diagnostics, hover, completion, go to definition and formatting.

eglot doesn’t use semantic tokens, so commands, their arguments and $ splices aren’t colored. Tree-sitter highlighting for Emacs is planned. For now, expect the LSP features but not the colors.

VS Code

Install weir from the VS Code Marketplace, or from Open VSX for VSCodium, Cursor and similar editors. The extension runs the same weir lsp server and adds syntax highlighting, so there is nothing to set up. If weir isn’t on PATH, set weir.serverPath to the binary. Give it only the binary’s path: the extension runs <path> lsp itself.

Zed

Zed is set up with an extension rather than config: editors/zed/. It runs the same weir lsp server and adds tree-sitter highlighting. It isn’t in the Zed extension registry yet, so install it as a dev extension: Extensions → Install Dev Extension → pick the editors/zed/ directory. This needs a local Rust toolchain.

If an install attempt fails, it leaves a stale grammars/ clone in the extension’s work directory. Delete it before you try again.

Troubleshooting

Scope

The server reads the text your editor sends, plus the files those documents reach through import or #sig. A file that is open in the editor is read from its buffer, any other from disk. The server reads nothing else, and it never runs anything. When you jump to a definition in another file, it’s your editor that opens the file, not the server. SECURITY.md has the full statement.