diff --git a/README.md b/README.md
index 5132166..02f3cce 100644
--- a/README.md
+++ b/README.md
@@ -5,7 +5,9 @@
- A plugin combines the power of LSP and 🌲🏡 Treesitter together. Not only provids a better highlight but also help you analyse symbol context effectively.
-- Fuzzy search & build ctags symbols
+- ctags fuzzy search & build ctags symbols
+
+-
- [![a short intro of navigator](https://user-images.githubusercontent.com/1681295/147378905-51eede5f-e36d-48f4-9799-ae562949babe.jpeg)](https://youtu.be/P1kd7Y8AatE)
@@ -94,7 +96,9 @@ variable is:
- ccls call hierarchy (Non-standard `ccls/call` API) supports
-- Syntax folding based on treesitter folding algorithm. (It behaves similar to vs-code)
+- Syntax folding based on treesitter or LSP_fold folding algorithm. (It behaves similar to vs-code); comment folding
+
+- Treesitter symbols sidebar, LSP document symbole sidebar. Both with preview and folding
- Fully support LSP CodeAction, CodeLens, CodeLens action. Help you improve code quality.
@@ -673,6 +677,13 @@ Using treesitter and LSP to view the symbol definition
![image](https://user-images.githubusercontent.com/1681295/139771978-bbc970a5-be9f-42cf-8942-3477485bd89c.png)
+### Sidebar, folding, outline
+Treesitter outline and Diagnostics
+
+
+
+
+
### GUI and multigrid support
You can load a different font size for floating win
diff --git a/autoload/folding.vim b/autoload/folding.vim
index bf2793a..89e30f9 100644
--- a/autoload/folding.vim
+++ b/autoload/folding.vim
@@ -1,4 +1,4 @@
-function! folding#foldexpr()
+function! folding#ngfoldexpr()
" return luaeval(printf('require"navigator.foldinglsp".get_fold_indic(%d)', v:lnum))
return luaeval(printf('require"navigator.foldts".get_fold_indic(%d)', v:lnum))
endfunction
diff --git a/lua/navigator/ctags.lua b/lua/navigator/ctags.lua
index 3d797e7..fc7f427 100644
--- a/lua/navigator/ctags.lua
+++ b/lua/navigator/ctags.lua
@@ -54,6 +54,8 @@ end
local function ctags_gen()
local cmd = 'ctags' -- -x -n -u -f - ' .. vfn.expand('%:p')
local output = _NgConfigValues.ctags.tagfile
+ -- rm file first
+ util.rm_file(output)
local options = '-R --exclude=.git --exclude=node_modules --exclude=test --exclude=vendor --excmd=number '
if _NgConfigValues.ctags then
cmd = _NgConfigValues.ctags.cmd
@@ -64,6 +66,7 @@ local function ctags_gen()
options = options .. '--language=' .. lang
cmd = cmd .. ' ' .. options
cmd = string.format('%s -f %s %s --language=%s', cmd, output, options, lang)
+ cmd = vim.split(cmd, ' ')
log(cmd)
vfn.jobstart(cmd, {
on_stdout = function(_, _, _)
@@ -72,7 +75,7 @@ local function ctags_gen()
on_exit = function(_, data, _) -- id, data, event
-- log(vim.inspect(data) .. "exit")
- if data and data.code ~= 0 then
+ if data and data ~= 0 then
return vim.notify(cmd .. ' failed ' .. tostring(data), vim.lsp.log_levels.ERROR)
else
vim.notify('ctags generated')
@@ -108,10 +111,10 @@ local function ctags_symbols()
local ft = vim.o.ft
local result = symbols_to_items(items)
- log(result)
if next(result) == nil then
return vim.notify('no symbols found')
end
+ log(result[1])
local opt = {
api = ' ',
ft = ft,
diff --git a/lua/navigator/diagnostics.lua b/lua/navigator/diagnostics.lua
index 5e6aebc..2829026 100644
--- a/lua/navigator/diagnostics.lua
+++ b/lua/navigator/diagnostics.lua
@@ -350,8 +350,6 @@ end
M.show_buf_diagnostics = function()
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]})
local results = diagnostic_list[vim.bo.filetype]
local display_items = {}
for _, client_items in pairs(results) do
@@ -369,7 +367,7 @@ M.show_buf_diagnostics = function()
enable_preview_edit = true,
})
if listview == nil then
- return log("nil listview")
+ return log('nil listview')
end
trace('new buffer', listview.bufnr)
if listview.bufnr then
@@ -471,6 +469,43 @@ function M.show_diagnostics(pos)
end
end
+function M.treesitter_and_diag_panel()
+ local Panel = require('guihua.panel')
+
+ local ft = vim.bo.filetype
+ local results = diagnostic_list[ft]
+ log(diagnostic_list, ft)
+
+ local bufnr = vim.api.nvim_get_current_buf()
+ local p = Panel:new({
+ header = 'treesitter',
+ render = function(b)
+ log('render for ', bufnr, b)
+ return require('navigator.treesitter').all_ts_nodes(b)
+ end,
+ })
+ p:add_section({
+ header = 'diagnostic',
+ render = function(bufnr)
+ if diagnostic_list[ft] ~= nil then
+ local display_items = {}
+ for _, client_items in pairs(results) do
+ for _, items in pairs(client_items) do
+ for _, it in pairs(items) do
+ log(it)
+ table.insert(display_items, it)
+ end
+ end
+ end
+ return display_items
+ else
+ return {}
+ end
+ end,
+ })
+ p:open(true)
+end
+
function M.config(cfg)
cfg = cfg or {}
local default_cfg = {
diff --git a/lua/navigator/foldlsp.lua b/lua/navigator/foldlsp.lua
index 0bba4be..ce05ae7 100644
--- a/lua/navigator/foldlsp.lua
+++ b/lua/navigator/foldlsp.lua
@@ -56,7 +56,6 @@ function M.setup_plugin()
M.active_folding_clients[client_id] = server_supports_folding
end
end
- -- print(vim.inspect(M.active_folding_clients))
end
function M.update_folds()
diff --git a/lua/navigator/foldts.lua b/lua/navigator/foldts.lua
index 42c2732..1219d93 100644
--- a/lua/navigator/foldts.lua
+++ b/lua/navigator/foldts.lua
@@ -44,7 +44,7 @@ function M.setup_fold()
local current_window = api.nvim_get_current_win()
api.nvim_win_set_option(current_window, 'foldmethod', 'expr')
- api.nvim_win_set_option(current_window, 'foldexpr', 'folding#foldexpr()')
+ api.nvim_win_set_option(current_window, 'foldexpr', 'folding#ngfoldexpr()')
end
-- This is cached on buf tick to avoid computing that multiple times
diff --git a/lua/navigator/hierarchy.lua b/lua/navigator/hierarchy.lua
index 1e2e01e..98d2536 100644
--- a/lua/navigator/hierarchy.lua
+++ b/lua/navigator/hierarchy.lua
@@ -1,7 +1,7 @@
local gui = require('navigator.gui')
local util = require('navigator.util')
local log = util.log
-local trace = util.trace
+local trace = util.log
local partial = util.partial
local lsphelper = require('navigator.lspwrapper')
@@ -9,94 +9,162 @@ local path_sep = require('navigator.util').path_sep()
local path_cur = require('navigator.util').path_cur()
local cwd = vim.loop.cwd()
local M = {}
-local function call_hierarchy_handler(direction, err, result, ctx, _, error_message)
+local outgoing_calls_handler
+local incoming_calls_handler
+
+local function call_hierarchy_handler(direction, err, result, ctx, config)
+ log(direction, err, result, ctx, config)
if not result then
vim.notify('No call hierarchy items found', vim.lsp.log_levels.WARN)
return
end
- trace('call_hierarchy', result)
+ -- trace('call_hierarchy', result)
local bufnr = vim.api.nvim_get_current_buf()
assert(next(vim.lsp.buf_get_clients(bufnr)), 'Must have a client running to use lsp_tags')
if err ~= nil then
log('dir', direction, 'result', result, 'err', err, ctx)
- vim.notify('ERROR: ' .. error_message, vim.lsp.log_levels.WARN)
+ vim.notify('ERROR: ' .. err, vim.lsp.log_levels.WARN)
return
end
- local items = {}
+ local items = ctx.items or {}
- for _, call_hierarchy_call in pairs(result) do
- local call_hierarchy_item = call_hierarchy_call[direction]
+ for _, call_hierarchy_result in pairs(result) do
+ local call_hierarchy_item = call_hierarchy_result[direction]
local kind = ' '
if call_hierarchy_item.kind then
kind = require('navigator.lspclient.lspkind').symbol_kind(call_hierarchy_item.kind) .. ' '
end
- -- for _, range in pairs(call_hierarchy_call.fromRanges) do
- local range = call_hierarchy_item.range or call_hierarchy_item.selectionRange
local filename = assert(vim.uri_to_fname(call_hierarchy_item.uri))
local display_filename = filename:gsub(cwd .. path_sep, path_cur, 1)
call_hierarchy_item.detail = call_hierarchy_item.detail or ''
call_hierarchy_item.detail = string.gsub(call_hierarchy_item.detail, '\n', ' ↳ ')
- trace(range, call_hierarchy_item)
+ trace(result, call_hierarchy_item)
- local disp_item = {
- uri = call_hierarchy_item.uri,
+ local disp_item = vim.tbl_deep_extend('force', {}, call_hierarchy_item)
+ disp_item = vim.tbl_deep_extend('force', disp_item, {
filename = filename,
display_filename = display_filename,
+ indent = ctx.depth,
text = kind .. call_hierarchy_item.name .. ' ﰲ ' .. call_hierarchy_item.detail,
- range = range,
- lnum = range.start.line + 1,
- col = range.start.character,
- }
-
+ lnum = call_hierarchy_item.selectionRange.start.line + 1,
+ col = call_hierarchy_item.selectionRange.start.character,
+ })
table.insert(items, disp_item)
- -- end
+ if ctx.depth or 0 > 0 then
+ local params = {
+ position = {
+ character = disp_item.selectionRange.start.character,
+ line = disp_item.selectionRange.start.line,
+ },
+ textDocument = {
+ uri = disp_item.uri,
+ },
+ }
+ local api = 'callHierarchy/outgoingCalls'
+ local handler = outgoing_calls_handler
+ if direction == 'incoming' then
+ api = 'callHierarchy/incomingCalls'
+ handler = incoming_calls_handler
+ end
+ lsphelper.call_sync(
+ api,
+ params,
+ ctx,
+ vim.lsp.with(
+ partial(handler, 0),
+ { depth = ctx.depth - 1, direction = 'to', items = ctx.items, no_show = true }
+ )
+ )
+ end
end
+ log(items)
return items
end
local call_hierarchy_handler_from = partial(call_hierarchy_handler, 'from')
local call_hierarchy_handler_to = partial(call_hierarchy_handler, 'to')
--- local function incoming_calls_handler(bang, err, result, ctx, cfg)
-local function incoming_calls_handler(_, err, result, ctx, cfg)
+incoming_calls_handler = function(_, err, result, ctx, cfg)
local bufnr = vim.api.nvim_get_current_buf()
assert(next(vim.lsp.buf_get_clients(bufnr)), 'Must have a client running to use lsp hierarchy')
local results = call_hierarchy_handler_from(err, result, ctx, cfg, 'Incoming calls not found')
- local ft = vim.api.nvim_buf_get_option(ctx.bufnr, 'ft')
- gui.new_list_view({ items = results, ft = ft, api = ' ' })
+ local ft = vim.api.nvim_buf_get_option(ctx.bufnr or vim.api.nvim_get_current_buf(), 'ft')
+ if ctx.no_show then
+ return results
+ end
+ local win = gui.new_list_view({ items = results, ft = ft, api = ' ' })
+ return results, win
end
-local function outgoing_calls_handler(_, err, result, ctx, cfg)
+outgoing_calls_handler = function(_, err, result, ctx, cfg)
local results = call_hierarchy_handler_to(err, result, ctx, cfg, 'Outgoing calls not found')
local ft = vim.api.nvim_buf_get_option(ctx.bufnr, 'ft')
- gui.new_list_view({ items = results, ft = ft, api = ' ' })
- -- fzf_locations(bang, "", "Outgoing Calls", results, false)
+ if ctx.no_show then
+ return results
+ end
+ local win = gui.new_list_view({ items = results, ft = ft, api = ' ' })
+ return result, win
end
-function M.incoming_calls(bang, opts)
- local bufnr = vim.api.nvim_get_current_buf()
- assert(next(vim.lsp.buf_get_clients(bufnr)), 'Must have a client running to use lsp hierarchy')
- if not lsphelper.check_capabilities('callHierarchyProvider') then
+local function request(method, params, handler)
+ return vim.lsp.buf_request(0, method, params, handler)
+end
+
+local function pick_call_hierarchy_item(call_hierarchy_items)
+ if not call_hierarchy_items then
return
end
+ if #call_hierarchy_items == 1 then
+ return call_hierarchy_items[1]
+ end
+ local items = {}
+ for i, item in pairs(call_hierarchy_items) do
+ local entry = item.detail or item.name
+ table.insert(items, string.format('%d. %s', i, entry))
+ end
+ local choice = vim.fn.inputlist(items)
+ if choice < 1 or choice > #items then
+ return
+ end
+ return choice
+end
+local function call_hierarchy(method, opts)
local params = vim.lsp.util.make_position_params()
- lsphelper.call_sync('callHierarchy/incomingCalls', params, opts, partial(incoming_calls_handler, bang))
+ opts = opts or {}
+ request(
+ 'textDocument/prepareCallHierarchy',
+ params,
+ vim.lsp.with(function(err, result, ctx)
+ if err then
+ vim.notify(err.message, vim.log.levels.WARN)
+ return
+ end
+ local call_hierarchy_item = pick_call_hierarchy_item(result)
+ log('result', result, 'items', call_hierarchy_item)
+ local client = vim.lsp.get_client_by_id(ctx.client_id)
+ if client then
+ client.request(method, { item = call_hierarchy_item }, nil, ctx.bufnr)
+ else
+ vim.notify(
+ string.format('Client with id=%d disappeared during call hierarchy request', ctx.client_id),
+ vim.log.levels.WARN
+ )
+ end
+ end, { direction = method, depth = opts.depth })
+ )
end
-function M.outgoing_calls(bang, opts)
- local bufnr = vim.api.nvim_get_current_buf()
- assert(next(vim.lsp.buf_get_clients(bufnr)), 'Must have a client running to use lsp_tags')
- if not lsphelper.check_capabilities('callHierarchyProvider') then
- return
- end
+function M.incoming_calls(opts)
+ call_hierarchy('callHierarchy/incomingCalls', opts)
+end
- local params = vim.lsp.util.make_position_params()
- lsphelper.call_sync('callHierarchy/outgoingCalls', params, opts, partial(outgoing_calls_handler, bang))
+function M.outgoing_calls(opts)
+ call_hierarchy('callHierarchy/outgoingCalls', opts)
end
M.incoming_calls_call = partial(M.incoming_calls, 0)
diff --git a/lua/navigator/lspclient/clients.lua b/lua/navigator/lspclient/clients.lua
index 678c3d4..098a61c 100644
--- a/lua/navigator/lspclient/clients.lua
+++ b/lua/navigator/lspclient/clients.lua
@@ -24,7 +24,25 @@ end
local util = lspconfig.util
local config = require('navigator').config_values()
-
+local disabled_ft = {
+ 'NvimTree',
+ 'guihua',
+ 'clap_input',
+ 'clap_spinner',
+ 'vista',
+ 'vista_kind',
+ 'TelescopePrompt',
+ 'guihua_rust',
+ 'csv',
+ 'txt',
+ 'defx',
+ 'packer',
+ 'gitcommit',
+ 'windline',
+ 'notify',
+ 'nofile',
+ '',
+}
-- local cap = vim.lsp.protocol.make_client_capabilities()
local on_attach = require('navigator.lspclient.attach').on_attach
-- gopls["ui.completion.usePlaceholders"] = true
@@ -708,6 +726,14 @@ local function get_cfg(client)
end
end
+local function ft_disabled(ft)
+ for i = 1, #disabled_ft do
+ if ft == disabled_ft[i] then
+ return true
+ end
+ end
+end
+
local function setup(user_opts, cnt)
user_opts = user_opts or {}
local ft = vim.bo.filetype
@@ -744,28 +770,10 @@ local function setup(user_opts, cnt)
log('navigator was loaded for ft', ft, bufnr)
return
end
- local disable_ft = {
- 'NvimTree',
- 'guihua',
- 'clap_input',
- 'clap_spinner',
- 'vista',
- 'vista_kind',
- 'TelescopePrompt',
- 'guihua_rust',
- 'csv',
- 'txt',
- 'defx',
- 'packer',
- 'gitcommit',
- 'windline',
- 'notify',
- }
- for i = 1, #disable_ft do
- if ft == disable_ft[i] then
- trace('navigator disabled for ft or it is loaded', ft)
- return
- end
+
+ if ft_disabled(ft) then
+ trace('navigator disabled for ft or it is loaded', ft)
+ return
end
if _NgConfigValues.lsp.servers then
add_servers(_NgConfigValues.lsp.servers)
@@ -840,4 +848,12 @@ local function on_filetype()
setup({ bufnr = bufnr })
end
-return { setup = setup, get_cfg = get_cfg, lsp = servers, add_servers = add_servers, on_filetype = on_filetype }
+return {
+ setup = setup,
+ get_cfg = get_cfg,
+ lsp = servers,
+ add_servers = add_servers,
+ on_filetype = on_filetype,
+ disabled_ft = disabled_ft,
+ ft_disabled = ft_disabled,
+}
diff --git a/lua/navigator/lspclient/mapping.lua b/lua/navigator/lspclient/mapping.lua
index b04040f..5f8a386 100644
--- a/lua/navigator/lspclient/mapping.lua
+++ b/lua/navigator/lspclient/mapping.lua
@@ -63,11 +63,13 @@ local key_maps = {
}
local commands = {
- [[command! -nargs=* Nctags lua require("navigator.ctags").ctags({})]],
+ [[command! -nargs=* Nctags lua require("navigator.ctags").ctags()]],
"command! -nargs=0 LspLog lua require'navigator.lspclient.config'.open_lsp_log()",
"command! -nargs=0 LspRestart lua require'navigator.lspclient.config'.reload_lsp()",
"command! -nargs=0 LspToggleFmt lua require'navigator.lspclient.mapping'.toggle_lspformat()",
"command! -nargs=0 LspKeymaps lua require'navigator.lspclient.mapping'.get_keymaps_help()",
+ "command! -nargs=0 LspSymbols lua require'navigator.symbols'.side_panel()",
+ "command! -nargs=0 TSymbols lua require'navigator.treesitter'.side_panel()",
}
local key_maps_help = {}
@@ -179,7 +181,7 @@ local function set_mapping(lsp_info)
elseif string.find(value.func, 'format') then
fmtkey = value.key
end
- log('binding', k, f)
+ trace('binding', k, f)
set_keymap(m, k, f, opts)
end
@@ -279,12 +281,12 @@ function M.setup(user_opts)
local client = user_opts.client or {}
local cap = client.server_capabilities or vim.lsp.protocol.make_client_capabilities()
- log('lsp cap:', cap)
+ log('lsp cap:', cap.codeActionProvider)
- if cap.call_hierarchy or cap.callHierarchyProvider then
- vim.lsp.handlers['callHierarchy/incomingCalls'] = require('navigator.hierarchy').incoming_calls_handler
- vim.lsp.handlers['callHierarchy/outgoingCalls'] = require('navigator.hierarchy').outgoing_calls_handler
- end
+ -- if cap.call_hierarchy or cap.callHierarchyProvider then
+ -- vim.lsp.handlers['callHierarchy/incomingCalls'] = require('navigator.hierarchy').incoming_calls_handler
+ -- vim.lsp.handlers['callHierarchy/outgoingCalls'] = require('navigator.hierarchy').outgoing_calls_handler
+ -- end
vim.lsp.handlers['textDocument/references'] = require('navigator.reference').reference_handler
-- vim.lsp.handlers["textDocument/codeAction"] = require"navigator.codeAction".code_action_handler
diff --git a/lua/navigator/lspwrapper.lua b/lua/navigator/lspwrapper.lua
index 3404197..7825b1d 100644
--- a/lua/navigator/lspwrapper.lua
+++ b/lua/navigator/lspwrapper.lua
@@ -145,18 +145,20 @@ end
function M.call_sync(method, params, opts, handler)
params = params or {}
opts = opts or {}
- local results_lsp, err = lsp.buf_request_sync(0, method, params, opts.timeout or vim.g.navtator_timeout or 1000)
+ log(method, params)
+ local results_lsp, err = lsp.buf_request_sync(opts.bufnr or 0, method, params, opts.timeout or 1000)
- handler(err, extract_result(results_lsp), { method = method }, nil)
+ return handler(err, extract_result(results_lsp), { method = method, no_show = opts.no_show }, nil)
end
-function M.call_async(method, params, handler)
+function M.call_async(method, params, handler, bufnr)
params = params or {}
local callback = function(...)
util.show(...)
handler(...)
end
- return lsp.buf_request(0, method, params, callback)
+ bufnr = bufnr or 0
+ return lsp.buf_request(bufnr, method, params, callback)
-- results_lsp, canceller
end
diff --git a/lua/navigator/sidepanel.lua b/lua/navigator/sidepanel.lua
new file mode 100644
index 0000000..e69de29
diff --git a/lua/navigator/symbols.lua b/lua/navigator/symbols.lua
index 0ea683e..64798a0 100644
--- a/lua/navigator/symbols.lua
+++ b/lua/navigator/symbols.lua
@@ -11,7 +11,6 @@ function M.workspace_symbols(query)
local bufnr = vim.api.nvim_get_current_buf()
local params = { query = query }
vim.lsp.for_each_buffer_client(bufnr, function(client, _, _bufnr)
- -- if client.resolved_capabilities.workspace_symbol then
if client.server_capabilities.workspaceSymbolProvider then
client.request('workspace/symbol', params, M.workspace_symbol_handler, _bufnr)
end
@@ -33,7 +32,6 @@ function M.document_symbols(opts)
params.context = { includeDeclaration = true }
params.query = opts.prompt or ''
vim.lsp.for_each_buffer_client(bufnr, function(client, _, _bufnr)
- -- if client.resolved_capabilities.document_symbol then
if client.server_capabilities.documentSymbolProvider then
client.request('textDocument/documentSymbol', params, M.document_symbol_handler, _bufnr)
end
@@ -51,7 +49,7 @@ M.document_symbol_handler = function(err, result, ctx)
end
if not result or vim.tbl_isempty(result) then
- vim.notify('symbol' .. query .. 'not found for buf' .. vim.inspect(ctx), vim.lsp.log_levels.WARN)
+ vim.notify('symbol ' .. query .. ' not found for buf ' .. vim.inspect(ctx), vim.lsp.log_levels.WARN)
return
end
local locations = {}
@@ -66,7 +64,7 @@ M.document_symbol_handler = function(err, result, ctx)
item.name = result[i].name
item.range = result[i].range or result[i].location.range
if item.range == nil then
- log("range missing in result", result[i])
+ log('range missing in result', result[i])
end
item.uri = uri
item.selectionRange = result[i].selectionRange
@@ -79,6 +77,10 @@ M.document_symbol_handler = function(err, result, ctx)
item.text = '[' .. kind .. ']' .. item.name .. ' ' .. item.detail
item.filename = fname
+ item.indent_level = 1
+
+ item.type = kind
+ item.node_text = item.name
table.insert(locations, item)
if result[i].children ~= nil then
@@ -88,16 +90,23 @@ M.document_symbol_handler = function(err, result, ctx)
child.name = c.name
child.range = c.range or c.location.range
local ckind = symbol_kind(child.kind)
+
+ child.node_text = child.name
+ child.type = ckind
child.selectionRange = c.selectionRange
child.filename = fname
child.uri = uri
child.lnum = child.range.start.line + 1
child.detail = c.detail or ''
+ child.indent_level = 2
child.text = ' ' .. ckind .. '' .. child.name .. ' ' .. child.detail
table.insert(locations, child)
end
end
end
+ if ctx.no_show then
+ return locations
+ end
local ft = vim.api.nvim_buf_get_option(bufnr, 'ft')
gui.new_list_view({
@@ -133,4 +142,26 @@ M.workspace_symbol_handler = function(err, result, ctx, cfg)
gui.new_list_view({ items = items, prompt = true, ft = ft, rowdata = true, api = ' ' })
end
+function M.side_panel()
+ local Panel = require('guihua.panel')
+ local buf = vim.api.nvim_get_current_buf()
+ local p = Panel:new({
+ render = function(bufnr)
+ local ft = vim.api.nvim_buf_get_option(bufnr, 'buftype')
+ if ft == 'nofile' or ft == 'guihua' or ft == 'prompt' then
+ return
+ end
+ local params = vim.lsp.util.make_range_params()
+ local sync_req = require('navigator.lspwrapper').call_sync
+ return sync_req(
+ 'textDocument/documentSymbol',
+ params,
+ { timeout = 1000, bufnr = bufnr, no_show = true },
+ vim.lsp.with(M.document_symbol_handler, { no_show = true })
+ )
+ end,
+ })
+ p:open(true)
+end
+
return M
diff --git a/lua/navigator/treesitter.lua b/lua/navigator/treesitter.lua
index 5179570..25e2202 100644
--- a/lua/navigator/treesitter.lua
+++ b/lua/navigator/treesitter.lua
@@ -110,7 +110,6 @@ end
--- This function copy from treesitter/refactor/navigation.lua
local function get_definitions(bufnr)
local local_nodes = ts_locals.get_locals(bufnr)
-
-- Make sure the nodes are unique.
local nodes_set = {}
for _, loc in ipairs(local_nodes) do
@@ -291,8 +290,12 @@ local function get_all_nodes(bufnr, filter, summary)
vim.notify('get_all_node invalide bufnr', vim.lsp.log_levels.WARN)
end
summary = summary or false
+ local ft = vim.api.nvim_buf_get_option(bufnr, 'filetype')
if not parsers.has_parser() then
- vim.notify('ts not loaded', vim.lsp.log_levels.Debug)
+ if not require('navigator.lspclient.clients').ft_disabled(ft) then
+ vim.notify('ts not loaded ' .. ft, vim.lsp.log_levels.Debug)
+ end
+ return {}
end
local path_sep = require('navigator.util').path_sep()
@@ -311,7 +314,7 @@ local function get_all_nodes(bufnr, filter, summary)
['arrow_function'] = true,
['type'] = true,
['class'] = true,
- ['var'] = true,
+ -- ['var'] = true,
['struct'] = true,
['method'] = true,
}
@@ -327,17 +330,31 @@ local function get_all_nodes(bufnr, filter, summary)
-- Step 2 find correct completions
local length = 10
local parents = {} -- stack of nodes a clever algorithm from treesiter refactor @Santos Gallegos
+ local loaded_symbol = {}
for _, def in ipairs(get_definitions(bufnr)) do
local n = #parents
for i = 1, n do
local index = n + 1 - i
local parent_def = parents[index]
+ log(parent_def.type, parent_def.node:type(), vim.treesitter.get_node_text(parent_def.node, bufnr))
+ log(def.node:type(), vim.treesitter.get_node_text(def.node, bufnr))
if
ts_utils.is_parent(parent_def.node, def.node)
- or (containers[parent_def.type] and ts_utils.is_parent(parent_def.node:parent(), def.node))
+ or (
+ containers[parent_def.type]
+ and (
+ ts_utils.is_parent(parent_def.node:parent(), def.node)
+ or (
+ parent_def.node:parent():type():find('dot_index')
+ and ts_utils.is_parent(parent_def.node:parent():parent(), def.node)
+ )
+ )
+ )
then
+ log('is parent', i, index)
break
else
+ log('leave node', i, index)
parents[index] = nil
end
end
@@ -353,6 +370,10 @@ local function get_all_nodes(bufnr, filter, summary)
trace(item.type, item.kind)
goto continue
end
+
+ if item.type == 'associated' then
+ goto continue
+ end
local tsdata = node.def
if node.def == nil then
@@ -369,20 +390,40 @@ local function get_all_nodes(bufnr, filter, summary)
if is_func then
-- hack for lua and maybe other language aswell
local parent = tsdata:parent()
- if parent ~= nil and parent:type() == 'function_name' or parent:type() == 'function_name_field' then
+ if parent ~= nil then
+ log(parent:type(), vim.treesitter.get_node_text(parent, bufnr), item.node_text, item.type)
+ end
+ if
+ parent ~= nil
+ and (
+ parent:type() == 'function_name'
+ -- or parent:type() == 'function'
+ -- or parent:type() == 'function_declaration' -- this bring in too much info
+ or parent:type() == 'method_name'
+ or parent:type() == 'function_name_field'
+ )
+ then
+ -- replace function name
item.node_text = vim.treesitter.get_node_text(parent, bufnr)
+ local cut = item.node_text:find('[\n\r]')
+ if cut then
+ item.node_text = item.node_text:sub(1, cut - 1)
+ end
log(parent:type(), item.node_text)
end
end
trace(item.node_text, item.kind, item.type)
if scope ~= nil then
- -- it is strange..
if not is_func and summary then
+ log(item.node_text, item.type)
goto continue
end
item.node_scope = ts_utils.node_to_lsp_range(scope)
end
+ if item.node_text == '_' then
+ goto continue
+ end
if summary then
if item.node_scope ~= nil then
table.insert(all_nodes, item)
@@ -394,7 +435,6 @@ local function get_all_nodes(bufnr, filter, summary)
tsdata:type(),
item.node_text,
item.kind,
- item.node_text,
'range',
item.node_scope.start.line,
item.node_scope['end'].line
@@ -405,10 +445,9 @@ local function get_all_nodes(bufnr, filter, summary)
item.range = ts_utils.node_to_lsp_range(tsdata)
local start_line_node, _, _ = tsdata:start()
- if item.node_text == '_' then
- goto continue
- end
- item.full_text = vim.trim(api.nvim_buf_get_lines(bufnr, start_line_node, start_line_node + 1, false)[1] or '')
+
+ local line_text = api.nvim_buf_get_lines(bufnr, start_line_node, start_line_node + 1, false)[1] or ''
+ item.full_text = vim.trim(line_text)
item.full_text = item.full_text:gsub('%s*[%[%(%{]*%s*$', '')
item.uri = uri
@@ -423,7 +462,23 @@ local function get_all_nodes(bufnr, filter, summary)
indent = string.rep(' ', #parents - 1) .. ' '
end
item.indent = indent
- item.indent_level = #parents
+ item.indent_level = #parents -- maybe use real indent level ?
+ if item.indent_level <= 1 then
+ local sp = string.match(line_text, '(%s*)')
+ log(line_text, #sp)
+ if sp then
+ local indent_level = #sp / (vim.o.shiftwidth or 4) + 1
+ item.indent_level = math.max(item.indent_level, indent_level)
+ end
+ end
+ if #parents > 0 then
+ log(parents[1].type, vim.treesitter.get_node_text(parents[1].node, bufnr))
+ if parents[2] then
+ log(parents[2].type, vim.treesitter.get_node_text(parents[2].node, bufnr))
+ end
+ else
+ log('root node')
+ end
if #all_nodes >= 1 then
all_nodes[#all_nodes].next_indent_level = #parents
end
@@ -432,7 +487,13 @@ local function get_all_nodes(bufnr, filter, summary)
if #item.text > length then
length = #item.text
end
- table.insert(all_nodes, item)
+ if
+ loaded_symbol[item.node_text .. item.kind] == nil
+ or not util.range_inside(loaded_symbol[item.node_text .. item.kind], item.node_scope)
+ then
+ table.insert(all_nodes, item)
+ loaded_symbol[item.node_text .. item.kind] = item.node_scope
+ end
::continue::
end
end
@@ -446,8 +507,12 @@ local function get_all_nodes(bufnr, filter, summary)
end
function M.buf_func(bufnr)
+ local ft = vim.api.nvim_buf_get_option(bufnr, 'buftype')
+ if vim.api.nvim_buf_get_option(bufnr, 'buftype') == 'nofile' then
+ return
+ end
if not ok or ts_locals == nil then
- error('treesitter not loaded')
+ error('treesitter not loaded: ' .. ft)
return
end
@@ -492,15 +557,33 @@ function M.buf_func(bufnr)
return all_nodes, width
end
-function M.buf_ts()
+function M.all_ts_nodes(bufnr)
if ts_locals == nil then
error('treesitter not loaded')
return
end
- local bufnr = api.nvim_get_current_buf()
+ local bufnr = bufnr or api.nvim_get_current_buf()
local all_nodes, width = get_all_nodes(bufnr)
+ return all_nodes, width
+end
+function M.side_panel()
+ Panel = require('guihua.panel')
+ local bufnr = api.nvim_get_current_buf()
+ local p = Panel:new({
+ header = 'treesitter',
+ render = function(b)
+ log('render for ', bufnr, b)
+ return require('navigator.treesitter').all_ts_nodes(b)
+ end,
+ })
+ p:open(true)
+end
+
+function M.buf_ts()
+ local all_nodes, width = M.all_ts_nodes()
+ local bufnr = api.nvim_get_current_buf()
local ft = vim.api.nvim_buf_get_option(bufnr, 'ft')
local listview = gui.new_list_view({
items = all_nodes,
@@ -512,7 +595,7 @@ function M.buf_ts()
width = width + 10,
api = _NgConfigValues.icons.treesitter_defult,
})
- return listview, all_nodes, width
+ return listview, all_nodes, width
end
M.get_all_nodes = get_all_nodes
diff --git a/lua/navigator/util.lua b/lua/navigator/util.lua
index e456621..640f224 100644
--- a/lua/navigator/util.lua
+++ b/lua/navigator/util.lua
@@ -71,6 +71,9 @@ function M.io_read(filename, total)
return content
end
+function M.rm_file(filename)
+ return os.remove(filename)
+end
function M.file_exists(name)
local f = io.open(name, "r")
@@ -417,9 +420,9 @@ function M.mk_handler(fn)
end
function M.partial(func, arg)
- return (M.mk_handler(function(...)
+ return function(...)
return func(arg, ...)
- end))
+ end
end
function M.empty(t)
@@ -443,7 +446,7 @@ function M.encoding(client)
end
local oe = client.offset_encoding
if oe == nil then
- return 'utf-16'
+ return 'utf-8'
end
if type(oe) == 'table' then
return oe[1]
@@ -465,4 +468,14 @@ function M.info(msg)
vim.notify('INF: ' .. msg, vim.lsp.log_levels.INFO)
end
+function M.range_inside(outer, inner)
+ if outer == nil or inner == nil then
+ return false
+ end
+ if outer.start == nil or outer['end'] == nil or inner.start == nil or inner['end'] == nil then
+ return false
+ end
+ return outer.start.line <= inner.start.line and outer['end'].line >= inner['end'].line
+end
+
return M