Vim diagnostic refactor (#63)

* multigrid support

* Tuning diagnostic performance, add codelens inline hint function

* add ctx to error marker handler

* setup lsp_signature from navigator

* diagnostic refact PR https://github.com/neovim/neovim/pull/15585

* diagnostic api changes

* allow disable emoji/nerdfont icons setup

* improve diagnostic/codeaction/codelens preview popup; add seperate line

* severity_sort set to reverse

* prettier for markdown. code action virtual text show title
neovim_0.6
rayx 3 years ago committed by GitHub
parent 90039247b4
commit 79fee5dda8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -13,23 +13,25 @@ The following screenshot shows javascript call tree 🌲 of variable `browser` i
![navigator](https://user-images.githubusercontent.com/1681295/126022829-291a7a2e-4d24-4fde-8293-5ae61562e67d.jpg)
Explanation:
- The first line of floating windows shows there are 3 references for the symbol <span style="color:red"> *browser* </span> in closure.js
- The first reference of browser is an assignment, an emoji 📝 indicates the value is changed in this line. In many
cases, we search for references to find out when the value changed.
- The first line of floating windows shows there are 3 references for the symbol <span style="color:red"> _browser_ </span> in closure.js
- The first reference of browser is an assignment, an emoji 📝 indicates the value is changed in this line. In many
cases, we search for references to find out when the value changed.
- The second reference of `browser` is inside function `displayName` and `displayName` sit inside `makeFunc`, So you
will see ` displayName{} <- makeFunc{}`
will see ` displayName{} <- makeFunc{}`
- The third similar to the second, as var browser is on the right side of '=', the value not changed in this line
and emoji is not shown.
and emoji is not shown.
#### Example: C++ definition
C++ example: search reference and definition
![cpp_ref](https://user-images.githubusercontent.com/1681295/119215215-8bd7a080-bb0f-11eb-82fc-8cdf1955e6e7.jpg)
You may find a 🦕 dinosaur(d) on the line of `Rectangle rect,` which means there is a definition (d for def) of rect in this line.
You may find a 🦕 dinosaur(d) on the line of `Rectangle rect,` which means there is a definition (d for def) of rect in this line.
``<- f main()`` means the definition is inside function main().
`<- f main()` means the definition is inside function main().
#### Golang struct type
Struct type references in multiple Go ﳑ files
![go_reference](https://user-images.githubusercontent.com/1681295/119123823-54b3b180-ba73-11eb-8790-097601e10f6a.gif)
@ -37,6 +39,7 @@ Struct type references in multiple Go ﳑ files
This feature can provide you info in which function/class/method the variable was referenced. It is handy for a large
project where class/function definition is too long to fit into the preview window. Also provides a bird's eye view of where the
variable is:
- Referenced
- Modified
- Defined
@ -45,14 +48,14 @@ variable is:
# Features:
- LSP easy setup. Support the most commonly used lsp clients setup. Dynamic lsp activation based on buffer type. This
also enables you to handle workspace with mixed types of codes (e.g. Go + javascript + yml). A better default setup is
included for LSP clients.
also enables you to handle workspace with mixed types of codes (e.g. Go + javascript + yml). A better default setup is
included for LSP clients.
- Out of box experience. 10 lines of minimum vimrc can turn your neovim into a full-featured LSP & Treesitter powered IDE
- Unorthodox UI with floating windows, navigator provides a visual way to manage and navigate through symbols, diagnostic errors, reference etc. It covers
all features(handler) provided by LSP from commonly used search reference, to less commonly used search for interface
implementation.
all features(handler) provided by LSP from commonly used search reference, to less commonly used search for interface
implementation.
- Luv async thread and tasks
@ -71,14 +74,14 @@ implementation.
- Grouping references/implementation/incoming/outgoing based on file names.
- Treesitter based variable/function context analysis. It is 10x times faster compared to purely rely on LSP. In most
of the case, it takes treesitter less than 4 ms to read and render all nodes for a file of 1,000 LOC.
of the case, it takes treesitter less than 4 ms to read and render all nodes for a file of 1,000 LOC.
- The first plugin, IMO, allows you to search in all treesitter symbols in the workspace.
- Nerdfont, emoji for LSP and treesitter kind
- Optimize display (remove trailing bracket/space), display the caller of reference, de-duplicate lsp results (e.g reference
in the same line). Using treesitter for file preview highlighter etc
in the same line). Using treesitter for file preview highlighter etc
- ccls call hierarchy (Non-standard `ccls/call` API) supports
@ -186,9 +189,6 @@ EOF
```
Nondefault configuration example:
```lua
@ -219,7 +219,7 @@ require'navigator'.setup({
code_action_prompt = {enable = true, sign = true, sign_priority = 40, virtual_text = true},
icons = {
-- Code action
code_action_icon = "",
code_action_icon = "🏏",
-- Diagnostics
diagnostic_head = '🐛',
diagnostic_head_severity_1 = "🈲",
@ -268,6 +268,7 @@ require'navigator'.setup({
### LSP clients
Built clients:
```lua
local servers = {
"angularls", "gopls", "tsserver", "flow", "bashls", "dockerls", "julials", "pylsp", "pyright",
@ -283,24 +284,24 @@ Navigator will try to load avalible lsp server/client based on filetype. The cli
incremental sync and debounce is enabled by navigator. And the lsp
snippet will be enabled. So you could use COQ and nvim-cmp snippet expand.
Other than above setup, additional none default setup are used for following lsp:
* gopls
* clangd
* rust_analyzer
* sqls
* sumneko_lua
* pyright
* ccls
- gopls
- clangd
- rust_analyzer
- sqls
- sumneko_lua
- pyright
- ccls
Please check [client setup](https://github.com/ray-x/navigator.lua/blob/26012cf9c172aa788a2e53018d94b32c5c75af75/lua/navigator/lspclient/clients.lua#L98-L234)
The plugin can work with multiple LSP, e.g sqls+gopls+efm. But there are cases you may need to disable some of the
servers. (Prevent loading multiple LSP for same source code.) e.g. I saw strange behaviours when I use pyls+pyright+pyls_ms
The plugin can work with multiple LSP, e.g sqls+gopls+efm. But there are cases you may need to disable some of the
servers. (Prevent loading multiple LSP for same source code.) e.g. I saw strange behaviours when I use pyls+pyright+pyls_ms
together. If you have multiple similar LSP installed and have trouble with the plugin, please enable only one at a time.
### Disable a lsp client loading from navigator
To disable a specific LSP, set `filetypes` to {} e.g.
```lua
@ -320,56 +321,54 @@ require'navigator'.setup({
### Default keymaps
| mode | key | function |
|--- |--- |--- |
| n | gr | show reference and context |
| i | \<m-k\> | signature help |
| n | \<c-k\> | signature help |
| n | gW | workspace symbol |
| n | gD | declaration |
| n | g0 | document symbol |
| n | \<C-]\> | go to definition (if multiple show listview) |
| n | gp | definition |
| n | \<C-LeftMouse\> | definition|
| n | g\<LeftMouse\> | implementation|
| n | gT | treesitter document symbol |
| n | \<Leader\>gT | treesitter symbol for all open buffers |
| n | K | hover doc |
| n | \<Space\>ca | code action (when you see 💡 ) |
| n | \<Space\>la | code lens action (when you see a codelens indicator) |
| v | \<Space\>cA | range code action (when you see 💡 ) |
| n | \<Space\>rn | rename with floating window|
| n | \<Leader\>re | rename (lsp default)|
| n | \<Leader\>gi | incoming calls|
| n | \<Leader\>go | outgoing calls|
| n | gi | implementation |
| n | \<Sapce\> D | type definition |
| n | gL | show line diagnostic |
| n | gG | show diagnostic for all buffers |
| n | ]d | next diagnostic|
| n | [d | previous diagnostic|
| n | ]r | next treesitter reference/usage|
| n | [r | previous treesitter reference/usage|
| n | \<Sapce\> wa | add workspace folder|
| n | \<Sapce\> wr | remove workspace folder|
| n | \<Sapce\> wl | print workspace folder|
| n | \<Leader\>k | toggle reference highlight |
| i/n | \<C-p\> | previous item in list|
| i/n | \<C-n\> | next item in list|
| i/n | number 1~9 | move to ith row/item in the list|
| i/n | \<Up\> | previous item in list|
| i/n | \<Down\> | next item in list|
| n | \<Ctrl-w\>j | move cursor to preview (windows move to bottom view point)|
| n | \<Ctrl-w\>k | move cursor to list (windows move to up view point)|
| i/n | \<C-o\> | open preview file in nvim/Apply action|
| n | \<C-v\> | open preview file in nvim with vsplit|
| n | \<C-s\> | open preview file in nvim with split|
| n | \<Enter\> | open preview file in nvim/Apply action|
| 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|
| mode | key | function |
| ---- | --------------- | ---------------------------------------------------------- |
| n | gr | show reference and context |
| i | \<m-k\> | signature help |
| n | \<c-k\> | signature help |
| n | gW | workspace symbol |
| n | gD | declaration |
| n | g0 | document symbol |
| n | \<C-]\> | go to definition (if multiple show listview) |
| n | gp | definition |
| n | \<C-LeftMouse\> | definition |
| n | g\<LeftMouse\> | implementation |
| n | gT | treesitter document symbol |
| n | \<Leader\>gT | treesitter symbol for all open buffers |
| n | K | hover doc |
| n | \<Space\>ca | code action (when you see 💡 ) |
| n | \<Space\>la | code lens action (when you see a codelens indicator) |
| v | \<Space\>cA | range code action (when you see 💡 ) |
| n | \<Space\>rn | rename with floating window |
| n | \<Leader\>re | rename (lsp default) |
| n | \<Leader\>gi | incoming calls |
| n | \<Leader\>go | outgoing calls |
| n | gi | implementation |
| n | \<Sapce\> D | type definition |
| n | gL | show line diagnostic |
| n | gG | show diagnostic for all buffers |
| n | ]d | next diagnostic |
| n | [d | previous diagnostic |
| n | ]r | next treesitter reference/usage |
| n | [r | previous treesitter reference/usage |
| n | \<Sapce\> wa | add workspace folder |
| n | \<Sapce\> wr | remove workspace folder |
| n | \<Sapce\> wl | print workspace folder |
| n | \<Leader\>k | toggle reference highlight |
| i/n | \<C-p\> | previous item in list |
| i/n | \<C-n\> | next item in list |
| i/n | number 1~9 | move to ith row/item in the list |
| i/n | \<Up\> | previous item in list |
| i/n | \<Down\> | next item in list |
| n | \<Ctrl-w\>j | move cursor to preview (windows move to bottom view point) |
| n | \<Ctrl-w\>k | move cursor to list (windows move to up view point) |
| i/n | \<C-o\> | open preview file in nvim/Apply action |
| n | \<C-v\> | open preview file in nvim with vsplit |
| n | \<C-s\> | open preview file in nvim with split |
| n | \<Enter\> | open preview file in nvim/Apply action |
| 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:
@ -382,11 +381,9 @@ hi default GHTextViewDark guifg=#e0d8f4 guibg=#332e55
hi default GHListDark guifg=#e0d8f4 guibg=#103234
```
There are other Lsp highlight been used in this plugin, e.g LspReferenceRead/Text/Write are used for document highlight,
There are other Lsp highlight been used in this plugin, e.g LspReferenceRead/Text/Write are used for document highlight,
LspDiagnosticsXXX are used for diagnostic. Please check highlight.lua and dochighlight.lua for more info.
## Dependency
- lspconfig
@ -399,13 +396,14 @@ 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).
## Integration with lspinstall
If you'd like to only use the lsp servers installed by lspinstall. Please set
```lua
lspinstall = false
```
In the config
## Usage
@ -431,22 +429,21 @@ require'navigator'.setup({on_attach = function(client, bufnr) require 'illuminat
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.
- 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
(Normal) and PmenuSel
- GHListDark and GHTextViewDark 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
- In future, I will use NormalFloat for floating view. But ATM, most of colorscheme does not define NormalFloat
You can override the above highlight to fit your current colorscheme
## commands
| command | function |
|--- |--- |
| LspToggleFmt | toggle lsp auto format |
| command | function |
| ------------ | ---------------------- |
| LspToggleFmt | toggle lsp auto format |
## Screenshots
@ -465,6 +462,7 @@ Pls check the first part of README
![workspace symbol](https://github.com/ray-x/files/blob/master/img/navigator/workspace_symbol.gif?raw=true)
### highlight document symbol and jump between reference
![multiple_symbol_hi3](https://user-images.githubusercontent.com/1681295/120067627-f9f80680-c0bf-11eb-9216-18e5c8547f59.gif)
# Current symbol highlight and jump backward/forward between symbols
@ -480,7 +478,6 @@ Visual studio code style show errors minimap in scroll bar area
![diagnostic_scroll_bar](https://user-images.githubusercontent.com/1681295/128736430-e365523d-810c-4c16-a3b4-c74969f45f0b.jpg)
Diagnostic in single bufer
![diagnostic](https://github.com/ray-x/files/blob/master/img/navigator/diag.jpg?raw=true)
@ -495,7 +492,6 @@ You can in place edit your code in floating window
https://user-images.githubusercontent.com/1681295/121832919-89cbc080-cd0e-11eb-9778-11d0f356b38d.mov
(Note: This feature only avalible in `find reference` and `find diagnostic`, You can not add/remove lines in floating window)
### Implementation
@ -549,14 +545,12 @@ Codelens for C++/ccls. Symbol reference
![codelens_cpp_ccls](https://user-images.githubusercontent.com/1681295/132429134-abc6547e-79cc-44a4-b7a9-23550b895e51.jpg)
### Predefined LSP symbol nerdfont/emoji
![nerdfont](https://github.com/ray-x/files/blob/master/img/navigator/icon_nerd.jpg?raw=true)
# Break changes and known issues
[known issues I am working on](https://github.com/ray-x/navigator.lua/issues/1)
# Todo

@ -8,6 +8,7 @@ _NgConfigValues = {
preview_lines_before = 5, -- lines before the highlight line
default_mapping = true,
keymaps = {}, -- e.g keymaps={{key = "GR", func = "references()"}, } this replace gr default mapping
external = nil, -- true: enable for goneovim multigrid otherwise false
border = "single", -- border style, can be one of 'none', 'single', 'double', "shadow"
combined_attach = "both", -- both: use both customized attach and navigator default attach, mine: only use my attach defined in vimrc
@ -33,7 +34,7 @@ _NgConfigValues = {
-- to load those files
diagnostic_virtual_text = true, -- show virtual for diagnostic message
diagnostic_update_in_insert = false, -- update diagnostic message in insert mode
diagnostic_scrollbar_sign = {'', ''}, -- set to nil to disable, set to {'╍', 'ﮆ'} to enable diagnostic status in scroll bar area
diagnostic_scrollbar_sign = {'', '', ''}, -- set to nil to disable, set to {'╍', 'ﮆ'} to enable diagnostic status in scroll bar area
tsserver = {
-- filetypes = {'typescript'} -- disable javascript etc,
-- set to {} to disable the lspclient for all filetype
@ -46,16 +47,22 @@ _NgConfigValues = {
},
lspinstall = false, -- set to true if you would like use the lsp installed by lspinstall
icons = {
icons = true, -- set to false to use system default ( if you using a terminal does not have nerd/icon)
-- Code action
code_action_icon = "",
code_action_icon = "🏏", -- "",
-- code lens
code_lens_action_icon = "",
-- Diagnostics
diagnostic_head = '🐛',
diagnostic_err = "📛",
diagnostic_warn = "👎",
diagnostic_info = [[👩]],
diagnostic_hint = [[💁]],
diagnostic_head_severity_1 = "🈲",
diagnostic_head_severity_2 = "☣️",
diagnostic_head_severity_3 = "👎",
diagnostic_head_description = "📛",
diagnostic_head_description = "👹",
diagnostic_virtual_text = "🦊",
diagnostic_file = "🚑",
-- Values
@ -131,7 +138,7 @@ M.setup = function(cfg)
-- log("navigator loader")
if _NgConfigValues.code_action_prompt.enable then
vim.cmd [[autocmd CursorHold * lua require'navigator.codeAction'.code_action_prompt()]]
vim.cmd [[autocmd CursorHold,CursorHoldI * lua require'navigator.codeAction'.code_action_prompt()]]
end
-- vim.cmd("autocmd BufNewFile,BufRead *.go setlocal noexpandtab tabstop=4 shiftwidth=4")
if not _NgConfigValues.loaded then
@ -141,12 +148,6 @@ M.setup = function(cfg)
if _NgConfigValues.ts_fold == true then
require('navigator.foldts').on_attach()
end
--- if code line enabled
if _NgConfigValues.lsp.code_lens then
require("navigator.codelens").setup()
end
end
return M

@ -5,9 +5,13 @@ local code_action = {}
local gui = require "navigator.gui"
local config = require("navigator").config_values()
local api = vim.api
local sign_name = "NavigatorLightBulb"
local diagnostic = vim.diagnostic or vim.lsp.diagnostic
code_action.code_action_handler = util.mk_handler(function(err, actions, ctx, cfg)
log(actions, ctx)
if actions == nil or vim.tbl_isempty(actions) then
if actions == nil or vim.tbl_isempty(actions) or err then
print("No code actions available")
return
end
@ -19,13 +23,16 @@ code_action.code_action_handler = util.mk_handler(function(err, actions, ctx, cf
table.insert(data, title)
actions[i].display_title = title
end
local width = 0
local width = 42
for _, str in ipairs(data) do
if #str > width then
width = #str
end
end
local divider = string.rep('', width + 2)
table.insert(data, 2, divider)
local apply = require('navigator.lspwrapper').apply_action
local function apply_action(action)
local action_chosen = nil
@ -42,7 +49,7 @@ code_action.code_action_handler = util.mk_handler(function(err, actions, ctx, cf
apply(action_chosen)
end
gui.new_list_view {
local listview = gui.new_list_view {
items = data,
width = width + 4,
loc = "top_center",
@ -58,6 +65,9 @@ code_action.code_action_handler = util.mk_handler(function(err, actions, ctx, cf
return pos
end
}
log("new buffer", listview.bufnr)
vim.api.nvim_buf_add_highlight(listview.bufnr, -1, 'Title', 0, 0, -1)
end)
-- https://github.com/glepnir/lspsaga.nvim/blob/main/lua/lspsaga/codeaction.lua
@ -71,22 +81,17 @@ local get_current_winid = function()
return api.nvim_get_current_win()
end
local sign_name = "NavigatorLightBulb"
if vim.tbl_isempty(vim.fn.sign_getdefined(sign_name)) then
vim.fn.sign_define(sign_name,
{text = config.icons.code_action_icon, texthl = "LspDiagnosticsSignHint"})
end
local function _update_virtual_text(line)
local function _update_virtual_text(line, actions)
local namespace = get_namespace()
pcall(api.nvim_buf_clear_namespace, 0, namespace, 0, -1)
if line then
log(line, actions)
local icon_with_indent = " " .. config.icons.code_action_icon
local title = actions[1].title
pcall(api.nvim_buf_set_extmark, 0, namespace, line, -1, {
virt_text = {{icon_with_indent, "LspDiagnosticsSignHint"}},
virt_text = {{icon_with_indent .. title, "LspDiagnosticsSignHint"}},
virt_text_pos = "overlay",
hl_mode = "combine"
})
@ -94,6 +99,11 @@ local function _update_virtual_text(line)
end
local function _update_sign(line)
if vim.tbl_isempty(vim.fn.sign_getdefined(sign_name)) then
vim.fn.sign_define(sign_name,
{text = config.icons.code_action_icon, texthl = "LspDiagnosticsSignHint"})
end
local winid = get_current_winid()
if code_action[winid] == nil then
code_action[winid] = {}
@ -110,11 +120,14 @@ local function _update_sign(line)
end
end
local need_check_diagnostic = {["go"] = true, ["python"] = true}
-- local need_check_diagnostic = {["go"] = true, ["python"] = true}
local need_check_diagnostic = {['python'] = true}
function code_action:render_action_virtual_text(line, diagnostics)
return function(_, _, actions)
return function(err, actions, context)
log(err, line, diagnostics, actions, context)
if actions == nil or type(actions) ~= "table" or vim.tbl_isempty(actions) then
-- no actions cleanup
if config.code_action_prompt.virtual_text then
_update_virtual_text(nil)
end
@ -127,6 +140,7 @@ function code_action:render_action_virtual_text(line, diagnostics)
if next(diagnostics) == nil then
_update_sign(nil)
else
-- no diagnostic, no code action sign..
_update_sign(line)
end
else
@ -139,10 +153,10 @@ function code_action:render_action_virtual_text(line, diagnostics)
if next(diagnostics) == nil then
_update_virtual_text(nil)
else
_update_virtual_text(line)
_update_virtual_text(line, actions)
end
else
_update_virtual_text(line)
_update_virtual_text(line, actions)
end
end
end
@ -186,7 +200,15 @@ code_action.code_action_prompt = function()
return
end
local diagnostics = vim.lsp.diagnostic.get_line_diagnostics()
local diagnostics
if diagnostic.get_line_diagnostics then
-- old version
diagnostics = diagnostic.get_line_diagnostics()
else
local lnum = vim.api.nvim_win_get_cursor(0)[1] - 1
diagnostics = diagnostic.get(vim.api.nvim_get_current_buf(), {lnum = lnum})
end
local winid = get_current_winid()
code_action[winid] = code_action[winid] or {}
code_action[winid].lightbulb_line = code_action[winid].lightbulb_line or 0

@ -69,7 +69,9 @@ function M.setup()
local on_codelens = vim.lsp.handlers["textDocument/codeLens"]
vim.lsp.handlers["textDocument/codeLens"] = mk_handler(
function(err, result, ctx, cfg)
trace(err, result, ctx.client_id, ctx.bufnr, cfg)
-- trace(err, result, ctx.client_id, ctx.bufnr, cfg or {})
cfg = cfg or {}
ctx = ctx or {bufnr = vim.api.nvim_get_current_buf()}
if nvim_0_6() then
on_codelens(err, result, ctx, cfg)
codelens_hdlr(err, result, ctx, cfg)
@ -139,8 +141,12 @@ function M.run_action()
end
apply(action_chosen)
end
local divider = string.rep('', width + 2)
table.insert(data, 2, divider)
if #data > 0 then
gui.new_list_view {
local lv = gui.new_list_view {
items = data,
width = width + 4,
loc = "top_center",
@ -156,7 +162,70 @@ function M.run_action()
return pos
end
}
vim.api.nvim_buf_add_highlight(lv.bufnr, -1, 'Title', 0, 0, -1)
end
end
local virtual_types_ns = api.nvim_create_namespace("ng_virtual_types");
function M.disable()
local bufnr = vim.api.nvim_get_current_buf()
vim.api.nvim_buf_clear_namespace(bufnr, virtual_types_ns, 0, -1)
is_enabled = false
end
M.inline = function()
local lsp = vim.lsp
if is_enabled == false then
return
end
if vim.fn.getcmdwintype() == ':' then
return
end
if #vim.lsp.buf_get_clients() == 0 then
return
end
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)
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
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
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
end
-- else
-- api.nvim_command("echohl WarningMsg | echo 'VirtualTypes: No response' | echohl None")
end
end
return M

@ -0,0 +1,29 @@
local M = {}
function M.debounce_trailing(ms, fn)
local timer = vim.loop.new_timer()
return function(...)
local argv = {...}
timer:start(ms, 0, function()
timer:stop()
fn(unpack(argv))
end)
end
end
function M.throttle_leading(ms, fn)
local timer = vim.loop.new_timer()
local running = false
return function(...)
if not running then
timer:start(ms, 0, function()
running = false
timer:stop()
end)
running = true
fn(...)
end
end
end
return M

@ -1,11 +1,11 @@
local gui = require "navigator.gui"
local diagnostic_list = {}
_NG_VT_NS = vim.api.nvim_create_namespace("navigator_lua")
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
-- trace = log
local error = util.error
local path_sep = require"navigator.util".path_sep()
@ -13,101 +13,160 @@ local mk_handler = require"navigator.util".mk_handler
local path_cur = require"navigator.util".path_cur()
diagnostic_list[vim.bo.filetype] = {}
local function error_marker(result, client_id)
if _NgConfigValues.lsp.diagnostic_scrollbar_sign == nil then -- not enabled or already shown
local function clear_diag_VT(bufnr) -- important for clearing out when no more errors
log(bufnr, _NG_VT_DIAG_NS)
if bufnr == nil or _NG_VT_DIAG_NS == nil then
return
end
local first_line = vim.fn.line('w0')
-- local rootfolder = vim.fn.expand('%:h:t') -- get the current file root folder
trace(result)
local bufnr = vim.uri_to_bufnr(result.uri)
if bufnr ~= vim.api.nvim_get_current_buf() then
-- log("not same buf", client_id, result.uri, bufnr, vim.fn.bufnr())
return
vim.api.nvim_buf_clear_namespace(bufnr, _NG_VT_DIAG_NS, 0, -1)
_NG_VT_DIAG_NS = nil
end
local function get_count(bufnr, level)
if vim.diagnostic ~= nil then
return #diagnostic.get(bufnr, {severity = level})
else
return diagnostic.get_count(bufnr, level)
end
trace(result, bufnr)
end
if result == nil or result.diagnostics == nil or #result.diagnostics == 0 then
local diag_cnt = vim.lsp.diagnostic.get_count(bufnr, [[Error]])
+ vim.lsp.diagnostic.get_count(bufnr, [[Warning]])
if diag_cnt == 0 and _NG_VT_NS ~= nil then
vim.api.nvim_buf_clear_namespace(bufnr, _NG_VT_NS, 0, -1)
local function error_marker(result, ctx, config)
vim.defer_fn(function()
if vim.tbl_isempty(result.diagnostics) then
return
end
return
end
if _NgConfigValues.lsp.diagnostic_scrollbar_sign == nil then -- not enabled or already shown
return
end
local first_line = vim.fn.line('w0')
-- local rootfolder = vim.fn.expand('%:h:t') -- get the current file root folder
-- total line num of current buffer
local bufnr = ctx.bufnr
if bufnr == nil then
bufnr = vim.uri_to_bufnr(result.uri)
end
local fname = vim.api.nvim_buf_get_name(bufnr)
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
-- local winid = vim.fn.win_getid(vim.fn.winnr())
-- local winid = vim.api.nvim_get_current_win()
bufnr = vim.api.nvim_get_current_buf()
local total_num = vim.fn.getbufinfo(bufnr)[1].linecount
-- local total_num = vim.fn.getbufinfo(vim.fn.winbufnr(winid))[1].linecount
-- window size of current buffer
if not vim.api.nvim_buf_is_loaded(bufnr) then
log("buf not loaded")
return
local stats = vim.api.nvim_list_uis()[1]
local wwidth = stats.width;
local wheight = stats.height;
end
-- local wwidth = vim.fn.winwidth(winid)
-- local wheight = vim.fn.winheight(winid)
if total_num <= wheight then
return
end
if _NG_VT_NS == nil then
_NG_VT_NS = vim.api.nvim_create_namespace("navigator_lua")
end
trace('schedule callback', result, ctx, config)
-- trace(result, bufnr)
vim.api.nvim_buf_clear_namespace(0, _NG_VT_NS, 0, -1)
if total_num <= wheight then
first_line = 0
end
local pos = {}
-- pos of virtual text
for _, diag in pairs(result.diagnostics) do
if diag.range and diag.range.start and diag.range.start.line then
local p = diag.range.start.line
p = util.round(p * wheight / math.max(wheight, total_num))
if pos[#pos] and pos[#pos].line == p then
pos[#pos] = {
line = p,
sign = _NgConfigValues.lsp.diagnostic_scrollbar_sign[2],
severity = diag.severity
}
else
table.insert(pos, {
line = p,
sign = _NgConfigValues.lsp.diagnostic_scrollbar_sign[1],
severity = diag.severity
})
if result == nil or result.diagnostics == nil or #result.diagnostics == 0 then
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)
end
return
end
trace("pos", pos, diag.range.start)
end
for i, s in pairs(pos) do
local hl = 'ErrorMsg'
if s.severity > 1 then
hl = 'WarningMsg'
-- 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 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 wwidth = stats.width;
local wheight = stats.height;
if total_num <= wheight then
return
end
local l = s.line + first_line
if l > total_num then
l = total_num
if _NG_VT_DIAG_NS == nil then
_NG_VT_DIAG_NS = vim.api.nvim_create_namespace("navigator_lua_diag")
end
vim.api.nvim_buf_set_extmark(bufnr, _NG_VT_NS, l, -1,
{virt_text = {{s.sign, hl}}, virt_text_pos = 'right_align'})
end
local pos = {}
local diags = result.diagnostics
for i, _ in ipairs(diags) do
if not diags[i].range then
diags[i].range = {start = {line = diags[i].lnum}}
end
end
table.sort(diags, function(a, b)
return a.range.start.line < b.range.start.line
end)
-- pos of virtual text
for _, diag in pairs(result.diagnostics) do
local p
if not diag.range then
diag.range = {start = {line = diag.lnum}}
end
if diag.range and diag.range.start and diag.range.start.line then
p = diag.range.start.line
p = util.round(p * wheight / math.max(wheight, total_num))
if pos[#pos] and pos[#pos].line == p then
local bar = ''
if pos[#pos] == _NgConfigValues.lsp.diagnostic_scrollbar_sign[2] then
bar = ''
end
pos[#pos] = {line = p, sign = bar, severity = math.min(diag.severity, pos[#pos].severity)}
else
table.insert(pos, {
line = p,
sign = _NgConfigValues.lsp.diagnostic_scrollbar_sign[1],
severity = diag.severity
})
end
end
trace("pos, line:", p, diag.severity, diag.range)
end
if not vim.tbl_isempty(pos) then
vim.api.nvim_buf_clear_namespace(bufnr, _NG_VT_DIAG_NS, 0, -1)
end
for i, s in pairs(pos) do
local hl = 'ErrorMsg'
if s.severity == 2 then
hl = 'WarningMsg'
else
hl = 'DiagnosticInfo'
end
local l = s.line + first_line
if l > total_num then
l = total_num
end
trace("add pos", s, bufnr)
vim.api.nvim_buf_set_extmark(bufnr, _NG_VT_DIAG_NS, l, -1,
{virt_text = {{s.sign, hl}}, virt_text_pos = 'right_align'})
end
end, 10) -- defer in 10ms
end
local update_err_marker_async = function()
local debounce = require'navigator.debounce'.debounce_trailing
return debounce(20, error_marker)
end
local diag_hdlr = mk_handler(function(err, result, ctx, config)
trace(result)
require"navigator.lspclient.highlight".diagnositc_config_sign()
if err ~= nil then
log(err, config)
log(err, config, result)
return
end
if vim.fn.mode() ~= 'n' and config.update_in_insert == false then
local mode = vim.api.nvim_get_mode().mode
if mode ~= 'n' and config.update_in_insert == false then
log("skip in insert mode")
return
end
@ -116,23 +175,26 @@ local diag_hdlr = mk_handler(function(err, result, ctx, config)
if diagnostic_list[ft] == nil then
diagnostic_list[vim.bo.filetype] = {}
end
-- vim.lsp.diagnostic.clear(vim.fn.bufnr(), client.id, nil, nil)
local client_id = ctx.client_id
-- not sure if I should do this hack
if vim.tbl_isempty(result.diagnostics) then
if vim.api.nvim_buf_is_loaded(ctx.bufnr) then
-- diagnostic.reset(ctx.client_id)
-- clear_diag_VT(ctx.bufnr)
end
return
end
if util.nvim_0_6() then
trace(err, result, ctx, config)
vim.lsp.diagnostic.on_publish_diagnostics(err, result, ctx, config)
else
log("old version of lsp nvim 050")
vim.lsp.diagnostic.on_publish_diagnostics(err, _, result, ctx.client_id, _, config)
end
local uri = result.uri
if err then
log("diag", err, result)
return
end
if vim.fn.mode() ~= 'n' and config.update_in_insert == false then
log("skip in insert mode")
return
end
trace("diag: ", vim.fn.mode(), result, ctx, config)
-- trace("diag: ", mode, result, ctx, config)
if result and result.diagnostics then
local item_list = {}
for _, v in ipairs(result.diagnostics) do
@ -155,6 +217,7 @@ local diag_hdlr = mk_handler(function(err, result, ctx, config)
local bufnr1 = vim.uri_to_bufnr(uri)
if not vim.api.nvim_buf_is_loaded(bufnr1) then
if _NgConfigValues.diagnostic_load_files then
-- print('load buffers')
vim.fn.bufload(bufnr1) -- this may slow down the neovim
local pos = v.range.start
local row = pos.line
@ -178,10 +241,12 @@ local diag_hdlr = mk_handler(function(err, result, ctx, config)
result.uri = uri
end
error_marker(result, ctx.client_id)
local marker = update_err_marker_async()
marker(result, ctx, config)
else
vim.api.nvim_buf_clear_namespace(0, _NG_VT_NS, 0, -1)
_NG_VT_NS = nil
trace("great, no diag errors")
vim.api.nvim_buf_clear_namespace(0, _NG_VT_DIAG_NS, 0, -1)
_NG_VT_DIAG_NS = nil
end
end)
@ -196,9 +261,7 @@ local diagnostic_cfg = {
-- and on, using buffer local variables
signs = true,
update_in_insert = _NgConfigValues.lsp.diagnostic_update_in_insert or false,
severity_sort = function(a, b)
return a.severity < b.severity
end
severity_sort = {reverse = true}
}
if _NgConfigValues.lsp.diagnostic_virtual_text == false then
@ -209,24 +272,13 @@ end
M.diagnostic_handler = vim.lsp.with(diag_hdlr, diagnostic_cfg)
M.hide_diagnostic = function()
if _NG_VT_NS then
vim.api.nvim_buf_clear_namespace(0, _NG_VT_NS, 0, -1)
_NG_VT_NS = nil
if _NG_VT_DIAG_NS then
vim.api.nvim_buf_clear_namespace(0, _NG_VT_DIAG_NS, 0, -1)
_NG_VT_DIAG_NS = nil
end
end
M.show_diagnostic = function()
vim.lsp.diagnostic.get_all()
local bufs = vim.api.nvim_list_bufs()
for _, buf in ipairs(bufs) do
local bname = vim.fn.bufname(buf)
if #bname > 0 and not util.exclude(bname) then
if vim.api.nvim_buf_is_loaded(buf) then
vim.lsp.diagnostic.get(buf, nil)
end
end
end
if diagnostic_list[vim.bo.filetype] ~= nil then
-- log(diagnostic_list[vim.bo.filetype])
-- vim.fn.setqflist({}, " ", {title = "LSP", items = diagnostic_list[vim.bo.filetype]})
@ -239,56 +291,81 @@ M.show_diagnostic = function()
end
-- log(display_items)
if #display_items > 0 then
gui.new_list_view({
local listview = gui.new_list_view({
items = display_items,
api = _NgConfigValues.icons.diagnostic_file .. _NgConfigValues.icons.diagnostic_head
.. " Diagnostic ",
enable_preview_edit = true
})
trace("new buffer", listview.bufnr)
vim.api.nvim_buf_add_highlight(listview.bufnr, -1, 'Title', 0, 0, -1)
end
end
end
-- set quickfix win
-- set loc list win
M.set_diag_loclist = function()
local bufnr = vim.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!")
return
end
local clients = vim.lsp.buf_get_clients(0)
local cfg = {open = diag_cnt > 0}
for _, client in pairs(clients) do
cfg.client_id = client['id']
break
end
if not vim.tbl_isempty(vim.lsp.buf_get_clients(0)) then
local err_cnt = vim.lsp.diagnostic.get_count(0, [[Error]])
local err_cnt = get_count(0, [[Error]])
if err_cnt > 0 and _NgConfigValues.lsp.disply_diagnostic_qf then
vim.lsp.diagnostic.set_loclist()
if diagnostic.set_loclist then
diagnostic.set_loclist(cfg)
else
cfg.namespaces = diagnostic.get_namespace(nil)
diagnostic.setloclist(cfg)
end
else
vim.cmd("lclose")
end
end
end
local function clear_diag_VT() -- important for clearing out when no more errors
vim.api.nvim_buf_clear_namespace(0, _NG_VT_NS, 0, -1)
_NG_VT_NS = nil
end
-- TODO: callback when scroll
function M.update_err_marker()
if _NG_VT_NS == nil then
trace("update err marker", _NG_VT_DIAG_NS)
if _NG_VT_DIAG_NS == nil then
-- nothing to update
return
end
local bufnr = vim.api.nvim_get_current_buf()
local diag_cnt = vim.lsp.diagnostic.get_count(bufnr, [[Error]])
+ vim.lsp.diagnostic.get_count(bufnr, [[Warning]])
if diag_cnt == 0 and _NG_VT_NS ~= nil then
vim.api.nvim_buf_clear_namespace(bufnr, _NG_VT_NS, 0, -1)
local diag_cnt = get_count(bufnr, [[Error]]) + get_count(bufnr, [[Warning]])
+ get_count(bufnr, [[Info]]) + get_count(bufnr, [[Hint]])
-- 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)
trace("no errors")
return
end
-- redraw
vim.api.nvim_buf_clear_namespace(0, _NG_VT_NS, 0, -1)
local errors = vim.lsp.diagnostic.get(bufnr)
vim.api.nvim_buf_clear_namespace(bufnr, _NG_VT_DIAG_NS, 0, -1)
local errors = diagnostic.get(bufnr)
if #errors == 0 then
trace("errors", errors)
return
end
local result = {diagnostics = errors, uri = errors[1].uri}
error_marker(result)
local uri = vim.uri_from_bufnr(bufnr)
local result = {diagnostics = errors, uri = errors[1].uri or uri}
trace(result)
local marker = update_err_marker_async()
marker(result, {bufnr = bufnr, method = 'textDocument/publishDiagnostics'})
end
-- TODO: update the marker
@ -300,4 +377,14 @@ if _NgConfigValues.lsp.diagnostic_scrollbar_sign then
vim.cmd [[autocmd WinScrolled * lua require'navigator.diagnostics'.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})
end
function M.show_line_diagnostics()
local lnum = vim.api.nvim_win_get_cursor(0)[1] - 1
diagnostic.show_line_diagnostics({border = 'single'}, vim.api.nvim_get_current_buf(), lnum)
end
return M

@ -58,6 +58,11 @@ function M._preview_location(opts) -- location, width, pos_x, pos_y
uri = uri,
allow_edit = opts.enable_edit
}
if _NgConfigValues.external then
win_opts.external = true
win_opts.relative = nil
end
-- win_opts.items = contents
win_opts.hl_line = opts.lnum - display_range.start.line
if win_opts.hl_line < 0 then
@ -84,7 +89,8 @@ function M._preview_location(opts) -- location, width, pos_x, pos_y
border = opts.border,
display_range = win_opts.display_range,
hl_line = win_opts.hl_line,
allow_edit = win_opts.allow_edit
allow_edit = win_opts.allow_edit,
external = win_opts.external
})
return w
end
@ -125,7 +131,7 @@ function M.new_list_view(opts)
if config.width ~= nil and config.width > 0.3 and config.width < 0.99 then
width = math.floor(wwidth * config.width)
end
width = math.min(120, width)
width = math.min(120, width, opts.width or 120)
local wheight = math.floor(1 + api.nvim_get_option("lines")
* (_NgConfigValues.height + _NgConfigValues.preview_height))
local pheight = math.max(_NgConfigValues.preview_lines, math.floor(
@ -173,6 +179,10 @@ function M.new_list_view(opts)
if transparency == 100 then
transparency = nil
end
local ext = _NgConfigValues.external
if ext then
opts.relative = nil
end
return ListView:new({
loc = loc,
prompt = prompt,
@ -186,6 +196,7 @@ function M.new_list_view(opts)
-- data = display_data,
data = data,
border = border,
external = ext,
on_confirm = opts.on_confirm or function(item, split_opts)
log(split_opts)
split_opts = split_opts or {}
@ -213,6 +224,7 @@ function M.new_list_view(opts)
offset_x = 0,
offset_y = offset_y,
border = border,
external = ext,
enable_edit = opts.enable_preview_edit or false
})
end

@ -1,7 +1,7 @@
local log = require"navigator.util".log
_LoadedClients = {}
local loader = nil
packer_plugins = packer_plugins or nil -- suppress warnings
local packer_plugins = packer_plugins or nil -- suppress warnings
-- packer only
if packer_plugins ~= nil then -- packer install

@ -14,6 +14,7 @@ local M = {}
M.on_attach = function(client, bufnr)
local uri = vim.uri_from_bufnr(bufnr)
if uri == "file://" or uri == "file:///" or #uri < 11 then
log("skip for float buffer", uri)
return {error = "invalid file", result = nil}
@ -24,7 +25,7 @@ M.on_attach = function(client, bufnr)
diagnostic_map(bufnr)
-- add highlight for Lspxxx
require"navigator.lspclient.highlight".add_highlight()
require"navigator.lspclient.highlight".diagnositc_config_sign()
api.nvim_buf_set_option(bufnr, "omnifunc", "v:lua.vim.lsp.omnifunc")
require("navigator.lspclient.mapping").setup({

@ -518,6 +518,11 @@ local function setup(user_opts)
wait_lsp_startup(ft, retry, lsp_opts)
--- if code line enabled
if _NgConfigValues.lsp.code_lens then
require("navigator.codelens").setup()
end
_LoadedClients[ft] = true
-- _LoadedClients[ft] = vim.tbl_extend("keep", _LoadedClients[ft] or {}, {ft})

@ -1,20 +1,62 @@
local M = {}
local log = require"navigator.util".log
local api = vim.api
-- lsp sign          ﮻         ﯭ        ﳀ  
function M.diagnositc_config_sign()
vim.fn.sign_define('LspDiagnosticsSignError',
{text = '', texthl = 'LspDiagnosticsSignError', linehl = '', numhl = ''})
vim.fn.sign_define('LspDiagnosticsSignWarning',
{text = '', texthl = 'LspDiagnosticsSignWarning', linehl = '', numhl = ''})
vim.fn.sign_define('LspDiagnosticsSignInformation', {
text = '',
texthl = 'LspDiagnosticsSignInformation',
linehl = '',
numhl = ''
})
vim.fn.sign_define('LspDiagnosticsSignHint',
{text = '💡', texthl = 'LspDiagnosticsSignHint', linehl = '', numhl = ''})
if M.configed then
return
end
local icons = _NgConfigValues.icons
local sign_name = "NavigatorLightBulb"
if vim.fn.sign_getdefined(sign_name).text == nil then
vim.fn
.sign_define(sign_name, {text = icons.code_action_icon, texthl = "LspDiagnosticsSignHint"})
sign_name = "NavigatorCodeLensLightBulb"
vim.fn.sign_define(sign_name,
{text = icons.code_lens_action_icon, texthl = "LspDiagnosticsSignHint"})
end
local e, w, i, h = icons.diagnostic_err, icons.diagnostic_warn, icons.diagnostic_info,
icons.diagnostic_hint
if vim.diagnostic ~= nil then
local t = vim.fn.sign_getdefined('DiagnosticSignWarn')
if vim.tbl_isempty(t) or t[1].text == "W " and icons.icons == true then
vim.fn.sign_define('DiagnosticSignError',
{text = e, texthl = 'DiagnosticError', linehl = '', numhl = ''})
vim.fn.sign_define('DiagnosticSignWarn',
{text = w, texthl = 'DiagnosticWarn', linehl = '', numhl = ''})
vim.fn.sign_define('DiagnosticSignInfo',
{text = i, texthl = 'DiagnosticInfo', linehl = '', numhl = ''})
vim.fn.sign_define('DiagnosticSignHint',
{text = h, texthl = 'DiagnosticHint', linehl = '', numhl = ''})
t = vim.fn.sign_getdefined('DiagnosticSignWarn')
log('*** t ', t, "diagnostic add sign")
end
else
local t = vim.fn.sign_getdefined('LspDiagnosticSignWarn')
if vim.tbl_isempty(t) or t[1].text == "W " and icons.icons == true then
vim.fn.sign_define('LspDiagnosticsSignError',
{text = e, texthl = 'LspDiagnosticsSignError', linehl = '', numhl = ''})
vim.fn.sign_define('LspDiagnosticsSignWarning',
{text = w, texthl = 'LspDiagnosticsSignWarning', linehl = '', numhl = ''})
vim.fn.sign_define('LspDiagnosticsSignInformation', {
text = i,
texthl = 'LspDiagnosticsSignInformation',
linehl = '',
numhl = ''
})
vim.fn.sign_define('LspDiagnosticsSignHint',
{text = h, texthl = 'LspDiagnosticsSignHint', linehl = '', numhl = ''})
end
end
M.configed = true
end
function M.add_highlight()
@ -24,8 +66,12 @@ function M.add_highlight()
api.nvim_command("hi! link LspDiagnosticsUnderlineWarning SpellRare")
api.nvim_command("hi! link LspDiagnosticsUnderlineInformation SpellRare")
api.nvim_command("hi! link LspDiagnosticsUnderlineHint SpellRare")
api.nvim_command("hi def link NGPreviewTitle Title")
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'},

@ -31,7 +31,7 @@ local key_maps = {
{key = "<Leader>go", func = "outgoing_calls()"},
{key = "gi", func = "implementation()"},
{key = "<Space>D", func = "type_definition()"},
{key = "gL", func = "diagnostic.show_line_diagnostics( { border = 'single' })"},
{key = "gL", func = "require('navigator.diagnostics').show_line_diagnostics()"},
{key = "gG", func = "require('navigator.diagnostics').show_diagnostic()"},
{key = "]d", func = "diagnostic.goto_next({ border = 'single' })"},
{key = "[d", func = "diagnostic.goto_prev({ border = 'single' })"},
@ -119,7 +119,11 @@ local function set_mapping(user_opts)
if string.find(value.func, "require") then
f = "<Cmd>lua " .. value.func .. "<CR>"
elseif string.find(value.func, "diagnostic") then
f = "<Cmd>lua vim.lsp." .. value.func .. "<CR>"
local diagnostic = '<Cmd>lua vim.'
if vim.lsp.diagnostic ~= nil then
diagnostic = '<Cmd>lua vim.lsp.'
end
f = diagnostic .. value.func .. "<CR>"
elseif string.find(value.func, "vim.") then
f = "<Cmd>lua " .. value.func .. "<CR>"
end
@ -241,9 +245,11 @@ function M.setup(user_opts)
require"navigator.diagnostics".diagnostic_handler
-- TODO: when active signature merge to neovim, remove this setup:
local hassig, sig = pcall(require, "lsp_signature")
if hassig then
if _NgConfigValues.signature_help_cfg then
if _NgConfigValues.signature_help_cfg then
log("setup signature from navigator")
local hassig, sig = pcall(require, "lsp_signature")
if hassig then
sig.setup(_NgConfigValues.signature_help_cfg)
end
else

@ -40,7 +40,7 @@ local function check_lhs(text, symbol)
return false
end
if s < eq and eq ~= eq2 then
log(symbol, "modified")
trace(symbol, "modified")
end
if eq == eq3 + 1 then
return false

@ -1,4 +1,4 @@
parameter
-- [[ -- parameter
{
position = {
character = 6,
@ -7,8 +7,7 @@ parameter
textDocument = {
uri = "file:///Users/username/lsp_test/go/interface.go"
}
}
} ]]
--[[ -- incomming/outgoing
@ -103,8 +102,8 @@ dir from result { {
-- [[ locations/reference from lsp
-- locations/reference from lsp
-- [[
{ {
range = {
["end"] = {
@ -130,7 +129,7 @@ dir from result { {
},
uri = "file:///Users/username/lsp-test/go/interface.go"
} }
--]]
]] --
-- definition
@ -1124,3 +1123,173 @@ definition.lua:9: { {
}
}
} }
-- rust code lens
{ {
result = { {
command = {
arguments = { {
args = {
cargoArgs = { "run", "--package", "hello", "--bin", "hello" },
cargoExtraArgs = {},
executableArgs = {},
workspaceRoot = "/Users/ray.xu/lsp_test/rust"
},
kind = "cargo",
label = "run hello",
location = {
targetRange = {
end = {
character = 1,
line = 68
},
start = {
character = 0,
line = 45
}
},
targetSelectionRange = {
end = {
character = 7,
line = 45
},
start = {
character = 3,
line = 45
}
},
targetUri = "file:///Users/ray.xu/lsp_test/rust/src/main.rs"
}
} },
command = "rust-analyzer.runSingle",
title = "▶︎ Run "
},
range = {
end = {
character = 7,
line = 45
},
start = {
character = 3,
line = 45
}
}
}, {
command = {
arguments = { {
args = {
cargoArgs = { "run", "--package", "hello", "--bin", "hello" },
cargoExtraArgs = {},
executableArgs = {},
workspaceRoot = "/Users/ray.xu/lsp_test/rust"
},
kind = "cargo",
label = "run hello",
location = {
targetRange = {
end = {
character = 1,
line = 68
},
start = {
character = 0,
line = 45
}
},
targetSelectionRange = {
end = {
character = 7,
line = 45
},
start = {
character = 3,
line = 45
}
},
targetUri = "file:///Users/ray.xu/lsp_test/rust/src/main.rs"
}
} },
command = "rust-analyzer.debugSingle",
title = "Debug"
},
range = {
end = {
character = 7,
line = 45
},
start = {
character = 3,
line = 45
}
}
}, {
data = {
impls = {
position = {
character = 6,
line = 2
},
textDocument = {
uri = "file:///Users/ray.xu/lsp_test/rust/src/main.rs"
}
}
},
range = {
end = {
character = 10,
line = 2
},
start = {
character = 6,
line = 2
}
}
}, {
data = {
impls = {
position = {
character = 7,
line = 28
},
textDocument = {
uri = "file:///Users/ray.xu/lsp_test/rust/src/main.rs"
}
}
},
range = {
end = {
character = 10,
line = 28
},
start = {
character = 7,
line = 28
}
}
}, {
data = {
impls = {
position = {
character = 7,
line = 31
},
textDocument = {
uri = "file:///Users/ray.xu/lsp_test/rust/src/main.rs"
}
}
},
range = {
end = {
character = 10,
line = 31
},
start = {
character = 7,
line = 31
}
}
} }
} }

@ -3,6 +3,9 @@ local trace = require"guihua.log".trace
local M = {}
local clone = require'guihua.util'.clone
local function filename(url)
if url == nil then
return ''
end
return url:match("^.+/(.+)$") or url
end

@ -393,4 +393,18 @@ function M.partial(func, arg)
end))
end
-- alternatively: use vim.notify("namespace does not exist or is anonymous", vim.log.levels.ERROR)
function M.warn(msg)
vim.api.nvim_echo({{"WRN: " .. msg, "WarningMsg"}}, true, {})
end
function M.error(msg)
vim.api.nvim_echo({{"ERR: " .. msg, "ErrorMsg"}}, true, {})
end
function M.info(msg)
vim.api.nvim_echo({{"Info: " .. msg}}, true, {})
end
return M

Loading…
Cancel
Save