add multiple symbol highlight

neovim_0_5
ray-x 3 years ago
parent 1546b6a604
commit 6a15e6838d

@ -56,6 +56,8 @@ implementation.
- FZY search with Lua-JIT
- LSP multiple symbol highlight and jump between reference
- Better navigation for diagnostic errors, Navigate through all files/buffers that contain errors/warnings
- Grouping references/implementation/incoming/outgoing based on file names.
@ -258,6 +260,9 @@ 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
Document highlight provided by LSP.

@ -1,7 +1,127 @@
local util = require "navigator.util"
local log = util.log
local trace = util.trace
local api = vim.api
local references = {}
_NG_hi_list = {}
_NG_current_symbol = ""
_NG_ref_hi_idx = 1
-- extract symbol from cursor
local function get_symbol()
local currentWord = vim.fn.expand('<cword>')
return currentWord
end
local function add_locs(bufnr, result)
local symbol = get_symbol()
if #result < 1 then
return
end
symbol = string.format("%s_%i_%i_%i", symbol, bufnr, result[1].range.start.line,
result[1].range.start.character)
if _NG_hi_list[symbol] == nil then
_NG_hi_list[symbol] = {range = {}}
end
if _NG_hi_list[symbol] ~= nil then
log("already added", symbol)
_NG_hi_list[symbol].range = {}
-- vim.fn.matchdelete(hid)
end
trace("add ", symbol)
_NG_hi_list[symbol].range = result
_NG_current_symbol = symbol
end
local function nohl()
for key, value in pairs(_NG_hi_list) do
if value.hi_ids ~= nil then
for _, v in ipairs(value.hi_ids) do
log("delete", v)
vim.fn.matchdelete(v)
end
_NG_hi_list[key].hi_ids = nil
end
end
end
local function hi_symbol()
local symbol_wd = get_symbol()
local symbol = _NG_current_symbol
if string.find(symbol, symbol_wd) == nil then
vim.lsp.buf.document_highlight()
symbol = _NG_current_symbol
end
if symbol == nil or symbol == "" then
log("nil symbol")
return
end
_NG_ref_hi_idx = _NG_ref_hi_idx + 1
if _NG_ref_hi_idx > 6 then -- 6 magic number for colors
_NG_ref_hi_idx = 1
end
local range = _NG_hi_list[symbol].range or {}
if _NG_hi_list[symbol].hi_ids ~= nil then
for _, value in ipairs(_NG_hi_list[symbol].hi_ids) do
log("delete", value)
vim.fn.matchdelete(value)
end
_NG_hi_list[symbol].hi_ids = nil
return
end
local cur_pos = vim.fn.getpos('.')
_NG_hi_list[symbol].hi_ids = {}
local totalref = #range
local cmd = string.format("%s/\\<%s\\>//gn", "%s", symbol_wd)
local total_match = 0
local match_result = vim.api.nvim_exec(cmd, true)
local p = match_result:find(" match")
vim.cmd("nohl")
vim.fn.setpos('.', cur_pos)
if p ~= nil then
p = match_result:sub(1, p)
total_match = tonumber(p)
end
if total_match == totalref then -- same number as matchpos
log(total_match, "use matchadd()")
local k = range[1].kind
local hi_name = string.format("NGHiReference_%i_%i", _NG_ref_hi_idx, k)
local m = string.format("\\<%s\\>", symbol_wd)
local r = vim.fn.matchadd(hi_name, m, 20)
trace("hi id", m, hi_name, r)
table.insert(_NG_hi_list[symbol].hi_ids, r)
--
-- vim.fn.matchdelete(r)
else
for _, value in ipairs(range) do
local k = value.kind
local l = value.range.start.line + 1
local el = value.range['end'].line + 1
local cs = value.range.start.character + 1
local ecs = value.range['end'].character + 1
if el ~= l and cs == 1 and ecs > 1 then
l = el
end
local w = value.range['end'].character - value.range.start.character
local hi_name = string.format("NGHiReference_%i_%i", _NG_ref_hi_idx, k)
log(hi_name, {l, cs, w})
local m = vim.fn.matchaddpos(hi_name, {{l, cs, w}}, 10)
table.insert(_NG_hi_list[symbol].hi_ids, m)
end
end
-- clean the _NG_hi_list
for key, value in pairs(_NG_hi_list) do
if value.hi_ids == nil then
_NG_hi_list[key] = nil
end
end
-- log(_NG_hi_list)
end
-- returns r1 < r2 based on start of range
local function before(r1, r2)
@ -71,10 +191,14 @@ local function goto_adjent_reference(opt)
vim.api.nvim_win_set_cursor(0, {next.start.line + 1, next.start.character})
return next
end
-- 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
local function cmd_nohl()
local cl = vim.trim(vim.fn.getcmdline())
if #cl > 3 and ('nohlsearch'):match(cl) then
vim.schedule(nohl)
end
end
local function documentHighlight()
api.nvim_exec([[
autocmd ColorScheme * |
@ -89,10 +213,15 @@ local function documentHighlight()
augroup END
]], false)
vim.lsp.handlers["textDocument/documentHighlight"] =
function(_, _, result, _, bufnr)
function(err, _, result, _, bufnr)
if err then
print(err)
return
end
if not result then
return
end
trace("dochl", result)
bufnr = api.nvim_get_current_buf()
vim.lsp.util.buf_clear_references(bufnr)
vim.lsp.util.buf_highlight_references(bufnr, result)
@ -105,11 +234,15 @@ local function documentHighlight()
return before(a.range, b.range)
end)
references[bufnr] = result
add_locs(bufnr, result)
end
end
return {
documentHighlight = documentHighlight,
goto_adjent_reference = goto_adjent_reference,
handle_document_highlight = handle_document_highlight
handle_document_highlight = handle_document_highlight,
hi_symbol = hi_symbol,
nohl = nohl,
cmd_nohl = cmd_nohl
}

