Compare commits

...

66 Commits

Author SHA1 Message Date
ray-x
cd98ca2c5b update floating width 2022-09-20 17:08:56 +10:00
ray-x
451d761f76 features side panel for symbol reference 2022-09-16 21:21:28 +10:00
sp4ke
8278f71878
make sure merge luadev config from user (#229)
Co-authored-by: spike <spike@w530>
2022-09-12 11:13:11 +10:00
ray-x
443fd4d585 issue #228 codelens sign missing 2022-09-08 00:43:24 +10:00
ray-x
10fd76d6d0 default severity 2022-09-07 17:01:01 +10:00
ray-x
8d00282020 volar and diangnostic severity level check 2022-09-07 16:55:59 +10:00
ray-x
9afcd37854 issue #227 2022-09-06 07:55:30 +10:00
ray-x
c70d032b08 mason setup 2022-09-04 23:25:46 +10:00
ray-x
fb6d19ddf4 issue #226 add example for mason setup 2022-09-04 15:54:28 +10:00
ray-x
af7fc7d649 some updates for mason 2022-09-04 14:34:46 +10:00
ray-x
d8f19f6fc1 range_code_action deprecated in neovim 0.8 2022-09-02 23:49:01 +10:00
ray-x
df7f4d7229 better format ts_context text 2022-09-01 09:19:37 +10:00
ray-x
fb87a0b1b7 long line improvement 2022-09-01 04:32:14 +10:00
ray-x
927c464b70 optimize for go and ts_contex 2022-08-29 18:20:27 +10:00
ray-x
e9a40aca40 diagnostic: show line diagnostic: offset the floating windows to first error pos 2022-08-29 14:28:01 +10:00
ray-x
edee3e39c6 merge changes for treesitter symbole context 2022-08-27 11:49:08 +10:00
sp4ke
a7886fc055
Fix keymap buffer (#223)
* apply key mapping to selected buffer only

* <help> filetype should not be handled by navigator

Co-authored-by: spike <spike@w530>
2022-08-25 08:59:00 +10:00
yyk
de018d9ae3
Fix invalid buffer in defer fn. (#221) 2022-08-24 03:40:30 +10:00
ray-x
ef0cee5bbd unit tests 2022-08-24 03:37:57 +10:00
ray-x
ab2e383b20 unit tests 2022-08-24 03:34:37 +10:00
ray-x
1b262556c0 reuse telecsope color scheme 2022-08-21 19:58:54 +10:00
rayx
b4ff1c43b9
Update codelens.lua 2022-08-09 03:40:23 -07:00
ray-x
ebd88f5d09 re-order code action so null-ls is not the first to see 2022-08-09 15:55:05 +10:00
ray-x
28d245510f using neovim 0.7 API 2022-08-05 19:48:27 +10:00
ray-x
213b30950e the missing options for treesitter folding 2022-08-04 19:24:05 +10:00
ray-x
f05d2ec142 lint, expand tab to space for treesitter folding 2022-08-04 19:17:00 +10:00
ray-x
9f151cf718 definition preview, show more contents and allow scroll 2022-08-04 11:07:16 +10:00
ray-x
b131251ad8 send floating view result to quickfix; de-duplicate references 2022-08-01 22:32:15 +10:00
ray-x
8978bdb1e3 issue #219 missing end 2022-08-01 08:45:14 +10:00
ray-x
ae251289b3 issue #218 range format operator 2022-08-01 03:09:43 +10:00
ray-x
a9c223cc22 de-duplicate 2022-07-31 23:17:03 +10:00
ray-x
0ab4b02ff7 update on_attach 2022-07-31 15:49:26 +10:00
ray-x
6c0e286170 update readme for on_attach 2022-07-31 15:49:00 +10:00
ray-x
f24a337f5d switch between buffer type 2022-07-31 15:41:08 +10:00
ray-x
3d87ed3b87 issue #217 README missing symbols 2022-07-31 02:01:51 +10:00
ray-x
5713f79265 clear autocmd #191 2022-07-29 19:02:43 +10:00
ray-x
01ef2ce1a1 typo highlight 2022-07-29 17:16:07 +10:00
ray-x
547f2bc15d doc highlight config options update 2022-07-29 16:43:00 +10:00
ray-x
dc0b8504bb allow document_highlight to be configurable, update REWADME 2022-07-29 09:59:02 +10:00
ray-x
486085070d #191 cleanup 2022-07-29 09:21:33 +10:00
ray-x
bc356d555f pipeline neovim 0.7.0 2022-07-28 10:10:11 +10:00
ray-x
5b5a946d73 add neovim 0.7.1 to pipeline 2022-07-28 10:04:38 +10:00
ray-x
fca2fa5aaa some version of neovim does not support underline etc 2022-07-28 09:38:27 +10:00
rayx
49dbca889d
Update clients.lua 2022-07-27 06:43:42 -07:00
ray-x
861ae038dd underdouble is not supported by 0.7.x 2022-07-27 18:21:11 +10:00
ray-x
814b712e91 no longer nvim 0.6.x 2022-07-27 18:19:42 +10:00
ray-x
dcc40278c5 use create_autocmd API; split clients.lua into 3 files 2022-07-27 18:17:07 +10:00
ray-x
6736293182 split sumneko 2022-07-27 17:25:02 +10:00
ray-x
10ef469286 issue #214 lsp_installer loading 2022-07-27 17:20:07 +10:00
ray-x
4775d43218 .gitignore 2022-07-27 15:59:01 +10:00
ray-x
89dd02c927 using neovim 0.7.0 api for autocmd 2022-07-27 14:36:29 +10:00
ray-x
bbdf86a66e refactor highlight setup. it is for #216 and also using API from neovim 0.7 now 2022-07-27 12:17:02 +10:00
ray-x
ed47d386e6 chore selene setup 2022-07-27 02:37:26 +10:00
ray-x
480824d3f3 lint does not support lua5.1 JIT ... 2022-07-27 02:34:08 +10:00
ray-x
c3ef990390 lint 2022-07-27 00:24:40 +10:00
ray-x
de5c88c766 lint pipeline 2022-07-26 20:35:09 +10:00
ray-x
348ab9dced mason support #215 2022-07-26 14:29:38 +10:00
ray-x
967fd32bae prevent autocmd being call in a loop 2022-07-20 00:51:16 +10:00
ray-x
4aef8dc5f2 dartls installer not working #212 2022-07-19 12:37:17 +10:00
ray-x
0de6c290cf issue #211 tsserver not working 2022-07-19 07:58:55 +10:00
ray-x
9aad2978dc resend filetype if lsp not ready 2022-07-18 21:43:55 +10:00
ray-x
49c3e5cd4d prevent compare number to bool. As the name for html LSP is html 2022-07-18 08:18:19 +10:00
ray-x
47545e03c0 default border hl to FloatBorder 2022-07-18 07:53:13 +10:00
ray-x
e5d16e4488 renaming highight group from GHxxx to Guihuaxxx 2022-07-18 07:45:23 +10:00
ray-x
3d9a9582dd bugfix #206 diagnostic failure 2022-07-17 09:33:41 +10:00
rayx
05dfed9ed9
issue #171 multiple lsp server started (#205)
* issue #171 multiple lsp server started

* neovim 0.6.1
2022-07-17 09:26:26 +10:00
36 changed files with 1232 additions and 720 deletions

View File

@ -15,11 +15,11 @@ jobs:
manager: sudo snap
packages: go
- os: ubuntu-22.04
url: https://github.com/neovim/neovim/releases/download/v0.7.2/nvim-linux64.tar.gz
url: https://github.com/neovim/neovim/releases/download/v0.7.0/nvim-linux64.tar.gz
manager: sudo snap
packages: go
- os: ubuntu-22.04
url: https://github.com/neovim/neovim/releases/download/v0.6.1/nvim-linux64.tar.gz
url: https://github.com/neovim/neovim/releases/download/v0.7.2/nvim-linux64.tar.gz
manager: sudo snap
packages: go
steps:

2
.gitignore vendored
View File

@ -1,3 +1,3 @@
selene.toml
lua/navigator.lua.bak
tests/fixtures/tests

134
README.md
View File

@ -257,12 +257,14 @@ require'navigator'.setup({
-- end,
-- The attach code will apply to all LSP clients
ts_fold = false, -- modified version of treesitter folding
default_mapping = true, -- set to false if you will remap every key or if you using old version of nvim-
keymaps = {{key = "gK", func = vim.lsp.declaration, desc = 'declaration'}}, -- a list of key maps
-- this kepmap gK will override "gD" mapping function declaration() in default kepmap
-- please check mapping.lua for all keymaps
treesitter_analysis = true, -- treesitter variable context
treesitter_analysis_max_num = 100, -- how many items to run treesitter analysis
treesitter_analysis_condense = true, -- condense form for treesitter analysis
-- this value prevent slow in large projects, e.g. found 100000 reference in a project
transparency = 50, -- 0 ~ 100 blur the main window, 100: fully transparent, 0: opaque, set to nil or 100 to disable it
@ -278,18 +280,23 @@ require'navigator'.setup({
-- refer to lua/navigator.lua for more icons setups
},
lsp_installer = false, -- set to true if you would like use the lsp installed by williamboman/nvim-lsp-installer
mason = false, -- set to true if you would like use the lsp installed by williamboman/mason
lsp = {
enable = true, -- skip lsp setup if disabled make sure add require('navigator.lspclient.mapping').setup() in you
-- own on_attach
code_action = {enable = true, sign = true, sign_priority = 40, virtual_text = true},
code_lens_action = {enable = true, sign = true, sign_priority = 40, virtual_text = true},
document_highlight = true, -- LSP reference highlight,
-- it might already supported by you setup, e.g. LunarVim
format_on_save = true, -- set to false to disable lsp code format on save (if you are using prettier/efm/formater etc)
format_options = {async=false}, -- async: disable by default, the option used in vim.lsp.buf.format({async={true|false}, name = 'xxx'})
disable_format_cap = {"sqls", "sumneko_lua", "gopls"}, -- a list of lsp disable format capacity (e.g. if you using efm or vim-codeformat etc), empty {} by default
-- If you using null-ls and want null-ls format your code
-- you should disable all other lsp and allow only null-ls.
disable_lsp = {'pylsd', 'sqlls'}, -- a list of lsp server disabled for your project, e.g. denols and tsserver you may
-- only want to enable one lsp server
--want to enable one lsp server at a time
-- to disable all default config and use your own lsp setup set
-- disable_lsp = 'all'
-- disable_lsp = 'all' and you may need to hook mapping.setup() in your on_attach
-- Default {}
diagnostic = {
underline = true,
@ -309,9 +316,9 @@ require'navigator'.setup({
},
ctags ={
cmd = 'ctags',
tagfile = 'tags'
options = '-R --exclude=.git --exclude=node_modules --exclude=test --exclude=vendor --excmd=number'
}
tagfile = 'tags',
options = '-R --exclude=.git --exclude=node_modules --exclude=test --exclude=vendor --excmd=number',
},
gopls = { -- gopls setting
on_attach = function(client, bufnr) -- on_attach for gopls
-- your special on attach here
@ -323,6 +330,18 @@ require'navigator'.setup({
gopls = {gofumpt = false} -- disable gofumpt etc,
}
},
-- the lsp setup can be a function, .e.g
gopls = function()
local go = pcall(require, "go")
if go then
local cfg = require("go.lsp").config()
cfg.on_attach = function(client)
client.server_capabilities.documentFormattingProvider = false -- efm/null-ls
end
return cfg
end
end,
sumneko_lua = {
sumneko_root_path = vim.fn.expand("$HOME") .. "/github/sumneko/lua-language-server",
sumneko_binary = vim.fn.expand("$HOME") .. "/github/sumneko/lua-language-server/bin/macOS/lua-language-server",
@ -430,7 +449,7 @@ In `playground` folder, there is a `init.lua` and source code for you to play wi
| n | gd | definition |
| n | g0 | document symbol |
| n | \<C-]\> | go to definition (if multiple show listview) |
| n | gp | definition preview (Go to Preview) |
| n | gp | definition preview (show Preview) |
| n | \<C-LeftMouse\> | definition |
| n | g\<LeftMouse\> | implementation |
| n | \<Leader>gt | treesitter document symbol |
@ -471,20 +490,21 @@ In `playground` folder, there is a `init.lua` and source code for you to play wi
| n | \<Enter\> | open preview file in nvim/Apply action |
| n | \<ESC\> | close listview of floating window |
| i/n | \<C-e\> | close listview of floating window |
| n | \<C-q\> | close listview and send results to quickfix |
| i/n | \<C-b\> | previous page in listview |
| i/n | \<C-f\> | next page in listview |
| i/n | \<C-s\> | save the modification to preview window to file |
### Colors/Highlight:
You can override default highlight GHListDark (listview) and GHTextViewDark (code view) and GHListHl (select item)
You can override default highlight GuihuaListDark (listview) and GuihuaTextViewDark (code view) and GuihuaListHl (select item)
e.g.
```vim
hi default GHTextViewDark guifg=#e0d8f4 guibg=#332e55
hi default GHListDark guifg=#e0d8f4 guibg=#103234
hi default GHListHl guifg=#e0d8f4 guibg=#404254
hi default GuihuaTextViewDark guifg=#e0d8f4 guibg=#332e55
hi default GuihuaListDark guifg=#e0d8f4 guibg=#103234
hi default GuihuaListHl guifg=#e0d8f4 guibg=#404254
```
There are other Lsp highlight been used in this plugin, e.g LspReferenceRead/Text/Write are used for document highlight,
@ -502,18 +522,18 @@ The plugin can be loaded lazily (packer `opt = true` ), And it will check if opt
The terminal will need to be able to output nerdfont and emoji correctly. I am using Kitty with nerdfont (Victor Mono).
## Integrat with lsp_installer (williamboman/nvim-lsp-installer)
## Integrat with mason (williamboman/mason.nvim) or lsp_installer (williamboman/nvim-lsp-installer, deprecated)
If you are using lsp_installer and would like to use the lsp servers installed by lsp_installer. Please set
If you are using mason or lsp_installer and would like to use the lsp servers installed by lsp_installer. Please set
```lua
lsp_installer = true
lsp_installer = true --lsp_installer users, deprecated
mason = true -- mason user
```
In the config. Also please setup the lsp server from installer setup with `server:setup{opts}`
example:
lsp-installer example:
```lua
use({
'williamboman/nvim-lsp-installer',
@ -526,14 +546,79 @@ example:
'ray-x/navigator.lua',
config = function()
require('navigator').setup({
debug = true,
lsp_installer = true,
keymaps = { { key = 'gR', func = "require('navigator.reference').async_ref()" } },
})
end,
})
```
for mason
```lua
use("williamboman/mason.nvim")
use({
"williamboman/mason-lspconfig.nvim",
config = function()
require("mason").setup()
require("mason-lspconfig").setup({})
end,
})
use({
"ray-x/navigator.lua",
requires = {
{ "ray-x/guihua.lua", run = "cd lua/fzy && make" },
{ "neovim/nvim-lspconfig" },
{ "nvim-treesitter/nvim-treesitter" },
},
config = function()
require("navigator").setup({
mason = true,
})
end,
})
```
Another way to setup mason is disable navigator lsp setup and using mason setup handlers, pylsp for example
```lua
use("williamboman/mason.nvim")
use({
"williamboman/mason-lspconfig.nvim",
config = function()
require("mason").setup()
require("mason-lspconfig").setup_handlers({
["pylsp"] = function()
require("lspconfig").pylsp.setup({
on_attach = function(client, bufnr)
require("navigator.lspclient.mapping").setup({ client = client, bufnr = bufnr }) -- setup navigator keymaps here,
require("navigator.dochighlight").documentHighlight(bufnr)
require("navigator.codeAction").code_action_prompt(bufnr)
end,
})
end,
})
require("mason-lspconfig").setup({})
end,
})
use({
"navigator.lua",
requires = {
{ "ray-x/guihua.lua", run = "cd lua/fzy && make" },
{ "nvim-lspconfig" },
{ "nvim-treesitter/nvim-treesitter" },
},
config = function()
require("navigator").setup({
mason = true,
lsp = { disable_lsp = { "pylsp" } }, -- disable pylsp setup from navigator
})
end,
})
```
Please refer to [lsp_installer_config](https://github.com/ray-x/navigator.lua/blob/master/playground/init_lsp_installer.lua)
for more info
@ -549,7 +634,9 @@ To start LSP installed by lsp_installer, please use following setups
require'navigator'.setup({
-- lsp_installer = false -- default value is false
lsp = {
tsserver = { cmd = {'your tsserver installed by lsp_installer'} }
tsserver = { cmd = {'your tsserver installed by lsp_installer or mason'} }
-- e.g. tsserver = { cmd = {'/home/username/.local/share/nvim/mason/packages/typescript-language-server/node_modules/typescript/bin/tsserver'} }
}
})
@ -564,6 +651,7 @@ require'navigator'.setup({
lsp = {
tsserver = {
cmd = { "/Users/username/.local/share/nvim/lsp_servers/python/node_modules/.bin/pyright-langserver", "--stdio" }
-- or mason: cmd = { "/Users/username/.local/share/nvim/mason/packages/pyright/node_modules/pyright/index.js", "--stdio"}
}
}
}
@ -623,6 +711,9 @@ require('rust-tools').setup({
server = {
on_attach = function(client, bufnr)
require('navigator.lspclient.mapping').setup({client=client, bufnr=bufnr}) -- setup navigator keymaps here,
require("navigator.dochighlight").documentHighlight(bufnr)
require('navigator.codeAction').code_action_prompt(bufnr)
-- otherwise, you can define your own commands to call navigator functions
end,
}
@ -632,6 +723,8 @@ require("clangd_extensions").setup {
server = {
on_attach = function(client, bufnr)
require('navigator.lspclient.mapping').setup({client=client, bufnr=bufnr}) -- setup navigator keymaps here,
require("navigator.dochighlight").documentHighlight(bufnr)
require('navigator.codeAction').code_action_prompt(bufnr)
-- otherwise, you can define your own commands to call navigator functions
end,
}
@ -667,7 +760,7 @@ Highlight I am using:
- LspReferenceRead, LspReferenceText and LspReferenceWrite are used for `autocmd CursorHold <buffer> lua vim.lsp.buf.document_highlight()`
That is where you saw the current symbol been highlighted.
- GHListDark and GHTextViewDark is used for floating listvew and TextView. They are be based on current background
- GuihuaListDark and GuihuaTextViewDark is used for floating listvew and TextView. They are be based on current background
(Normal) and PmenuSel
- In future, I will use NormalFloat for floating view. But ATM, most of colorscheme does not define NormalFloat
@ -684,6 +777,7 @@ You can override the above highlight to fit your current colorscheme
| LspRestart | reload lsp |
| LspToggleFmt | toggle lsp format |
| LspSymbols | document symbol in side panel |
| NRefPanel | show symbol reference in side panel |
| TSymobls | treesitter symbol in side panel |
| Calltree {args} | lsp call hierarchy call tree, args: -i (incomming default), -o (outgoing) |
@ -823,7 +917,7 @@ Codelens for C++/ccls. Symbol reference
### VS-code style folding with treesitter
Folding is using a hacked version of treesitter folding.
Folding is using a hacked version of treesitter folding. (option: ts_fold)
#### folding function

View File

@ -477,13 +477,13 @@ DEFAULT KEYMAPS *navigator-default_keymap
COLORS/HIGHLIGHT: *navigator-colors/highlight:*
You can override default highlight GHListDark (listview) and GHTextViewDark (code view) and GHListHl (select item)
You can override default highlight GuihuaListDark (listview) and GuihuaTextViewDark (code view) and GuihuaListHl (select item)
e.g.
>
hi default GHTextViewDark guifg=#e0d8f4 guibg=#332e55
hi default GHListDark guifg=#e0d8f4 guibg=#103234
hi default GHListHl guifg=#e0d8f4 guibg=#404254
hi default GuihuaTextViewDark guifg=#e0d8f4 guibg=#332e55
hi default GuihuaListDark guifg=#e0d8f4 guibg=#103234
hi default GuihuaListHl guifg=#e0d8f4 guibg=#404254
<
There are other Lsp highlight been used in this plugin, e.g LspReferenceRead/Text/Write are used for document highlight,
@ -644,7 +644,7 @@ Highlight I am using:
* LspReferenceRead, LspReferenceText and LspReferenceWrite are used for `autocmd CursorHold <buffer> lua vim.lsp.buf.document_highlight()`
That is where you saw the current symbol been highlighted.
* GHListDark and GHTextViewDark is used for floating listvew and TextView. They are be based on current background
* GuihuaListDark and GuihuaTextViewDark is used for floating listvew and TextView. They are be based on current background
(Normal) and PmenuSel
* In future, I will use NormalFloat for floating view. But ATM, most of colorscheme does not define NormalFloat
@ -660,8 +660,9 @@ COMMANDS *navigator-command
| Nctags {args} | show ctags symbols, args: -g regen ctags |
| LspRestart | reload lsp |
| LspSymbols | document symbol in side panel |
| NRefPanel |symbol reference in side panel |
| TSymobls | treesitter symbol in side panel |
| CallTree {args} | lsp call hierarchy call tree, args: -i (incomming default), -o (outgoing) |
| Calltree {args} | lsp call hierarchy call tree, args: -i (incomming default), -o (outgoing) |
:LspToggleFmt *:LspToggleFmt*
Toggle lsp auto format.
@ -683,6 +684,9 @@ COMMANDS *navigator-command
:TSSymbols *:TSSymbols*
Treesitter symbol in side panel.
:NRefPanel *:NRefPanel*
Symbol reference in side panel.
:Calltree [flags] *:Calltree*
Lsp call hierarchy call tree.
[flags]:

View File

@ -1,12 +1,13 @@
local M = {}
local api = vim.api
local function warn(msg)
vim.api.nvim_echo({ { 'WRN: ' .. msg, 'WarningMsg' } }, true, {})
api.nvim_echo({ { 'WRN: ' .. msg, 'WarningMsg' } }, true, {})
end
local function info(msg)
if _NgConfigValues.debug then
vim.api.nvim_echo({ { 'Info: ' .. msg } }, true, {})
api.nvim_echo({ { 'Info: ' .. msg } }, true, {})
end
end
@ -31,11 +32,16 @@ _NgConfigValues = {
ts_fold = false,
treesitter_analysis = true, -- treesitter variable context
treesitter_analysis_max_num = 100, -- how many items to run treesitter analysis
treesitter_analysis_condense = true, -- short format of function
transparency = 50, -- 0 ~ 100 blur the main window, 100: fully transparent, 0: opaque, set to nil to disable it
lsp_signature_help = true, -- if you would like to hook ray-x/lsp_signature plugin in navigator
-- setup here. if it is nil, navigator will not init signature help
signature_help_cfg = { debug = false }, -- if you would like to init ray-x/lsp_signature plugin in navigator, pass in signature help
ctags = { cmd = 'ctags', tagfile = '.tags' },
ctags = {
cmd = 'ctags',
tagfile = '.tags',
options = '-R --exclude=.git --exclude=node_modules --exclude=test --exclude=vendor --excmd=number',
},
lsp = {
enable = true, -- if disabled make sure add require('navigator.lspclient.mapping').setup() in you on_attach
code_action = {
@ -45,6 +51,7 @@ _NgConfigValues = {
virtual_text = true,
virtual_text_icon = true,
},
document_highlight = true, -- highlight reference a symbol
code_lens_action = {
enable = true,
sign = true,
@ -86,6 +93,7 @@ _NgConfigValues = {
servers = {}, -- you can add additional lsp server so navigator will load the default for you
},
lsp_installer = false, -- set to true if you would like use the lsp installed by williamboman/nvim-lsp-installer
mason = false, -- set to true if you would like use the lsp installed by williamboman/mason
icons = {
icons = true, -- set to false to use system default ( if you using a terminal does not have nerd/icon)
-- Code action
@ -208,7 +216,7 @@ local extend_config = function(opts)
else
if _NgConfigValues[key][k] == nil then
if key == 'lsp' then
local lsp = require('navigator.lspclient.clients').lsp
local lsp = require('navigator.lspclient.servers')
if not vim.tbl_contains(lsp or {}, k) and k ~= 'efm' and k ~= 'null-ls' then
info(string.format('[] extend LSP support for %s %s ', key, k))
end
@ -243,7 +251,14 @@ M.setup = function(cfg)
cfg = cfg or {}
extend_config(cfg)
vim.cmd([[autocmd FileType,BufEnter * lua require'navigator.lspclient.clients'.on_filetype()]]) -- BufWinEnter BufNewFile,BufRead ?
local cmd_group = api.nvim_create_augroup('NGFtGroup', {})
api.nvim_create_autocmd({ 'FileType', 'BufEnter' }, {
group = cmd_group,
pattern = '*',
callback = function()
require('navigator.lspclient.clients').on_filetype()
end,
})
require('navigator.lazyloader').init()
require('navigator.lspclient.clients').setup(_NgConfigValues)
@ -271,7 +286,6 @@ M.setup = function(cfg)
local _start_client = vim.lsp.start_client
vim.lsp.start_client = function(lsp_config)
-- add highlight for Lspxxx
require('navigator.dochighlight').documentHighlight()
require('navigator.lspclient.highlight').add_highlight()
require('navigator.lspclient.highlight').diagnositc_config_sign()
-- require('navigator.lspclient.mapping').setup()

View File

@ -152,9 +152,13 @@ local code_action_req = function(_call_back_fn, diagnostics)
end
local function sort_select(action_tuples, opts, on_user_choice)
-- table.sort(action_tuples, function(a, b)
-- return a[1] > b[1]
-- end)
if action_tuples ~= nil and action_tuples[1][2] ~= nil and action_tuples[1][2].command then
table.sort(action_tuples, function(a, b)
return a[1] > b[1]
end)
end
trace(action_tuples)
require('guihua.gui').select(action_tuples, opts, on_user_choice)
end
@ -162,8 +166,6 @@ code_action.code_action = function()
local original_select = vim.ui.select
vim.ui.select = sort_select
log('codeaction')
vim.lsp.buf.code_action()
vim.defer_fn(function()
vim.ui.select = original_select
@ -186,17 +188,19 @@ code_action.range_code_action = function(startpos, endpos)
local original_input = vim.ui.input
vim.ui.input = require('guihua.input').input
vim.lsp.buf.range_code_action(context, startpos, endpos)
if vim.fn.has('nvim-0.8') then
vim.lsp.buf.code_action({context=context ,range={start = startpos, ['end'] = endpos}})
else
vim.lsp.buf.range_code_action(context, startpos, endpos)
end
vim.defer_fn(function()
vim.ui.select = original_select
end, 1000)
vim.defer_fn(function()
vim.ui.input = original_input
end, 1000)
end
code_action.code_action_prompt = function()
code_action.code_action_prompt = function(bufnr)
if special_buffers[vim.bo.filetype] then
log('skip buffer', vim.bo.filetype)
return

View File

@ -5,7 +5,7 @@ local codelens = require('vim.lsp.codelens')
local log = require('navigator.util').log
local trace = require('navigator.util').trace
-- trace = log
local lsphelper = require('navigator.lspwrapper')
local api = vim.api
local M = {}
@ -61,24 +61,19 @@ local codelens_hdlr = function(err, result, ctx, cfg)
end
end
function M.setup()
vim.cmd('highlight! link LspCodeLens LspDiagnosticsHint')
vim.cmd('highlight! link LspCodeLensText LspDiagnosticsInformation')
vim.cmd('highlight! link LspCodeLensTextSign LspDiagnosticsSignInformation')
vim.cmd('highlight! link LspCodeLensTextSeparator Boolean')
vim.cmd('augroup navigator.codelenses')
vim.cmd(' autocmd!')
vim.cmd("autocmd BufEnter,CursorHold,InsertLeave <buffer> lua require('navigator.codelens').refresh()")
vim.cmd('augroup end')
local on_codelens = vim.lsp.handlers['textDocument/codeLens']
vim.lsp.handlers['textDocument/codeLens'] = function(err, result, ctx, cfg)
-- trace(err, result, ctx.client_id, ctx.bufnr, cfg or {})
cfg = cfg or {}
ctx = ctx or { bufnr = vim.api.nvim_get_current_buf() }
on_codelens(err, result, ctx, cfg)
codelens_hdlr(err, result, ctx, cfg)
end
function M.setup(bufnr)
log('setup for ****** ', bufnr)
vim.api.nvim_set_hl(0, 'LspCodeLens', { link = 'DiagnosticsHint', default = true })
vim.api.nvim_set_hl(0, 'LspCodeLensText', { link = 'DiagnosticsInformation', default = true })
vim.api.nvim_set_hl(0, 'LspCodeLensSign', { link = 'DiagnosticsInformation', default = true })
vim.api.nvim_set_hl(0, 'LspCodeLensSeparator', { link = 'Boolean', default = true })
vim.api.nvim_create_autocmd({ 'CursorHold', 'CursorHoldI', 'InsertLeave' }, {
group = vim.api.nvim_create_augroup('nv__codelenses', {}),
buffer = bufnr or vim.api.nvim_win_get_buf(),
callback = function()
require('navigator.codelens').refresh()
end,
})
end
M.lsp_clients = {}
@ -91,7 +86,7 @@ function M.refresh()
if not lsphelper.check_capabilities('codeLensProvider') then
return
end
vim.lsp.codelens.refresh()
M.inline()
end
local virtual_types_ns = api.nvim_create_namespace('ng_virtual_types')
@ -106,12 +101,13 @@ function M.run_action()
local original_select = vim.ui.select
vim.ui.select = require('guihua.gui').select
log('codeaction')
log('codelens action')
codelens.run()
vim.defer_fn(function()
vim.ui.select = original_select
end, 1000)
end
M.inline = function()
@ -129,42 +125,20 @@ M.inline = function()
local bufnr = api.nvim_get_current_buf()
local parameter = lsp.util.make_position_params()
local response = lsp.buf_request_sync(bufnr, 'textDocument/codeLens', parameter)
-- Clear previous highlighting
api.nvim_buf_clear_namespace(bufnr, virtual_types_ns, 0, -1)
local on_codelens = vim.lsp.handlers['textDocument/codeLens']
lsp.buf_request(bufnr, 'textDocument/codeLens', parameter, function(err, response, ctx, _)
-- Clear previous highlighting
api.nvim_buf_clear_namespace(bufnr, virtual_types_ns, 0, -1)
if response then
log(response)
for _, v in ipairs(response) do
if v == nil or v.result == nil then
return
end -- no response
for _, vv in pairs(v.result) do
local start_line = -1
for _, vvv in pairs(vv.range) do
start_line = tonumber(vvv.line)
end
if response then
trace(response)
local cmd = vv.command
local msg = _NgConfigValues.icons.code_action_icon .. ' '
if cmd then
local txt = cmd.title or ''
txt = txt .. ' ' .. (cmd.command or '') .. ' '
msg = msg .. txt .. ' '
end
on_codelens(err, response, ctx, _)
log(msg)
api.nvim_buf_set_extmark(bufnr, virtual_types_ns, start_line, -1, {
virt_text = { { msg, 'LspCodeLensText' } },
virt_text_pos = 'overlay',
hl_mode = 'combine',
})
end
codelens_hdlr (err, response, ctx, _)
end
-- else
-- api.nvim_command("echohl WarningMsg | echo 'VirtualTypes: No response' | echohl None")
end
end)
end
return M

View File

@ -89,7 +89,7 @@ local function ctags_symbols()
local height = _NgConfigValues.height or 0.4
local width = _NgConfigValues.width or 0.7
height = math.floor(height * vfn.winheight('%'))
width = math.floor(width * vfn.winwidth('%'))
width = math.floor(vim.api.nvim_get_option('columns') * width)
local items = {}
local ctags_file = _NgConfigValues.ctags.tagfile
if not util.file_exists(ctags_file) then
@ -118,7 +118,7 @@ local function ctags_symbols()
local opt = {
api = '',
ft = ft,
bg = 'GHListDark',
bg = 'GuihuaListDark',
data = result,
items = result,
enter = true,

View File

@ -74,7 +74,7 @@ local function def_preview(timeout_ms)
local row = range.start.line
-- in case there are comments
row = math.max(row - 3, 1)
local delta = range.start.line - row + 1
local delta = range.start.line - row + 3
local uri = data[1].uri or data[1].targetUri
if not uri then
return
@ -85,7 +85,12 @@ local function def_preview(timeout_ms)
end
local ok, parsers = pcall(require, 'nvim-treesitter.parsers')
local lines_num = 12
-- TODO: 32/64 should be an option
local lines_num = 64
if range['end'] ~= nil then
lines_num = math.max(lines_num, range['end'].line - range.start.line + 4)
end
if ok then
local ts = require('navigator.treesitter')
local root = parsers.get_parser(bufnr)
@ -97,10 +102,10 @@ local function def_preview(timeout_ms)
local sr, _, er, _ = ts.get_node_scope(def_node)
log(sr, er)
lines_num = math.max(lines_num, er - sr + 3) -- comments etc
lines_num = math.max(lines_num, er - sr + 5) -- comments etc
end
-- TODO: 12 should be an option
-- TODO: 32 should be an option
local definition = vim.api.nvim_buf_get_lines(bufnr, row, range['end'].line + lines_num, false)
local def_line = vim.api.nvim_buf_get_lines(bufnr, range.start.line, range.start.line + 1, false)
for _ = 1, math.min(3, #definition), 1 do
@ -112,7 +117,8 @@ local function def_preview(timeout_ms)
end
end
local width = 40
local maxwidth = math.floor(vim.fn.winwidth(0) * 4 / 5)
local maxwidth = math.floor( vim.api.nvim_get_option('columns') * 0.8)
for _, value in pairs(definition) do
-- log(key, value, width)
width = math.max(width, #value + 4)
@ -126,7 +132,7 @@ local function def_preview(timeout_ms)
relative = 'cursor',
style = 'minimal',
ft = filetype,
rect = { width = width, height = #definition + 3, pos_y = 2 },
rect = { width = width, height = math.min(#definition + 3, 16), pos_y = 2 }, -- TODO: 16 hardcoded
data = definition,
enter = true,
border = _NgConfigValues.border or 'shadow',

View File

@ -2,7 +2,6 @@ local gui = require('navigator.gui')
local diagnostic_list = {}
local diagnostic = vim.diagnostic or vim.lsp.diagnostic
-- local hide = diagnostic.hide or diagnostic.clear
_NG_VT_DIAG_NS = vim.api.nvim_create_namespace('navigator_lua_diag')
local util = require('navigator.util')
local log = util.log
local trace = require('guihua.log').trace
@ -11,6 +10,8 @@ local error = util.error
local path_sep = require('navigator.util').path_sep()
local path_cur = require('navigator.util').path_cur()
local empty = util.empty
local api = vim.api
_NG_VT_DIAG_NS = api.nvim_create_namespace('navigator_lua_diag')
if not util.nvim_0_6_1() then
util.warn('Navigator 0.4+ only support nvim-0.6+, please use Navigator 0.3.x or a newer version of neovim')
@ -57,15 +58,18 @@ local function error_marker(result, ctx, config)
if bufnr == nil then
bufnr = vim.uri_to_bufnr(result.uri)
end
local fname = vim.api.nvim_buf_get_name(bufnr)
local success, fname = pcall(api.nvim_buf_get_name, bufnr)
if not success then
return
end
local uri = vim.uri_from_fname(fname)
if uri ~= result.uri then
log('not same buf', ctx, result.uri, bufnr, vim.fn.bufnr())
return
end
if not vim.api.nvim_buf_is_loaded(bufnr) then
log('buf not loaded', bufnr)
if not api.nvim_buf_is_loaded(bufnr) then
trace('buf not loaded', bufnr)
return
end
@ -76,7 +80,7 @@ local function error_marker(result, ctx, config)
local diag_cnt = get_count(bufnr, [[Error]]) + get_count(bufnr, [[Warning]])
if diag_cnt == 0 and _NG_VT_DIAG_NS ~= nil then
log('great no errors')
vim.api.nvim_buf_clear_namespace(bufnr, _NG_VT_DIAG_NS, 0, -1)
api.nvim_buf_clear_namespace(bufnr, _NG_VT_DIAG_NS, 0, -1)
end
return
end
@ -84,12 +88,12 @@ local function error_marker(result, ctx, config)
-- total line num of current buffer
-- local winid = vim.fn.win_getid(vim.fn.winnr())
-- local winid = vim.api.nvim_get_current_win()
local total_num = vim.api.nvim_buf_line_count(bufnr)
-- local winid = api.nvim_get_current_win()
local total_num = api.nvim_buf_line_count(bufnr)
-- local total_num = vim.fn.getbufinfo(vim.fn.winbufnr(winid))[1].linecount
-- window size of current buffer
local stats = vim.api.nvim_list_uis()[1]
local stats = api.nvim_list_uis()[1]
-- local wwidth = stats.width;
local wheight = stats.height
@ -97,7 +101,7 @@ local function error_marker(result, ctx, config)
return
end
if _NG_VT_DIAG_NS == nil then
_NG_VT_DIAG_NS = vim.api.nvim_create_namespace('navigator_lua_diag')
_NG_VT_DIAG_NS = api.nvim_create_namespace('navigator_lua_diag')
end
local pos = {}
@ -139,7 +143,7 @@ local function error_marker(result, ctx, config)
end
if not vim.tbl_isempty(pos) then
vim.api.nvim_buf_clear_namespace(bufnr, _NG_VT_DIAG_NS, 0, -1)
api.nvim_buf_clear_namespace(bufnr, _NG_VT_DIAG_NS, 0, -1)
end
for _, s in pairs(pos) do
local hl = 'ErrorMsg'
@ -160,7 +164,7 @@ local function error_marker(result, ctx, config)
end
trace('add pos', s, bufnr)
vim.api.nvim_buf_set_extmark(
api.nvim_buf_set_extmark(
bufnr,
_NG_VT_DIAG_NS,
l,
@ -184,9 +188,9 @@ local diag_hdlr = function(err, result, ctx, config)
return
end
local mode = vim.api.nvim_get_mode().mode
local mode = api.nvim_get_mode().mode
if mode ~= 'n' and config.update_in_insert == false then
log('skip sign update in insert mode')
trace('skip sign update in insert mode')
end
local cwd = vim.loop.cwd()
local ft = vim.bo.filetype
@ -222,14 +226,18 @@ local diag_hdlr = function(err, result, ctx, config)
item.uri = uri
-- trace(item)
local head = _NgConfigValues.icons.diagnostic_head
if v.severity == 1 then
head = _NgConfigValues.icons.diagnostic_head_severity_1
end
if v.severity == 2 then
head = _NgConfigValues.icons.diagnostic_head_severity_2
end
if v.severity > 2 then
head = _NgConfigValues.icons.diagnostic_head_severity_3
if v.severity then
if v.severity == 1 then
head = _NgConfigValues.icons.diagnostic_head_severity_1
end
if v.severity == 2 then
head = _NgConfigValues.icons.diagnostic_head_severity_2
end
if v.severity > 2 then
head = _NgConfigValues.icons.diagnostic_head_severity_3
end
else
v.severity = 2
end
if v.relatedInformation and v.relatedInformation[1] then
local info = v.relatedInformation[1]
@ -242,7 +250,7 @@ local diag_hdlr = function(err, result, ctx, config)
end
end
local bufnr1 = vim.uri_to_bufnr(uri)
local loaded = vim.api.nvim_buf_is_loaded(bufnr1)
local loaded = api.nvim_buf_is_loaded(bufnr1)
if _NgConfigValues.diagnostic_load_files then
-- print('load buffers')
if not loaded then
@ -250,7 +258,7 @@ local diag_hdlr = function(err, result, ctx, config)
end
local pos = v.range.start
local row = pos.line
local line = (vim.api.nvim_buf_get_lines(bufnr1, row, row + 1, false) or { '' })[1]
local line = (api.nvim_buf_get_lines(bufnr1, row, row + 1, false) or { '' })[1]
if line ~= nil then
item.text = head .. line .. _NgConfigValues.icons.diagnostic_head_description .. v.message
else
@ -284,7 +292,7 @@ local diag_hdlr = function(err, result, ctx, config)
marker(result, ctx, config)
else
trace('great, no diag errors')
vim.api.nvim_buf_clear_namespace(0, _NG_VT_DIAG_NS, 0, -1)
api.nvim_buf_clear_namespace(0, _NG_VT_DIAG_NS, 0, -1)
_NG_VT_DIAG_NS = nil
end
end
@ -327,18 +335,24 @@ function M.setup()
vim.diagnostic.config(diagnostic_cfg)
if _NgConfigValues.lsp.diagnostic_scrollbar_sign then
vim.cmd([[autocmd WinScrolled * lua require'navigator.diagnostics'.update_err_marker()]])
api.nvim_create_autocmd({ 'WinScrolled' }, {
group = api.nvim_create_augroup('NGWinScrolledGroup', {}),
pattern = '*',
callback = function()
require('navigator.diagnostics').update_err_marker()
end,
})
end
end
local function clear_diag_VT(bufnr) -- important for clearing out when no more errors
bufnr = bufnr or vim.api.nvim_get_current_buf()
bufnr = bufnr or api.nvim_get_current_buf()
log(bufnr, _NG_VT_DIAG_NS)
if _NG_VT_DIAG_NS == nil then
return
end
vim.api.nvim_buf_clear_namespace(bufnr, _NG_VT_DIAG_NS, 0, -1)
api.nvim_buf_clear_namespace(bufnr, _NG_VT_DIAG_NS, 0, -1)
_NG_VT_DIAG_NS = nil
end
@ -380,15 +394,15 @@ M.show_buf_diagnostics = function()
end
trace('new buffer', listview.bufnr)
if listview.bufnr then
vim.api.nvim_buf_add_highlight(listview.bufnr, -1, 'Title', 0, 0, -1)
api.nvim_buf_add_highlight(listview.bufnr, -1, 'Title', 0, 0, -1)
end
end
end
end
-- set loc list win
M.set_diag_loclist = function()
local bufnr = vim.api.nvim_get_current_buf()
M.set_diag_loclist = function(bufnr)
bufnr = bufnr or api.nvim_get_current_buf()
local diag_cnt = get_count(bufnr, [[Error]]) + get_count(bufnr, [[Warning]])
if diag_cnt == 0 then
log('great, no errors!')
@ -408,7 +422,7 @@ M.set_diag_loclist = function()
if diagnostic.set_loclist then
diagnostic.set_loclist(cfg)
else
cfg.namespaces = diagnostic.get_namespace(nil)
cfg.namespaces = diagnostic.get_namespaces()
diagnostic.setloclist(cfg)
end
else
@ -424,7 +438,7 @@ function M.update_err_marker()
-- nothing to update
return
end
local bufnr = vim.api.nvim_get_current_buf()
local bufnr = api.nvim_get_current_buf()
local diag_cnt = get_count(bufnr, [[Error]])
+ get_count(bufnr, [[Warning]])
@ -433,12 +447,12 @@ function M.update_err_marker()
-- redraw
if diag_cnt == 0 and _NG_VT_DIAG_NS ~= nil then
vim.api.nvim_buf_clear_namespace(bufnr, _NG_VT_DIAG_NS, 0, -1)
api.nvim_buf_clear_namespace(bufnr, _NG_VT_DIAG_NS, 0, -1)
trace('no errors')
return
end
vim.api.nvim_buf_clear_namespace(bufnr, _NG_VT_DIAG_NS, 0, -1)
api.nvim_buf_clear_namespace(bufnr, _NG_VT_DIAG_NS, 0, -1)
local errors = diagnostic.get(bufnr)
if #errors == 0 then
trace('no errors', errors)
@ -453,25 +467,39 @@ function M.update_err_marker()
end
function M.get_line_diagnostic()
local lnum = vim.api.nvim_win_get_cursor(0)[1] - 1
return diagnostic.get(vim.api.nvim_get_current_buf(), { lnum = lnum })
local lnum = api.nvim_win_get_cursor(0)[1] - 1
local diags = diagnostic.get(api.nvim_get_current_buf(), { lnum = lnum })
table.sort(diags, function(diag1, diag2)
return diag1.severity < diag2.severity
end)
return diags
end
function M.show_diagnostics(pos)
local bufnr = vim.api.nvim_get_current_buf()
local lnum = vim.api.nvim_win_get_cursor(0)[1] - 1
local opt = { border = 'single' }
if diagnostic.open_float and type(diagnostic.open_float) == 'function' then
local bufnr = api.nvim_get_current_buf()
local lnum, col = unpack(api.nvim_win_get_cursor(0))
lnum = lnum - 1
local opt = { border = 'single', severity_sort = true }
if pos ~= nil and type(pos) == 'number' then
opt.scope = 'buffer'
else
if pos == true then
opt.scope = 'cursor'
else
opt.scope = 'line'
end
diagnostic.open_float(bufnr, opt)
else
-- deprecated
diagnostic.show_line_diagnostics(opt, bufnr, lnum)
end
local diags = M.get_line_diagnostic()
if diags == nil or next(diags) == nil then
return
end
local diag1 = diags[1]
opt.offset_x = -1 * (col - diag1.col)
diagnostic.open_float(bufnr, opt)
end
function M.treesitter_and_diag_panel()
@ -481,7 +509,7 @@ function M.treesitter_and_diag_panel()
local results = diagnostic_list[ft]
log(diagnostic_list, ft)
local bufnr = vim.api.nvim_get_current_buf()
local bufnr = api.nvim_get_current_buf()
local p = Panel:new({
header = 'treesitter',
render = function(b)
@ -491,7 +519,8 @@ function M.treesitter_and_diag_panel()
})
p:add_section({
header = 'diagnostic',
render = function(bufnr)
render = function(buf)
log(buf, diagnostic)
if diagnostic_list[ft] ~= nil then
local display_items = {}
for _, client_items in pairs(results) do

View File

@ -145,7 +145,6 @@ local handle_document_highlight = function(_, result, ctx)
return
end
if type(result) ~= 'table' or vim.fn.empty(result) == 1 then
log('clear up', result)
vim.lsp.util.buf_clear_references(ctx.bufnr)
return
end
@ -205,29 +204,45 @@ local function cmd_nohl()
end
end
local nav_doc_hl = function()
local bufnr = vim.api.nvim_get_current_buf()
local nav_doc_hl = function(bufnr)
trace('nav_doc_hl', bufnr)
bufnr = bufnr or vim.api.nvim_get_current_buf()
local ref_params = vim.lsp.util.make_position_params()
vim.lsp.for_each_buffer_client(bufnr, function(client, _, _)
if client.server_capabilities.documentHighlightProvider == true then
trace('sending doc highlight', client.name, bufnr)
client.request('textDocument/documentHighlight', ref_params, handle_document_highlight, bufnr)
end
end)
end
local function documentHighlight()
api.nvim_exec(
[[
augroup lsp_document_highlight
autocmd! * <buffer>
autocmd CursorHold,CursorHoldI <buffer> lua require('navigator.dochighlight').nav_doc_hl()
autocmd CursorMoved <buffer> lua vim.lsp.buf.clear_references()
augroup END
]],
false
)
local function documentHighlight(bufnr)
bufnr = bufnr or api.nvim_get_current_buf()
if _NgConfigValues.lsp.document_highlight == true then
local group_name = string.format('%s%d', 'NGHiGroup', bufnr)
local cmd_group = api.nvim_create_augroup(group_name, {})
api.nvim_create_autocmd({ 'CursorHold', 'CursorHoldI' }, {
group = cmd_group,
buffer = bufnr,
desc = 'document highlight',
callback = function()
require('navigator.dochighlight').nav_doc_hl(bufnr)
end,
})
api.nvim_create_autocmd({ 'CursorMoved', 'CursorMovedI' }, {
group = cmd_group,
buffer = bufnr,
desc = 'clear document highlight',
callback = function()
vim.lsp.util.buf_clear_references(bufnr)
end,
})
end
vim.lsp.handlers['textDocument/documentHighlight'] = function(err, result, ctx)
local bufnr = ctx.bufnr or api.nvim_get_current_buf()
local buffer = ctx.bufnr or api.nvim_get_current_buf()
if err then
vim.notify(err, vim.lsp.log_levels.ERROR)
return
@ -236,19 +251,18 @@ local function documentHighlight()
return
end
trace('dochl', result)
bufnr = bufnr or 0
if type(result) ~= 'table' then
vim.lsp.util.buf_clear_references(bufnr)
vim.lsp.util.buf_clear_references(buffer)
return
end
local client_id = ctx.client_id
vim.lsp.util.buf_clear_references(bufnr)
vim.lsp.util.buf_highlight_references(bufnr, result, util.encoding(client_id))
vim.lsp.util.buf_clear_references(buffer)
vim.lsp.util.buf_highlight_references(buffer, result, util.encoding(client_id))
table.sort(result, function(a, b)
return before(a.range, b.range)
end)
references[bufnr] = result
add_locs(bufnr, result)
references[buffer] = result
add_locs(buffer, result)
end
end

View File

@ -28,19 +28,14 @@ function M.on_attach()
end
function M.setup_plugin()
api.nvim_command('augroup FoldingCommand')
api.nvim_command('autocmd! * <buffer>')
api.nvim_command("autocmd BufEnter <buffer> lua require'navigator.foldlsp'.update_folds()")
api.nvim_command("autocmd BufWritePost <buffer> lua require'navigator.foldlsp'.update_folds()")
api.nvim_command('augroup end')
-- vim.cmd([[
--
-- function! folding_nvim#foldexpr()
-- return luaeval(printf('require"navigator.foldlsp".get_fold_indic(%d)', v:lnum))
-- endfunction
--
-- ]])
local cmd_group = api.nvim_create_augroup('NGFoldGroup', {})
api.nvim_create_autocmd({ 'BufEnter', 'BufWritePost' }, {
group = cmd_group,
pattern = '*',
callback = function()
require('navigator.foldlsp').update_folds()
end,
})
local clients = vim.lsp.buf_get_clients(0)

View File

@ -21,7 +21,12 @@ function NG_custom_fold_text()
local line = vim.fn.getline(vim.v.foldstart)
local line_count = vim.v.foldend - vim.v.foldstart + 1
-- log("" .. line .. " // " .. line_count .. " lines")
return '' .. line .. ': ' .. line_count .. ' lines'
local ss, se = line:find('^%s*')
local spaces = line:sub(ss, se)
local tabspace = string.rep(' ', vim.o.tabstop)
spaces = spaces:gsub('\t', tabspace)
line = line:gsub('^%s*(.-)%s*$', '%1')
return spaces .. '' .. line .. ': ' .. line_count .. ' lines'
end
vim.opt.foldtext = NG_custom_fold_text()
@ -220,7 +225,7 @@ function M.get_fold_indic(lnum)
local buf = api.nvim_get_current_buf()
local shown = false
for i = 1, vim.fn.tabpagenr('$') do
for key, value in pairs(vim.fn.tabpagebuflist(i)) do
for _, value in pairs(vim.fn.tabpagebuflist(i)) do
if value == buf then
shown = true
end

View File

@ -1,5 +1,6 @@
-- https://github.com/wention/dotfiles/blob/master/.config/nvim/lua/config/lsp.lua
-- https://github.com/lukas-reineke/dotfiles/blob/master/vim/lua/lsp/handlers.lua
return {
format_hdl = function(err, result, ctx, _) -- FIXME: bufnr is nil
if err ~= nil or result == nil then
@ -31,11 +32,13 @@ return {
end
end, 100)
end,
range_foramt = function(err, result, ctx, _)
range_format = function()
local old_func = vim.go.operatorfunc
_G.op_func_formatting = function()
print('formatting range')
local start = vim.api.nvim_buf_get_mark(0, '[')
local finish = vim.api.nvim_buf_get_mark(0, ']')
print(vim.inspect(start), vim.inspect(finish))
vim.lsp.buf.range_formatting({}, start, finish)
vim.go.operatorfunc = old_func
_G.op_func_formatting = nil

View File

@ -1,6 +1,6 @@
local M = {}
local ListView = require('guihua.listview')
local TextView = require('guihua.textview')
-- local ListView = require('guihua.listview')
-- local TextView = require('guihua.textview')
local util = require('navigator.util')
local log = util.log
local trace = require('navigator.util').trace
@ -16,7 +16,7 @@ function M.new_list_view(opts)
local winnr = active_list_view.win
local bufnr = active_list_view.buf
if bufnr and vim.api.nvim_buf_is_valid(bufnr) and winnr and vim.api.nvim_win_is_valid(winnr) then
if bufnr and api.nvim_buf_is_valid(bufnr) and winnr and api.nvim_win_is_valid(winnr) then
log('list view already present')
return active_list_view
end
@ -35,6 +35,14 @@ function M.new_list_view(opts)
opts.border = config.border or 'shadow'
if vim.fn.hlID('TelescopePromptBorder') > 0 then
opts.border_hl = 'TelescopePromptBorder'
opts.list_hl = 'TelescopeNormal'
opts.bg_hl = 'TelescopePreviewNormal'
opts.sel_hl = 'TelescopeSelection'
else
opts.border_hl = 'FloatBorder'
opts.bg_hl = 'NormalFloat'
opts.list_hl = 'NormalFloat'
opts.sel_hl = 'PmenuSel'
end
if not items or vim.tbl_isempty(items) then
log('empty data return')

View File

@ -100,7 +100,7 @@ hierarchy_handler = function(dir, handler, show, api, err, result, ctx, cfg)
trace(dir, handler, api, show, err, result, ctx, cfg)
ctx = ctx or {} -- can be nil if it is async call
cfg = cfg or {}
opts = ctx.opts or {}
local opts = ctx.opts or {}
vim.validate({ handler = { handler, 'function' }, show = { show, 'function' }, api = { api, 'string' } })
local bufnr = ctx.bufnr or vim.api.nvim_get_current_buf()
assert(next(vim.lsp.buf_get_clients(bufnr)), 'Must have a client running to use lsp hierarchy')
@ -142,11 +142,12 @@ local function display_panel(args)
local Panel = require('guihua.panel')
local bufnr = args.bufnr or vim.api.nvim_get_current_buf()
local ft = args.ft or vim.api.nvim_buf_get_option(bufnr, 'buftype')
-- local ft = args.ft or vim.api.nvim_buf_get_option(bufnr, 'buftype')
local items = args.items
local p = Panel:new({
header = args.header or 'Call Hierarchy',
render = function(bufnr)
render = function(buf)
log(buf)
return items
end,
fold = function(panel, node)

View File

@ -1,7 +1,6 @@
return {
init = function()
local loader = nil
local packer_plugins = packer_plugins or nil -- suppress warnings
local log = require('navigator.util').log
-- packer only
if packer_plugins ~= nil then -- packer install
@ -51,7 +50,7 @@ return {
end,
load = function(plugin_name, path)
local loader = nil
local packer_plugins = packer_plugins or nil -- suppress warnings
packer_plugins = packer_plugins or nil -- suppress warnings
-- packer only
if packer_plugins ~= nil then -- packer install
local lazy_plugins = {}

View File

@ -4,7 +4,7 @@ local lsp = require('vim.lsp')
local util = require('navigator.util')
local log = util.log
local trace = util.trace
_NG_Attached = {}
local M = {}
M.on_attach = function(client, bufnr)
@ -23,6 +23,7 @@ M.on_attach = function(client, bufnr)
log('attaching: ', bufnr, client.name, uri)
trace(client)
_NG_Attached[client.name] = true
-- add highlight for Lspxxx
require('navigator.lspclient.highlight').add_highlight()
@ -35,9 +36,16 @@ M.on_attach = function(client, bufnr)
})
if client.server_capabilities.documentHighlightProvider == true then
require('navigator.dochighlight').documentHighlight()
trace('attaching doc highlight: ', bufnr, client.name)
vim.defer_fn(function()
require('navigator.dochighlight').documentHighlight(bufnr)
end, 50) -- allow a bit time for it to settle down
else
log('skip doc highlight: ', bufnr, client.name)
end
require('navigator.lspclient.lspkind').init()
local config = require('navigator').config_values()
@ -62,9 +70,13 @@ M.on_attach = function(client, bufnr)
if _NgConfigValues.lsp.code_action.enable then
if client.server_capabilities.codeActionProvider and client.name ~= 'null-ls' then
log('code action enabled for client', client.server_capabilities.codeActionProvider)
api.nvim_command('augroup NCodeAction')
vim.cmd([[autocmd CursorHold,CursorHoldI <buffer> lua require'navigator.codeAction'.code_action_prompt()]])
api.nvim_command('augroup end')
api.nvim_create_autocmd({ 'CursorHold', 'CursorHoldI' }, {
group = api.nvim_create_augroup('NGCodeActGroup_'..tostring(bufnr), {}),
buffer = bufnr,
callback = function()
require('navigator.codeAction').code_action_prompt(bufnr)
end,
})
end
end
end

View File

@ -4,6 +4,7 @@ local log = ng_util.log
local trace = ng_util.trace
local empty = ng_util.empty
local warn = ng_util.warn
local vfn = vim.fn
_NG_Loaded = {}
_LoadedFiletypes = {}
@ -41,6 +42,7 @@ local disabled_ft = {
'windline',
'notify',
'nofile',
'help',
'',
}
-- local cap = vim.lsp.protocol.make_client_capabilities()
@ -65,324 +67,43 @@ local luadevcfg = {
local luadev = {}
local user_luadev = _NgConfigValues.lsp['lua-dev']
if user_luadev then
luadev = vim.tbl_deep_extend('force', luadev, user_luadev)
luadev = vim.tbl_deep_extend('force', luadev, user_luadev)
end
require('navigator.lazyloader').load('lua-dev.nvim', 'folke/lua-dev.nvim')
if _NgConfigValues.lsp_installer then
require('navigator.lazyloader').load('nvim-lsp-installer', 'williamboman/nvim-lsp-installer')
end
local ok, l = pcall(require, 'lua-dev')
if ok and l then
luadev = l.setup(luadevcfg)
if _NgConfigValues.mason then
require('navigator.lazyloader').load('mason.nvim', 'williamboman/mason.nvim')
require('navigator.lazyloader').load('mason-lspconfig.nvim', 'williamboman/mason-lspconfig.nvim')
end
local function add(lib)
for _, p in pairs(vim.fn.expand(lib, false, true)) do
p = vim.loop.fs_realpath(p)
if p then
library[p] = true
end
end
end
-- add runtime
add('$VIMRUNTIME')
-- add your config
-- local home = vim.fn.expand("$HOME")
add(vim.fn.stdpath('config'))
-- add plugins it may be very slow to add all in path
-- if vim.fn.isdirectory(home .. "/.config/share/nvim/site/pack/packer") then
-- add(home .. "/.local/share/nvim/site/pack/packer/opt/*")
-- add(home .. "/.local/share/nvim/site/pack/packer/start/*")
-- end
library[vim.fn.expand('$VIMRUNTIME/lua')] = true
library[vim.fn.expand('$VIMRUNTIME/lua/vim')] = true
library[vim.fn.expand('$VIMRUNTIME/lua/vim/lsp')] = true
-- [vim.fn.expand("~/repos/nvim/lua")] = true
-- TODO remove onece PR #944 merged to lspconfig
local path_sep = require('navigator.util').path_sep()
local strip_dir_pat = path_sep .. '([^' .. path_sep .. ']+)$'
local strip_sep_pat = path_sep .. '$'
local dirname = function(pathname)
if not pathname or #pathname == 0 then
return
end
local result = pathname:gsub(strip_sep_pat, ''):gsub(strip_dir_pat, '')
if #result == 0 then
return '/'
end
return result
end
-- TODO end
local setups = {
clojure_lsp = {
root_dir = function(fname)
return util.root_pattern('deps.edn', 'build.boot', 'project.clj', 'shadow-cljs.edn', 'bb.edn', '.git')(fname)
or util.path.dirname(fname)
end,
on_attach = on_attach,
filetypes = { 'clojure', 'edn' },
message_level = vim.lsp.protocol.MessageType.error,
cmd = { 'clojure-lsp' },
},
elixirls = {
on_attach = on_attach,
filetypes = { 'elixir', 'eelixir' },
cmd = { 'elixir-ls' },
message_level = vim.lsp.protocol.MessageType.error,
settings = {
elixirLS = {
dialyzerEnabled = true,
fetchDeps = false,
},
},
root_dir = function(fname)
return util.root_pattern('mix.exs', '.git')(fname) or util.path.dirname(fname)
end,
},
gopls = {
on_attach = on_attach,
-- capabilities = cap,
filetypes = { 'go', 'gomod', 'gohtmltmpl', 'gotexttmpl' },
message_level = vim.lsp.protocol.MessageType.Error,
cmd = {
'gopls', -- share the gopls instance if there is one already
'-remote=auto', --[[ debug options ]] --
-- "-logfile=auto",
-- "-debug=:0",
'-remote.debug=:0',
-- "-rpc.trace",
},
flags = { allow_incremental_sync = true, debounce_text_changes = 1000 },
settings = {
gopls = {
-- more settings: https://github.com/golang/tools/blob/master/gopls/doc/settings.md
-- flags = {allow_incremental_sync = true, debounce_text_changes = 500},
-- not supported
analyses = { unusedparams = true, unreachable = false },
codelenses = {
generate = true, -- show the `go generate` lens.
gc_details = true, -- // Show a code lens toggling the display of gc's choices.
test = true,
tidy = true,
},
usePlaceholders = true,
completeUnimported = true,
staticcheck = true,
matcher = 'fuzzy',
diagnosticsDelay = '500ms',
experimentalWatchedFileDelay = '1000ms',
symbolMatcher = 'fuzzy',
gofumpt = false, -- true, -- turn on for new repos, gofmpt is good but also create code turmoils
buildFlags = { '-tags', 'integration' },
-- buildFlags = {"-tags", "functional"}
},
},
root_dir = function(fname)
return util.root_pattern('go.mod', '.git')(fname) or dirname(fname) -- util.path.dirname(fname)
end,
},
clangd = {
flags = { allow_incremental_sync = true, debounce_text_changes = 500 },
cmd = {
'clangd',
'--background-index',
'--suggest-missing-includes',
'--clang-tidy',
'--header-insertion=iwyu',
'--clang-tidy-checks=-*,llvm-*,clang-analyzer-*',
'--cross-file-rename',
},
filetypes = { 'c', 'cpp', 'objc', 'objcpp' },
on_attach = function(client, bufnr)
client.server_capabilities.documentFormattingProvider = client.server_capabilities.documentFormattingProvider
or true
on_attach(client, bufnr)
end,
},
rust_analyzer = {
root_dir = function(fname)
return util.root_pattern('Cargo.toml', 'rust-project.json', '.git')(fname) or util.path.dirname(fname)
end,
filetypes = { 'rust' },
message_level = vim.lsp.protocol.MessageType.error,
on_attach = on_attach,
settings = {
['rust-analyzer'] = {
assist = { importMergeBehavior = 'last', importPrefix = 'by_self' },
cargo = { loadOutDirsFromCheck = true },
procMacro = { enable = true },
},
},
flags = { allow_incremental_sync = true, debounce_text_changes = 500 },
},
sqls = {
filetypes = { 'sql' },
on_attach = function(client, _)
client.server_capabilities.executeCommandProvider = client.server_capabilities.documentFormattingProvider or true
highlight.diagnositc_config_sign()
require('sqls').setup({ picker = 'telescope' }) -- or default
end,
flags = { allow_incremental_sync = true, debounce_text_changes = 500 },
settings = {
cmd = { 'sqls', '-config', '$HOME/.config/sqls/config.yml' },
-- alterantively:
-- connections = {
-- {
-- driver = 'postgresql',
-- datasourcename = 'host=127.0.0.1 port=5432 user=postgres password=password dbname=user_db sslmode=disable',
-- },
-- },
},
},
sumneko_lua = {
cmd = { 'lua-language-server' },
filetypes = { 'lua' },
on_attach = on_attach,
flags = { allow_incremental_sync = true, debounce_text_changes = 500 },
settings = {
Lua = {
runtime = {
-- Tell the language server which version of Lua you're using (most likely LuaJIT in the case of Neovim)
version = 'LuaJIT',
},
diagnostics = {
enable = true,
-- Get the language server to recognize the `vim` global
globals = { 'vim', 'describe', 'it', 'before_each', 'after_each', 'teardown', 'pending' },
},
completion = { callSnippet = 'Both' },
workspace = {
-- Make the server aware of Neovim runtime files
library = library,
maxPreload = 2000,
preloadFileSize = 40000,
},
telemetry = { enable = false },
},
},
on_new_config = function(cfg, root)
local libs = vim.tbl_deep_extend('force', {}, library)
libs[root] = nil
cfg.settings.Lua.workspace.library = libs
return cfg
end,
},
pyright = {
on_attach = on_attach,
cmd = { 'pyright-langserver', '--stdio' },
filetypes = { 'python' },
flags = { allow_incremental_sync = true, debounce_text_changes = 500 },
settings = {
python = {
formatting = { provider = 'black' },
analysis = {
autoSearchPaths = true,
useLibraryCodeForTypes = true,
diagnosticMode = 'workspace',
},
},
},
},
ccls = {
on_attach = on_attach,
init_options = {
compilationDatabaseDirectory = 'build',
root_dir = [[ util.root_pattern("compile_commands.json", "compile_flags.txt", "CMakeLists.txt", "Makefile", ".git") or util.path.dirname ]],
index = { threads = 2 },
clang = { excludeArgs = { '-frounding-math' } },
},
flags = { allow_incremental_sync = true },
},
jdtls = {
settings = {
java = { signatureHelp = { enabled = true }, contentProvider = { preferred = 'fernflower' } },
},
},
omnisharp = {
cmd = { 'omnisharp', '--languageserver', '--hostPID', tostring(vim.fn.getpid()) },
},
terraformls = {
filetypes = { 'terraform', 'tf' },
},
sourcekit = {
cmd = { 'sourcekit-lsp' },
filetypes = { 'swift' }, -- This is recommended if you have separate settings for clangd.
},
}
setups.sumneko_lua = vim.tbl_deep_extend('force', luadev, setups.sumneko_lua)
local servers = {
'angularls',
'gopls',
'tsserver',
'flow',
'bashls',
'dockerls',
'julials',
'pylsp',
'pyright',
'jedi_language_server',
'jdtls',
'sumneko_lua',
'vimls',
'html',
'jsonls',
'solargraph',
'cssls',
'yamlls',
'clangd',
'ccls',
'sqls',
'denols',
'graphql',
'dartls',
'dotls',
'kotlin_language_server',
'nimls',
'intelephense',
'vuels',
'phpactor',
'omnisharp',
'r_language_server',
'rust_analyzer',
'terraformls',
'svelte',
'texlab',
'clojure_lsp',
'elixirls',
'sourcekit',
'fsautocomplete',
'vls',
'hls',
'tflint',
'terraform_lsp',
}
local setups = require('navigator.lspclient.clients_default').defaults()
local servers = require('navigator.lspclient.servers')
local lsp_installer_servers = {}
local has_lspinst = false
local has_mason = false
if config.lsp_installer == true then
has_lspinst, _ = pcall(require, 'nvim-lsp-installer')
if has_lspinst then
local srvs = require('nvim-lsp-installer.servers').get_installed_servers()
log('lsp_installered servers', srvs)
if #srvs > 0 then
lsp_installer_servers = srvs
end
has_lspinst, _ = pcall(require, 'nvim-lsp-installer')
if has_lspinst then
local srvs = require('nvim-lsp-installer.servers').get_installed_servers()
if #srvs > 0 then
lsp_installer_servers = srvs
end
log(lsp_installer_servers)
end
has_mason, _ = pcall(require, 'mason-lspconfig')
if has_mason then
local srvs=require'mason-lspconfig'.get_installed_servers()
if #srvs > 0 then
lsp_installer_servers = srvs
end
end
log("lsp_installer:", lsp_installer_servers)
if config.lsp.disable_lsp == 'all' then
config.lsp.disable_lsp = servers
end
@ -393,8 +114,8 @@ local ng_default_cfg = {
}
-- check and load based on file type
local function load_cfg(ft, client, cfg, loaded)
log(ft, client, loaded)
local function load_cfg(ft, client, cfg, loaded, starting)
log(ft, client, loaded, starting)
trace(cfg)
if lspconfig[client] == nil then
log('not supported by nvim', client)
@ -403,6 +124,7 @@ local function load_cfg(ft, client, cfg, loaded)
local lspft = lspconfig[client].document_config.default_config.filetypes
local additional_ft = setups[client] and setups[client].filetypes or {}
local bufnr = vim.api.nvim_get_current_buf()
local cmd = cfg.cmd
vim.list_extend(lspft, additional_ft)
@ -418,19 +140,46 @@ local function load_cfg(ft, client, cfg, loaded)
end
trace('lsp for client', client, cfg)
if cmd == nil or #cmd == 0 or vim.fn.executable(cmd[1]) == 0 then
log('lsp not installed for client', client, cmd)
if cmd == nil or #cmd == 0 or vfn.executable(cmd[1]) == 0 then
log('lsp not installed for client', client, cmd, "fallback")
return
end
if _NG_Loaded == nil then
return log('_NG_Loaded not set')
end
for k, c in pairs(loaded) do
if client == k then
-- loaded
log(client, 'already been loaded for', ft, loaded, c)
if not _NG_Loaded[bufnr] or _NG_Loaded[bufnr] < 4 then
log('doautocmd filetype')
vim.defer_fn(function()
vim.cmd('doautocmd FileType')
_NG_Loaded[bufnr] = (_NG_Loaded[bufnr] or 0 ) + 1
end, 100)
return
end
end
end
local clients = vim.lsp.buf_get_clients(0)
for _, c in pairs(clients or {}) do
log("lsp start up in progress client", client, c.name)
if c.name == client then
_NG_Loaded[bufnr] = 100
return
end
end
if starting and (starting.cnt or 0) > 0 then
log("lsp start up in progress", starting)
return vim.defer_fn(function()
load_cfg(ft, client, cfg, loaded, { cnt = starting.cnt - 1 })
end,
200)
end
if lspconfig[client] == nil then
error('client ' .. client .. ' not supported')
return
@ -440,8 +189,27 @@ local function load_cfg(ft, client, cfg, loaded)
log('lspconfig setup')
-- log(lspconfig.available_servers())
-- force reload with config
lspconfig[client].setup(cfg)
log(client, 'loading for', ft)
-- lets have a guard here
if not _NG_Loaded[client] then
log(client, 'loading for', ft, cfg)
log(lspconfig[client])
lspconfig[client].setup(cfg)
_NG_Loaded[client] = true
vim.defer_fn(function()
log('send filetype event')
vim.cmd([[doautocmd Filetype]])
_NG_Loaded[bufnr] = (_NG_Loaded[bufnr] or 0 )+ 1
end, 400)
else
log('send filetype event')
if not _NG_Loaded[bufnr] or _NG_Loaded[bufnr] < 4 then
log('doautocmd filetype')
vim.defer_fn(function()
vim.cmd('doautocmd FileType')
_NG_Loaded[bufnr] = (_NG_Loaded[bufnr] or 0 ) + 1
end, 100)
end
end
end
-- need to verify the lsp server is up
end
@ -459,7 +227,7 @@ local function setup_fmt(client, enabled)
client.server_capabilities.documentFormattingProvider = false
else
client.server_capabilities.documentFormattingProvider = client.server_capabilities.documentFormattingProvider
or enabled
or enabled
end
end
@ -485,7 +253,7 @@ end
local loaded = {}
local function lsp_startup(ft, retry, user_lsp_opts)
retry = retry or false
local path_sep = require('navigator.util').path_sep()
local capabilities = update_capabilities()
for _, lspclient in ipairs(servers) do
@ -555,7 +323,7 @@ local function lsp_startup(ft, retry, user_lsp_opts)
log(lspclient)
-- if user provides override values
cfg.capabilities = capabilities
-- cfg.capabilities = capabilities
log(lspclient, config.lsp.disable_format_cap)
if vim.tbl_contains(config.lsp.disable_format_cap or {}, lspclient) then
log('fileformat disabled for ', lspclient)
@ -639,16 +407,21 @@ local function lsp_startup(ft, retry, user_lsp_opts)
log('lsp installer server config ' .. lspconfig[lspclient].name, installer_cfg)
if installed and installer_cfg then
local paths = installer_cfg:get_default_options().cmd_env.PATH
local paths = installer_cfg:get_default_options().cmd_env and installer_cfg:get_default_options().cmd_env.PATH
if not paths then
-- for some reason lspinstaller does not install the binary, check default PATH
log('lsp installer does not install the lsp in its path, fallback')
return load_cfg(ft, lspclient, cfg, loaded)
end
paths = vim.split(paths, ':')
if vim.fn.empty(cfg.cmd) == 1 then
if vfn.empty(cfg.cmd) == 1 then
cfg.cmd = { installer_cfg.name }
end
if vim.fn.executable(cfg.cmd[1]) == 0 then
if vfn.executable(cfg.cmd[1]) == 0 then
for _, path in ipairs(paths) do
log(path)
if vim.fn.isdirectory(path) == 1 and string.find(path, installer_cfg.root_dir) then
if vfn.isdirectory(path) == 1 and string.find(path, installer_cfg.root_dir) then
cfg.cmd[1] = path .. path_sep .. cfg.cmd[1]
log(cfg.cmd)
break
@ -660,17 +433,49 @@ local function lsp_startup(ft, retry, user_lsp_opts)
end
end
end
if has_mason and _NgConfigValues.mason then
local servers = require'mason-lspconfig'.get_installed_servers()
if not vim.tbl_contains(servers, lspconfig[lspclient].name) then
log('mason server not installed', lspconfig[lspclient].name)
-- return
end
local pkg_name = require "mason-lspconfig.mappings.server".lspconfig_to_package[lspconfig[lspclient].name]
local pkg = require "mason-registry".get_package(pkg_name)
if vim.fn.executable(cfg.cmd[1]) == 0 then
log('lsp installer server config ' .. lspconfig[lspclient].name, pkg)
if pkg then
local path = pkg:get_install_path()
if not path then
-- for some reason lspinstaller does not install the binary, check default PATH
log('lsp installer does not install the lsp in its path, fallback')
return load_cfg(ft, lspclient, cfg, loaded)
end
cfg.cmd = cfg.cmd or {}
cfg.cmd[1] = table.concat({vfn.stdpath('data'), 'mason', 'bin', pkg.name}, path_sep)
if vfn.executable(cfg.cmd[1]) == 0 then
log('failed to find cmd', cfg.cmd[1], "fallback")
return load_cfg(ft, lspclient, cfg, loaded)
else
log('cmd installed', cfg.cmd)
end
end
end
if vfn.executable(cfg.cmd[1]) == 0 then
log('lsp server not installed in path ' .. lspclient .. vim.inspect(cfg.cmd), vim.lsp.log_levels.WARN)
end
if _NG_Loaded[lspclient] then
log('client loaded ?', lspclient)
log('client loaded ?', lspclient, _NG_Loaded[lspclient])
end
local starting = {}
if _NG_Loaded[lspclient] == true then
starting = { cnt = 1 }
end
load_cfg(ft, lspclient, cfg, loaded)
_NG_Loaded[lspclient] = true
load_cfg(ft, lspclient, cfg, loaded, starting)
-- load_cfg(ft, lspclient, {}, loaded)
::continue::
end
@ -744,7 +549,7 @@ local function setup(user_opts, cnt)
local bufnr = user_opts.bufnr or vim.api.nvim_get_current_buf()
if ft == '' or ft == nil then
log('nil filetype, callback')
local ext = vim.fn.expand('%:e')
local ext = vfn.expand('%:e')
if ext ~= '' then
cnt = cnt or 0
local opts = vim.deepcopy(user_opts)
@ -824,7 +629,7 @@ local function setup(user_opts, cnt)
--- if code lens enabled
if _NgConfigValues.lsp.code_lens_action.enable then
require('navigator.codelens').setup()
require('navigator.codelens').setup(bufnr)
end
-- _LoadedFiletypes[ft .. tostring(bufnr)] = true -- may prevent lsp config when reboot lsp
@ -839,23 +644,38 @@ local function on_filetype()
return
end
if uri == 'file://' or uri == 'file:///' then
log('skip loading for ft ', ft, uri)
trace('skip loading for ft ', ft, uri)
return
end
log (_NG_Loaded)
if _NG_Loaded[bufnr] and type(_NG_Loaded[bufnr]) == 'number' and _NG_Loaded[bufnr] > 1 then
log('navigator was loaded for ft', ft, bufnr)
return
end
-- on_filetype should only be trigger only once for each bufnr
if _NG_Loaded[bufnr] ~= nil and type(_NG_Loaded[bufnr] == 'number') then
_NG_Loaded[bufnr] = _NG_Loaded[bufnr] + 1 -- do not hook and trigger filetype event multiple times
end
if _NG_Loaded[bufnr] == true then
_NG_Loaded[bufnr] = 1 -- record the count
end
-- as setup will send filetype event as well
log(uri)
local wids = vim.fn.win_findbuf(bufnr)
local wids = vfn.win_findbuf(bufnr)
if empty(wids) then
log('buf not shown return')
end
setup({ bufnr = bufnr })
_NG_Loaded[bufnr] = 1
end
return {
setup = setup,
get_cfg = get_cfg,
lsp = servers,
add_servers = add_servers,
on_filetype = on_filetype,
disabled_ft = disabled_ft,

View File

@ -0,0 +1,191 @@
local M = {}
local vfn = vim.fn
M.defaults = function()
local has_lsp, lspconfig = pcall(require, 'lspconfig')
local highlight = require('navigator.lspclient.highlight')
if not has_lsp then
return {
setup = function()
vim.notify('loading lsp config failed LSP may not working correctly', vim.lsp.log_levels.WARN)
end,
}
end
local util = lspconfig.util
local on_attach = require('navigator.lspclient.attach').on_attach
local setups = {
clojure_lsp = {
root_dir = function(fname)
return util.root_pattern('deps.edn', 'build.boot', 'project.clj', 'shadow-cljs.edn', 'bb.edn', '.git')(fname)
or util.path.dirname(fname)
end,
on_attach = on_attach,
filetypes = { 'clojure', 'edn' },
message_level = vim.lsp.protocol.MessageType.error,
cmd = { 'clojure-lsp' },
},
elixirls = {
on_attach = on_attach,
filetypes = { 'elixir', 'eelixir' },
cmd = { 'elixir-ls' },
message_level = vim.lsp.protocol.MessageType.error,
settings = {
elixirLS = {
dialyzerEnabled = true,
fetchDeps = false,
},
},
root_dir = function(fname)
return util.root_pattern('mix.exs', '.git')(fname) or util.path.dirname(fname)
end,
},
gopls = {
on_attach = on_attach,
-- capabilities = cap,
filetypes = { 'go', 'gomod', 'gohtmltmpl', 'gotexttmpl' },
message_level = vim.lsp.protocol.MessageType.Error,
cmd = {
'gopls', -- share the gopls instance if there is one already
'-remote=auto', --[[ debug options ]] --
-- "-logfile=auto",
-- "-debug=:0",
'-remote.debug=:0',
-- "-rpc.trace",
},
flags = { allow_incremental_sync = true, debounce_text_changes = 1000 },
settings = {
gopls = {
-- more settings: https://github.com/golang/tools/blob/master/gopls/doc/settings.md
-- flags = {allow_incremental_sync = true, debounce_text_changes = 500},
-- not supported
analyses = { unusedparams = true, unreachable = false },
codelenses = {
generate = true, -- show the `go generate` lens.
gc_details = true, -- // Show a code lens toggling the display of gc's choices.
test = true,
tidy = true,
},
usePlaceholders = true,
completeUnimported = true,
staticcheck = true,
matcher = 'fuzzy',
diagnosticsDelay = '500ms',
experimentalWatchedFileDelay = '1000ms',
symbolMatcher = 'fuzzy',
gofumpt = false, -- true, -- turn on for new repos, gofmpt is good but also create code turmoils
buildFlags = { '-tags', 'integration' },
-- buildFlags = {"-tags", "functional"}
},
},
root_dir = function(fname)
return util.root_pattern('go.mod', '.git')(fname) or dirname(fname) -- util.path.dirname(fname)
end,
},
clangd = {
flags = { allow_incremental_sync = true, debounce_text_changes = 500 },
cmd = {
'clangd',
'--background-index',
'--suggest-missing-includes',
'--clang-tidy',
'--header-insertion=iwyu',
'--clang-tidy-checks=-*,llvm-*,clang-analyzer-*',
'--cross-file-rename',
},
filetypes = { 'c', 'cpp', 'objc', 'objcpp' },
on_attach = function(client, bufnr)
client.server_capabilities.documentFormattingProvider = client.server_capabilities.documentFormattingProvider
or true
on_attach(client, bufnr)
end,
},
rust_analyzer = {
root_dir = function(fname)
return util.root_pattern('Cargo.toml', 'rust-project.json', '.git')(fname) or util.path.dirname(fname)
end,
filetypes = { 'rust' },
message_level = vim.lsp.protocol.MessageType.error,
on_attach = on_attach,
settings = {
['rust-analyzer'] = {
assist = { importMergeBehavior = 'last', importPrefix = 'by_self' },
cargo = { loadOutDirsFromCheck = true },
procMacro = { enable = true },
},
},
flags = { allow_incremental_sync = true, debounce_text_changes = 500 },
},
sqls = {
filetypes = { 'sql' },
on_attach = function(client, _)
client.server_capabilities.executeCommandProvider = client.server_capabilities.documentFormattingProvider
or true
highlight.diagnositc_config_sign()
require('sqls').setup({ picker = 'telescope' }) -- or default
end,
flags = { allow_incremental_sync = true, debounce_text_changes = 500 },
settings = {
cmd = { 'sqls', '-config', '$HOME/.config/sqls/config.yml' },
-- alterantively:
-- connections = {
-- {
-- driver = 'postgresql',
-- datasourcename = 'host=127.0.0.1 port=5432 user=postgres password=password dbname=user_db sslmode=disable',
-- },
-- },
},
},
pyright = {
on_attach = on_attach,
cmd = { 'pyright-langserver', '--stdio' },
filetypes = { 'python' },
flags = { allow_incremental_sync = true, debounce_text_changes = 500 },
settings = {
python = {
formatting = { provider = 'black' },
analysis = {
autoSearchPaths = true,
useLibraryCodeForTypes = true,
diagnosticMode = 'workspace',
},
},
},
},
ccls = {
on_attach = on_attach,
init_options = {
compilationDatabaseDirectory = 'build',
root_dir = [[ util.root_pattern("compile_commands.json", "compile_flags.txt", "CMakeLists.txt", "Makefile", ".git") or util.path.dirname ]],
index = { threads = 2 },
clang = { excludeArgs = { '-frounding-math' } },
},
flags = { allow_incremental_sync = true },
},
jdtls = {
settings = {
java = { signatureHelp = { enabled = true }, contentProvider = { preferred = 'fernflower' } },
},
},
omnisharp = {
cmd = { 'omnisharp', '--languageserver', '--hostPID', tostring(vfn.getpid()) },
},
terraformls = {
filetypes = { 'terraform', 'tf' },
},
sourcekit = {
cmd = { 'sourcekit-lsp' },
filetypes = { 'swift' }, -- This is recommended if you have separate settings for clangd.
},
}
setups.sumneko_lua = require('navigator.lspclient.sumneko_lua').sumneko_lua()
return setups
end
return M

View File

@ -1,5 +1,3 @@
local lsp = require("vim.lsp")
local M = {}
local capabilities = vim.lsp.protocol.make_client_capabilities()
capabilities.textDocument.completion.completionItem.snippetSupport = true

View File

@ -3,6 +3,7 @@ local M = {}
-- local log = require('navigator.util').log
local api = vim.api
local cmd_group = api.nvim_create_augroup('NGHiGroup', {})
-- lsp sign          ﮻         ﯭ        ﳀ  
function M.diagnositc_config_sign()
if M.configed then
@ -31,35 +32,41 @@ function M.diagnositc_config_sign()
M.configed = true
end
local colors = {
{ '#aefe00', '#aede00', '#aebe00', '#4e7efe' },
{ '#ff00e0', '#df00e0', '#af00e0', '#fedefe' },
{ '#1000ef', '#2000df', '#2000cf', '#f0f040' },
{ '#d8a8a3', '#c8a8a3', '#b8a8a3', '#4e2c33' },
{ '#ffa724', '#efa024', '#dfa724', '#0040ff' },
{ '#afdc2b', '#09dc4b', '#08d04b', '#ef4f8f' },
}
function M.add_highlight()
-- lsp system default
api.nvim_command('hi! link DiagnosticUnderlineError SpellBad')
api.nvim_command('hi! link DiagnosticUnderlineWarning SpellRare')
api.nvim_command('hi! link DiagnosticUnderlineInformation SpellRare')
api.nvim_command('hi! link DiagnosticUnderlineHint SpellRare')
api.nvim_command('hi def link NGPreviewTitle Title')
local colors = {
{ '#aefe00', '#aede00', '#aebe00', '#4e7efe' },
{ '#ff00e0', '#df00e0', '#af00e0', '#fedefe' },
{ '#1000ef', '#2000df', '#2000cf', '#f0f040' },
{ '#d8a8a3', '#c8a8a3', '#b8a8a3', '#4e2c33' },
{ '#ffa724', '#efa024', '#dfa724', '#0040ff' },
{ '#afdc2b', '#09dc4b', '#08d04b', '#ef4f8f' },
}
api.nvim_set_hl(0, 'DiagnosticUnderlineError', { link = 'SpellBad', default = true })
api.nvim_set_hl(0, 'DiagnosticUnderlineWarning', { link = 'SpellRare', default = true })
api.nvim_set_hl(0, 'DiagnosticUnderlineInformation', { link = 'SpellRare', default = true })
api.nvim_set_hl(0, 'DiagnosticUnderlineHint', { link = 'SpellRare', default = true })
api.nvim_set_hl(0, 'NGPreviewTitle', { link = 'Title', default = true })
api.nvim_set_hl(0, 'LspReferenceRead', { default = true, link = 'IncSearch'})
api.nvim_set_hl(0, 'LspReferenceText', { default = true, link = 'Visual'})
api.nvim_set_hl( 0, 'LspReferenceWrite', { default = true, link = 'Search'})
for i = 1, #colors do
for j = 1, 3 do
local cmd = string.format('hi! default NGHiReference_%i_%i guibg=%s guifg=%s ', i, j, colors[i][j], colors[i][4])
vim.cmd(cmd)
local hlg = string.format('NGHiReference_%i_%i', i, j) -- , colors[i][j], colors[i][4]
api.nvim_set_hl(0, hlg, { fg = colors[i][j], bg = colors[i][4], default = true })
end
end
vim.cmd([[
autocmd ColorScheme * |
hi default LspReferenceRead cterm=bold gui=Bold ctermbg=yellow guifg=yellow guibg=purple4 |
hi default LspReferenceText cterm=bold gui=Bold ctermbg=red guifg=SlateBlue guibg=MidnightBlue |
hi default LspReferenceWrite cterm=bold gui=Bold,Italic ctermbg=red guifg=DarkSlateBlue guibg=MistyRose
]])
end
api.nvim_create_autocmd('ColorScheme', {
group = cmd_group,
pattern = '*',
callback = function()
M.add_highlight()
end,
})
return M

View File

@ -3,12 +3,6 @@ local log = util.log
local trace = util.trace
local api = vim.api
local event_hdlrs = {
{ ev = 'BufWritePre', func = require('navigator.diagnostics').set_diag_loclist },
{ ev = { 'CursorHold', 'CursorHoldI' }, func = vim.lsp.buf.document_highlight },
{ ev = 'CursorMoved', func = vim.lsp.buf.clear_references },
}
if vim.lsp.buf.format == nil then
vim.lsp.buf.format = vim.lsp.buf.formatting
end
@ -67,22 +61,16 @@ local key_maps = {
},
{ key = '<Space>ff', func = vim.lsp.buf.format, mode = 'n', desc = 'format' },
{ key = '<Space>ff', func = vim.lsp.buf.range_formatting, mode = 'v', desc = 'range format' },
{ key = '<Space>rf', func = require('navigator.formatting').range_format, mode = 'n', desc = 'range_fmt_v' },
{
key = '<Space>gm',
func = require('navigator.formatting').range_format,
mode = 'n',
desc = 'range format operator e.g gmip',
},
{ key = '<Space>wl', func = require('navigator.workspace').list_workspace_folders, desc = 'list_workspace_folders' },
{ key = '<Space>la', mode = 'n', func = require('navigator.codelens').run_action, desc = 'run code lens action' },
}
local commands = {
[[command! -nargs=* Nctags lua require("navigator.ctags").ctags(<f-args>)]],
"command! -nargs=0 LspLog lua require'navigator.lspclient.config'.open_lsp_log()",
"command! -nargs=0 LspRestart lua require'navigator.lspclient.config'.reload_lsp()",
"command! -nargs=0 LspToggleFmt lua require'navigator.lspclient.mapping'.toggle_lspformat()<CR>",
"command! -nargs=0 LspKeymaps lua require'navigator.lspclient.mapping'.get_keymaps_help()<CR>",
"command! -nargs=0 LspSymbols lua require'navigator.symbols'.side_panel()<CR>",
"command! -nargs=0 TSymbols lua require'navigator.treesitter'.side_panel()<CR>",
"command! -nargs=* Calltree lua require'navigator.hierarchy'.calltree(<f-args>)<CR>",
}
local key_maps_help = {}
-- LuaFormatter on
local M = {}
@ -127,6 +115,18 @@ local check_cap = function(opts)
end
local function set_cmds(_)
local commands = {
[[command! -nargs=* Nctags lua require("navigator.ctags").ctags(<f-args>)]],
"command! -nargs=0 LspLog lua require'navigator.lspclient.config'.open_lsp_log()",
"command! -nargs=0 LspRestart lua require'navigator.lspclient.config'.reload_lsp()",
"command! -nargs=0 LspToggleFmt lua require'navigator.lspclient.mapping'.toggle_lspformat()<CR>",
"command! -nargs=0 LspKeymaps lua require'navigator.lspclient.mapping'.get_keymaps_help()<CR>",
"command! -nargs=0 LspSymbols lua require'navigator.symbols'.side_panel()<CR>",
"command! -nargs=0 TSymbols lua require'navigator.treesitter'.side_panel()<CR>",
"command! -nargs=0 NRefPanel lua require'navigator.reference'.side_panel()<CR>",
"command! -nargs=* Calltree lua require'navigator.hierarchy'.calltree(<f-args>)<CR>",
}
for _, value in pairs(commands) do
vim.cmd(value)
end
@ -183,7 +183,8 @@ local function set_mapping(lsp_attach_info)
key_maps = _NgConfigValues.keymaps or {}
log('setting maps to ', key_maps)
end
local fmtkey, rfmtkey
local fmtkey, rfmtkey, nrfmtkey
require('navigator.formatting')
for _, value in pairs(key_maps) do
if value.doc then
vim.notify('doc field no longer supported in navigator mapping, use desc instead')
@ -216,15 +217,18 @@ local function set_mapping(lsp_attach_info)
if value.desc then
opts.desc = value.desc
end
opts.buffer = bufnr
vim.keymap.set(value.mode or 'n', value.key, value.func, opts)
if string.find(value.desc, 'range format') then
if string.find(value.desc, 'range format') and value.mode == 'v' then
rfmtkey = value.key
elseif string.find(value.desc, 'format') then
fmtkey = value.key
if string.find(value.desc, 'range format') and value.mode == 'n' then
nrfmtkey = value.key
elseif string.find(value.desc, 'format') then
fmtkey = value.key
end
end
end
end
for _, val in pairs(key_maps) do
local helper_msg = ''
if val.desc then
@ -270,6 +274,9 @@ local function set_mapping(lsp_attach_info)
del_keymap('v', rfmtkey)
end
if not range_fmt and nrfmtkey then
del_keymap('n', nrfmtkey)
end
log('enable format ', doc_fmt, range_fmt, _NgConfigValues.lsp.format_on_save)
end
@ -282,42 +289,6 @@ local function autocmd()
})
end
local function set_event_handler(user_opts)
user_opts = user_opts or {}
local file_types = {
'*.c',
'*.cpp',
'*.h',
'*.go',
'*.python',
'*.vim',
'*.sh',
'*.javascript',
'*.html',
'*.css',
'*.lua',
'*.typescript',
'*.rust',
'*.javascriptreact',
'*.typescriptreact',
'*.kotlin',
'*.php',
'*.dart',
'*.nim',
'*.java',
}
-- local format_files = "c,cpp,h,go,python,vim,javascript,typescript" --html,css,
local gn = api.nvim_create_augroup('nvim_nv_event_autos', {})
for _, value in pairs(event_hdlrs) do
api.nvim_create_autocmd(value.ev, {
group = gn,
pattern = file_types,
callback = value.func,
})
end
end
M.toggle_lspformat = function(on)
if on == nil then
_NgConfigValues.lsp.format_on_save = not _NgConfigValues.lsp.format_on_save
@ -349,7 +320,6 @@ function M.setup(attach_opts)
set_cmds(attach_opts)
autocmd()
set_event_handler(attach_opts)
local client = attach_opts.client or {}
local cap = client.server_capabilities or vim.lsp.protocol.make_client_capabilities()
@ -392,6 +362,14 @@ function M.setup(attach_opts)
})
end
api.nvim_create_autocmd({ 'BufWritePre' }, {
group = api.nvim_create_augroup('nvim_nv_event_autos', {}),
buffer = attach_opts.bufnr,
callback = function()
require('navigator.diagnostics').set_diag_loclist(attach_opts.bufnr)
end,
})
local border_style = single
if _NgConfigValues.border == 'double' then
border_style = double

View File

@ -0,0 +1,47 @@
return {
'angularls',
'gopls',
'tsserver',
'flow',
'bashls',
'dockerls',
'julials',
'pylsp',
'pyright',
'jedi_language_server',
'jdtls',
'sumneko_lua',
'vimls',
'html',
'jsonls',
'solargraph',
'cssls',
'yamlls',
'clangd',
'ccls',
'sqls',
'denols',
'graphql',
'dartls',
'dotls',
'kotlin_language_server',
'nimls',
'intelephense',
'vuels',
'volar',
'phpactor',
'omnisharp',
'r_language_server',
'rust_analyzer',
'terraformls',
'svelte',
'texlab',
'clojure_lsp',
'elixirls',
'sourcekit',
'fsautocomplete',
'vls',
'hls',
'tflint',
'terraform_lsp',
}

View File

@ -0,0 +1,89 @@
local vfn = vim.fn
local library = {}
local sumneko_cfg = {
cmd = { 'lua-language-server' },
filetypes = { 'lua' },
on_attach = on_attach,
flags = { allow_incremental_sync = true, debounce_text_changes = 500 },
settings = {
Lua = {
runtime = {
-- Tell the language server which version of Lua you're using (most likely LuaJIT in the case of Neovim)
version = 'LuaJIT',
},
diagnostics = {
enable = true,
-- Get the language server to recognize the `vim` global
globals = { 'vim', 'describe', 'it', 'before_each', 'after_each', 'teardown', 'pending' },
},
completion = { callSnippet = 'Both' },
workspace = {
-- Make the server aware of Neovim runtime files
library = library,
maxPreload = 2000,
preloadFileSize = 40000,
},
telemetry = { enable = false },
},
},
on_new_config = function(cfg, root)
local libs = vim.tbl_deep_extend('force', {}, library)
libs[root] = nil
cfg.settings.Lua.workspace.library = libs
return cfg
end,
}
local function add(lib)
for _, p in pairs(vfn.expand(lib, false, true)) do
p = vim.loop.fs_realpath(p)
if p then
library[p] = true
end
end
end
local function sumneko_lua()
-- add runtime
-- add plugins it may be very slow to add all in path
add('$VIMRUNTIME')
-- add your config
-- local home = vfn.expand("$HOME")
add(vfn.stdpath('config'))
library[vfn.expand('$VIMRUNTIME/lua')] = true
library[vfn.expand('$VIMRUNTIME/lua/vim')] = true
library[vfn.expand('$VIMRUNTIME/lua/vim/lsp')] = true
local on_attach = require('navigator.lspclient.attach').on_attach
local luadevcfg = {
library = {
vimruntime = true, -- runtime path
types = true, -- full signature, docs and completion of vim.api, vim.treesitter, vim.lsp and others
plugins = { 'nvim-treesitter', 'plenary.nvim' },
},
lspconfig = {
-- cmd = {sumneko_binary},
on_attach = on_attach,
},
}
local luadev = {}
local user_luadev = _NgConfigValues.lsp['lua-dev']
if user_luadev then
luadevcfg = vim.tbl_deep_extend('force', luadevcfg, user_luadev)
end
require('navigator.lazyloader').load('lua-dev.nvim', 'folke/lua-dev.nvim')
local ok, l = pcall(require, 'lua-dev')
if ok and l then
luadev = l.setup(luadevcfg)
end
sumneko_cfg = vim.tbl_deep_extend('force', sumneko_cfg, luadev)
return sumneko_cfg
end
return {
sumneko_lua = sumneko_lua,
}

View File

@ -19,7 +19,7 @@ cwd = gutil.add_pec(cwd)
local ts_nodes = require('navigator.lru').new(1000, 1024 * 1024)
local ts_nodes_time = require('navigator.lru').new(1000)
local TS_analysis_enabled = require('navigator').config_values().treesitter_analysis
local nts = require('navigator.treesitter')
-- extract symbol from range
function M.get_symbol(text, range)
if range == nil then
@ -169,7 +169,7 @@ local function ts_functions(uri, optional)
lerr('ts not enabled')
return nil
end
local ts_func = require('navigator.treesitter').buf_func
local ts_func = nts.buf_func
local bufnr = vim.uri_to_bufnr(uri)
local x = os.clock()
trace(ts_nodes)
@ -230,7 +230,7 @@ local function ts_definition(uri, range, optional)
if optional then
return
end
local ts_def = require('navigator.treesitter').find_definition
local ts_def = nts.find_definition
local bufnr = vim.uri_to_bufnr(uri)
local x = os.clock()
trace(ts_nodes)
@ -252,6 +252,7 @@ local function ts_definition(uri, range, optional)
end
local function find_ts_func_by_range(funcs, range)
log(funcs, range)
if funcs == nil or range == nil then
return nil
end
@ -352,7 +353,6 @@ function M.locations_to_items(locations, ctx)
local unload_bufnrs = {}
for i, loc in ipairs(locations) do
local funcs = nil
local item = lsp.util.locations_to_items({ loc }, enc)[1]
item.range = locations[i].range or locations[i].targetRange
item.uri = locations[i].uri or locations[i].targetUri
@ -363,13 +363,25 @@ function M.locations_to_items(locations, ctx)
log(cwd)
end
-- only load top 30 file.
local proj_file = item.uri:find(cwd) or is_win or i < 30
local proj_file = item.uri:find(cwd) or is_win or i < _NgConfigValues.treesitter_analysis_max_num
local unload, def
if TS_analysis_enabled and proj_file then
funcs, unload = ts_functions(item.uri, ts_optional(i, #unload_bufnrs))
local context = ''
if TS_analysis_enabled and proj_file and not ctx.no_show then
local ts_context = nts.ref_context
local bufnr = vim.uri_to_bufnr(item.uri)
if not api.nvim_buf_is_loaded(bufnr) then
log('! load buf !', item.uri, bufnr)
vim.fn.bufload(bufnr)
unload = bufnr
end
context = ts_context({ bufnr = bufnr, pos = item.range }) or ''
log(context)
-- TODO: unload buffers
if unload then
table.insert(unload_bufnrs, unload)
unload = nil
end
if not uri_def[item.uri] then
-- find def in file
@ -408,9 +420,15 @@ function M.locations_to_items(locations, ctx)
end
item.filename = assert(vim.uri_to_fname(item.uri))
local filename = item.filename:gsub(cwd .. path_sep, path_cur, 1)
if ctx.no_show then
local shorten = require('guihua.util').shorten
filename = shorten(filename)
end
item.display_filename = filename or item.filename
item.call_by = find_ts_func_by_range(funcs, item.range)
item.call_by = context -- find_ts_func_by_range(funcs, item.range)
item.rpath = util.get_relative_path(cwd, item.filename)
width = math.max(width, #item.text)
item.symbol_name = M.get_symbol(item.text, item.range)

View File

@ -11,10 +11,11 @@ local locations_to_items = lsphelper.locations_to_items
local M = {}
local ref_view = function(err, locations, ctx, cfg)
cfg = cfg or {}
local truncate = cfg and cfg.truncate or 20
local opts = {}
trace('arg1', err, ctx, locations)
log(#locations, locations[1])
-- log(#locations, locations[1])
if ctx.combine then
-- wait for both reference and definition LSP request
if ctx.results == nil then
@ -41,27 +42,16 @@ local ref_view = function(err, locations, ctx, cfg)
end
vim.list_extend(locations, definitions.result)
end
if references and references.result and #references.result > 0 then
local refs = references.result
for _, value in pairs(locations) do
local vrange = value.range or { start = { line = 0 }, ['end'] = { line = 0 } }
for i = 1, #refs, 1 do
local rg = refs[i].range or {}
trace(value, refs[i])
trace(rg, vrange)
if rg.start.line == vrange.start.line and rg['end'].line == vrange['end'].line then
table.remove(refs, i)
break
end
end
end
vim.list_extend(locations, refs)
end
err = nil
trace(locations)
-- lets de-dup first 10 elements. some lsp does not recognize definition and reference difference
locations = util.dedup(locations)
trace(locations)
end
-- log("num", num)
-- log("bfnr", bufnr)
@ -89,11 +79,11 @@ local ref_view = function(err, locations, ctx, cfg)
local thread_items = vim.deepcopy(items)
log('splits: ', #items, #second_part)
local ft = vim.api.nvim_buf_get_option(ctx.bufnr, 'ft')
local ft = vim.api.nvim_buf_get_option(ctx.bufnr or 0, 'ft')
local wwidth = vim.api.nvim_get_option('columns')
local mwidth = _NgConfigValues.width
width = math.min(width + 30, 120, math.floor(wwidth * mwidth))
width = math.min(width + 30, math.floor(wwidth * mwidth))
-- log(items)
-- log(width)
opts = {
@ -105,12 +95,22 @@ local ref_view = function(err, locations, ctx, cfg)
api = 'Reference',
enable_preview_edit = true,
}
local listview = gui.new_list_view(opts)
local listview
if not ctx.no_show then
listview = gui.new_list_view(opts)
if listview == nil then
vim.notify('failed to create preview windows', vim.lsp.log_levels.INFO)
return
if listview == nil then
vim.notify('failed to create preview windows', vim.lsp.log_levels.INFO)
return
end
end
if ctx.no_show then
opts.side_panel = true
local data = require('navigator.render').prepare_for_render(items, opts)
return data
end
-- trace("update items", listview.ctrl.class)
local nv_ref_async
nv_ref_async = vim.loop.new_async(vim.schedule_wrap(function()
@ -145,6 +145,9 @@ end
local ref_hdlr = function(err, locations, ctx, cfg)
_NgConfigValues.closer = nil
trace(err, locations, ctx, cfg)
if ctx.no_show then
return ref_view(err, locations, ctx, cfg)
end
M.async_hdlr = vim.loop.new_async(vim.schedule_wrap(function()
ref_view(err, locations, ctx, cfg)
if M.async_hdlr:is_active() then
@ -219,7 +222,36 @@ local ref = function()
end)
end
local function side_panel()
local Panel = require('guihua.panel')
local currentWord = vim.fn.expand('<cword>')
local p = Panel:new({
scope = 'range',
header = '' .. currentWord .. ' ref ',
render = function(bufnr)
local ft = vim.api.nvim_buf_get_option(bufnr, 'buftype')
if ft == 'nofile' or ft == 'guihua' or ft == 'prompt' then
return
end
local ref_params = vim.lsp.util.make_position_params()
local sync_req = require('navigator.lspwrapper').call_sync
return sync_req(
'textDocument/references',
ref_params,
{ timeout = 1000, bufnr = bufnr, no_show = true },
vim.lsp.with(function(err, locations, ctx, cfg)
cfg.side_panel = true
return ref_hdlr(err, locations, ctx, cfg)
end, { no_show = true })
)
end,
})
p:open(true)
end
return {
side_panel = side_panel,
reference_handler = ref_hdlr,
reference = ref_req,
ref_view = ref_view,

View File

@ -1,7 +1,9 @@
local log = require('guihua.log').info
local trace = require('guihua.log').trace
local M = {}
local util = require('navigator.util')
local log = util.log
local trace = util.trace
local clone = require('guihua.util').clone
local M = {}
local function filename(url)
if url == nil then
return ''
@ -69,7 +71,7 @@ function M.prepare_for_render(items, opts)
icon = devicons.get_icon(fn, ext) or icon
end
-- local call_by_presented = false
opts.width = opts.width or 100
opts.width = opts.width or math.floor(vim.api.nvim_get_option('columns') * 0.8)
local win_width = opts.width -- buf
for i = 1, #items do
@ -150,52 +152,28 @@ function M.prepare_for_render(items, opts)
trace(ts_report, header_len)
item.text = item.text:gsub('%s*[%[%(%{]*%s*$', '')
if item.call_by ~= nil and #item.call_by > 0 then
trace('call_by:', #item.call_by)
for _, value in pairs(item.call_by) do
if value.node_text then
local txt = value.node_text:gsub('%s*[%[%(%{]*%s*$', '')
local endwise = '{}'
if value.type == 'method' or value.type == 'function' then
endwise = '()'
local syb = items[i].symbol_name
if txt == items[i].symbol_name or (#txt > #syb and txt:sub(#txt - #syb + 1) == syb) then
if ts_report ~= _NgConfigValues.icons.value_definition .. ' ' then
ts_report = ts_report .. _NgConfigValues.icons.value_definition .. ' '
end
header_len = #ts_report + 1
else
ts_report = ts_report .. ''
end
end
if #ts_report > header_len then
ts_report = ts_report .. ''
end
ts_report = ts_report .. value.kind .. txt .. endwise
trace(item)
end
end
if item.call_by ~= nil and item.call_by ~= '' then
ts_report = ts_report .. '' .. item.call_by
end
if #ts_report > 1 then
space, trim = get_pads(win_width, item.text, ts_report)
local l = math.max(20, opts.width - math.min(20, #ts_report))
if trim and #item.text < l then
trim = false
end
if trim then
local ts_r = ts_report or ''
item.text = string.sub(item.text, 1, math.max(1, opts.width - math.max(20, #ts_r)))
local _, j = string.gsub(item.text, [["]], '')
if j % 2 == 1 then
item.text = item.text .. '"'
end
_, j = string.gsub(item.text, [[']], '')
if j % 2 == 1 then
item.text = item.text .. [[']]
end
item.text = item.text .. ''
item.text = string.sub(item.text, 1, l)
item.text = util.sub_match(item.text)
-- let check if there are unmatched "/'
end
if #space + #item.text + #ts_report >= win_width then
if #item.text + #ts_report > win_width then
trace('exceeding', #item.text, #ts_report, win_width)
space = ' '
if #item.text + #ts_report >= win_width then
space = ' '
local len = math.max(win_width - #item.text - 4, 16)
trace('exceeding', #item.text, #ts_report, win_width, len)
ts_report = ts_report:sub(1, len)
else
local remain = win_width - #item.text - #ts_report
trace('remain', remain)

View File

@ -23,6 +23,7 @@ local cwd = vim.loop.cwd()
local log = require('navigator.util').log
local lerr = require('navigator.util').error
local trace = function(...) end
trace = log
if vim.fn.has('nvim-0.7') == 1 then
local trace = require('navigator.util').trace
end
@ -109,6 +110,96 @@ function M.find_definition(range, bufnr)
end
end
function M.get_tsnode_at_pos(pos, bufnr, ignore_injected_langs)
if not pos or not pos.start then
return
end
local cursor_range = { pos.start.line, pos.start.character }
local buf = bufnr
local root_lang_tree = parsers.get_parser(buf)
if not root_lang_tree then
return
end
local root
if ignore_injected_langs then
for _, tree in ipairs(root_lang_tree:trees()) do
local tree_root = tree:root()
if tree_root and ts_utils.is_in_node_range(tree_root, cursor_range[1], cursor_range[2]) then
root = tree_root
break
end
end
else
root = ts_utils.get_root_for_position(cursor_range[1], cursor_range[2], root_lang_tree)
end
if not root then
return
end
return root:named_descendant_for_range(cursor_range[1], cursor_range[2], cursor_range[1], cursor_range[2])
end
-- Trim spaces and opening brackets from end
local transform_line = function(line)
line = line:gsub("%s*[%[%(%{]*%s*$", "")
line = line:gsub("function", "")
line = line:gsub("func%w*%s+", "")
if _NgConfigValues.treesitter_analysis_condense then
line = line:gsub("%([%a%.,%s%[%]%*]+%)", "()")
-- this is for multi return
line = line:gsub("%([%a%.,%s%[%]%*]+%)", "()")
line = line:gsub("%(%)%s*%(%)", "()")
end
return line
end
function M.ref_context(opts)
if not parsers.has_parser() then
return
end
local options = opts or {}
local bufnr = options.bufnr or 0
local pos = options.pos
if not pos then
pos = {start = vim.lsp.util.make_position_params().position}
end
local indicator_size = options.indicator_size or 100
local type_patterns = options.type_patterns or { "class", "function", "method" }
local transform_fn = options.transform_fn or transform_line
local separator = options.separator or ""
local current_node = M.get_tsnode_at_pos(pos, bufnr)
if not current_node then
log('no node at pos', bufnr, pos)
return ""
end
local lines = {}
local expr = current_node
while expr do
local line = ts_utils._get_line_for_node(expr, type_patterns, transform_fn, bufnr)
log(line)
if line ~= "" and not vim.tbl_contains(lines, line) then
table.insert(lines, 1, line)
end
expr = expr:parent()
end
local text = table.concat(lines, separator)
local text_len = #text
if text_len > indicator_size then
local str = text:sub(1, text_len)
return util.sub_match(str)
end
return text
end
--- Get definitions of bufnr (unique and sorted by order of appearance).
--- This function copy from treesitter/refactor/navigation.lua
local function get_definitions(bufnr)
@ -121,23 +212,23 @@ local function get_definitions(bufnr)
ts_locals.recurse_local_nodes(loc.definition, function(_, node, _, match)
-- lua doesn't compare tables by value,
-- use the value from byte count instead.
local k, l, start = node:start()
local row, col, offset = node:start()
local erow, ecol, end_ = node:end_()
trace(node, match)
trace(k, l, start, node:parent(), node:parent():start(), node:parent():type())
trace(row, col, erow, offset, node:parent(), node:parent():start(), node:parent():type())
if node and node:parent() and string.find(node:parent():type(), 'parameter_declaration') then
log('parameter_declaration skip')
return
end
nodes_set[start] = { node = node, type = match or '' }
nodes_set[offset] = { node = node, type = match or '' }
end)
end
if loc.method then -- for go
ts_locals.recurse_local_nodes(loc.method, function(def, node, full_match, match)
local k, l, start = node:start()
trace(k, l, start, def, node, full_match, match, node:parent(), node:parent():start(), node:parent():type())
local row, col, start = node:start()
trace(row, col, start, def, node, full_match, match, node:parent(), node:parent():start(), node:parent():type())
if node:type() == 'field_identifier' and nodes_set[start] == nil then
nodes_set[start] = { node = node, type = 'method' }
end
@ -154,16 +245,32 @@ local function get_definitions(bufnr)
end
if loc.reference then -- for go
ts_locals.recurse_local_nodes(loc.reference, function(def, node, full_match, match)
local k, l, start = node:start()
local row, col, start = node:start()
local p1, p1t = '', ''
local p2, p2t = '', ''
local p3, p3t = '', ''
if node:parent() and node:parent():parent() then
p1 = node:parent()
p1t = node:parent():type()
p2 = node:parent():parent()
p2t = node:parent():parent():type()
end
trace(k, l, start, def, node, full_match, match, p1t, p1, node:parent():start(), node:parent():type(), p2, p2t)
if p2 and p2:parent() then
p3 = p2:parent()
p3t = p2:parent():type()
end
trace(row, col, start, def, node, full_match, match, p1t, p1, node:parent():start(), node:parent():type(), p2, p2t, p3, p3t)
if p1t == 'arrow_function' then
row, col, start = p1:start()
trace('arrow_function 1', row, col)
nodes_set[start] = { node = p1, type = p1t }
end
if p2t == 'arrow_function' then
row, col, start = p2:start()
trace('arrow_function 2', row, col)
nodes_set[start] = { node = p2, type = p2t }
end
if nodes_set[start] == nil then
if -- qualified_type : e.g. io.Reader inside interface
node:parent()
@ -210,7 +317,7 @@ local function get_scope(type, source)
local parent = current:parent()
trace(source:type(), source:range(), parent)
if type == 'method' or type == 'function' and parent ~= nil then
if type == 'method' or type:find('function') and parent ~= nil then
trace(parent:type(), parent:range())
-- a function name
if parent:type() == 'function_name' then
@ -345,7 +452,7 @@ local function get_all_nodes(bufnr, filter, summary)
trace(bufnr, filter, summary)
if not bufnr then
vim.notify('get_all_node invalide bufnr', vim.lsp.log_levels.WARN)
vim.notify('get_all_node invalid bufnr', vim.lsp.log_levels.WARN)
end
summary = summary or false
local ft = vim.api.nvim_buf_get_option(bufnr, 'filetype')
@ -362,17 +469,13 @@ local function get_all_nodes(bufnr, filter, summary)
local display_filename = fname:gsub(cwd .. path_sep, path_cur, 1)
local all_nodes = {}
-- Support completion-nvim customized label map
-- local customized_labels = vim.g.completion_customize_lsp_label or {}
-- Force some types to act like they are parents
-- instead of neighbors of the next nodes.
local containers = {
local containers = filter or {
['function'] = true,
['local_function'] = true,
['arrow_function'] = true,
['type'] = true,
['class'] = true,
['call_expression'] = true,
-- ['var'] = true,
['struct'] = true,
['method'] = true,
@ -395,8 +498,8 @@ local function get_all_nodes(bufnr, filter, summary)
for i = 1, n do
local index = n + 1 - i
local parent_def = parents[index]
log(parent_def.type, parent_def.node:type(), vim.treesitter.get_node_text(parent_def.node, bufnr))
log(def.node:type(), vim.treesitter.get_node_text(def.node, bufnr))
-- trace(parent_def.type, parent_def.node:type(), vim.treesitter.get_node_text(parent_def.node, bufnr))
-- trace(def.node:type(), vim.treesitter.get_node_text(def.node, bufnr))
if
ts_utils.is_parent(parent_def.node, def.node)
or (
@ -410,10 +513,10 @@ local function get_all_nodes(bufnr, filter, summary)
)
)
then
log('is parent', i, index)
-- trace('is parent', i, index)
break
else
log('leave node', i, index)
-- trace('leave node', i, index)
parents[index] = nil
end
end
@ -440,7 +543,10 @@ local function get_all_nodes(bufnr, filter, summary)
trace('skipped', item.type, item.kind)
goto continue
end
item.node_text = vim.treesitter.get_node_text(tsdata, bufnr) or ''
local text = vim.treesitter.get_node_text(tsdata, bufnr) or ''
text = vim.split(text, '\n')[1] or ''
item.node_text = text
log(item.node_text)
local scope, is_func
if summary then
@ -448,6 +554,7 @@ local function get_all_nodes(bufnr, filter, summary)
else
scope, is_func = get_smallest_context(tsdata)
end
log(item, scope, is_func)
if is_func then
-- hack for lua and maybe other language aswell
local parent = tsdata:parent()
@ -477,7 +584,7 @@ local function get_all_nodes(bufnr, filter, summary)
trace(item.node_text, item.kind, item.type)
if scope ~= nil then
if not is_func and summary then
log('skipped', item.node_text, item.type)
trace('skipped', item.node_text, item.type)
goto continue
end
item.node_scope = ts_utils.node_to_lsp_range(scope)
@ -581,6 +688,7 @@ function M.buf_func(bufnr)
local all_nodes, width = get_all_nodes(bufnr, {
['function'] = true,
['arrow_function'] = true,
['var'] = true,
['method'] = true,
['class'] = true,
@ -614,6 +722,7 @@ function M.buf_func(bufnr)
return false
end)
end
log(all_nodes)
return all_nodes, width
end

View File

@ -61,7 +61,7 @@ function M.get_data_from_file(filename, startLine)
return { data = data, line = displayLine }
end
function M.io_read(filename, total)
function M.io_read(filename)
local f = io.open(filename, 'r')
if f == nil then
return nil
@ -504,7 +504,7 @@ function M.dedup(locations)
if not range then
break
end
local key = (range.uri or value.targetUri or '')
local key = (value.uri or range.uri or value.targetUri or '')
.. ':'
.. tostring(range.start.line)
.. ':'
@ -524,7 +524,9 @@ function M.dedup(locations)
end
end
end
table.sort(del)
for i = #del, 1, -1 do
M.log('remove ', del[i])
table.remove(locations, del[i])
end
return locations
@ -540,4 +542,31 @@ function M.range_inside(outer, inner)
return outer.start.line <= inner.start.line and outer['end'].line >= inner['end'].line
end
function M.dirname(pathname)
local path_sep = require('navigator.util').path_sep()
local strip_dir_pat = path_sep .. '([^' .. path_sep .. ']+)$'
local strip_sep_pat = path_sep .. '$'
if not pathname or #pathname == 0 then
return
end
local result = pathname:gsub(strip_sep_pat, ''):gsub(strip_dir_pat, '')
if #result == 0 then
return '/'
end
return result
end
function M.sub_match(str)
local _, j = string.gsub(str, [["]], '')
if j % 2 == 1 then
str = str .. '"'
end
_, j = string.gsub(str, [[']], '')
if j % 2 == 1 then
str = str .. [[']]
end
str = str .. ''
return str
end
return M

View File

@ -19,7 +19,7 @@ M.remove_workspace_folder = function()
local folders = vim.lsp.buf.list_workspace_folders()
if #folders > 1 then
select(folders, { prompt = 'select workspace to delete' }, function(workspace)
return select(folders, { prompt = 'select workspace to delete' }, function(workspace)
vim.lsp.buf.remove_workspace_folder(workspace)
end)
end
@ -37,7 +37,7 @@ function M.workspace_symbol_live()
local height = _NgConfigValues.height or 0.4
height = math.floor(height * vfn.winheight('%'))
local width = _NgConfigValues.width or 0.7
width = math.floor(width * vfn.winwidth('%'))
width = math.floor(vim.api.nvim_get_option('columns') * width)
local bufnr = vim.api.nvim_get_current_buf()
local ft = vim.o.ft
local data = { { text = 'input the symbol name to start fuzzy search' } }
@ -47,7 +47,7 @@ function M.workspace_symbol_live()
local ListView = require('guihua.listview')
local opt = {
api = '',
bg = 'GHListDark',
bg = 'GuihuaListDark',
data = data,
items = data,
enter = true,

View File

@ -1 +1,6 @@
std="lua51+vim"
std="lua52+vim"
[rules]
global_usage = "allow"
multiple_statements = "allow"
unused_variable = "allow"

View File

@ -60,10 +60,10 @@ describe('should run lsp call hierarchy', function()
-- eq(panel.activePanel.sections[1].nodes[1].name, 'measure')
end)
it('should show hierarchy', function()
it('should not crash and show hierarchy', function()
vim.fn.setpos('.', { bufn, 24, 15, 0 })
local ret = require('navigator.hierarchy')._call_hierarchy()
vim.wait(400, function() end)
eq(ret, {})
eq(ret, ret) -- make sure doesn't crash the result
end)
end)

View File

@ -114,9 +114,9 @@ describe('should run lsp reference', function()
-- print('win', vim.inspect(win))
print('items', vim.inspect(items))
eq(win.ctrl.data[1].display_filename, './interface.go')
eq(win.ctrl.data[1].display_filename, './tests/fixtures/interface.go')
eq(win.ctrl.data[2].range.start.line, 14)
eq(items[1].display_filename, './interface.go')
eq(items[1].display_filename, './tests/fixtures/interface.go')
-- eq(width, 60)
end)
@ -137,7 +137,7 @@ describe('should run lsp reference', function()
-- print('win', vim.inspect(win))
print('items', vim.inspect(items))
-- eq(win.ctrl.data, "./interface.go")
eq(win.ctrl.data[1].display_filename, './interface.go')
eq(win.ctrl.data[1].display_filename, './tests/fixtures/interface.go')
eq(win.ctrl.data[2].range.start.line, 14)
-- eq(items[1].display_filename, "./interface.go")

View File

@ -1,5 +1,5 @@
[selene]
base = "lua51"
base = "lua52"
name = "vim"
[vim]
@ -8,9 +8,11 @@ any = true
[_G]
property = true
writable = "new-fields"
[_NgConfigValues]
property = true
writable = "new-fields"
any = true
# property = true
# writable = "full-write"
[debug]
property = true

47
vim.yml Normal file
View File

@ -0,0 +1,47 @@
---
base: lua52
name: vim
globals:
_G:
property: new-fields
_NgConfigValues:
any: true
after_each:
args:
- type: function
assert.equals:
args:
- type: any
- type: any
- required: false
type: any
assert.is_not:
any: true
assert.same:
args:
- type: any
- type: any
assert.spy:
args:
- type: any
assert.stub:
args:
- type: any
assert.truthy:
args:
- type: any
before_each:
args:
- type: function
debug:
property: read-only
describe:
args:
- type: string
- type: function
it:
args:
- type: string
- type: function
vim:
any: true