Editors
Neovim and Vim
Neovim has no JavaScript server of its own, but most configurations start one:
ts_ls or vtsls through nvim-lspconfig. It reads a
Flow file as TypeScript. uf's Neovim file starts uf lsp in a uf
project and keeps those servers off that project's buffers, while every other
project keeps them.
What you will be able to do: edit a uf project in Neovim with uf's diagnostics, hover, definitions, completion, quick fixes and formatting, and no TypeScript errors on Flow syntax.
What you need first: uf installed, a project with a
uf.config.js, and Neovim 0.8 or later.
1. Start uf in a uf project
uf editor install neovim writes uf.lua to ~/.config/nvim/lua/. It will not
replace a file of that name that uf did not write. Or copy editors/neovim/lua/uf.lua
to ~/.config/nvim/lua/uf.lua, then in init.lua:
require("uf").setup({
cmd = { "uf", "lsp" }, -- or { "./node_modules/.bin/uf", "lsp" }
format_on_save = true,
})
A javascript or javascriptreact buffer gets a client when a uf.config.js
is in its directory or above. The server is started in that directory, which is
where uf lsp reads the project's configuration. :UfRestart restarts it after
you edit uf.config.js.
2. Keep the TypeScript servers off uf projects
setup does this by default. Its exclude option lists the clients to keep
away from uf projects: ts_ls, tsserver, vtsls, denols and
typescript-tools, whichever you have. When one of them attaches to a buffer
in a uf project, uf.lua detaches it again and drops the diagnostics it
publishes for files there. It does this whatever started the client
(nvim-lspconfig, vim.lsp.enable, a plugin). Buffers outside a uf project are
untouched.
require("uf").setup({ exclude = { "ts_ls", "vtsls" } }) -- only these
require("uf").setup({ exclude = {} }) -- keep them all
On Neovim 0.11 and later you can instead stop ts_ls from starting in a uf
project at all. A root_dir function that never calls on_dir does not start
the client for that buffer:
vim.lsp.config("ts_ls", {
root_dir = function(bufnr, on_dir)
if vim.fs.root(bufnr, { "uf.config.js" }) then
return -- a uf project: uf serves it
end
on_dir(vim.fs.root(bufnr, { "tsconfig.json", "jsconfig.json", "package.json", ".git" }))
end,
})
This replaces nvim-lspconfig's own root_dir for ts_ls, including the part
that skips Deno projects. The markers are then yours to maintain.
Per project instead
To keep the configuration in the project, Neovim's exrc option reads a
.nvim.lua from the directory Neovim starts in, after you approve it once with
:trust. With vim.o.exrc = true in your own configuration, commit a
.nvim.lua that calls require("uf").setup(). uf editor setup neovim writes
it.
Vim
Vim has no LSP client of its own. uf's registration for
vim-lsp is
editors/vim/uf.vim.
uf editor install vim puts it in ~/.vim/plugin/. Otherwise, source it
after vim-lsp is loaded. It runs uf lsp --cwd <root> for a uf
project. vim-lsp chooses servers by file type, not by project, so uf.vim
cannot keep typescript-language-server off a uf project. If
vim-lsp-settings registers that server for you, its documented per-server
disabled option, set in the project's local vimrc, turns it off. That option
is not checked here.
Check that it worked
:checkhealth vim.lsp(or:LspInfo) listsuffor a Flow buffer and nots_ls.:lua vim.diagnostic.open_float()on a finding shows sourceuforflow.:lua vim.lsp.buf.format({ name = "uf" }), thenuf fmt --checkin a terminal: they agree when the server read the project'suf.config.js.
Checked against
uf.lua is run in headless Neovim by the Editors workflow, with a stand-in
server in place of uf lsp and ts_ls. The run checks that uf attaches in a
uf project and starts in its root, that ts_ls is detached there and its
diagnostics dropped, that nothing changes outside a uf project, and that
:UfRestart starts a new client. It has been run on Neovim 0.8, 0.11 and
0.12. The root_dir/on_dir contract and exrc were read from Neovim's
lsp.txt and options.txt. uf.vim is not run by CI.
Edit this pagedocs/app/guide/editors/neovim/$page.mdx