@ -151,6 +151,28 @@ function M.new_list_view(opts)
offset_y = offset_y + 1 -- need to check this out
end
local function idx(data_list, pos)
-- first check if fzy is set
local fzy_on = false
for _, value in ipairs(data_list) do
if value.fzy ~= nil then
fzy_on = true
break
end
end
if fzy_on == true then
local i = 1
for _, value in ipairs(data_list) do
if value.fzy ~= nil then
if i == pos then
return value
end
i = i + 1
end
end
end
return data[pos]
end
return ListView:new({
loc = loc,
prompt = prompt,
@ -166,7 +188,8 @@ function M.new_list_view(opts)
if pos == 0 then
pos = 1
end
local l = data[pos]
local l = idx(data, pos) -- bug it not work with fzy filter
log(data)
if l.filename ~= nil then
trace("openfile ", l.filename, l.lnum, l.col)
util.open_file_at(l.filename, l.lnum, l.col)
@ -176,7 +199,9 @@ function M.new_list_view(opts)
if pos == 0 then
pos = 1
end
local l = data[pos]
local l = idx(data, pos) -- bug it not work with fzy filter
log(data)
trace("on move", pos, l)
trace("on move", pos, l.text or l, l.uri, l.filename)
-- todo fix

@ -1,7 +1,7 @@
-- todo allow config passed in
local log = require"navigator.util".log
local trace = require"navigator.util".trace
local uv = vim.loop
_Loading = false
_LoadedClients = {}
@ -68,6 +68,23 @@ library[vim.fn.expand("$VIMRUNTIME/lua/vim")] = true
library[vim.fn.expand("$VIMRUNTIME/lua/vim/lsp")] = true
-- [vim.fn.expand("~/repos/nvim/lua")] = true
-- TODO remove onece PR #944 merged to lspconfig
local is_windows = uv.os_uname().version:match("Windows")
local path_sep = is_windows and "\\" or "/"
local strip_dir_pat = path_sep .. "([^" .. path_sep .. "]+)$"
local strip_sep_pat = path_sep .. "$"
local dirname = function(path)
if not path or #path == 0 then
return
end
local result = path:gsub(strip_sep_pat, ""):gsub(strip_dir_pat, "")
if #result == 0 then
return "/"
end
return result
end
-- TODO end
local setups = {
gopls = {
on_attach = on_attach,
@ -101,7 +118,7 @@ local setups = {
}
},
root_dir = function(fname)
return util.root_pattern("go.mod", ".git")(fname) or util.path.dirname(fname)
return util.root_pattern("go.mod", ".git")(fname) or dirname(fname) -- util.path.dirname(fname)
end
},
clangd = {

@ -3,10 +3,18 @@ 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=''})
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 = ''})
end
function M.add_highlight()
@ -18,6 +26,19 @@ function M.add_highlight()
api.nvim_command("hi! link LspDiagnosticsUnderlineHint SpellRare")
api.nvim_command("hi def link DefinitionPreviewTitle 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'}
}
for i = 1, #colors do
for j = 1, 3 do
local cmd = string.format("hi! default NGHiReference_%i_%i guibg=%s guifg=%s ", i, j,
colors[i][j], colors[i][4])
vim.cmd(cmd)
end
end
end
return M

