Feature/198 calltree (#199)

* refactor hierarchy.lua

* show side panel for hierarchy

* allow call hierarchy to fold and expand to show call tree

* update command maps
neovim_0.6^2
rayx 2 years ago committed by GitHub
parent aba0d89745
commit 9f7bd6ebff
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -100,6 +100,8 @@ variable is:
- Treesitter symbols sidebar, LSP document symbole sidebar. Both with preview and folding - Treesitter symbols sidebar, LSP document symbole sidebar. Both with preview and folding
- Calltree: Display and expand Lsp incoming/outgoing calls hierarchy-tree with sidebar
- Fully support LSP CodeAction, CodeLens, CodeLens action. Help you improve code quality. - Fully support LSP CodeAction, CodeLens, CodeLens action. Help you improve code quality.
- LRU cache for treesitter nodes - LRU cache for treesitter nodes
@ -108,6 +110,8 @@ variable is:
- Multigrid support (different font and detachable) - Multigrid support (different font and detachable)
- Side panel (sidebar) and floating windows
# Why a new plugin # Why a new plugin
I'd like to go beyond what the system is offering. I'd like to go beyond what the system is offering.
@ -671,6 +675,12 @@ You can override the above highlight to fit your current colorscheme
| ------------ | ------------------------- | | ------------ | ------------------------- |
| LspToggleFmt | toggle lsp auto format | | LspToggleFmt | toggle lsp auto format |
| LspKeymaps | show LSP releated keymaps | | LspKeymaps | show LSP releated keymaps |
| Nctags {args} | show ctags symbols, args: -g regen ctags |
| LspRestart | reload lsp |
| LspToggleFmt | toggle lsp format |
| LspSymbols | document symbol in side panel |
| TSymobls | treesitter symbol in side panel |
| Calltree {args} | lsp call hierarchy call tree, args: -i (incomming default), -o (outgoing) |
## Screenshots ## Screenshots
@ -691,6 +701,8 @@ Treesitter outline and Diagnostics
<img width="708" alt="image" src="https://user-images.githubusercontent.com/1681295/174791609-0023e68f-f1f4-4335-9ea2-d2360e9f0bfd.png"> <img width="708" alt="image" src="https://user-images.githubusercontent.com/1681295/174791609-0023e68f-f1f4-4335-9ea2-d2360e9f0bfd.png">
<img width="733" alt="image" src="https://user-images.githubusercontent.com/1681295/174804579-26f87fbf-426b-46d0-a7a3-a5aab69c032f.png"> <img width="733" alt="image" src="https://user-images.githubusercontent.com/1681295/174804579-26f87fbf-426b-46d0-a7a3-a5aab69c032f.png">
Calltree (LSP call hierarchy)
<img width="892" alt="image" src="https://user-images.githubusercontent.com/1681295/176054287-edede515-118d-458d-835a-097319ba99c3.png">
### GUI and multigrid support ### GUI and multigrid support

@ -18,10 +18,12 @@ CONTENTS *navigator-content
5.4.1. LSP clients.................................|navigator-lsp_clients| 5.4.1. LSP clients.................................|navigator-lsp_clients|
5.4.1.1. Add your own servers.........|navigator-add_your_own_servers| 5.4.1.1. Add your own servers.........|navigator-add_your_own_servers|
5.4.2. Disable a lsp client loading from navigator.|navigator-disable_a_lsp_client_loading_from_navigator| 5.4.2. Disable a lsp client loading from navigator.|navigator-disable_a_lsp_client_loading_from_navigator|
5.4.3. Default keymaps.........................|navigator-default_keymaps| 5.4.3. Try it your self.......................|navigator-try_it_your_self|
5.4.4. Colors/Highlight:.....................|navigator-colors/highlight:| 5.4.4. Default keymaps.........................|navigator-default_keymaps|
5.4.5. Colors/Highlight:.....................|navigator-colors/highlight:|
5.5. Dependency.........................................|navigator-dependency| 5.5. Dependency.........................................|navigator-dependency|
5.6. Integration with lsp_installer (williamboman/nvim-lsp-installer).|navigator-integration_with_lsp_installer_(williamboman/nvim-lsp-installer)| 5.6. Integrat with lsp_installer (williamboman/nvim-lsp-installer).|navigator-integrat_with_lsp_installer_(williamboman/nvim-lsp-installer)|
5.6.1. Integration with other lsp plugins (e.g. rust-tools, go.nvim, clangd extension).|navigator-integration_with_other_lsp_plugins_(e.g._rust-tools,_go.nvim,_clangd_extension)|
5.7. Usage...................................................|navigator-usage| 5.7. Usage...................................................|navigator-usage|
5.8. Configuration...................................|navigator-configuration| 5.8. Configuration...................................|navigator-configuration|
5.9. Highlight...........................................|navigator-highlight| 5.9. Highlight...........................................|navigator-highlight|
@ -29,10 +31,11 @@ CONTENTS *navigator-content
5.11. Screenshots......................................|navigator-screenshots| 5.11. Screenshots......................................|navigator-screenshots|
5.11.1. Reference....................................|navigator-reference| 5.11.1. Reference....................................|navigator-reference|
5.11.2. Definition preview..................|navigator-definition_preview| 5.11.2. Definition preview..................|navigator-definition_preview|
5.11.3. GUI and multigrid support....|navigator-gui_and_multigrid_support| 5.11.3. Sidebar, folding, outline....|navigator-sidebar,_folding,_outline|
5.11.4. Document Symbol........................|navigator-document_symbol| 5.11.4. GUI and multigrid support....|navigator-gui_and_multigrid_support|
5.11.5. Workspace Symbol......................|navigator-workspace_symbol| 5.11.5. Document Symbol and navigate through the list.|navigator-document_symbol_and_navigate_through_the_list|
5.11.6. highlight document symbol and jump between reference.|navigator-highlight_document_symbol_and_jump_between_reference| 5.11.6. Workspace Symbol......................|navigator-workspace_symbol|
5.11.7. highlight document symbol and jump between reference.|navigator-highlight_document_symbol_and_jump_between_reference|
6. Current symbol highlight and jump backward/forward between symbols.|navigator-current_symbol_highlight_and_jump_backward/forward_between_symbols| 6. Current symbol highlight and jump backward/forward between symbols.|navigator-current_symbol_highlight_and_jump_backward/forward_between_symbols|
6.1. Diagnostic.....................................|navigator-diagnostic| 6.1. Diagnostic.....................................|navigator-diagnostic|
6.2. Edit in preview window.............|navigator-edit_in_preview_window| 6.2. Edit in preview window.............|navigator-edit_in_preview_window|
@ -48,6 +51,9 @@ CONTENTS *navigator-content
6.11. Light bulb if codeAction available.|navigator-light_bulb_if_codeaction_available| 6.11. Light bulb if codeAction available.|navigator-light_bulb_if_codeaction_available|
6.12. Codelens........................................|navigator-codelens| 6.12. Codelens........................................|navigator-codelens|
6.13. Predefined LSP symbol nerdfont/emoji.|navigator-predefined_lsp_symbol_nerdfont/emoji| 6.13. Predefined LSP symbol nerdfont/emoji.|navigator-predefined_lsp_symbol_nerdfont/emoji|
6.14. VS-code style folding with treesitter.|navigator-vs-code_style_folding_with_treesitter|
6.14.1. folding function..................|navigator-folding_function|
6.14.2. folding comments..................|navigator-folding_comments|
7. Debug the plugin...................................|navigator-debug_the_plugin| 7. Debug the plugin...................................|navigator-debug_the_plugin|
8. Break changes and known issues.......|navigator-break_changes_and_known_issues| 8. Break changes and known issues.......|navigator-break_changes_and_known_issues|
9. Todo...........................................................|navigator-todo| 9. Todo...........................................................|navigator-todo|
@ -56,8 +62,14 @@ CONTENTS *navigator-content
================================================================================ ================================================================================
NAVIGATOR *navigator-navigator* NAVIGATOR *navigator-navigator*
* Source code analysis and navigate tool
* Easy code navigation, view diagnostic errors, see relationships of functions, variables * Easy code navigation, view diagnostic errors, see relationships of functions, variables
* A plugin combines the power of LSP and 🌲🏡 Treesitter together. Not only provids a better highlight but also help you analyse symbol context effectively. * A plugin combines the power of LSP and 🌲🏡 Treesitter together. Not only provids a better highlight but also help you analyse symbol context effectively.
* ctags fuzzy search & build ctags symbols
-
* [](https://youtu.be/P1kd7Y8AatE)
Here are some examples Here are some examples
@ -127,7 +139,8 @@ FEATURES: *navigator-features
* Optimize display (remove trailing bracket/space), display the caller of reference, de-duplicate lsp results (e.g reference * Optimize display (remove trailing bracket/space), display the caller of reference, de-duplicate lsp results (e.g reference
in the same line). Using treesitter for file preview highlighter etc in the same line). Using treesitter for file preview highlighter etc
* ccls call hierarchy (Non-standard `ccls/call` API) supports * 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. * Fully support LSP CodeAction, CodeLens, CodeLens action. Help you improve code quality.
* LRU cache for treesitter nodes * LRU cache for treesitter nodes
* Lazy loader friendly * Lazy loader friendly
@ -151,7 +164,7 @@ SIMILAR PROJECTS / SPECIAL MENTIONS: *navigator-similar_projects_/_special_menti
================================================================================ ================================================================================
INSTALL *navigator-install* INSTALL *navigator-install*
Require nvim-0.6.1 or nightly Require nvim-0.6.1 or above, nightly (0.8) prefered
You can remove your lspconfig setup and use this plugin. 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)). 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)).
@ -161,11 +174,17 @@ The plugin depends on lspconfig and guihua.lua (https://github.com/ray-x/guihua.
Plug 'ray-x/navigator.lua' Plug 'ray-x/navigator.lua'
< <
Note: Highly recommened: 'nvim-treesitter/nvim-treesitter' Note: Highly recommend: 'nvim-treesitter/nvim-treesitter'
Packer Packer
> >
use {'ray-x/navigator.lua', requires = {'ray-x/guihua.lua', run = 'cd lua/fzy && make'}} use({
'ray-x/navigator.lua',
requires = {
{ 'ray-x/guihua.lua', run = 'cd lua/fzy && make' },
{ 'neovim/nvim-lspconfig' },
},
})
< <
-------------------------------------------------------------------------------- --------------------------------------------------------------------------------
@ -183,11 +202,11 @@ SAMPLE VIMRC TURNING YOUR NEOVIM INTO A FULL-FEATURED IDE *navigator-sample_vimr
Plug 'neovim/nvim-lspconfig' Plug 'neovim/nvim-lspconfig'
Plug 'ray-x/guihua.lua', {'do': 'cd lua/fzy && make' } Plug 'ray-x/guihua.lua', {'do': 'cd lua/fzy && make' }
Plug 'ray-x/navigator.lua' Plug 'ray-x/navigator.lua'
" Plug 'hrsh7th/nvim-compe' and other plugins you commenly use... " Plug 'hrsh7th/nvim-cmp' and other plugins you commenly use...
" optional, if you need treesitter symbol support " optional, if you need treesitter symbol support
Plug 'nvim-treesitter/nvim-treesitter', {'do': ':TSUpdate'} Plug 'nvim-treesitter/nvim-treesitter', {'do': ':TSUpdate'}
call plug#end() call plug#end()
" No need for rquire('lspconfig'), navigator will configure it for you " No need for require('lspconfig'), navigator will configure it for you
lua <<EOF lua <<EOF
require'navigator'.setup() require'navigator'.setup()
EOF EOF
@ -238,7 +257,7 @@ ALL CONFIGURE OPTIONS *navigator-all_configure_option
Nondefault configuration example: Nondefault configuration example:
> >
require'navigator'.setup({ require'navigator'.setup({
debug = false, -- log output, set to true and log path: ~/.local/share/nvim/gh.log debug = false, -- log output, set to true and log path: ~/.cache/nvim/gh.log
width = 0.75, -- max width ratio (number of cols for the floating window) / (window width) width = 0.75, -- max width ratio (number of cols for the floating window) / (window width)
height = 0.3, -- max list window height, 0.3 by default height = 0.3, -- max list window height, 0.3 by default
preview_height = 0.35, -- max height of preview windows preview_height = 0.35, -- max height of preview windows
@ -258,6 +277,9 @@ Nondefault configuration example:
-- please check mapping.lua for all keymaps -- please check mapping.lua for all keymaps
treesitter_analysis = true, -- treesitter variable context treesitter_analysis = true, -- treesitter variable context
transparency = 50, -- 0 ~ 100 blur the main window, 100: fully transparent, 0: opaque, set to nil or 100 to disable it transparency = 50, -- 0 ~ 100 blur the main window, 100: fully transparent, 0: opaque, set to nil or 100 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 = nil, -- if you would like to init ray-x/lsp_signature plugin in navigator, and pass in your own config to signature help
icons = { icons = {
-- Code action -- Code action
code_action_icon = "🏏", code_action_icon = "🏏",
@ -268,23 +290,37 @@ Nondefault configuration example:
}, },
lsp_installer = false, -- set to true if you would like use the lsp installed by williamboman/nvim-lsp-installer lsp_installer = false, -- set to true if you would like use the lsp installed by williamboman/nvim-lsp-installer
lsp = { lsp = {
enable = true, -- skip lsp setup if disabled make sure add require('navigator.lspclient.mapping').setup() in you
-- own on_attach
code_action = {enable = true, sign = true, sign_priority = 40, virtual_text = true}, code_action = {enable = true, sign = true, sign_priority = 40, virtual_text = true},
code_lens_action = {enable = true, sign = true, sign_priority = 40, virtual_text = true}, code_lens_action = {enable = true, sign = true, sign_priority = 40, virtual_text = true},
format_on_save = true, -- set to false to disasble lsp code format on save (if you are using prettier/efm/formater etc) format_on_save = true, -- set to false to disable lsp code format on save (if you are using prettier/efm/formater etc)
disable_format_cap = {"sqls", "sumneko_lua", "gopls"}, -- a list of lsp disable format capacity (e.g. if you using efm or vim-codeformat etc), empty {} by default disable_format_cap = {"sqls", "sumneko_lua", "gopls"}, -- a list of lsp disable format capacity (e.g. if you using efm or vim-codeformat etc), empty {} by default
disable_lsp = {'pylsd', 'sqlls'}, -- a list of lsp server disabled for your project, e.g. denols and tsserver you may disable_lsp = {'pylsd', 'sqlls'}, -- a list of lsp server disabled for your project, e.g. denols and tsserver you may
-- only want to enable one lsp server -- only want to enable one lsp server
-- to disable all default config and use your own lsp setup set -- to disable all default config and use your own lsp setup set
-- disable_lsp = 'all' -- disable_lsp = 'all'
-- Default {} -- 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, diagnostic_scrollbar_sign = {'▃', '▆', '█'}, -- experimental: diagnostic status in scroll bar area; set to false to disable the diagnostic sign,
-- for other style, set to {'╍', 'ﮆ'} or {'-', '='} -- 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 disply_diagnostic_qf = true, -- always show quickfix if there are diagnostic errors, set to false if you want to
ignore it ignore it
tsserver = { tsserver = {
filetypes = {'typescript'} -- disable javascript etc, filetypes = {'typescript'} -- disable javascript etc,
-- set to {} to disable the lspclient for all filetypes -- set to {} to disable the lspclient for all filetypes
}, },
ctags ={
cmd = 'ctags',
tagfile = 'tags'
options = '-R --exclude=.git --exclude=node_modules --exclude=test --exclude=vendor --excmd=number'
}
gopls = { -- gopls setting gopls = { -- gopls setting
on_attach = function(client, bufnr) -- on_attach for gopls on_attach = function(client, bufnr) -- on_attach for gopls
-- your special on attach here -- your special on attach here
@ -300,7 +336,8 @@ Nondefault configuration example:
sumneko_root_path = vim.fn.expand("$HOME") .. "/github/sumneko/lua-language-server", 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", sumneko_binary = vim.fn.expand("$HOME") .. "/github/sumneko/lua-language-server/bin/macOS/lua-language-server",
}, },
servers = {'cmake', 'ltex'}, -- by default empty, but if you whant navigator load e.g. `cmake` and `ltex` for you , you servers = {'cmake', 'ltex'}, -- by default empty, and it should load all LSP clients avalible based on filetype
-- but if you whant navigator load e.g. `cmake` and `ltex` for you , you
-- can put them in the `servers` list and navigator will auto load them. -- can put them in the `servers` list and navigator will auto load them.
-- you could still specify the custom config like this -- you could still specify the custom config like this
-- cmake = {filetypes = {'cmake', 'makefile'}, single_file_support = false}, -- cmake = {filetypes = {'cmake', 'makefile'}, single_file_support = false},
@ -317,7 +354,8 @@ Built clients:
"jedi_language_server", "jdtls", "sumneko_lua", "vimls", "html", "jsonls", "solargraph", "cssls", "jedi_language_server", "jdtls", "sumneko_lua", "vimls", "html", "jsonls", "solargraph", "cssls",
"yamlls", "clangd", "ccls", "sqls", "denols", "graphql", "dartls", "dotls", "yamlls", "clangd", "ccls", "sqls", "denols", "graphql", "dartls", "dotls",
"kotlin_language_server", "nimls", "intelephense", "vuels", "phpactor", "omnisharp", "kotlin_language_server", "nimls", "intelephense", "vuels", "phpactor", "omnisharp",
"r_language_server", "rust_analyzer", "terraformls", "svelte", "texlab", "clojure_lsp" "r_language_server", "rust_analyzer", "terraformls", "svelte", "texlab", "clojure_lsp", "elixirls",
"sourcekit", "fsautocomplete", "vls", "hls"
} }
< <
@ -347,12 +385,12 @@ ADD YOUR OWN SERVERS *navigator-add_your_own_server
Above servers covered a small part neovim lspconfig support, You can still use lspconfig to add and config servers not Above servers covered a small part neovim lspconfig support, You can still use lspconfig to add and config servers not
in the list. If you would like to add a server not in the list, you can check this PR https://github.com/ray-x/navigator.lua/pull/107 in the list. If you would like to add a server not in the list, you can check this PR https://github.com/ray-x/navigator.lua/pull/107
Also, an option in setup: Alternatively, update following option in setup(if you do not want a PR):
> >
require'navigator'setup{lsp={servers={'cmake', 'lexls'}}} require'navigator'setup{lsp={servers={'cmake', 'lexls'}}}
< <
Above example add cmake and lexls to the default server list Above option add cmake and lexls to the default server list
DISABLE A LSP CLIENT LOADING FROM NAVIGATOR *navigator-disable_a_lsp_client_loading_from_navigator* DISABLE A LSP CLIENT LOADING FROM NAVIGATOR *navigator-disable_a_lsp_client_loading_from_navigator*
@ -375,11 +413,16 @@ Or:
}) })
< <
TRY IT YOUR SELF *navigator-try_it_your_self*
In `playground` folder, there is a `init.lua` and source code for you to play with. Check playground/README.md (https://github.com/ray-x/navigator.lua/blob/master/playground/README.md) for more details
DEFAULT KEYMAPS *navigator-default_keymaps* DEFAULT KEYMAPS *navigator-default_keymaps*
| mode | key | function | | mode | key | function |
| ---- | --------------- | ---------------------------------------------------------- | | ---- | --------------- | ---------------------------------------------------------- |
| n | gr | show reference and context | | n | gr | async references, definitions and context |
| n | <Leader>gr | show reference and context |
| i | <m-k> | signature help | | i | <m-k> | signature help |
| n | <c-k> | signature help | | n | <c-k> | signature help |
| n | gW | workspace symbol | | n | gW | workspace symbol |
@ -390,18 +433,20 @@ DEFAULT KEYMAPS *navigator-default_keymap
| n | gp | definition preview (Go to Preview) | | n | gp | definition preview (Go to Preview) |
| n | <C-LeftMouse> | definition | | n | <C-LeftMouse> | definition |
| n | g<LeftMouse> | implementation | | n | g<LeftMouse> | implementation |
| n | gT | treesitter document symbol | | n | <Leader>gt | treesitter document symbol |
| n | <Leader>gT | treesitter symbol for all open buffers | | n | <Leader>gT | treesitter symbol for all open buffers |
| n | <Leader> ct | ctags symbol search |
| n | <Leader> cg | ctags symbol generate |
| n | K | hover doc | | n | K | hover doc |
| n | <Space>ca | code action (when you see 🏏 ) | | n | <Space>ca | code action (when you see 🏏 ) |
| n | <Space>la | code lens action (when you see a codelens indicator) | | n | <Space>la | code lens action (when you see a codelens indicator) |
| v | <Space>cA | range code action (when you see 🏏 ) | | v | <Space>ca | range code action (when you see 🏏 ) |
| n | <Space>rn | rename with floating window | | n | <Space>rn | rename with floating window |
| n | <Leader>re | rename (lsp default) | | n | <Leader>re | rename (lsp default) |
| n | <Leader>gi | hierarchy incoming calls | | n | <Leader>gi | hierarchy incoming calls |
| n | <Leader>go | hierarchy outgoing calls | | n | <Leader>go | hierarchy outgoing calls |
| n | gi | implementation | | n | gi | implementation |
| n | <Sapce> D | type definition | | n | <Space> D | type definition |
| n | gL | show line diagnostic | | n | gL | show line diagnostic |
| n | gG | show diagnostic for all buffers | | n | gG | show diagnostic for all buffers |
| n | ]d | next diagnostic | | n | ]d | next diagnostic |
@ -409,9 +454,9 @@ DEFAULT KEYMAPS *navigator-default_keymap
| n | <Leader> dt | diagnostic toggle(enable/disable) | | n | <Leader> dt | diagnostic toggle(enable/disable) |
| n | ]r | next treesitter reference/usage | | n | ]r | next treesitter reference/usage |
| n | [r | previous treesitter reference/usage | | n | [r | previous treesitter reference/usage |
| n | <Sapce> wa | add workspace folder | | n | <Space> wa | add workspace folder |
| n | <Sapce> wr | remove workspace folder | | n | <Space> wr | remove workspace folder |
| n | <Sapce> wl | print workspace folder | | n | <Space> wl | print workspace folder |
| n | <Leader>k | toggle reference highlight | | n | <Leader>k | toggle reference highlight |
| i/n | <C-p> | previous item in list | | i/n | <C-p> | previous item in list |
| i/n | <C-n> | next item in list | | i/n | <C-n> | next item in list |
@ -458,19 +503,43 @@ The plugin can be loaded lazily (packer `opt = true` ), And it will check if opt
The terminal 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).
-------------------------------------------------------------------------------- --------------------------------------------------------------------------------
INTEGRATION WITH LSP_INSTALLER (WILLIAMBOMAN/NVIM-LSP-INSTALLER) *navigator-integration_with_lsp_installer_(williamboman/nvim-lsp-installer)* INTEGRAT WITH LSP_INSTALLER (WILLIAMBOMAN/NVIM-LSP-INSTALLER) *navigator-integrat_with_lsp_installer_(williamboman/nvim-lsp-installer)*
If you'd like to only use the lsp servers installed by lsp_installer. Please set If you are using lsp_installer and would like to use the lsp servers installed by lsp_installer. Please set
> >
lsp_installer = true lsp_installer = true
< <
In the config. In the config. Also please setup the lsp server from installer setup with `server:setup{opts}`
example:
>
use({
'williamboman/nvim-lsp-installer',
config = function()
local lsp_installer = require('nvim-lsp-installer')
lsp_installer.setup{}
end,
})
use({
'ray-x/navigator.lua',
config = function()
require('navigator').setup({
debug = true,
lsp_installer = true,
keymaps = { { key = 'gR', func = "require('navigator.reference').async_ref()" } },
})
end,
})
<
Navigator will startup the server installed by lsp-installer. Please do not call `server:setup{opts}` from lsp installer Please refer to lsp_installer_config (https://github.com/ray-x/navigator.lua/blob/master/playground/init_lsp_installer.lua)
for more info
Alternatively, Navigator can be used to startup the server installed by lsp-installer.
as it will override the navigator setup as it will override the navigator setup
Also, could use following setups To start LSP installed by lsp_installer, please use following setups
> >
require'navigator'.setup({ require'navigator'.setup({
-- lsp_installer = false -- default value is false -- lsp_installer = false -- default value is false
@ -482,7 +551,70 @@ Also, could use following setups
example cmd setup (mac) for pyright : example cmd setup (mac) for pyright :
> >
cmd = { "/Users/username/.local/share/nvim/lsp_servers/python/node_modules/.bin/pyright-langserver", "--stdio" } require'navigator'.setup({
-- lsp_installer = false -- default value is false
lsp = {
tsserver = {
cmd = { "/Users/username/.local/share/nvim/lsp_servers/python/node_modules/.bin/pyright-langserver", "--stdio" }
}
}
}
<
The lsp servers installed by nvim-lsp-installer is in following dir
>
local path = require 'nvim-lsp-installer.path'
local install_root_dir = path.concat {vim.fn.stdpath 'data', 'lsp_servers'}
<
And you can setup binary full path to this: (e.g. with gopls)
`install_root_dir .. '/go/gopls'` So the config is
>
local path = require 'nvim-lsp-installer.path'
local install_root_dir = path.concat {vim.fn.stdpath 'data', 'lsp_servers'}
require'navigator'.setup({
-- lsp_installer = false -- default value is false
lsp = {
gopls = {
cmd = { install_root_dir .. '/go/gopls' }
}
}
}
<
Use lsp_installer configs
You can delegate the lsp server setup to lsp_installer with `server:setup{opts}`
Here is an example init_lsp_installer.lua (https://github.com/ray-x/navigator.lua/blob/master/playground/init_lsp_installer.lua)
INTEGRATION WITH OTHER LSP PLUGINS (E.G. RUST-TOOLS, GO.NVIM, CLANGD EXTENSION) *navigator-integration_with_other_lsp_plugins_(e.g._rust-tools,_go.nvim,_clangd_extension)*
There are lots of plugins provides lsp support
go.nvim allow you either hook gopls from go.nvim or from navigator and it can export the lsp setup from go.nvim.
rust-tools and clangd allow you to setup on_attach from config server
Here is an example to setup rust with rust-tools
>
require'navigator'.setup({
lsp = {
disable_lsp = { "rust_analyzer", "clangd" }, -- will not run rust_analyzer setup from navigator
}
})
require('rust-tools').setup({
server = {
on_attach = function(_, _)
require('navigator.lspclient.mapping').setup() -- setup navigator keymaps here,
-- otherwise, you can define your own commands to call navigator functions
end,
}
})
require("clangd_extensions").setup {
server = {
on_attach = function(_, _)
require('navigator.lspclient.mapping').setup() -- setup navigator keymaps here,
-- otherwise, you can define your own commands to call navigator functions
end,
}
}
< <
-------------------------------------------------------------------------------- --------------------------------------------------------------------------------
@ -521,10 +653,41 @@ You can override the above highlight to fit your current colorscheme
-------------------------------------------------------------------------------- --------------------------------------------------------------------------------
COMMANDS *navigator-commands* COMMANDS *navigator-commands*
| command | function | | command | function |
| ------------ | ---------------------- | | ------------ | ------------------------- |
| LspToggleFmt | toggle lsp auto format | | LspToggleFmt | toggle lsp auto format |
| LspKeymaps | show LSP releated keymaps |
| Nctags {args} | show ctags symbols, args: -g regen ctags |
| LspRestart | reload lsp |
| LspSymbols | document symbol in side panel |
| TSymobls | treesitter symbol in side panel |
| CallTree {args} | lsp call hierarchy call tree, args: -i (incomming default), -o (outgoing) |
:LspToggleFmt *:LspToggleFmt*
Toggle lsp auto format.
:LspKeymaps *:LspKeymaps*
Show Lsp keymaps.
:Nctags [flags] *:Nctags*
Show ctags symbols.
[flags]:
-g regen ctags
:LspRestart *:LspRestart*
Restart Lsp.
:LspSymbols *:LspSymbols*
Lsp document symbol in side panel.
:TSSymbols *:TSSymbols*
Treesitter symbol in side panel.
:Calltree [flags] *:Calltree*
Lsp call hierarchy call tree.
[flags]:
-i: incomming default
-o: outgoing
-------------------------------------------------------------------------------- --------------------------------------------------------------------------------
SCREENSHOTS *navigator-screenshots* SCREENSHOTS *navigator-screenshots*
@ -540,15 +703,27 @@ Using treesitter and LSP to view the symbol definition
SIDEBAR, FOLDING, OUTLINE *navigator-sidebar,_folding,_outline*
Treesitter outline and Diagnostics
GUI AND MULTIGRID SUPPORT *navigator-gui_and_multigrid_support* GUI AND MULTIGRID SUPPORT *navigator-gui_and_multigrid_support*
You can load a different font size for floating win You can load a different font size for floating win
DOCUMENT SYMBOL *navigator-document_symbol* DOCUMENT SYMBOL AND NAVIGATE THROUGH THE LIST *navigator-document_symbol_and_navigate_through_the_list*
The key binding to navigate in the list.
* up and down key
* `<Ctrl-f/b>` for page up and down
* number key 1~9 go to the ith item.
* If there are loads of results, would be good to use fzy search prompt to filter out the result you are interested.
WORKSPACE SYMBOL *navigator-workspace_symbol* WORKSPACE SYMBOL *navigator-workspace_symbol*
@ -647,6 +822,16 @@ PREDEFINED LSP SYMBOL NERDFONT/EMOJI *navigator-predefined_lsp_symbol_nerdfont/e
VS-CODE STYLE FOLDING WITH TREESITTER *navigator-vs-code_style_folding_with_treesitter*
FOLDING FUNCTION *navigator-folding_function*
FOLDING COMMENTS *navigator-folding_comments*
================================================================================ ================================================================================
DEBUG THE PLUGIN *navigator-debug_the_plugin* DEBUG THE PLUGIN *navigator-debug_the_plugin*
@ -689,3 +874,6 @@ ERRORS AND BUG REPORTING *navigator-errors_and_bug_reportin
* Check console output * Check console output
* Check `LspInfo` and treesitter status with `checkhealth` * 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 * Turn on log and attach the log to your issue if possible you can remove any personal/company info in the log
* Submit Issue with minium vimrc. Please check playground/init.lua as a vimrc template. !!!Please DONOT use a packer vimrc
that installs everything to default folder!!! Also check this repo navigator bug report (https://github.com/fky2015/navigator.nvim-bug-report)

@ -1,27 +1,58 @@
local gui = require('navigator.gui') local gui = require('navigator.gui')
local util = require('navigator.util') local util = require('navigator.util')
local log = util.log local log = util.log
local trace = util.log local trace = util.trace
local partial = util.partial local partial = util.partial
local lsphelper = require('navigator.lspwrapper') local lsphelper = require('navigator.lspwrapper')
local path_sep = require('navigator.util').path_sep() local path_sep = require('navigator.util').path_sep()
local path_cur = require('navigator.util').path_cur() local path_cur = require('navigator.util').path_cur()
local cwd = vim.loop.cwd() local cwd = vim.loop.cwd()
local in_method = 'callHierarchy/incomingCalls'
local out_method = 'callHierarchy/outgoingCalls'
local lsp_method = { to = out_method, from = in_method }
local panel_method = { to = out_method, from = in_method }
local M = {} local M = {}
local outgoing_calls_handler local outgoing_calls_handler
local incoming_calls_handler local incoming_calls_handler
local hierarchy_handler
local call_hierarchy
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_handler(direction, err, result, ctx, config) -- convert lsp result to navigator items
log(direction, err, result, ctx, config) local function call_hierarchy_result_procesor(direction, err, result, ctx, config)
math.randomseed(os.clock() * 100000000000)
trace(direction, err, ctx, config)
trace(result)
if not result then if not result then
vim.notify('No call hierarchy items found', vim.lsp.log_levels.WARN) vim.notify('No call hierarchy items found', vim.lsp.log_levels.WARN)
return return
end end
-- trace('call_hierarchy', result) -- trace('call_hierarchy', result)
local bufnr = vim.api.nvim_get_current_buf() local bufnr = ctx.bufnr or vim.api.nvim_get_current_buf()
assert(next(vim.lsp.buf_get_clients(bufnr)), 'Must have a client running to use lsp_tags') assert(next(vim.lsp.buf_get_clients(bufnr)), 'Must have a client running to use call hierarchy')
if err ~= nil then if err ~= nil then
log('dir', direction, 'result', result, 'err', err, ctx) log('dir', direction, 'result', result, 'err', err, ctx)
vim.notify('ERROR: ' .. err, vim.lsp.log_levels.WARN) vim.notify('ERROR: ' .. err, vim.lsp.log_levels.WARN)
@ -30,9 +61,9 @@ local function call_hierarchy_handler(direction, err, result, ctx, config)
local items = ctx.items or {} local items = ctx.items or {}
local kind = ''
for _, call_hierarchy_result in pairs(result) do for _, call_hierarchy_result in pairs(result) do
local call_hierarchy_item = call_hierarchy_result[direction] local call_hierarchy_item = call_hierarchy_result[direction]
local kind = ''
if call_hierarchy_item.kind then if call_hierarchy_item.kind then
kind = require('navigator.lspclient.lspkind').symbol_kind(call_hierarchy_item.kind) .. ' ' kind = require('navigator.lspclient.lspkind').symbol_kind(call_hierarchy_item.kind) .. ' '
end end
@ -40,103 +71,190 @@ local function call_hierarchy_handler(direction, err, result, ctx, config)
local display_filename = filename:gsub(cwd .. path_sep, path_cur, 1) local display_filename = filename:gsub(cwd .. path_sep, path_cur, 1)
call_hierarchy_item.detail = call_hierarchy_item.detail or '' call_hierarchy_item.detail = call_hierarchy_item.detail or ''
call_hierarchy_item.detail = string.gsub(call_hierarchy_item.detail, '\n', '') call_hierarchy_item.detail = string.gsub(call_hierarchy_item.detail, '\n', '')
trace(result, call_hierarchy_item) trace(call_hierarchy_item)
local disp_item = vim.tbl_deep_extend('force', {}, call_hierarchy_item) local disp_item = vim.tbl_deep_extend('force', {}, call_hierarchy_item)
disp_item = vim.tbl_deep_extend('force', disp_item, { disp_item = vim.tbl_deep_extend('force', disp_item, {
filename = filename, filename = filename,
display_filename = display_filename, display_filename = display_filename,
indent = ctx.depth, indent_level = ctx.depth or 1,
method = lsp_method[direction],
node_text = call_hierarchy_item.name,
type = kind,
id = math.random(1, 100000),
text = kind .. call_hierarchy_item.name .. '' .. call_hierarchy_item.detail, text = kind .. call_hierarchy_item.name .. '' .. call_hierarchy_item.detail,
lnum = call_hierarchy_item.selectionRange.start.line + 1, lnum = call_hierarchy_item.selectionRange.start.line + 1,
col = call_hierarchy_item.selectionRange.start.character, col = call_hierarchy_item.selectionRange.start.character,
}) })
table.insert(items, disp_item) table.insert(items, disp_item)
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 end
log(items) trace(items)
return items return items
end end
local call_hierarchy_handler_from = partial(call_hierarchy_handler, 'from') local call_hierarchy_handler_from = partial(call_hierarchy_result_procesor, 'from')
local call_hierarchy_handler_to = partial(call_hierarchy_handler, 'to') local call_hierarchy_handler_to = partial(call_hierarchy_result_procesor, 'to')
incoming_calls_handler = function(_, err, result, ctx, cfg) -- the handler that deal all lsp request
local bufnr = vim.api.nvim_get_current_buf() hierarchy_handler = function(dir, handler, show, api, err, result, ctx, cfg)
trace(dir, handler, api, show, err, result, ctx, cfg)
ctx = ctx or {} -- can be nil if it is async call
cfg = cfg or {}
opts = ctx.opts or {}
vim.validate({ handler = { handler, 'function' }, show = { show, 'function' }, api = { api, 'string' } })
local bufnr = ctx.bufnr or vim.api.nvim_get_current_buf()
assert(next(vim.lsp.buf_get_clients(bufnr)), 'Must have a client running to use lsp hierarchy') 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 results = handler(err, result, ctx, cfg, 'Incoming calls not found')
local ft = vim.api.nvim_buf_get_option(ctx.bufnr or vim.api.nvim_get_current_buf(), 'ft') local ft = vim.api.nvim_buf_get_option(ctx.bufnr or vim.api.nvim_get_current_buf(), 'ft')
if ctx.no_show then if ctx.no_show then
return results return results
end end
local win = gui.new_list_view({ items = results, ft = ft, api = '' }) -- local panel = args.panel
-- local items = args.items
-- local parent_node = args.node
-- local section_id = args.section_id or 1
local show_args = {
items = results,
ft = ft,
api = api,
bufnr = bufnr,
panel = opts.panel,
parent_node = opts.parent_node,
}
local win = show(show_args)
return results, win return results, win
end end
outgoing_calls_handler = function(_, err, result, ctx, cfg) local make_params = function(uri, pos)
local results = call_hierarchy_handler_to(err, result, ctx, cfg, 'Outgoing calls not found') return {
textDocument = {
local ft = vim.api.nvim_buf_get_option(ctx.bufnr, 'ft') uri = uri,
if ctx.no_show then },
return results position = pos,
end }
local win = gui.new_list_view({ items = results, ft = ft, api = '' })
return result, win
end end
local function request(method, params, handler) local function display_panel(args)
return vim.lsp.buf_request(0, method, params, handler) -- args = {items=results, ft=ft, api=api}
log(args)
local Panel = require('guihua.panel')
local bufnr = args.bufnr or vim.api.nvim_get_current_buf()
local ft = args.ft or vim.api.nvim_buf_get_option(bufnr, 'buftype')
local items = args.items
local p = Panel:new({
header = args.header or 'Call Hierarchy',
render = function(bufnr)
return items
end,
fold = function(panel, node)
if node.expanded ~= nil then
node.expanded = not node.expanded
vim.cmd('normal! za')
else
expand(panel, node)
node.expanded = true
end
log('fold')
return node
end,
})
p:open(true)
end end
local function pick_call_hierarchy_item(call_hierarchy_items) local function expand_item(args)
if not call_hierarchy_items then -- args = {items=results, ft=ft, api=api}
return print('dispaly panel')
end trace(args, args.parent_node)
if #call_hierarchy_items == 1 then local panel = args.panel
return call_hierarchy_items[1] local items = args.items
local parent_node = args.parent_node
local section_id = args.section_id or 1
local sect
local sectid = 1
for i, s in pairs(panel.sections) do
if s.id == section_id then
sectid = i
break
end
end end
local items = {} sect = panel.sections[sectid]
for i, item in pairs(call_hierarchy_items) do for i, node in pairs(sect.nodes) do
local entry = item.detail or item.name if node.id == parent_node.id then
table.insert(items, string.format('%d. %s', i, entry)) for j in ipairs(items) do
items[j].indent_level = parent_node.indent_level + 1
table.insert(sect.nodes, i + j, args.items[j])
end
sect.nodes[i].expanded = true
sect.nodes[i].expandable = false
break
end
end end
local choice = vim.fn.inputlist(items) trace(panel.sections[sectid])
if choice < 1 or choice > #items then -- render the panel again
return panel:redraw(false)
end
incoming_calls_handler = util.partial4(
hierarchy_handler,
'from',
call_hierarchy_handler_from,
gui.new_list_view,
''
)
outgoing_calls_handler = util.partial4(hierarchy_handler, 'to', call_hierarchy_handler_to, gui.new_list_view, '')
local incoming_calls_panel = util.partial4(
hierarchy_handler,
'from',
call_hierarchy_handler_from,
display_panel,
''
)
local outgoing_calls_panel = util.partial4(hierarchy_handler, 'to', call_hierarchy_handler_to, display_panel, '')
local incoming_calls_expand = util.partial4(hierarchy_handler, 'from', call_hierarchy_handler_from, expand_item, '')
local outgoing_calls_expand = util.partial4(hierarchy_handler, 'to', call_hierarchy_handler_to, expand_item, '')
function expand(panel, node)
trace(panel, node)
local params = make_params(node.uri, {
line = node.range.start.line,
character = node.range.start.character,
})
local handler = incoming_calls_expand
if node.api == out_method then
handler = outgoing_calls_expand
end end
return choice
local bufnr = vim.uri_to_bufnr(node.uri)
call_hierarchy(node.method, {
params = params,
panel = panel,
parent_node = node,
handler = handler,
bufnr = bufnr,
})
end end
local function call_hierarchy(method, opts) local request = vim.lsp.buf_request
local params = vim.lsp.util.make_position_params()
-- call_hierarchy with floating window
call_hierarchy = function(method, opts)
trace(method, opts)
opts = opts or {} opts = opts or {}
local params = opts.params or vim.lsp.util.make_position_params()
local bufnr = opts.bufnr
local handler = function(err, result, ctx, cfg)
ctx.opts = opts
return opts.handler(err, result, ctx, cfg)
end
-- log(opts, params)
request( request(
bufnr,
'textDocument/prepareCallHierarchy', 'textDocument/prepareCallHierarchy',
params, params,
vim.lsp.with(function(err, result, ctx) vim.lsp.with(function(err, result, ctx)
@ -145,32 +263,47 @@ local function call_hierarchy(method, opts)
return return
end end
local call_hierarchy_item = pick_call_hierarchy_item(result) 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) local client = vim.lsp.get_client_by_id(ctx.client_id)
if client then if client then
client.request(method, { item = call_hierarchy_item }, nil, ctx.bufnr) trace('result', result, 'items', call_hierarchy_item, method, ctx, client.name)
client.request(method, {
item = call_hierarchy_item,
args = {
method = method,
},
}, handler, ctx.bufnr)
else else
vim.notify( vim.notify(string.format('Client with id=%d stopped', ctx.client_id), vim.log.levels.WARN)
string.format('Client with id=%d disappeared during call hierarchy request', ctx.client_id),
vim.log.levels.WARN
)
end end
end, { direction = method, depth = opts.depth }) end, { direction = method, depth = opts.depth })
) )
end end
function M.incoming_calls(opts) function M.incoming_calls(opts)
call_hierarchy('callHierarchy/incomingCalls', opts) call_hierarchy(in_method, opts)
end end
function M.outgoing_calls(opts) function M.outgoing_calls(opts)
call_hierarchy('callHierarchy/outgoingCalls', opts) call_hierarchy(out_method, opts)
end end
M.incoming_calls_call = partial(M.incoming_calls, 0) function M.incoming_calls_panel(opts)
M.outgoing_calls_call = partial(M.outgoing_calls, 0) opts = vim.tbl_extend('force', { handler = incoming_calls_panel }, opts or {})
call_hierarchy(in_method, opts)
end
M.incoming_calls_handler = partial(incoming_calls_handler, 0) function M.outgoing_calls_panel(opts)
M.outgoing_calls_handler = partial(outgoing_calls_handler, 0) opts = vim.tbl_extend('force', { handler = outgoing_calls_panel }, opts or {})
call_hierarchy(out_method, opts)
end
M.incoming_calls_handler = incoming_calls_handler
M.outgoing_calls_handler = outgoing_calls_handler
function M.calltree(args)
if args == '-o' then
return M.outgoing_calls_panel()
end
M.incoming_calls_panel()
end
return M return M

@ -70,6 +70,7 @@ local commands = {
"command! -nargs=0 LspKeymaps lua require'navigator.lspclient.mapping'.get_keymaps_help()<CR>", "command! -nargs=0 LspKeymaps lua require'navigator.lspclient.mapping'.get_keymaps_help()<CR>",
"command! -nargs=0 LspSymbols lua require'navigator.symbols'.side_panel()<CR>", "command! -nargs=0 LspSymbols lua require'navigator.symbols'.side_panel()<CR>",
"command! -nargs=0 TSymbols lua require'navigator.treesitter'.side_panel()<CR>", "command! -nargs=0 TSymbols lua require'navigator.treesitter'.side_panel()<CR>",
"command! -nargs=* Calltree lua require'navigator.hierarchy'.calltree(<f-args>)<CR>",
} }
local key_maps_help = {} local key_maps_help = {}

@ -426,6 +426,24 @@ function M.partial(func, arg)
end end
end end
function M.partial2(func, arg1, arg2)
return function(...)
return func(arg1, arg2, ...)
end
end
function M.partial3(func, arg1, arg2, arg3)
return function(...)
return func(arg1, arg2, arg3, ...)
end
end
function M.partial4(func, arg1, arg2, arg3, arg4)
return function(...)
return func(arg1, arg2, arg3, arg4, ...)
end
end
function M.empty(t) function M.empty(t)
if t == nil then if t == nil then
return true return true

Loading…
Cancel
Save