diff --git a/README.md b/README.md
index 699c87a..97a1c67 100644
--- a/README.md
+++ b/README.md
@@ -2,45 +2,57 @@
- Easy code navigation through LSP and π²π‘Treesitter symbols; view diagnostic errors.
-- Combine LSP and treesitter parser together. Not only providing better highlight but also help you analysis symbol context
-and scope.
+- A plugin combine LSP and treesitter parser together. Not only providing a better highlight but also help you analyse symbol context effectively.
-Here is an example
+Here are examples
-Following screen shot shows javascript call tree π² of variable `browser` insides a closure. This feature is similar to incoming&outgoing calls from LSP. It is designed for the symbol analysis.
+#### Example: Javascripts closure
+
+The following screenshot shows javascript call tree π² of variable `browser` insides a closure. This feature is similar to incoming&outgoing calls from LSP. It is designed for the symbol analysis.
![js_closure_call_tree](https://user-images.githubusercontent.com/1681295/119120589-cee23700-ba6f-11eb-95c5-b9ac8d445c31.jpg)
-Explains:
-- First line of floating windows shows there are 3 references for the symbol *browser* in closure.js
-- The first reference of browser is an assigement, an emoji of π indicates the value changed in this line. In many
-cases, we search for reference to find out where the value changed.
+Explanation:
+- The first line of floating windows shows there are 3 references for the symbol *browser* in closure.js
+- The first reference of browser is an assignment, an emoji π indicates the value changed in this line. In many
+cases, we search for references to find out where the value changed.
- The second reference of `browser` is inside function `displayName` and `displayName` sit inside `makeFunc`, So you
will see ` displayName{} <- makeFunc{}`
- The third similar to the second, as var browser is on the right side of '=', the value not changed in this line
and emoji is not shown.
+#### Example: C++ defination
+
+Another example for C++
+![cpp_ref](https://user-images.githubusercontent.com/1681295/119215215-8bd7a080-bb0f-11eb-82fc-8cdf1955e6e7.jpg)
+You may find that a π¦ dinosaur(d) on the line of `Rectangle rect;` which means there is a defination (d for def) of rect in this line
+
+#### Golang struct type
Struct type references in multiple Go ο³ files
![go_reference](https://user-images.githubusercontent.com/1681295/119123823-54b3b180-ba73-11eb-8790-097601e10f6a.gif)
This feature can provide you info in which function/class/method the variable was referenced. It is handy for large
-project where class/function defination is too long to fit into preview window. Also provides a birdview of where the
-variable is referenced.
+project where class/function definition is too long to fit into the preview window. Also provides a birdview of where the
+variable is
+- Referenced
+- Modified
+- Defined
+- called
# Features:
- LSP easy setup. Support the most commonly used lsp clients setup. Dynamic lsp activation based on buffer type. This
-also enable you handle workspace combine mix types of codes (e.g. Go + javascript + yml)
+also enables you to handle workspace combine mixed types of codes (e.g. Go + javascript + yml)
- Out of box experience. 10 lines of minimum vimrc can turn your neovim into a full-featured LSP & Treesitter powered IDE
-- Unorthodox UI with floating windows, navigator provides a visual way to manage and navigate through symbols, diagnostic errors, reference etc. Is covers
-all features(handler) provided by LSP from commenly used search reference, to less commenly used search for interface
+- Unorthodox UI with floating windows, navigator provides a visual way to manage and navigate through symbols, diagnostic errors, reference etc. It covers
+all features(handler) provided by LSP from commonly used search reference, to less commonly used search for interface
implementation.
- Async request with lsp.buf_request for reference search
-- Treesitter symbol search. It is handy for large filas (Some of LSP e.g. sumneko_lua, there is a 100kb file size limition?)
+- Treesitter symbol search. It is handy for large files (Some of LSP e.g. sumneko_lua, there is a 100kb file size limition?)
- FZY search with Lua-JIT
@@ -144,7 +156,7 @@ require.'navigator'.setup({
-- -- the on_attach will be called at end of navigator on_attach
-- end,
- treesitter_call_tree = true, -- treesitter variable context
+ treesitter_analysis = true, -- treesitter variable context
sumneko_root_path = vim.fn.expand("$HOME") .. "/github/sumneko/lua-language-server",
sumneko_binary = vim.fn.expand("$HOME") ..
"/github/sumneko/lua-language-server/bin/macOS/lua-language-server",
@@ -164,6 +176,18 @@ require.'navigator'.setup({
})
+```
+
+The plugin can work with multiple LSP, e.g sqls+gopls+efm. But there are cases you may need to disable some of the
+servers. (Prevent loading multiple LSP for same source code.) e.g. I saw strange behaviours when I use pyls+pyright+pyls_ms
+together. If you have multiple similar LSP installed and have trouble with the plugin, please enable only one at a time.
+To disable a LSP server, set `filetypes` to {} e.g.
+```lua
+
+require.'navigator'.setup({
+ pyls={filetype={}}
+})
+
```
@@ -177,7 +201,7 @@ require.'navigator'.setup({
The plugin can be loaded lazily (packer `opt = true` ), And it will check if optional plugins existance and load those plugins only if they existed.
-The termianl will need to be able to output nerdfont and emoji correctly. I am using Kitty with nerdfont (Victor Mono).
+The terminal will need to be able to output nerdfont and emoji correctly. I am using Kitty with nerdfont (Victor Mono).
## Usage
@@ -185,11 +209,11 @@ Please refer to lua/navigator/lspclient/mapping.lua on key mappings. Should be a
- Use \ or `:q!` to kill the floating window
- (or \, \) to move
-- \ or \ to open location or apply code actions. Note: \ might be binded in insert mode by other plugins
+- \ or \ to open location or apply code actions. Note: \ might be bound in insert mode by other plugins
## Configuration
-In `navigator.lua` there is a default configration. You can override the values by pass you own values
+In `navigator.lua` there is a default configuration. You can override the values by passing your own values
e.g
@@ -204,7 +228,7 @@ colorscheme: [aurora](https://github.com/ray-x/aurora)
### Reference
-Pls check first part of README
+Pls check the first part of README
### Document Symbol
@@ -280,7 +304,7 @@ Improved signature help with current parameter highlighted
# Todo
-- Early phase, bugs expected, PR and suggestions are welcome
+- The project is in the early phase, bugs expected, PRs and suggestions are welcome
- Async (some of the requests is slow on large codebases and might be good to use co-rountine)
- More clients. I use go, python, js/ts, java, c/cpp, lua most of the time. Did not test other languages (e.g dart, swift etc)
- Configuration options
diff --git a/lua/navigator.lua b/lua/navigator.lua
index c0adf2e..85c86ea 100644
--- a/lua/navigator.lua
+++ b/lua/navigator.lua
@@ -13,7 +13,7 @@ _NgConfigValues = {
sumneko_binary = vim.fn.expand("$HOME") ..
"/github/sumneko/lua-language-server/bin/macOS/lua-language-server",
code_action_prompt = {enable = true, sign = true, sign_priority = 40, virtual_text = true},
- treesitter_call_tree = true, -- treesitter variable context
+ treesitter_analysis = true, -- treesitter variable context
lsp = {
format_on_save = true, -- set to false to disasble lsp code format on save (if you are using prettier/efm/formater etc)
tsserver = {
diff --git a/lua/navigator/lspwrapper.lua b/lua/navigator/lspwrapper.lua
index 63daf89..feb8b41 100644
--- a/lua/navigator/lspwrapper.lua
+++ b/lua/navigator/lspwrapper.lua
@@ -13,7 +13,7 @@ ts_nodes = {}
ts_nodes_time = {}
local ts_enabled, _ = pcall(require, "nvim-treesitter.locals")
-local calltree_enabled = require"navigator".config_values().treesitter_call_tree
+local TS_analysis_enabled = require"navigator".config_values().treesitter_analysis
-- extract symbol from range
local function get_symbol(text, range)
@@ -24,8 +24,15 @@ local function get_symbol(text, range)
end
local function check_lhs(text, symbol)
- local s = string.find(text, symbol)
+ local find = require'guihua.util'.word_find
+ local s = find(text, symbol)
local eq = string.find(text, '=') or 0
+ if not s or not eq then
+ return false
+ end
+ if s < eq then
+ log(symbol, "modified")
+ end
return s < eq
end
@@ -136,7 +143,7 @@ function M.call_async(method, params, handler)
end
local function ts_functions(uri)
- if not ts_enabled or not calltree_enabled then
+ if not ts_enabled or not TS_analysis_enabled then
lerr("ts not enabled")
return nil
end
@@ -173,6 +180,32 @@ local function ts_functions(uri)
return funcs
end
+local function ts_defination(uri, range)
+ if not ts_enabled or not TS_analysis_enabled then
+ lerr("ts not enabled")
+ return nil
+ end
+ local ts_def = require"navigator.treesitter".find_definition
+ local bufnr = vim.uri_to_bufnr(uri)
+ local x = os.clock()
+ trace(ts_nodes)
+ local unload = false
+ if not api.nvim_buf_is_loaded(bufnr) then
+ log("! load buf !", uri, bufnr)
+ vim.fn.bufload(bufnr)
+ unload = true
+ end
+
+ local def_range = ts_def(range, bufnr)
+ if unload then
+ local cmd = string.format("bd %d", bufnr)
+ log(cmd)
+ -- vim.cmd(cmd) -- todo: not sure if it is needed
+ end
+ log(string.format(" ts def elapsed time: %.4f\n", os.clock() - x), def_range)
+ return def_range
+end
+
local function find_ts_func_by_range(funcs, range)
if funcs == nil or range == nil then
return nil
@@ -209,11 +242,30 @@ function M.locations_to_items(locations)
return i.uri < j.uri
end
end)
+ local uri_def = {}
for i, loc in ipairs(locations) do
local item = lsp.util.locations_to_items({loc})[1]
item.uri = locations[i].uri
local funcs = ts_functions(item.uri)
+
item.range = locations[i].range
+
+ if TS_analysis_enabled then
+ if uri_def[item.uri] == nil then
+ -- find def in file
+ local def = ts_defination(item.uri, item.range)
+ uri_def[item.uri] = def or {}
+ end
+ log(uri_def[item.uri], item.range)
+ local def = uri_def[item.uri]
+ if def.start and item.range then
+ if def.start.line == item.range.start.line then
+ log("ts def found")
+ item.definition = true
+ end
+ end
+ end
+
item.filename = assert(vim.uri_to_fname(item.uri))
local filename = item.filename:gsub(cwd .. "/", "./", 1)
item.display_filename = filename or item.filename
@@ -224,6 +276,7 @@ function M.locations_to_items(locations)
item.symbol_name = get_symbol(item.text, item.range)
item.lhs = check_lhs(item.text, item.symbol_name)
end
+ trace(uri_def)
return items, width + 24 -- TODO handle long line?
end
diff --git a/lua/navigator/render.lua b/lua/navigator/render.lua
index 0336497..9dca803 100644
--- a/lua/navigator/render.lua
+++ b/lua/navigator/render.lua
@@ -95,11 +95,16 @@ function M.prepare_for_render(items, opts)
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 call_by = ""
+ local ts_report = ""
if item.lhs then
- call_by = 'π '
+ ts_report = 'π '
end
+ if item.definition then
+ ts_report = ts_report .. 'π¦ '
+ end
+ trace(ts_report)
+
item.text = item.text:gsub('%s*[%[%(%{]*%s*$', '')
if item.call_by ~= nil and #item.call_by > 0 then
trace("call_by:", #item.call_by)
@@ -109,29 +114,29 @@ function M.prepare_for_render(items, opts)
local endwise = '{}'
if value.type == 'method' or value.type == 'function' then
endwise = '()'
- call_by = 'ο£Ά '
+ ts_report = ts_report .. 'ο£Ά '
end
- if #call_by > 8 then
- call_by = call_by .. ' ο '
+ if #ts_report > 8 then
+ ts_report = ts_report .. ' ο '
end
- call_by = call_by .. value.kind .. txt .. endwise
+ ts_report = ts_report .. value.kind .. txt .. endwise
trace(item)
end
end
end
- if #call_by > 1 then
- space = get_pads(win_width, item.text, call_by)
- if #space + #item.text + #call_by >= win_width then
- if #item.text + #call_by > win_width then
- log("exceeding", #item.text, #call_by, win_width)
+ if #ts_report > 1 then
+ space = get_pads(win_width, item.text, ts_report)
+ if #space + #item.text + #ts_report >= win_width then
+ if #item.text + #ts_report > win_width then
+ log("exceeding", #item.text, #ts_report, win_width)
space = ' '
else
- local remain = win_width - #item.text - #call_by
+ local remain = win_width - #item.text - #ts_report
log("remain", remain)
space = string.rep(' ', remain)
end
end
- item.text = item.text .. space .. call_by
+ item.text = item.text .. space .. ts_report
end
local tail = display_items[#display_items].text
if tail ~= item.text then -- deduplicate
diff --git a/lua/navigator/treesitter.lua b/lua/navigator/treesitter.lua
index 6a6ba2e..ab04cb4 100644
--- a/lua/navigator/treesitter.lua
+++ b/lua/navigator/treesitter.lua
@@ -57,24 +57,31 @@ end
-- use lsp range to find def
function M.find_definition(range, bufnr)
- if not range then
-
+ if not range or not range.start then
+ lerr("find_def incorrect range", range)
return
end
bufnr = bufnr or api.nvim_get_current_buf()
- local cursor = {range.start.line, range.start.character} -- +1 or not?
-
- local node_at_point = ts_utils.get_node_at_cursor()
-
+ local parser = parsers.get_parser(bufnr)
+ local symbolpos = {range.start.line, range.start.character} -- +1 or not?
+ local root = ts_utils.get_root_for_position(range.start.line, range.start.character, parser)
+ if not root then
+ return {}
+ end
+ local node_at_point = root:named_descendant_for_range(symbolpos[1], symbolpos[2], symbolpos[1],
+ symbolpos[2])
if not node_at_point then
lerr("no node at cursor")
- return
+ return {}
end
local definition = locals.find_definition(node_at_point, bufnr)
-
- log(definition)
- return
+ log("def found:", definition, definition:range())
+ if definition then
+ local r, c = definition:range()
+ return {start = {line = r, character = c}}
+ end
+ return {}
end
--- Get definitions of bufnr (unique and sorted by order of appearance).
@@ -137,6 +144,18 @@ local function get_scope(type, source)
if parent:type() == 'function_name_field' then
return parent:parent():parent(), true
end
+
+ -- for C++
+ local n = source
+ for i = 1, 4, 1 do
+ if n == nil or n:parent() == nil then
+ break
+ end
+ n = n:parent()
+ if n:type() == 'function_definition' then
+ return n, true
+ end
+ end
return parent, true
end
@@ -151,8 +170,9 @@ local function get_scope(type, source)
trace(source, source:type())
return source, false
end
- else -- M.fun1 = function() end
- -- lets work up and see next node
+ else
+ -- M.fun1 = function() end
+ -- lets work up and see next node, lua
local n = source
for i = 1, 4, 1 do
if n == nil or n:parent() == nil then