diff --git a/README.md b/README.md index 036d692..5d02957 100644 --- a/README.md +++ b/README.md @@ -116,7 +116,7 @@ I'd like to go beyond what the system is offering. # Install -Require nvim-0.5.0 (a.k.a nightly) +Require nvim-0.6.1, nightly prefered You can remove your lspconfig setup and use this plugin. The plugin depends on lspconfig and [guihua.lua](https://github.com/ray-x/guihua.lua), which provides GUI and fzy support(migrate from [romgrk's project](romgrk/fzy-lua-native)). @@ -271,6 +271,12 @@ require'navigator'.setup({ -- to disable all default config and use your own lsp setup set -- disable_lsp = 'all' -- Default {} + diagnostic = { + underline = true, + virtual_text = true, -- show virtual for diagnostic message + update_in_insert = false, -- update diagnostic message in insert mode + }, + diagnostic_scrollbar_sign = {'▃', '▆', '█'}, -- experimental: diagnostic status in scroll bar area; set to false to disable the diagnostic sign, -- for other style, set to {'╍', 'ﮆ'} or {'-', '='} diagnostic_virtual_text = true, -- show virtual for diagnostic message @@ -389,8 +395,8 @@ In `playground` folder, there is a `init.lua` and source code for you to play wi | mode | key | function | | ---- | --------------- | ---------------------------------------------------------- | -| n | gr | show reference and context | -| n | Gr | async references, definitions and context (experiential) | +| n | gr | async references, definitions and context | +| n | \gr | show reference and context | | i | \ | signature help | | n | \ | signature help | | n | gW | workspace symbol | @@ -759,7 +765,7 @@ end # Errors and Bug Reporting - Please double check your setup and check if minium setup works or not -- It should works for 0.5.1, neovim 0.6.x prefered. +- It should works for 0.6.1, neovim 0.7.x prefered. - Check console output - Check `LspInfo` and treesitter status with `checkhealth` - Turn on log and attach the log to your issue if possible you can remove any personal/company info in the log diff --git a/doc/navigator.txt b/doc/navigator.txt index 9112195..c34347b 100644 --- a/doc/navigator.txt +++ b/doc/navigator.txt @@ -151,7 +151,7 @@ SIMILAR PROJECTS / SPECIAL MENTIONS: *navigator-similar_projects_/_special_menti ================================================================================ INSTALL *navigator-install* -Require nvim-0.5.0 (a.k.a nightly) +Require nvim-0.6.1 or nightly You can remove your lspconfig setup and use this plugin. The plugin depends on lspconfig and guihua.lua (https://github.com/ray-x/guihua.lua), which provides GUI and fzy support(migrate from romgrk's project (romgrk/fzy-lua-native)). @@ -279,8 +279,6 @@ Nondefault configuration example: -- Default {} diagnostic_scrollbar_sign = {'▃', '▆', '█'}, -- experimental: diagnostic status in scroll bar area; set to false to disable the diagnostic sign, -- for other style, set to {'╍', 'ﮆ'} or {'-', '='} - diagnostic_virtual_text = true, -- show virtual for diagnostic message - diagnostic_update_in_insert = false, -- update diagnostic message in insert mode disply_diagnostic_qf = true, -- always show quickfix if there are diagnostic errors, set to false if you want to ignore it tsserver = { @@ -687,8 +685,7 @@ TODO *navigator-tod ERRORS AND BUG REPORTING *navigator-errors_and_bug_reporting* * Please double check your setup and check if minium setup works or not -* It should works for 0.5.1, neovim 0.6.x prefered. +* It should works for 0.6.1, neovim 0.7.x prefered. * Check console output * Check `LspInfo` and treesitter status with `checkhealth` * Turn on log and attach the log to your issue if possible you can remove any personal/company info in the log - diff --git a/lua/navigator.lua b/lua/navigator.lua old mode 100644 new mode 100755 index 249c86d..a9302d9 --- a/lua/navigator.lua +++ b/lua/navigator.lua @@ -33,7 +33,7 @@ _NgConfigValues = { 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 + signature_help_cfg = {debug=false}, -- if you would like to init ray-x/lsp_signature plugin in navigator, pass in signature help lsp = { code_action = { enable = true, @@ -49,6 +49,12 @@ _NgConfigValues = { virtual_text = true, virtual_text_icon = true, }, + diagnostic = { + underline = true, + virtual_text = { spacing = 3 }, -- show virtual for diagnostic message + update_in_insert = false, -- update diagnostic message in insert mode + severity_sort = { reverse = true }, + }, format_on_save = true, -- set to false to disasble lsp code format on save (if you are using prettier/efm/formater etc) disable_format_cap = {}, -- a list of lsp disable file format (e.g. if you using efm or vim-codeformat etc), empty by default disable_lsp = {}, -- a list of lsp server disabled for your project, e.g. denols and tsserver you may @@ -218,28 +224,34 @@ M.setup = function(cfg) extend_config(cfg) vim.cmd([[autocmd FileType,BufEnter * lua require'navigator.lspclient.clients'.on_filetype()]]) -- BufWinEnter BufNewFile,BufRead ? - -- local log = require"navigator.util".log - -- log(debug.traceback()) - -- log(cfg, _NgConfigValues) - -- print("loading navigator") require('navigator.lazyloader').init() require('navigator.lspclient.clients').setup(_NgConfigValues) - -- keymaps should be added to on_attach. in case on_attach is not called - -- require('navigator.lspclient.mapping').setup(_NgConfigValues) require('navigator.reference') require('navigator.definition') require('navigator.hierarchy') require('navigator.implementation') - -- log("navigator loader") - - -- vim.cmd("autocmd BufNewFile,BufRead *.go setlocal noexpandtab tabstop=4 shiftwidth=4") + require('navigator.diagnostics').config(cfg.diagnostic) if not _NgConfigValues.loaded then _NgConfigValues.loaded = true end if _NgConfigValues.ts_fold == true then - require('navigator.foldts').on_attach() + local ok, _ = pcall(require, 'nvim-treesitter') + if ok then + require('navigator.foldts').on_attach() + end + end + + 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() + require('navigator.lspclient.lspkind').init() + return _start_client(lsp_config) end end diff --git a/lua/navigator/codeAction.lua b/lua/navigator/codeAction.lua index d8c6d2f..1200c05 100644 --- a/lua/navigator/codeAction.lua +++ b/lua/navigator/codeAction.lua @@ -138,9 +138,16 @@ local code_action_req = function(_call_back_fn, diagnostics) vim.lsp.buf_request(0, 'textDocument/codeAction', params, callback) end +local function sort_select(action_tuples, opts, on_user_choice) + table.sort(action_tuples, function(a, b) + return a[1] > b[1] + end) + require('guihua.gui').select(action_tuples, opts, on_user_choice) +end + code_action.code_action = function() local original_select = vim.ui.select - vim.ui.select = require('guihua.gui').select + vim.ui.select = sort_select log('codeaction') diff --git a/lua/navigator/codelens.lua b/lua/navigator/codelens.lua index 927220e..49f6ebd 100644 --- a/lua/navigator/codelens.lua +++ b/lua/navigator/codelens.lua @@ -5,7 +5,7 @@ local codelens = require('vim.lsp.codelens') local log = require('navigator.util').log local mk_handler = require('navigator.util').mk_handler -local nvim_0_6 = require('navigator.util').nvim_0_6 +local nvim_0_6_1 = require('navigator.util').nvim_0_6_1 local trace = require('navigator.util').trace local lsphelper = require('navigator.lspwrapper') @@ -50,7 +50,7 @@ local function _update_sign(line) end local codelens_hdlr = mk_handler(function(err, result, ctx, cfg) - log(ctx, result) + trace(ctx, result) M.codelens_ctx = ctx if err or result == nil then if err then @@ -79,7 +79,7 @@ function M.setup() -- 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 + if nvim_0_6_1() then on_codelens(err, result, ctx, cfg) codelens_hdlr(err, result, ctx, cfg) else @@ -110,20 +110,16 @@ function M.disable() is_enabled = false end - function M.run_action() local original_select = vim.ui.select - vim.ui.select = require("guihua.gui").select + vim.ui.select = require('guihua.gui').select log('codeaction') codelens.run() - vim.defer_fn( - function () - vim.ui.select = original_select - end, 1000 - ) - + vim.defer_fn(function() + vim.ui.select = original_select + end, 1000) end M.inline = function() diff --git a/lua/navigator/definition.lua b/lua/navigator/definition.lua index 56792b5..87873d8 100644 --- a/lua/navigator/definition.lua +++ b/lua/navigator/definition.lua @@ -8,7 +8,7 @@ local TextView = require('guihua.textview') local definition_hdlr = util.mk_handler(function(err, locations, ctx, _) -- log(locations) if err ~= nil then - vim.notify('Defination: ', tostring(err) .. vim.inspect(ctx), vim.lsp.log_levels.WARN) + vim.notify('Defination: ' .. tostring(err) .. vim.inspect(ctx), vim.lsp.log_levels.WARN) return end if type(locations) == 'number' then diff --git a/lua/navigator/diagnostics.lua b/lua/navigator/diagnostics.lua index 8a24e0d..e40c158 100644 --- a/lua/navigator/diagnostics.lua +++ b/lua/navigator/diagnostics.lua @@ -33,6 +33,29 @@ if vim.diagnostic then } end +local diagnostic_cfg = { + -- Enable underline, use default values + underline = _NgConfigValues.lsp.diagnostic.underline, + -- Enable virtual text, override spacing to 3 (prevent overlap) + virtual_text = { + spacing = _NgConfigValues.lsp.diagnostic.virtual_text.spacing, + prefix = _NgConfigValues.icons.diagnostic_virtual_text, + }, + -- Use a function to dynamically turn signs off + -- and on, using buffer local variables + signs = true, + update_in_insert = _NgConfigValues.lsp.diagnostic.update_in_insert or false, + severity_sort = _NgConfigValues.lsp.diagnostic.severity_sort, + float = { + focusable = false, + style = 'minimal', + border = 'rounded', + source = 'always', + header = '', + prefix = '', + }, +} + local function get_count(bufnr, level) if vim.diagnostic ~= nil then return #diagnostic.get(bufnr, { severity = diag_map[level] }) @@ -182,6 +205,7 @@ end local diag_hdlr = mk_handler(function(err, result, ctx, config) require('navigator.lspclient.highlight').diagnositc_config_sign() + config = config or diagnostic_cfg if err ~= nil then log(err, config, result) return @@ -203,11 +227,11 @@ local diag_hdlr = mk_handler(function(err, result, ctx, config) trace('diagnostic', result.diagnostics, ctx, config) end - if util.nvim_0_6() then + if util.nvim_0_6_1() then trace(err, result, ctx, config) vim.lsp.diagnostic.on_publish_diagnostics(err, result, ctx, config) else - log('old version of lsp nvim 050') + log('old version of lsp nvim <=0.5.0') vim.lsp.diagnostic.on_publish_diagnostics(err, _, result, ctx.client_id, _, config) end local uri = result.uri @@ -215,7 +239,7 @@ local diag_hdlr = mk_handler(function(err, result, ctx, config) local diag_cnt = get_count(bufnr, [[Error]]) + get_count(bufnr, [[Warning]]) if empty(result.diagnostics) and diag_cnt > 0 then - log('no result? ', diag_cnt) + trace('no result? ', diag_cnt) return end -- trace("diag: ", mode, result, ctx, config) @@ -303,27 +327,15 @@ local diag_hdlr_async = function() end local M = {} -local diagnostic_cfg = { - -- Enable underline, use default values - underline = true, - -- Enable virtual text, override spacing to 3 (prevent overlap) - virtual_text = { - spacing = 3, - prefix = _NgConfigValues.icons.icons and _NgConfigValues.icons.diagnostic_virtual_text or "" }, - -- Use a function to dynamically turn signs off - -- and on, using buffer local variables - signs = true, - update_in_insert = _NgConfigValues.lsp.diagnostic_update_in_insert or false, - severity_sort = { reverse = true }, -} - -if _NgConfigValues.lsp.diagnostic_virtual_text == false then +if _NgConfigValues.lsp.diagnostic.virtual_text == false then diagnostic_cfg.virtual_text = false end -- vim.lsp.handlers["textDocument/publishDiagnostics"] M.diagnostic_handler = vim.lsp.with(diag_hdlr, diagnostic_cfg) +vim.diagnostic.config(diagnostic_cfg) + M.hide_diagnostic = function() if _NG_VT_DIAG_NS then vim.api.nvim_buf_clear_namespace(0, _NG_VT_DIAG_NS, 0, -1) @@ -361,7 +373,9 @@ M.show_buf_diagnostics = function() enable_preview_edit = true, }) trace('new buffer', listview.bufnr) - vim.api.nvim_buf_add_highlight(listview.bufnr, -1, 'Title', 0, 0, -1) + if listview.bufnr then + vim.api.nvim_buf_add_highlight(listview.bufnr, -1, 'Title', 0, 0, -1) + end end end end @@ -431,11 +445,6 @@ function M.update_err_marker() marker(result, { bufnr = bufnr, method = 'textDocument/publishDiagnostics' }) end --- TODO: update the marker -if _NgConfigValues.diagnostic_scrollbar_sign then - vim.notify('config deprecated, set lsp.diagnostic_scrollbar_sign instead', vim.lsp.log_levels.WARN) -end - if _NgConfigValues.lsp.diagnostic_scrollbar_sign then vim.cmd([[autocmd WinScrolled * lua require'navigator.diagnostics'.update_err_marker()]]) end @@ -462,4 +471,18 @@ function M.show_diagnostics(pos) end end +function M.config(cfg) + cfg = cfg + or { + underline = true, + virtual_text = true, + signs = { _NgConfigValues.icons.diagnostic_err }, + update_in_insert = false, + } + vim.diagnostic.config(cfg) +end + +if not util.nvim_0_6_1() then + util.warn('Navigator 0.4+ only support nvim-0.6+, please use 0.3.x') +end return M diff --git a/lua/navigator/dochighlight.lua b/lua/navigator/dochighlight.lua index a00cbde..742c183 100644 --- a/lua/navigator/dochighlight.lua +++ b/lua/navigator/dochighlight.lua @@ -219,14 +219,9 @@ end local function documentHighlight() api.nvim_exec( [[ - 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 - augroup lsp_document_highlight autocmd! * - autocmd CursorHold lua nav_doc_hl() + autocmd CursorHold,CursorHoldI lua nav_doc_hl() autocmd CursorMoved lua vim.lsp.buf.clear_references() augroup END ]], diff --git a/lua/navigator/foldts.lua b/lua/navigator/foldts.lua index d96fe0f..2ac54cb 100644 --- a/lua/navigator/foldts.lua +++ b/lua/navigator/foldts.lua @@ -1,6 +1,7 @@ -- NOTE: this file is a modified version of fold.lua from nvim-treesitter local log = require('navigator.util').log +local trace = require('navigator.util').trace local api = vim.api local tsutils = require('nvim-treesitter.ts_utils') local query = require('nvim-treesitter.query') @@ -23,7 +24,7 @@ function _G.custom_fold_text() return ' ⚡' .. line .. ': ' .. line_count .. ' lines' end -vim.opt.foldtext = custom_fold_text() +vim.opt.foldtext = _G.custom_fold_text() vim.opt.fillchars = { eob = '-', fold = ' ' } @@ -61,7 +62,7 @@ local folds_levels = tsutils.memoize_by_buf_tick(function(bufnr) local parser = parsers.get_parser(bufnr) if not parser then - warn('treesitter parser not loaded') + log('treesitter parser not loaded') return {} end @@ -148,12 +149,12 @@ local folds_levels = tsutils.memoize_by_buf_tick(function(bufnr) levels[lnum + 1] = tostring(trimmed_level) else -- if levels[lnum + 1] == nil then - levels[lnum + 1] = tostring(trimmed_level + 1) + levels[lnum + 1] = tostring(trimmed_level + 1) -- end end end end - log(levels) + trace(levels) return levels end) diff --git a/lua/navigator/gui.lua b/lua/navigator/gui.lua index c9b20dc..78ad5aa 100644 --- a/lua/navigator/gui.lua +++ b/lua/navigator/gui.lua @@ -12,7 +12,7 @@ function M.new_list_view(opts) local config = require('navigator').config_values() if active_list_view ~= nil then - log(active_list_view) + trace(active_list_view) local winnr = active_list_view.win local bufnr = active_list_view.buf @@ -48,7 +48,7 @@ function M.new_list_view(opts) opts.external = _NgConfigValues.external opts.preview_lines_before = 3 - log(opts) + trace(opts) active_list_view = require('guihua.gui').new_list_view(opts) return active_list_view end diff --git a/lua/navigator/lspclient/attach.lua b/lua/navigator/lspclient/attach.lua index 2c9ef45..ec5d246 100644 --- a/lua/navigator/lspclient/attach.lua +++ b/lua/navigator/lspclient/attach.lua @@ -5,11 +5,6 @@ local util = require('navigator.util') local log = util.log local trace = util.trace -local diagnostic_map = function(bufnr) - local opts = { noremap = true, silent = true } - api.nvim_buf_set_keymap(bufnr, 'n', ']O', ':lua vim.lsp.diagnostic.set_loclist()', opts) -end - local M = {} M.on_attach = function(client, bufnr) @@ -29,7 +24,6 @@ M.on_attach = function(client, bufnr) trace(client) - diagnostic_map(bufnr) -- add highlight for Lspxxx require('navigator.lspclient.highlight').add_highlight() require('navigator.lspclient.highlight').diagnositc_config_sign() @@ -38,7 +32,6 @@ M.on_attach = function(client, bufnr) require('navigator.lspclient.mapping').setup({ client = client, bufnr = bufnr, - cap = client.resolved_capabilities, }) if client.resolved_capabilities.document_highlight then diff --git a/lua/navigator/lspclient/clients.lua b/lua/navigator/lspclient/clients.lua index 5668737..1f7eace 100644 --- a/lua/navigator/lspclient/clients.lua +++ b/lua/navigator/lspclient/clients.lua @@ -1,3 +1,4 @@ +-- todo allow config passed in local util = require('navigator.util') local log = util.log local trace = util.trace @@ -7,6 +8,7 @@ local warn = util.warn _NG_Loaded = {} _LoadedFiletypes = {} +local loader = nil packer_plugins = packer_plugins or nil -- suppress warnings -- packer only @@ -429,6 +431,8 @@ end local function update_capabilities() + trace(ft, 'lsp startup') + local loaded = {} local capabilities = vim.lsp.protocol.make_client_capabilities() capabilities.textDocument.completion.completionItem.snippetSupport = true capabilities.textDocument.completion.completionItem.preselectSupport = true @@ -436,7 +440,7 @@ local function update_capabilities() capabilities.textDocument.completion.completionItem.labelDetailsSupport = true capabilities.textDocument.completion.completionItem.deprecatedSupport = true capabilities.textDocument.completion.completionItem.commitCharactersSupport = true - -- capabilities.textDocument.completion.completionItem.tagSupport = { valueSet = { 1 } } + capabilities.textDocument.completion.completionItem.tagSupport = { valueSet = { 1 } } capabilities.textDocument.completion.completionItem.resolveSupport = { properties = { 'documentation', 'detail', 'additionalTextEdits' }, } @@ -510,6 +514,7 @@ local function lsp_startup(ft, retry, user_lsp_opts) default_config = vim.tbl_deep_extend('force', default_config, ng_default_cfg) local cfg = setups[lspclient] or {} + cfg = vim.tbl_deep_extend('keep', cfg, default_config) -- filetype disabled if not vim.tbl_contains(cfg.filetypes or {}, ft) then diff --git a/lua/navigator/lspclient/highlight.lua b/lua/navigator/lspclient/highlight.lua index 46417cc..bd70e94 100644 --- a/lua/navigator/lspclient/highlight.lua +++ b/lua/navigator/lspclient/highlight.lua @@ -1,6 +1,6 @@ local M = {} -local log = require"navigator.util".log +local log = require('navigator.util').log local api = vim.api -- lsp sign          ﮻         ﯭ        ﳀ   @@ -10,80 +10,56 @@ function M.diagnositc_config_sign() end local icons = _NgConfigValues.icons - local sign_name = "NavigatorLightBulb" + 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' }) - 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"}) + 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 = ''}) + local e, w, i, h = icons.diagnostic_err, icons.diagnostic_warn, icons.diagnostic_info, icons.diagnostic_hint + 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') - 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 + t = vim.fn.sign_getdefined('DiagnosticSignWarn') end M.configed = true end function M.add_highlight() - -- lsp system default - api.nvim_command("hi! link LspDiagnosticsUnderlineError SpellBad") - 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! 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") + 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'} + { '#aefe00', '#aede00', '#aebe00', '#4e7efe' }, + { '#ff00e0', '#df00e0', '#af00e0', '#fedefe' }, + { '#1000ef', '#2000df', '#2000cf', '#f0f040' }, + { '#d8a8a3', '#c8a8a3', '#b8a8a3', '#4e2c33' }, + { '#ffa724', '#efa024', '#dfa724', '#0040ff' }, + { '#afdc2b', '#09dc4b', '#08d04b', '#ef4f8f' }, } 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]) + local cmd = string.format('hi! default NGHiReference_%i_%i guibg=%s guifg=%s ', i, j, colors[i][j], colors[i][4]) vim.cmd(cmd) 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 return M diff --git a/lua/navigator/lspclient/mapping.lua b/lua/navigator/lspclient/mapping.lua index c5c7296..bb55a3a 100644 --- a/lua/navigator/lspclient/mapping.lua +++ b/lua/navigator/lspclient/mapping.lua @@ -1,5 +1,6 @@ -local log = require('navigator.util').log -local trace = require('navigator.util').trace +local util = require('navigator.util') +local log = util.log +local trace = util.trace local event_hdlrs = { { ev = 'BufWritePre', func = [[require "navigator.diagnostics".set_diag_loclist()]] }, @@ -13,8 +14,8 @@ local single = { '╭', '─', '╮', '│', '╯', '─', '╰', '│' } -- TODO https://github.com/neovim/neovim/pull/16591 use vimkeymap.set/del -- LuaFormatter off local key_maps = { - { key = 'gr', func = "require('navigator.reference').reference()" }, - { key = 'Gr', func = "require('navigator.reference').async_ref()" }, + { key = 'gr', func = "require('navigator.reference').async_ref()" }, + { key = 'gr', func = "require('navigator.reference').reference()" }, -- reference deprecated { mode = 'i', key = '', func = 'signature_help()' }, { key = '', func = 'signature_help()' }, { key = 'g0', func = "require('navigator.symbols').document_symbols()" }, @@ -39,6 +40,7 @@ local key_maps = { { key = 'dt', func = "require('navigator.diagnostics').toggle_diagnostics()" }, { key = ']d', func = "diagnostic.goto_next({ border = 'rounded', max_width = 80})" }, { key = '[d', func = "diagnostic.goto_prev({ border = 'rounded', max_width = 80})" }, + { key = ']O', func = 'diagnostic.set_loclist()' }, { key = ']r', func = "require('navigator.treesitter').goto_next_usage()" }, { key = '[r', func = "require('navigator.treesitter').goto_previous_usage()" }, { key = '', func = 'definition()' }, @@ -138,8 +140,10 @@ local function set_mapping(user_opts) f = 'lua ' .. value.func .. '' elseif string.find(value.func, 'diagnostic') then local diagnostic = 'lua vim.' - if vim.lsp.diagnostic ~= nil then - diagnostic = 'lua vim.lsp.' + if vim.diagnostic ~= nil then + diagnostic = 'lua vim.' + else + util.error('Please update nvim to 0.6.1+') end f = diagnostic .. value.func .. '' elseif string.find(value.func, 'vim.') then @@ -152,7 +156,7 @@ local function set_mapping(user_opts) elseif string.find(value.func, 'formatting') then fmtkey = value.key end - log('binding', k, f) + trace('binding', k, f) set_keymap(m, k, f, opts) end @@ -172,6 +176,7 @@ local function set_mapping(user_opts) elseif fmtkey then del_keymap('n', fmtkey) end + if user_opts.cap and user_opts.cap.document_range_formatting then log('formatting enabled', user_opts.cap) end @@ -247,7 +252,9 @@ function M.setup(user_opts) autocmd(user_opts) set_event_handler(user_opts) - local cap = user_opts.cap or vim.lsp.protocol.make_client_capabilities() + local client = user_opts.client or {} + local cap = client.resolved_capabilities or vim.lsp.protocol.make_client_capabilities() + log('lsp cap:', cap) if cap.call_hierarchy or cap.callHierarchy then diff --git a/lua/navigator/lspwrapper.lua b/lua/navigator/lspwrapper.lua index 889278d..fad9945 100644 --- a/lua/navigator/lspwrapper.lua +++ b/lua/navigator/lspwrapper.lua @@ -1,7 +1,7 @@ local M = {} local util = require('navigator.util') -local nvim_0_6 = util.nvim_0_6() +local nvim_0_6_1 = util.nvim_0_6_1() local gutil = require('guihua.util') local lsp = require('vim.lsp') @@ -145,7 +145,7 @@ function M.call_sync(method, params, opts, handler) opts = opts or {} local results_lsp, err = lsp.buf_request_sync(0, method, params, opts.timeout or vim.g.navtator_timeout or 1000) - if nvim_0_6() then + if nvim_0_6_1() then handler(err, extract_result(results_lsp), { method = method }, nil) else handler(err, method, extract_result(results_lsp), nil, nil) @@ -263,6 +263,10 @@ end local function order_locations(locations) table.sort(locations, function(i, j) + if i == nil or j == nil or i.uri == nil or j.uri == nil then + -- log(i, j) + return false + end if i.uri == j.uri then if i.range and i.range.start then return i.range.start.line < j.range.start.line @@ -337,9 +341,9 @@ function M.locations_to_items(locations, ctx) for i, loc in ipairs(locations) do local funcs = nil local item = lsp.util.locations_to_items({ loc }, enc)[1] - -- log(item) item.range = locations[i].range or locations[i].targetRange item.uri = locations[i].uri or locations[i].targetUri + item.definition = locations[i].definition if is_win then log(item.uri) -- file:///C:/path/to/file @@ -416,6 +420,7 @@ function M.locations_to_items(locations, ctx) vim.cmd([[set eventignore-=FileType]]) + log(items) return items, width + 24, second_part -- TODO handle long line? end @@ -431,6 +436,9 @@ function M.symbol_to_items(locations) if i.definition then return true end + if j.definition then + return false + end if i.uri == j.uri then if i.range and i.range.start then return i.range.start.line < j.range.start.line diff --git a/lua/navigator/reference.lua b/lua/navigator/reference.lua index bc2d4f0..6efdfbc 100644 --- a/lua/navigator/reference.lua +++ b/lua/navigator/reference.lua @@ -22,29 +22,41 @@ local ref_view = function(err, locations, ctx, cfg) if ctx.results == nil then return end - if #ctx.results.definitions.result == nil or ctx.results.references.result == nil then + if (ctx.results.definitions == nil) or (ctx.results.references == nil) then log('not all requests returned') return end local definitions = ctx.results.definitions local references = ctx.results.references + log(ctx) if definitions.error and references.error then vim.notify('lsp ref callback error' .. vim.inspect(ctx.result), vim.lsp.log_levels.WARN) end locations = {} - if definitions.result then + if definitions and definitions.result then for i, _ in ipairs(definitions.result) do definitions.result[i].definition = true end vim.list_extend(locations, definitions.result) end - if references.result then - vim.list_extend(locations, references.result) + if references and references.result and #references.result > 0 then + local refs = references.result + for _, value in pairs(locations) do + vrange = value.range or { start = { line = 0 }, ['end'] = { line = 0 } } + for i = 1, #refs, 1 do + local rg = refs[i].range or {} + log(value, refs[i]) + log(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 - ctx = references.ctx or definitions.ctx err = nil - cfg = references.config or definitions.config - trace(ctx, locations) + log(locations) end -- log("num", num) -- log("bfnr", bufnr) @@ -63,7 +75,7 @@ local ref_view = function(err, locations, ctx, cfg) return end if locations == nil or vim.tbl_isempty(locations) then - vim.notify('References not found', vim.lsp.log_levels.WARN) + vim.notify('References not found', vim.lsp.log_levels.INFO) return end @@ -137,11 +149,17 @@ end) local async_ref = function() local ref_params = vim.lsp.util.make_position_params() - local results = { definitions = {}, references = {} } + local results = {} ref_params.context = { includeDeclaration = false } lsp.call_async('textDocument/definition', ref_params, function(err, result, ctx, config) trace(err, result, ctx, config) + for i = 1, #result do + if result[i].range == nil and result[i].targetRange then + result[i].range = result[i].targetRange + end + end results.definitions = { error = err, result = result, ctx = ctx, config = config } + log(result) ctx = ctx or {} ctx.results = results ctx.combine = true diff --git a/lua/navigator/render.lua b/lua/navigator/render.lua index de66bc3..c9cdd0c 100644 --- a/lua/navigator/render.lua +++ b/lua/navigator/render.lua @@ -1,16 +1,16 @@ -local log = require"guihua.log".info -local trace = require"guihua.log".trace +local log = require('guihua.log').info +local trace = require('guihua.log').trace local M = {} -local clone = require'guihua.util'.clone +local clone = require('guihua.util').clone local function filename(url) if url == nil then return '' end - return url:match("^.+/(.+)$") or url + return url:match('^.+/(.+)$') or url end local function extension(url) - local ext = url:match("^.+(%..+)$") or "txt" + local ext = url:match('^.+(%..+)$') or 'txt' return string.sub(ext, 2) end @@ -38,7 +38,6 @@ local function get_pads(win_width, text, postfix) i = i + rem * 10 -- log(i) end - end if i > 3 then @@ -52,18 +51,18 @@ end function M.prepare_for_render(items, opts) opts = opts or {} if items == nil or #items < 1 then - vim.notify("no item found or empty fields", vim.lsp.log_levels.INFO) + vim.notify('no item found or empty fields', vim.lsp.log_levels.INFO) return end local item = clone(items[1]) - local display_items = {item} + local display_items = { item } local last_summary_idx = 1 local total_ref_in_file = 1 local total = opts.total - local icon = " " - local lspapi = opts.api or "∑" + local icon = ' ' + local lspapi = opts.api or '∑' - local ok, devicons = pcall(require, "nvim-web-devicons") + local ok, devicons = pcall(require, 'nvim-web-devicons') if ok then local fn = filename(items[1].filename) local ext = extension(fn) @@ -85,7 +84,7 @@ function M.prepare_for_render(items, opts) local space local trim local lspapi_display = lspapi - items[i].symbol_name = items[i].symbol_name or "" -- some LSP API does not have range for this + items[i].symbol_name = items[i].symbol_name or '' -- some LSP API does not have range for this local fn = display_items[last_summary_idx].filename local dfn = items[i].display_filename @@ -103,13 +102,18 @@ function M.prepare_for_render(items, opts) if trim and opts.width > 50 and #dfn > opts.width - 20 then local fn1 = string.sub(dfn, 1, opts.width - 50) local fn2 = string.sub(dfn, #dfn - 10, #dfn) - display_items[last_summary_idx].display_filename = fn1 .. "" .. fn2 + display_items[last_summary_idx].display_filename = fn1 .. '' .. fn2 space = ' ' -- log("trim", fn1, fn2) end - local api_disp = string.format("%s %s%s%s %i", icon, - display_items[last_summary_idx].display_filename, space, - lspapi_display, total_ref_in_file) + local api_disp = string.format( + '%s %s%s%s %i', + icon, + display_items[last_summary_idx].display_filename, + space, + lspapi_display, + total_ref_in_file + ) if total then api_disp = api_disp .. ' of: ' .. tostring(total) @@ -118,20 +122,17 @@ function M.prepare_for_render(items, opts) display_items[last_summary_idx].text = api_disp total_ref_in_file = total_ref_in_file + 1 else - lspapi_display = lspapi item = clone(items[i]) - space, trim = get_pads(opts.width, icon .. ' ' .. item.display_filename, - lspapi_display .. ' 12 of 33') + space, trim = get_pads(opts.width, icon .. ' ' .. item.display_filename, lspapi_display .. ' 12 of 33') if trim and opts.width > 52 and #item.display_filename > opts.width - 20 then - item.display_filename = string.sub(item.display_filename, 1, opts.width - 52) .. "" - .. string.sub(item.display_filename, - #item.display_filename - 10, - #item.display_filename) + item.display_filename = string.sub(item.display_filename, 1, opts.width - 52) + .. '' + .. string.sub(item.display_filename, #item.display_filename - 10, #item.display_filename) space = ' ' end - item.text = string.format("%s %s%s%s 1", icon, item.display_filename, space, lspapi_display) + item.text = string.format('%s %s%s%s 1', icon, item.display_filename, space, lspapi_display) trace(item.text) table.insert(display_items, item) @@ -140,14 +141,16 @@ function M.prepare_for_render(items, opts) end -- content of code lines item = clone(items[i]) - item.text = require'navigator.util'.trim_and_pad(item.text) - item.text = string.format("%4i: %s", item.lnum, item.text) - local ts_report = "" + item.text = require('navigator.util').trim_and_pad(item.text) + item.text = string.format('%4i: %s', item.lnum, item.text) + local ts_report = '' if item.lhs then ts_report = _NgConfigValues.icons.value_changed end + log(item) if item.definition then + log('definition', item) ts_report = ts_report .. _NgConfigValues.icons.value_definition .. ' ' end local header_len = #ts_report + 4 -- magic number 2 @@ -155,7 +158,7 @@ function M.prepare_for_render(items, opts) item.text = item.text:gsub('%s*[%[%(%{]*%s*$', '') if item.call_by ~= nil and #item.call_by > 0 then - trace("call_by:", #item.call_by) + 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*$', '') @@ -183,15 +186,15 @@ function M.prepare_for_render(items, opts) if #ts_report > 1 then space, trim = get_pads(win_width, item.text, ts_report) if trim then - item.text = string.sub(item.text, 1, opts.width - 20) .. "" + item.text = string.sub(item.text, 1, opts.width - 20) .. '' 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) + trace('exceeding', #item.text, #ts_report, win_width) space = ' ' else local remain = win_width - #item.text - #ts_report - trace("remain", remain) + trace('remain', remain) space = string.rep(' ', remain) end end diff --git a/lua/navigator/util.lua b/lua/navigator/util.lua index 78cf6c7..4101c94 100644 --- a/lua/navigator/util.lua +++ b/lua/navigator/util.lua @@ -3,8 +3,8 @@ -- Some of function copied from https://github.com/RishabhRD/nvim-lsputils local M = { log_path = vim.lsp.get_log_path() } -- local is_windows = uv.os_uname().version:match("Windows") - -local nvim_0_6 +local guihua = require('guihua.util') +local nvim_0_6_1 M.path_sep = function() local is_win = vim.loop.os_uname().sysname:find('Windows') @@ -281,19 +281,7 @@ M.open_file = function(filename) vim.api.nvim_command(string.format('e! %s', filename)) end -M.open_file_at = function(filename, line, col, split) - if split == nil then - -- code - vim.api.nvim_command(string.format('e! +%s %s', line, filename)) - elseif split == 'v' then - vim.api.nvim_command(string.format('vsp! +%s %s', line, filename)) - elseif split == 's' then - vim.api.nvim_command(string.format('sp! +%s %s', line, filename)) - end - -- vim.api.nvim_command(string.format("e! %s", filename)) - col = col or 1 - vim.fn.cursor(line, col) -end +M.open_file_at = guihua.open_file_at function M.exists(var) for k, _ in pairs(_G) do @@ -355,32 +343,21 @@ function M.get_current_winid() return api.nvim_get_current_win() end -function M.nvim_0_6() - if nvim_0_6 ~= nil then - return nvim_0_6 +function M.nvim_0_6_1() + if nvim_0_6_1 ~= nil then + return nvim_0_6_1 end - if debug.getinfo(vim.lsp.handlers.signature_help).nparams == 4 then - nvim_0_6 = true - else - nvim_0_6 = false + nvim_0_6_1 = vim.fn.has('nvim-0.6.1') == 1 + if nvim_0_6_1 == false then + M.warn('Please use navigator 0.3 version for neovim version < 0.6.1') end - return nvim_0_6 + return nvim_0_6_1 end function M.mk_handler(fn) return function(...) - local config_or_client_id = select(4, ...) - local is_new = M.nvim_0_6() - if is_new then + if M.nvim_0_6_1() then return fn(...) - else - local err = select(1, ...) - local method = select(2, ...) - local result = select(3, ...) - local client_id = select(4, ...) - local bufnr = select(5, ...) - local config = select(6, ...) - return fn(err, result, { method = method, client_id = client_id, bufnr = bufnr }, config) end end end @@ -422,15 +399,15 @@ 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, {}) + vim.notify('WRN: ' .. msg, vim.lsp.log_levels.WARN) end function M.error(msg) - vim.api.nvim_echo({ { 'ERR: ' .. msg, 'ErrorMsg' } }, true, {}) + vim.notify('ERR: ' .. msg, vim.lsp.log_levels.EROR) end function M.info(msg) - vim.api.nvim_echo({ { 'Info: ' .. msg } }, true, {}) + vim.notify('INF: ' .. msg, vim.lsp.log_levels.INFO) end return M diff --git a/playground/README.md b/playground/README.md index e929157..5f73db5 100644 --- a/playground/README.md +++ b/playground/README.md @@ -12,13 +12,14 @@ most used plugins for programmer. - luasnip - aurora (colorscheme used in the screenshot) -There also three folder `js`, `go`, `py`. Those folder have some basic source code you can play with. +There are three folders `js`, `go`, `py`. Those folders have some basic source code you can play with. +The init will install the plugins in ``/tmp/nvim`` folder. It will not affect your current setup. ## Install LSP The playground has js, py, go folder, so you can install either one your self in your PATH. If you want to try lua, Please check sumneko setup in init.lua make sure it pointed to correct path. By default it -potint to ~/github/sumneko +potint to ~/github/sumneko if not existed in your PATH. ## run init.lua diff --git a/playground/init.lua b/playground/init.lua index fb29b5f..0785b5b 100644 --- a/playground/init.lua +++ b/playground/init.lua @@ -10,7 +10,7 @@ local sumneko_root_path = vim.fn.expand('$HOME') .. '/github/sumneko/lua-languag local sumneko_binary = vim.fn.expand('$HOME') .. '/github/sumneko/lua-language-server/bin/macOS/lua-language-server' local lua_cfg = { - cmd = { sumneko_binary, '-E', sumneko_root_path .. '/main.lua' }, + -- cmd = { sumneko_binary, '-E', sumneko_root_path .. '/main.lua' }, settings = { Lua = { runtime = { version = 'LuaJIT', path = vim.split(package.path, ';') }, @@ -19,6 +19,10 @@ local lua_cfg = { }, } +if vim.fn.executable('lua-language-server') == 0 then + lua_cfg.cmd = { sumneko_binary, '-E', sumneko_root_path .. '/main.lua' } +end + local function load_plugins() require('packer').startup({ function(use) diff --git a/playground/py/go.py b/playground/py/go.py new file mode 100644 index 0000000..8fb8de7 --- /dev/null +++ b/playground/py/go.py @@ -0,0 +1,14 @@ +from random import shuffle +a = list(range(5)) + +def go(beg, c, b): + if beg >= len(a): + print(a ) + for i in range(beg, len(a)): + a[beg], a[i] = a[i], a[beg] + go(beg + 1) + a[beg], a[i] = a[i], a[beg] + print(a, b) + +go(0, 1, 4) +shuffle([1, 2,3 ])