Goose

Goose in other editors

The compiler is its own language server: goose lsp speaks the Language Server Protocol on stdin and stdout, so any editor with an LSP client can use it. VS Code has an extension that starts it for you. For Neovim, Helix and Emacs, the configuration below is all it takes.

Every snippet starts goose lsp with the compiler on PATH; where it is not, put the executable's full path in place of goose. The server finds the standard library the way goose check does (GOOSE_STDLIB, or the stdlib/ directory near the executable). For a compiler away from its checkout, add --stdlib and the directory to the command: goose lsp --stdlib /path/to/goose/stdlib.

Each open file is analyzed as a program of its own, with the files it imports. To have a module checked as part of the program that imports it (and the errors of that program shown in it), name the program's entry file in the client's initialization options, as an absolute path: { "entryFiles": ["/path/to/project/main.goose"] }. The snippets show where these options go.

The server's semantic tokens color names by what they resolve to (functions, types, fields, variants, parameters, variables), not keywords, strings or comments; the TextMate grammar is VS Code's alone.

Neovim

Neovim 0.11 or later, in init.lua:

vim.filetype.add({ extension = { goose = 'goose' } })
vim.lsp.config('goose', {
  cmd = { 'goose', 'lsp' },
  filetypes = { 'goose' },
  root_markers = { '.git' },
  -- init_options = { entryFiles = { '/path/to/project/main.goose' } },
})
vim.lsp.enable('goose')

On Neovim 0.10, start it from the filetype instead:

vim.filetype.add({ extension = { goose = 'goose' } })
vim.api.nvim_create_autocmd('FileType', {
  pattern = 'goose',
  callback = function(ev)
    vim.lsp.start({ name = 'goose', cmd = { 'goose', 'lsp' }, root_dir = vim.fs.root(ev.buf, { '.git' }) })
  end,
})

What it shows: diagnostics, hover (K), go to definition (CTRL-]), references (grr), rename (grn), document symbols (gO), signature help (CTRL-S in Insert mode), completion (CTRL-X CTRL-O, or as you type with vim.lsp.completion.enable) and semantic highlighting, by default; inlay hints with vim.lsp.inlay_hint.enable(), folding with foldmethod=expr and foldexpr=v:lua.vim.lsp.foldexpr(), and code lenses with vim.lsp.codelens.refresh() (on BufEnter and InsertLeave, say). The lenses above generic functions count their instantiations; to list them with vim.lsp.codelens.run(), give Neovim the command and tell the server it has it:

vim.lsp.commands['goose.showInstantiations'] = function(command)
  vim.ui.select(command.arguments[2], { prompt = 'Instantiations of ' .. command.arguments[1] }, function() end)
end
-- and in vim.lsp.config('goose', ...):
--   init_options = { commands = { 'goose.showInstantiations' } },

Helix

In languages.toml (in Helix's configuration directory, or .helix/ in the project):

[language-server.goose]
command = "goose"
args = ["lsp"]
# config = { entryFiles = ["/path/to/project/main.goose"] }

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

(config is what Helix sends as the initialization options.)

What it shows: diagnostics, hover (space k), go to definition (gd), references (gr), rename (space r), document and workspace symbols (space s, space S), signature help and completion as you type, and inlay hints with display-inlay-hints = true under [editor.lsp] in config.toml. Helix highlights with tree-sitter grammars, of which Goose has none, and has no semantic tokens, folding or code lenses, so files show uncolored.

Emacs

With Eglot (built in since Emacs 29), in init.el:

(define-derived-mode goose-mode prog-mode "Goose"
  (setq-local comment-start "// "))
(add-to-list 'auto-mode-alist '("\\.goose\\'" . goose-mode))
(with-eval-after-load 'eglot
  (add-to-list 'eglot-server-programs '(goose-mode "goose" "lsp")))
(add-hook 'goose-mode-hook #'eglot-ensure)

For entry files, the server program takes the options after the command: '(goose-mode "goose" "lsp" :initializationOptions (:entryFiles ["/path/to/project/main.goose"])).

What it shows: diagnostics through Flymake, hover and signature help in ElDoc, go to definition (M-.), references (M-?), rename (eglot-rename), document symbols in Imenu, workspace symbols (xref-find-apropos), completion (completion-at-point) and inlay hints; the newest Eglot, from GNU ELPA, highlights with semantic tokens too (eglot-semantic-tokens-mode). Eglot has no folding or code lenses.