Skip to content
LogoLogo

Neovim

Neovim 0.10 or later runs vibelang --lsp --stdio with its built-in LSP client through one Lua module. .vibe files get the vibe filetype, TypeScript highlighting, and the project's compiler as their language server: node_modules/.bin/vibelang, else vibelang on PATH.

1. Check Neovim

Run nvim --version. The first line is NVIM v0.10.0 or later.

2. Add the module

Save this file as ~/.config/nvim/lua/vibelang.lua:

-- VibeLang for Neovim 0.10 or later, with the built-in LSP client.
--
-- Copy this file to ~/.config/nvim/lua/vibelang.lua and add
--
--   require("vibelang").setup()
--
-- to init.lua. .vibe files then get the vibe filetype, TypeScript
-- highlighting, and `vibelang --lsp --stdio` as their language server: the
-- project's node_modules/.bin/vibelang, else vibelang on PATH.
--
-- setup({ typescript = true }) also runs vibelang for .ts and .js files. Turn off
-- your other TypeScript server (ts_ls, vtsls) in those projects first, or
-- both report every .ts file.
local M = {}
 
local typescript_filetypes = { "typescript", "typescriptreact", "javascript", "javascriptreact" }
 
-- esc_command returns the vibelang that serves a project rooted at root.
local function esc_command(root)
  if root then
    local local_esc = vim.fs.joinpath(root, "node_modules", ".bin", "vibelang")
    if vim.fn.executable(local_esc) == 1 then
      return local_esc
    end
  end
  return "vibelang"
end
 
function M.setup(opts)
  opts = opts or {}
  vim.filetype.add({ extension = { vibe = "vibe" } })
  vim.treesitter.language.register("typescript", "vibe")
 
  local filetypes = { "vibe" }
  if opts.typescript then
    vim.list_extend(filetypes, typescript_filetypes)
  end
  vim.api.nvim_create_autocmd("FileType", {
    group = vim.api.nvim_create_augroup("vibelang", { clear = true }),
    pattern = filetypes,
    callback = function(args)
      if vim.bo[args.buf].filetype == "vibe" and not pcall(vim.treesitter.start, args.buf, "typescript") then
        -- No tree-sitter parser for TypeScript: use Vim's TypeScript syntax.
        vim.bo[args.buf].syntax = "typescript"
      end
      local root = vim.fs.root(args.buf, { "tsconfig.json", "package.json", ".git" })
      vim.lsp.start({
        name = "vibelang",
        cmd = { opts.cmd or esc_command(root), "--lsp", "--stdio" },
        root_dir = root,
      }, { bufnr = args.buf })
    end,
  })
end
 
return M

Add this line to ~/.config/nvim/init.lua, unless it is there already:

require("vibelang").setup()

setup({ typescript = true }) also attaches the server to .ts and .js files, so a .ts file that imports a .vibe module resolves it. Turn off the other TypeScript server, such as ts_ls or vtsls, for those projects first, or both report every .ts file. setup({ cmd = "/path/to/vibelang" }) names another compiler.

3. Check the filetype and the server

nvim --headless "+lua io.write((vim.filetype.match({ filename = 'main.vibe' })))" +qa

The output is vibe. Then, from the project directory, open one of its .vibe files, here src/main.vibe:

nvim --headless src/main.vibe "+lua vim.wait(5000, function() return #vim.lsp.get_clients({ name = 'vibelang' }) > 0 end)" "+lua io.write(#vim.lsp.get_clients({ name = 'vibelang' }) .. ' vibelang client')" +qa

The output is 1 vibelang client. An error that the language server failed to spawn means Neovim found no vibelang: install the project's dependencies.