diff --git a/README.md b/README.md index cae5ab3..46f9b2c 100644 --- a/README.md +++ b/README.md @@ -257,8 +257,8 @@ require'navigator'.setup({ -- end, -- The attach code will apply to all LSP clients - default_mapping = true, -- set to false if you will remap every key - keymaps = {{key = "gK", func = "declaration()"}}, -- a list of key maps + 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, doc = '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 @@ -271,7 +271,7 @@ require'navigator'.setup({ signature_help_cfg = nil, -- if you would like to init ray-x/lsp_signature plugin in navigator, and pass in your own config to signature help icons = { -- Code action - code_action_icon = "🏏", + code_action_icon = "🏏", -- note: need terminal support, for those not support unicode, might crash -- Diagnostics diagnostic_head = '🐛', diagnostic_head_severity_1 = "🈲", diff --git a/lua/navigator.lua b/lua/navigator.lua index 403b3c7..b5cad47 100755 --- a/lua/navigator.lua +++ b/lua/navigator.lua @@ -5,7 +5,9 @@ local function warn(msg) end local function info(msg) - vim.api.nvim_echo({ { 'Info: ' .. msg } }, true, {}) + if _NgConfigValues.debug then + vim.api.nvim_echo({ { 'Info: ' .. msg } }, true, {}) + end end _NgConfigValues = { @@ -16,7 +18,7 @@ _NgConfigValues = { preview_lines = 40, -- total lines in preview screen 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 + keymaps = {}, -- e.g keymaps={{key = "GR", func = vim.lsp.buf.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" @@ -204,7 +206,7 @@ local extend_config = function(opts) info(string.format('[] extend LSP support for %s %s ', key, k)) end elseif key == 'keymaps' then - info('keymap override') + info('keymap override', v) -- skip key check and allow mapping to handle that else warn(string.format('[] Key %s %s not valid', key, k)) diff --git a/lua/navigator/formatting.lua b/lua/navigator/formatting.lua index 9ad1cc8..4da3393 100644 --- a/lua/navigator/formatting.lua +++ b/lua/navigator/formatting.lua @@ -31,4 +31,16 @@ return { end end, 100) end, + range_foramt = function(err, result, ctx, _) + local old_func = vim.go.operatorfunc + _G.op_func_formatting = function() + local start = vim.api.nvim_buf_get_mark(0, '[') + local finish = vim.api.nvim_buf_get_mark(0, ']') + vim.lsp.buf.range_formatting({}, start, finish) + vim.go.operatorfunc = old_func + _G.op_func_formatting = nil + end + vim.go.operatorfunc = 'v:lua.op_func_formatting' + vim.api.nvim_feedkeys('g@', 'n', false) + end, } diff --git a/lua/navigator/lspclient/mapping.lua b/lua/navigator/lspclient/mapping.lua index 482f62f..4d35ad5 100644 --- a/lua/navigator/lspclient/mapping.lua +++ b/lua/navigator/lspclient/mapping.lua @@ -1,11 +1,12 @@ local util = require('navigator.util') 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', func = 'document_highlight()' }, - { ev = 'CursorHoldI', func = 'document_highlight()' }, - { ev = 'CursorMoved', func = 'clear_references()' }, + { 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 @@ -20,45 +21,55 @@ 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').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()" }, - { key = 'gW', func = "require('navigator.workspace').workspace_symbol_live()" }, - { key = '', func = "require('navigator.definition').definition()" }, - { key = 'gd', func = "require('navigator.definition').definition()" }, - { key = 'gD', func = "declaration({ border = 'rounded', max_width = 80 })" }, - { key = 'gp', func = "require('navigator.definition').definition_preview()" }, - { key = 'gt', func = "require('navigator.treesitter').buf_ts()" }, - { key = 'gT', func = "require('navigator.treesitter').bufs_ts()" }, - { key = 'ct', func = "require('navigator.ctags').ctags()" }, - { key = 'K', func = 'hover({ popup_opts = { border = single, max_width = 80 }})' }, - { key = 'ca', mode = 'n', func = "require('navigator.codeAction').code_action()" }, - { key = 'ca', mode = 'v', func = "require('navigator.codeAction').range_code_action()" }, + { key = 'gr', func = require('navigator.reference').async_ref, doc = 'async_ref' }, + { key = 'gr', func = require('navigator.reference').reference, doc = 'reference' }, -- reference deprecated + { mode = 'i', key = '', func = vim.lsp.signature_help, doc = 'signature_help' }, + { key = '', func = vim.lsp.buf.signature_help, doc = 'signature_help' }, + { key = 'g0', func = require('navigator.symbols').document_symbols, doc = 'document_symbols' }, + { key = 'gW', func = require('navigator.workspace').workspace_symbol_live, doc = 'workspace_symbol_live' }, + { key = '', func = require('navigator.definition').definition, doc = 'definition' }, + { key = 'gd', func = require('navigator.definition').definition, doc = 'definition' }, + { key = 'gD', func = vim.lsp.buf.declaration, doc = 'declaration' }, + { key = 'gp', func = require('navigator.definition').definition_preview, doc = 'definition_preview' }, + { key = 'gt', func = require('navigator.treesitter').buf_ts, doc = 'buf_ts' }, + { key = 'gT', func = require('navigator.treesitter').bufs_ts, doc = 'bufs_ts' }, + { key = 'ct', func = require('navigator.ctags').ctags, doc = 'ctags' }, + { key = 'K', func = vim.lsp.hover, doc = 'hover' }, + { key = 'ca', mode = 'n', func = require('navigator.codeAction').code_action, doc = 'code_action' }, + { + key = 'ca', + mode = 'v', + func = require('navigator.codeAction').range_code_action, + doc = 'range_code_action', + }, -- { key = 're', func = 'rename()' }, - { key = 'rn', func = "require('navigator.rename').rename()" }, - { key = 'gi', func = 'incoming_calls()' }, - { key = 'go', func = 'outgoing_calls()' }, - { key = 'gi', func = 'implementation()' }, - { key = 'D', func = 'type_definition()' }, - { key = 'gL', func = "require('navigator.diagnostics').show_diagnostics()" }, - { key = 'gG', func = "require('navigator.diagnostics').show_buf_diagnostics()" }, - { 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()' }, - { key = 'g', func = 'implementation()' }, - { key = 'k', func = "require('navigator.dochighlight').hi_symbol()" }, - { key = 'wa', func = "require('navigator.workspace').add_workspace_folder()" }, - { key = 'wr', func = "require('navigator.workspace').remove_workspace_folder()" }, - { key = 'ff', func = 'format({async = true})', mode = 'n' }, - { key = 'ff', func = 'range_formatting()', mode = 'v' }, - { key = 'wl', func = "require('navigator.workspace').list_workspace_folders()" }, - { key = 'la', mode = 'n', func = "require('navigator.codelens').run_action()" }, + { key = 'rn', func = require('navigator.rename').rename, doc = 'rename' }, + { key = 'gi', func = vim.lsp.buf.incoming_calls, doc = 'incoming_calls' }, + { key = 'go', func = vim.lsp.buf.outgoing_calls, doc = 'outgoing_calls' }, + { key = 'gi', func = vim.lsp.buf.implementation, doc = 'implementation' }, + { key = 'D', func = vim.lsp.buf.type_definition, doc = 'type_definition' }, + { key = 'gL', func = require('navigator.diagnostics').show_diagnostics, doc = 'show_diagnostics' }, + { key = 'gG', func = require('navigator.diagnostics').show_buf_diagnostics, doc = 'show_buf_diagnostics' }, + { key = 'dt', func = require('navigator.diagnostics').toggle_diagnostics, doc = 'toggle_diagnostics' }, + { key = ']d', func = vim.diagnostic.goto_next, doc = 'next diagnostics' }, + { key = '[d', func = vim.diagnostic.goto_prev, doc = 'prev diagnostics' }, + { key = ']O', func = vim.diagnostic.set_loclist, doc = 'diagnostics set loclist' }, + { key = ']r', func = require('navigator.treesitter').goto_next_usage, doc = 'goto_next_usage' }, + { key = '[r', func = require('navigator.treesitter').goto_previous_usage, doc = 'goto_previous_usage' }, + { key = '', func = vim.lsp.buf.definition, doc = 'definition' }, + { key = 'g', func = vim.lsp.buf.implementation, doc = 'implementation' }, + { key = 'k', func = require('navigator.dochighlight').hi_symbol, doc = 'hi_symbol' }, + { key = 'wa', func = require('navigator.workspace').add_workspace_folder, doc = 'add_workspace_folder' }, + { + key = 'wr', + func = require('navigator.workspace').remove_workspace_folder, + doc = 'remove_workspace_folder', + }, + { key = 'ff', func = vim.lsp.buf.format, mode = 'n', doc = 'format' }, + { key = 'ff', func = vim.lsp.buf.range_formatting, mode = 'v', doc = 'range format' }, + { key = 'rf', func = require('navigator.formatting').range_format, mode = 'n', doc = 'range_fmt_v' }, + { key = 'wl', func = require('navigator.workspace').list_workspace_folders, doc = 'list_workspace_folders' }, + { key = 'la', mode = 'n', func = require('navigator.codelens').run_action, doc = 'run code lens action' }, } local commands = { @@ -77,8 +88,8 @@ local key_maps_help = {} local M = {} local ccls_mappings = { - { key = 'gi', func = "require('navigator.cclshierarchy').incoming_calls()" }, - { key = 'go', func = "require('navigator.cclshierarchy').outgoing_calls()" }, + { key = 'gi', func = require('navigator.cclshierarchy').incoming_calls, doc = 'incoming_calls' }, + { key = 'go', func = require('navigator.cclshierarchy').outgoing_calls, doc = 'outgoing_calls' }, } local check_cap = function(opts) @@ -133,13 +144,17 @@ local function set_mapping(lsp_attach_info) local user_key = _NgConfigValues.keymaps or {} local bufnr = lsp_attach_info.bufnr or 0 - local function del_keymap(...) - vim.api.nvim_buf_del_keymap(bufnr, ...) + local function del_keymap(mode, key, ...) + local ks = vim.api.nvim_buf_get_keymap(bufnr, mode) + if vim.tbl_contains(ks, key) then + vim.api.nvim_buf_del_keymap(bufnr, mode, key, ...) + end end local function set_keymap(...) vim.api.nvim_buf_set_keymap(bufnr, ...) end + -- local function buf_set_option(...) -- vim.api.nvim_buf_set_option(bufnr, ...) -- end @@ -169,40 +184,66 @@ local function set_mapping(lsp_attach_info) end local fmtkey, rfmtkey for _, value in pairs(key_maps) do - local f = 'lua vim.lsp.buf.' .. value.func .. '' - if string.find(value.func, 'require') or string.find(value.func, 'vim.') then - f = 'lua ' .. value.func .. '' - elseif string.find(value.func, 'diagnostic') then - local diagnostic = 'lua vim.' - diagnostic = 'lua vim.' - f = diagnostic .. value.func .. '' - -- elseif string.find(value.func, 'vim.') then - -- f = 'lua ' .. value.func .. '' + if type(value.func) == 'string' then -- deprecated will remove when 0.8 is out + vim.notify('keymap config updated: ' .. value.key .. ' func ' .. value.func .. ' should be a function') + local f = 'lua vim.lsp.buf.' .. value.func .. '' + if string.find(value.func, 'require') or string.find(value.func, 'vim.') then + f = 'lua ' .. value.func .. '' + elseif string.find(value.func, 'diagnostic') then + local diagnostic = 'lua vim.' + diagnostic = 'lua vim.' + f = diagnostic .. value.func .. '' + end + + local k = value.key + local m = value.mode or 'n' + if string.find(value.func, 'range_formatting') then + rfmtkey = value.key + elseif string.find(value.func, 'format') then + fmtkey = value.key + end + trace('binding', k, f) + set_keymap(m, k, f, opts) end - local k = value.key - local m = value.mode or 'n' - if string.find(value.func, 'range_formatting') then - rfmtkey = value.key - elseif string.find(value.func, 'format') then - fmtkey = value.key + if type(value.func) == 'function' then -- new from 0.7.x + -- neovim 0.7.0 + + opts.buffer = key_maps.buffer or value.buffer + vim.keymap.set(value.mode or 'n', value.key, value.func, opts) + if string.find(value.doc, 'range format') then + rfmtkey = value.key + elseif string.find(value.doc, 'format') then + fmtkey = value.key + end end - trace('binding', k, f) - set_keymap(m, k, f, opts) end for _, val in pairs(key_maps) do - table.insert(key_maps_help, (val.mode or 'n') .. '|' .. val.key .. '|' .. val.func) + local helper_msg = '' + if val.doc then + helper_msg = val.doc + elseif type(val.func) == 'string' then + helper_msg = val.func + end + + local item = (val.mode or 'n') .. '|' .. val.key .. '|' .. helper_msg + if not vim.tbl_contains(key_maps_help, item) then + table.insert(key_maps_help, (val.mode or 'n') .. '|' .. val.key .. '|' .. helper_msg) + end end -- if user_opts.cap.document_formatting then if doc_fmt and _NgConfigValues.lsp.format_on_save then - vim.cmd([[ - aug NavigatorAuFormat - au! - autocmd BufWritePre lua vim.lsp.buf.format({async = true}) - aug END - ]]) + local gn = api.nvim_create_augroup('NavAuGroupFormat', {}) + + api.nvim_create_autocmd({ 'BufWritePre' }, { + group = gn, + buffer = bufnr, + callback = function() + vim.lsp.buf.format({ async = true }) + end, + }) elseif fmtkey then del_keymap('n', fmtkey) end @@ -219,41 +260,48 @@ local function set_mapping(lsp_attach_info) end local function autocmd() - vim.api.nvim_exec( - [[ - aug NavigatorDocHlAu - au! - au CmdlineLeave : lua require('navigator.dochighlight').cmd_nohl() - aug END - ]], - false - ) + local gn = api.nvim_create_augroup('NavAuGroupDocHlAu', {}) + + api.nvim_create_autocmd({ 'BufWritePre' }, { + group = gn, + callback = require('navigator.dochighlight').cmd_nohl, + }) 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 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, - vim.api.nvim_command([[augroup nvim_nv_lsp_autos]]) - vim.api.nvim_command([[autocmd!]]) + local gn = api.nvim_create_augroup('nvim_nv_event_autos', {}) for _, value in pairs(event_hdlrs) do - local f = '' - if string.find(value.func, 'require') ~= nil then - f = 'lua ' .. value.func - else - f = 'lua vim.lsp.buf.' .. value.func - end - local cmd = 'autocmd FileType ' - .. file_types - .. ' autocmd nvim_nv_lsp_autos ' - .. value.ev - .. ' silent! ' - .. f - vim.api.nvim_command(cmd) + api.nvim_create_autocmd(value.ev, { + group = gn, + pattern = file_types, + callback = value.func, + }) end - vim.api.nvim_command([[augroup END]]) end M.toggle_lspformat = function(on) @@ -348,7 +396,7 @@ M.get_keymaps_help = function() border = 'none', prompt = true, enter = true, - rect = { height = 20, width = 90 }, + rect = { height = 24, width = 50 }, data = key_maps_help, }) diff --git a/playground/init.lua b/playground/init.lua index e73ce97..f13b687 100644 --- a/playground/init.lua +++ b/playground/init.lua @@ -47,6 +47,8 @@ local function load_plugins() config = function() require('navigator').setup({ lsp_signature_help = true, + debug = true, + keymaps = { { key = 'gK', func = vim.lsp.buf.definition, doc = 'definition' } }, }) end, })