@ -27,7 +27,8 @@ local key_maps = {
{key = "]d", func = "diagnostic.goto_next()"}, {key = "[d", func = "diagnostic.goto_prev()"},
{key = "]r", func = "require('navigator.treesitter').goto_next_usage()"},
{key = "[r", func = "require('navigator.treesitter').goto_previous_usage()"},
{key = "<C-LeftMouse>", func = "definition()"}, {key = "g<LeftMouse>", func = "implementation()"}
{key = "<C-LeftMouse>", func = "definition()"}, {key = "g<LeftMouse>", func = "implementation()"},
{key = "<Leader>k", func = "require('navigator.dochighlight').hi_symbol()"}
}
local function set_mapping(user_opts)
@ -99,6 +100,15 @@ local function set_mapping(user_opts)
end
end
local function autocmd(user_opts)
vim.api.nvim_exec([[
aug NavigatorAu
au!
au CmdlineLeave : lua require('navigator.dochighlight').cmd_nohl()
aug END
]], false)
end
local function set_event_handler(user_opts)
user_opts = user_opts or {}
local file_types =
@ -129,6 +139,7 @@ function M.setup(user_opts)
set_mapping(user_opts)
end
autocmd(user_opts)
set_event_handler(user_opts)
local cap = user_opts.cap or vim.lsp.protocol.make_client_capabilities()

@ -122,8 +122,8 @@ function M.prepare_for_render(items, opts)
if item.definition then
ts_report = ts_report .. '🦕 '
end
local header_len = #ts_report + 2 -- magic number 2
trace(ts_report)
local header_len = #ts_report + 4 -- magic number 2
log(ts_report, header_len)
item.text = item.text:gsub('%s*[%[%(%{]*%s*$', '')
if item.call_by ~= nil and #item.call_by > 0 then

@ -75,7 +75,9 @@ function M.workspace_symbols(opts)
end
function M.document_symbol_handler(err, _, result, _, bufnr)
if err then print(bufnr, "failed to get document symbol") end
if err then
print(bufnr, "failed to get document symbol")
end
if not result or vim.tbl_isempty(result) then
print(bufnr, "symbol not found for buf")
@ -96,10 +98,12 @@ function M.document_symbol_handler(err, _, result, _, bufnr)
item.uri = uri
item.selectionRange = result[i].selectionRange
item.detail = result[i].detail or ""
if item.detail == "()" then item.detail = "func" end
if item.detail == "()" then
item.detail = "func"
end
item.lnum = result[i].range.start.line + 1
item.text = "[" .. kind .. "]" .. item.detail .. " " .. item.name
item.text = "[" .. kind .. "]" .. item.name .. " " .. item.detail
item.filename = fname
@ -116,7 +120,7 @@ function M.document_symbol_handler(err, _, result, _, bufnr)
child.uri = uri
child.lnum = c.range.start.line + 1
child.detail = c.detail or ""
child.text = "  [" .. ckind .. "] " .. child.detail .. " " .. child.name
child.text = "  [" .. ckind .. "] " .. child.name .. " " .. child.detail
table.insert(locations, child)
end
end
@ -149,7 +153,9 @@ function M.document_symbol_handler(err, _, result, _, bufnr)
end
function M.workspace_symbol_handler(err, _, result, _, bufnr)
if err then print(bufnr, "failed to get workspace symbol") end
if err then
print(bufnr, "failed to get workspace symbol")
end
if not result or vim.tbl_isempty(result) then
print(bufnr, "symbol not found for buf")
return

Loading…
Cancel
Save