Neovim-0.5版本集成了LSP,并且内置用lua来配置vim和编写vim插件,本来4月18号就该发布0.5版本了,已经过期7天了,还好可以使用nightly版本,
记录一下Nvim的配置过程,主要是LSP的集成,但是正式版本还没有发布,部分api和插件可能还有变化.
1. TODO
2. 问题
3. 学习
4. Reference
5. Commands
重启LSP server
1
|
:lua require('lspconfig').pyright.autostart()
|
检查是否启动
1
|
:lua print(vim.inspect(vim.lsp.buf_get_clients()))
|
6. LSP
nvm0.5的核心功能,通过lua扩展实现了LSP,Neovim核心团队实现的LSP插件
参考: nvm-lspconfig
安装完插件以后就可以使用了
1
|
require'lspconfig'.<server>.setup{<config>}
|
6.1. setup方法
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
|
lspconfig.SERVER.setup{config}
The `config` parameter has the same shape as that of
|vim.lsp.start_client()|, with these additions and changes:
{root_dir}
Required for some servers, optional for others.
Function of the form `function(filename, bufnr)`.
Called on new candidate buffers being attached-to.
Returns either a root_dir or nil.
If a root_dir is returned, then this file will also be attached. You
can optionally use {filetype} to help pre-filter by filetype.
If a root_dir is returned which is unique from any previously returned
root_dir, a new server will be spawned with that root_dir.
If nil is returned, the buffer is skipped.
See |lspconfig.util.search_ancestors()| and the functions which use it:
- |lspconfig.util.root_pattern(pattern1, pattern2...)| is a variadic function which
takes string patterns as arguments, and finds an ancestor
which contains one of the files matching the pattern.
Each pattern can be a specific filename, such as ".git", or a glob.
See `:help glob` for allowed patterns. This is equivalent to
coc.nvim's "rootPatterns"
- Related utilities for common tools:
- |lspconfig.util.find_git_root()|
- |lspconfig.util.find_node_modules_root()|
- |lspconfig.util.find_package_json_root()|
{name}
Defaults to the server's name.
{filetypes}
Set of filetypes to filter for consideration by {root_dir}.
May be empty.
Server may specify a default value.
{autostart}
Whether to automatically start a language server when a matching filetype is detected.
Defaults to true.
{settings}
Map with case-sensitive keys corresponding to `workspace/configuration`
event responses.
We also notify the server *once* on `initialize` with
`workspace/didChangeConfiguration`.
If you change the settings later on, you must emit the notification
with `client.workspace_did_change_configuration({settings})`
Example: `settings = { keyName = { subKey = 1 } }`
{on_attach}
`function(client, bufnr)` Runs the on_attach function from the client's
config if it was defined. Useful for doing buffer-local setup.
{on_new_config}
`function(new_config, new_root_dir)` will be executed after a new configuration has been
created as a result of {root_dir} returning a unique value. You can use this
as an opportunity to further modify the new_config or use it before it is
sent to |vim.lsp.start_client()|. If you set a custom `on_new_config`, ensure that
`new_config.cmd = cmd` is present within the function body.
|
6.2. 自定义配置
自己定义的一个lsp服务
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
local lspconfig = require'lspconfig'
local configs = require'lspconfig/configs'
-- Check if it's already defined for when reloading this file.
if not lspconfig.foo_lsp then
configs.foo_lsp = {
default_config = {
cmd = {'/home/ashkan/works/3rd/lua-language-server/run.sh'};
filetypes = {'lua'};
root_dir = function(fname)
return lspconfig.util.find_git_ancestor(fname) or vim.loop.os_homedir()
end;
settings = {};
};
}
end
lspconfig.foo_lsp.setup{}
|
6.3. 补全和键绑定
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
|
local nvim_lsp = require('lspconfig')
local on_attach = function(client, bufnr)
local function buf_set_keymap(...) vim.api.nvim_buf_set_keymap(bufnr, ...) end
local function buf_set_option(...) vim.api.nvim_buf_set_option(bufnr, ...) end
buf_set_option('omnifunc', 'v:lua.vim.lsp.omnifunc')
-- Mappings.
local opts = { noremap=true, silent=true }
buf_set_keymap('n', 'gD', '<Cmd>lua vim.lsp.buf.declaration()<CR>', opts)
buf_set_keymap('n', 'gd', '<Cmd>lua vim.lsp.buf.definition()<CR>', opts)
buf_set_keymap('n', 'K', '<Cmd>lua vim.lsp.buf.hover()<CR>', opts)
buf_set_keymap('n', 'gi', '<cmd>lua vim.lsp.buf.implementation()<CR>', opts)
buf_set_keymap('n', '<C-k>', '<cmd>lua vim.lsp.buf.signature_help()<CR>', opts)
buf_set_keymap('n', '<space>wa', '<cmd>lua vim.lsp.buf.add_workspace_folder()<CR>', opts)
buf_set_keymap('n', '<space>wr', '<cmd>lua vim.lsp.buf.remove_workspace_folder()<CR>', opts)
buf_set_keymap('n', '<space>wl', '<cmd>lua print(vim.inspect(vim.lsp.buf.list_workspace_folders()))<CR>', opts)
buf_set_keymap('n', '<space>D', '<cmd>lua vim.lsp.buf.type_definition()<CR>', opts)
buf_set_keymap('n', '<space>rn', '<cmd>lua vim.lsp.buf.rename()<CR>', opts)
buf_set_keymap('n', 'gr', '<cmd>lua vim.lsp.buf.references()<CR>', opts)
buf_set_keymap('n', '<space>e', '<cmd>lua vim.lsp.diagnostic.show_line_diagnostics()<CR>', opts)
buf_set_keymap('n', '[d', '<cmd>lua vim.lsp.diagnostic.goto_prev()<CR>', opts)
buf_set_keymap('n', ']d', '<cmd>lua vim.lsp.diagnostic.goto_next()<CR>', opts)
buf_set_keymap('n', '<space>q', '<cmd>lua vim.lsp.diagnostic.set_loclist()<CR>', opts)
-- Set some keybinds conditional on server capabilities
if client.resolved_capabilities.document_formatting then
buf_set_keymap("n", "<space>f", "<cmd>lua vim.lsp.buf.formatting()<CR>", opts)
elseif client.resolved_capabilities.document_range_formatting then
buf_set_keymap("n", "<space>f", "<cmd>lua vim.lsp.buf.range_formatting()<CR>", opts)
end
-- Set autocommands conditional on server_capabilities
if client.resolved_capabilities.document_highlight then
vim.api.nvim_exec([[
hi LspReferenceRead cterm=bold ctermbg=red guibg=LightYellow
hi LspReferenceText cterm=bold ctermbg=red guibg=LightYellow
hi LspReferenceWrite cterm=bold ctermbg=red guibg=LightYellow
augroup lsp_document_highlight
autocmd! * <buffer>
autocmd CursorHold <buffer> lua vim.lsp.buf.document_highlight()
autocmd CursorMoved <buffer> lua vim.lsp.buf.clear_references()
augroup END
]], false)
end
end
-- Use a loop to conveniently both setup defined servers
-- and map buffer local keybindings when the language server attaches
local servers = { "pyright", "rust_analyzer", "tsserver" }
for _, lsp in ipairs(servers) do
nvim_lsp[lsp].setup { on_attach = on_attach }
end
|
7. 语言配置
7.1. bash
1
|
npm i -g bash-language-server
|
7.2. Lua
1
2
3
4
5
6
7
8
9
10
11
|
git clone https://hub.fastgit.org/sumneko/lua-language-server
# 在vim里替换github的地址
# 执行下面的替换命令
# :%s/github\.com/hub\.fastgit\.org/g
# 然后把子项目拉下来
git submodule update --init --recursive
# 编译关联项目
cd 3rd/luamake
ninja -f ninja/linux.ninja
cd ../..
./3rd/luamake/luamake rebuild
|
配置
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
|
-- ###########################
-- Lua LSP
-- ###########################
-- set the path to the sumneko installation; if you previously installed via the now deprecated :LspInstall, use
local sumneko_root_path = '/home/coco/softs/lua-language-server'
local sumneko_binary = sumneko_root_path.."/bin/"..system_name.."/lua-language-server"
nvim_lsp.sumneko_lua.setup {
cmd = {sumneko_binary, "-E", sumneko_root_path .. "/main.lua"};
settings = {
Lua = {
runtime = {
-- Tell the language server which version of Lua you're using (most likely LuaJIT in the case of Neovim)
version = 'LuaJIT',
-- Setup your lua path
path = vim.split(package.path, ';'),
},
diagnostics = {
-- Get the language server to recognize the `vim` global
globals = {'vim'},
},
workspace = {
-- Make the server aware of Neovim runtime files
library = {
[vim.fn.expand('$VIMRUNTIME/lua')] = true,
[vim.fn.expand('$VIMRUNTIME/lua/vim/lsp')] = true,
},
},
-- Do not send telemetry data containing a randomized but unique identifier
telemetry = {
enable = false,
},
},
},
on_attach=on_attach
}
|
7.3. Golang
1
|
go get golang.org/x/tools/gopls@latest
|
7.4. Vim script
1
|
npm install -g vim-language-server
|
7.5. json
1
|
npm install -g vscode-json-languageserver
|
7.6. python
LSP settings
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
|
-- vim:set ft=lua et sts=4 ts=4 sw=4 tw=78:
local on_attach = function(client, bufnr)
require('completion').on_attach()
local function buf_set_keymap(...) vim.api.nvim_buf_set_keymap(bufnr, ...) end
local function buf_set_option(...) vim.api.nvim_buf_set_option(bufnr, ...) end
buf_set_option('omnifunc', 'v:lua.vim.lsp.omnifunc')
-- Mappings.
local opts = { noremap=true, silent=true }
buf_set_keymap('n', 'gD', '<Cmd>lua vim.lsp.buf.declaration()<CR>', opts)
buf_set_keymap('n', 'gd', '<Cmd>lua vim.lsp.buf.definition()<CR>', opts)
buf_set_keymap('n', 'K', '<Cmd>lua vim.lsp.buf.hover()<CR>', opts)
buf_set_keymap('n', 'gi', '<cmd>lua vim.lsp.buf.implementation()<CR>', opts)
buf_set_keymap('n', '<C-k>', '<cmd>lua vim.lsp.buf.signature_help()<CR>', opts)
buf_set_keymap('n', '<space>wa', '<cmd>lua vim.lsp.buf.add_workspace_folder()<CR>', opts)
buf_set_keymap('n', '<space>wr', '<cmd>lua vim.lsp.buf.remove_workspace_folder()<CR>', opts)
buf_set_keymap('n', '<space>wl', '<cmd>lua print(vim.inspect(vim.lsp.buf.list_workspace_folders()))<CR>', opts)
buf_set_keymap('n', '<space>D', '<cmd>lua vim.lsp.buf.type_definition()<CR>', opts)
buf_set_keymap('n', '<space>rn', '<cmd>lua vim.lsp.buf.rename()<CR>', opts)
buf_set_keymap('n', 'gr', '<cmd>lua vim.lsp.buf.references()<CR>', opts)
buf_set_keymap('n', '<space>e', '<cmd>lua vim.lsp.diagnostic.show_line_diagnostics()<CR>', opts)
buf_set_keymap('n', '[d', '<cmd>lua vim.lsp.diagnostic.goto_prev()<CR>', opts)
buf_set_keymap('n', ']d', '<cmd>lua vim.lsp.diagnostic.goto_next()<CR>', opts)
buf_set_keymap('n', '<space>q', '<cmd>lua vim.lsp.diagnostic.set_loclist()<CR>', opts)
-- Set some keybinds conditional on server capabilities
if client.resolved_capabilities.document_formatting then
buf_set_keymap("n", "<space>f", "<cmd>lua vim.lsp.buf.formatting()<CR>", opts)
elseif client.resolved_capabilities.document_range_formatting then
buf_set_keymap("n", "<space>f", "<cmd>lua vim.lsp.buf.range_formatting()<CR>", opts)
end
-- Set autocommands conditional on server_capabilities
if client.resolved_capabilities.document_highlight then
vim.api.nvim_exec([[
hi LspReferenceRead cterm=bold ctermbg=red guibg=LightYellow
hi LspReferenceText cterm=bold ctermbg=red guibg=LightYellow
hi LspReferenceWrite cterm=bold ctermbg=red guibg=LightYellow
augroup lsp_document_highlight
autocmd! * <buffer>
autocmd CursorHold <buffer> lua vim.lsp.buf.document_highlight()
autocmd CursorMoved <buffer> lua vim.lsp.buf.clear_references()
augroup END
]], false)
end
end
local nvim_lsp = require('lspconfig')
local util = require 'lspconfig/util'
nvim_lsp.pyright.setup{
-- on_attach=require'completion'.on_attach
on_attach=on_attach
}
|
最重要的部分,和pyenv整合,可以识别项目的虚拟环境,在项目里添加pyrightconfig.json
1
2
3
4
|
{
"venvPath": "/home/coco/.pyenv/versions/3.9.2/envs",
"venv": "daocidi"
}
|
7.7. javascript
7.7.1. Node js设置(tsserver)
1
|
npm install -g typescript typescript-language-server
|
7.7.2. Deno js设置(denols)
Install denojs
1
|
curl -fsSL https://deno.land/x/install/install.sh | sh
|
修改环境变量
1
2
3
4
5
|
# ======================================
# denojs
# ======================================
export DENO_INSTALL=$HOME/.deno
export PATH="$DENO_INSTALL/bin:$PATH"
|
8. 相关插件
8.1. ctag安装
1
2
|
git clone https://hub.fastgit.org/universal-ctags/ctags.git --depth=1
|
8.2. packer.nvim
https://github.com/wbthomason/packer.nvim
新的neovim包管理lua实现
8.3. tree-sitter
https://github.com/tree-sitter/tree-sitter
用来解析语法的,为了更好的语法着色?
8.4. telescope.nvim
https://github.com/nvim-telescope/telescope.nvim
一个fuzzy查询的工具, 支持文件,git,lsp和treesitter
8.5. nvim-tree.lua
https://github.com/kyazdani42/nvim-tree.lua
文件导航,lua的一个实现
-
move around like in any vim buffer
-
<CR>
or o
on ..
will cd in the above directory
-
<C-]>
will cd in the directory under the cursor
-
<BS>
will close current opened directory or parent
-
type a
to add a file. Adding a directory requires leaving a leading /
at the end of the path.
you can add multiple directories by doing foo/bar/baz/f and it will add foo bar and baz directories and f as a file
-
type r
to rename a file
-
type <C-r>
to rename a file and omit the filename on input
-
type x
to add/remove file/directory to cut clipboard
-
type c
to add/remove file/directory to copy clipboard
-
type p
to paste from clipboard. Cut clipboard has precedence over copy (will prompt for confirmation)
-
type d
to delete a file (will prompt for confirmation)
-
type ]c
to go to next git item
-
type [c
to go to prev git item
-
type ‘-’ to naviate up to the parent directory of the current file/directory
-
if the file is a directory, <CR>
will open the directory otherwise it will open the file in the buffer near the tree
-
if the file is a symlink, <CR>
will follow the symlink (if the target is a file)
-
<C-v>
will open the file in a vertical split
-
<C-x>
will open the file in a horizontal split
-
<C-t>
will open the file in a new tab
-
<Tab>
will open the file as a preview (keeps the cursor in the tree)
-
I
will toggle visibility of folders hidden via |g:nvim_tree_ignore|
-
H
will toggle visibility of dotfiles (files/folders starting with a .
)
-
R
will refresh the tree
-
Double left click acts like <CR>
-
Double right click acts like <C-]>
8.6. defx
https://github.com/Shougo/defx.nvim
文件导航
8.7. completion-nvim
https://github.com/nvim-lua/completion-nvim
补全插件,旨在提供更好的补全体验,只支持neovim0.5的内置LSP,不支持其他LSP插件
8.8. nvim-compe
https://github.com/hrsh7th/nvim-compe
另一个补全插件
8.9. vim-which-key
https://github.com/liuchengxu/vim-which-key
8.10. hop
https://github.com/phaazon/hop.nvim
类似easymotion的一个移动增强
8.11. vim-floaterm
https://github.com/voldikss/vim-floaterm
浮动的终端窗口插件
8.12. lspsaga
https://github.com/glepnir/lspsaga.nvim
lsp插件, 将lspconfig里的命令集中进行管理,提供统一的接口
8.13. dashboard-nvim
https://github.com/glepnir/dashboard-nvim
启动界面
8.14. codi.vim
https://github.com/metakirby5/codi.vim
一个scratchpad插件,支持大部分主流语言
8.15. galaxyline.nvim
https://github.com/glepnir/galaxyline.nvim
一个新的nvim的powerline, 文档比较少,定制稍微麻烦点
8.16. lightline.vim
https://github.com/itchyny/lightline.vim
可自定义的statusline,比较少的依赖,定制比较简单
8.17. barbar
https://github.com/romgrk/barbar.nvim
tab栏增强插件
8.18. nvim-bufferline.lua
https://github.com/akinsho/nvim-bufferline.lua
8.19. vim-clap
liuchengxu/vim-clap: Modern performant generic finder and dispatcher for Vim and NeoVim (github.com)
一个fuzzy查询
8.20. vim-signify
mhinz/vim-signify: Show a diff using Vim its sign column. (github.com)
在状态栏显示文件的改动
8.21. vim-easy-align
https://github.com/junegunn/vim-easy-align
自动对齐插件
8.22. nvim-web-devicons
https://github.com/kyazdani42/nvim-web-devicons
vim-devicons的lua实现
8.23. limelight.vim
https://github.com/junegunn/limelight.vim
集中注意力写作, 高亮正在编辑的段落, 配合goyo使用
8.24. goyo.vim
https://github.com/junegunn/goyo.vim
zen模式写作,排除干扰,配合limelight使用
https://github.com/terrortylor/nvim-comment
lua实现的注释插件
8.26. vim-bookmarks
https://github.com/MattesGroeger/vim-bookmarks
书签插件,可以定制icon
8.27. gitsigns.nvim
https://github.com/lewis6991/gitsigns.nvim
git导航和视图工具
8.28. git-blame.nvim
https://github.com/f-person/git-blame.nvim
lua版的git blame工具
8.29. plenary.nvim
https://github.com/nvim-lua/plenary.nvim
lua的一些包装,写插件的时候有用
https://github.com/mhartington/formatter.nvim
格式化插件
1
|
npm i -g prettier lua-fmt
|
8.31. lspkind-nvim
https://github.com/onsails/lspkind-nvim
美化lsp提示,增加图标
8.32. nvim-lightbulb
https://github.com/kosayoda/nvim-lightbulb
模仿vscode的交互式提示信息,比如需要import的时候,选择性操作
8.33. indent-blankline.nvim
https://github.com/lukas-reineke/indent-blankline.nvim
给缩进加上竖线
8.34. nvim-ts-rainbow
https://github.com/p00f/nvim-ts-rainbow
给闭合标签加上彩色,方便识别
9. 主题
9.1. oceanic-material
glepnir/oceanic-material: Oceanic Material Colorscheme on Vim/NeoVim (github.com)
9.2. gruvbuddy
tjdevries/gruvbuddy.nvim: Gruvbox colors using https://github.com/tjdevries/colorbuddy.vim
installation
1
2
3
4
5
|
Plug 'tjdevries/colorbuddy.vim'
Plug 'tjdevries/gruvbuddy.nvim'
" And then somewhere in your vimrc, to set the colorscheme
lua require('colorbuddy').colorscheme('gruvbuddy')
|
9.3. zephyr-nvim
glepnir/zephyr-nvim: A dark neovim colorscheme written in lua (github.com)