1

Regenerate nvim config

This commit is contained in:
2024-06-02 03:29:20 +02:00
parent 75eea0c030
commit ef2e28883d
5576 changed files with 604886 additions and 503 deletions

View File

@ -0,0 +1 @@
github: SmiteshP

View File

@ -0,0 +1 @@
doc/tags

View File

@ -0,0 +1,201 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright [yyyy] [name of copyright owner]
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

View File

@ -0,0 +1,450 @@
# 🛰️ nvim-navic
A simple statusline/winbar component that uses LSP to show your current code context.
Named after the Indian satellite navigation system.
![2022-06-11 17-02-33](https://user-images.githubusercontent.com/43147494/173186210-c8d689ad-1f8a-43cf-8125-127c7bd5be35.gif)
>You might also be interested in [nvim-navbuddy](https://github.com/SmiteshP/nvim-navbuddy). Paired with nvim-navic, it will give you complete breadcrumbs experience like in an IDE!
## ⚡️ Requirements
* Neovim >= 0.7.0
* [nvim-lspconfig](https://github.com/neovim/nvim-lspconfig)
## 📦 Installation
Install the plugin with your preferred package manager:
### [packer](https://github.com/wbthomason/packer.nvim)
```lua
use {
"SmiteshP/nvim-navic",
requires = "neovim/nvim-lspconfig"
}
```
### [vim-plug](https://github.com/junegunn/vim-plug)
```vim
Plug "neovim/nvim-lspconfig"
Plug "SmiteshP/nvim-navic"
```
## ⚙️ Setup
For nvim-navic to work, it needs attach to the lsp server. You can pass the nvim-navic's `attach` function as `on_attach` while setting up the lsp server. You can skip this step if you have enabled auto_attach option during setup.
Note: nvim-navic can attach to only one server per buffer.
Example:
```lua
local navic = require("nvim-navic")
require("lspconfig").clangd.setup {
on_attach = function(client, bufnr)
navic.attach(client, bufnr)
end
}
```
If you're sharing your `on-attach` function between lspconfigs, better wrap nvim-navic's `attach` function to make sure `documentSymbolProvider` is enabled:
Example:
```lua
local on_attach = function(client, bufnr)
...
if client.server_capabilities.documentSymbolProvider then
navic.attach(client, bufnr)
end
...
end
require("lspconfig").clangd.setup {
on_attach = on_attach
}
```
>NOTE: You can set `vim.g.navic_silence = true` to supress error messages thrown by nvim-navic. However this is not recommended as the error messages indicate that there is problem in your setup. That is, you are attaching nvim-navic to servers that don't support documentSymbol or are attaching navic to multiple servers for a single buffer.
>NOTE: You can set `vim.b.navic_lazy_update_context = true` for specific buffers, where you want the the updates to not occur on every `CursorMoved` event. It should help if you are facing performance issues in large files. Read the docs for example usage of this variable. Alternatively, you can pass `lazy_update_context=true` to the `setup` function to turn off context updates on the `CursorMoved` event completely for all buffers. It's useful when you just want context updates to happen only on `CursorHold` events and not on `CursorMoved`.
## 🪄 Customise
Use the `setup` function to modify default parameters.
* `icons` : Indicate the type of symbol captured. Default icons assume you have nerd-fonts.
* `highlight` : If set to true, will add colors to icons and text as defined by highlight groups `NavicIcons*` (`NavicIconsFile`, `NavicIconsModule`.. etc.), `NavicText` and `NavicSeparator`.
* `depth_limit` : Maximum depth of context to be shown. If the context hits this depth limit, it is truncated.
* `depth_limit_indicator` : Icon to indicate that `depth_limit` was hit and the shown context is truncated.
* `format_text` : A function to customize the text displayed in each segment.
* `lazy_update_context` : If true, turns off context updates for the "CursorMoved" event.
* `safe_output` : Sanitize the output for use in statusline and winbar.
* `click` : Single click to goto element, double click to open nvim-navbuddy on the clicked element.
* `lsp` :
* `auto_attach` : Enable to have nvim-navic automatically attach to every LSP for current buffer. Its disabled by default.
* `preference` : Table ranking lsp_servers. Lower the index, higher the priority of the server. If there are more than one server attached to a buffer, nvim-navic will refer to this list to make a decision on which one to use. For example - In case a buffer is attached to clangd and ccls both and the preference list is `{ "clangd", "pyright" }`. Then clangd will be preferred.
```lua
navic.setup {
icons = {
File = "󰈙 ",
Module = " ",
Namespace = "󰌗 ",
Package = " ",
Class = "󰌗 ",
Method = "󰆧 ",
Property = " ",
Field = " ",
Constructor = " ",
Enum = "󰕘",
Interface = "󰕘",
Function = "󰊕 ",
Variable = "󰆧 ",
Constant = "󰏿 ",
String = "󰀬 ",
Number = "󰎠 ",
Boolean = "◩ ",
Array = "󰅪 ",
Object = "󰅩 ",
Key = "󰌋 ",
Null = "󰟢 ",
EnumMember = " ",
Struct = "󰌗 ",
Event = " ",
Operator = "󰆕 ",
TypeParameter = "󰊄 ",
},
lsp = {
auto_attach = false,
preference = nil,
},
highlight = false,
separator = " > ",
depth_limit = 0,
depth_limit_indicator = "..",
safe_output = true,
lazy_update_context = false,
click = false,
format_text = function(text)
return text
end,
}
```
For highlights to work, highlight groups must be defined. These may be defined in your colourscheme, if not you can define them yourself too as shown in below code snippet.
<details>
<summary>Example highlight definitions</summary>
```lua
vim.api.nvim_set_hl(0, "NavicIconsFile", {default = true, bg = "#000000", fg = "#ffffff"})
vim.api.nvim_set_hl(0, "NavicIconsModule", {default = true, bg = "#000000", fg = "#ffffff"})
vim.api.nvim_set_hl(0, "NavicIconsNamespace", {default = true, bg = "#000000", fg = "#ffffff"})
vim.api.nvim_set_hl(0, "NavicIconsPackage", {default = true, bg = "#000000", fg = "#ffffff"})
vim.api.nvim_set_hl(0, "NavicIconsClass", {default = true, bg = "#000000", fg = "#ffffff"})
vim.api.nvim_set_hl(0, "NavicIconsMethod", {default = true, bg = "#000000", fg = "#ffffff"})
vim.api.nvim_set_hl(0, "NavicIconsProperty", {default = true, bg = "#000000", fg = "#ffffff"})
vim.api.nvim_set_hl(0, "NavicIconsField", {default = true, bg = "#000000", fg = "#ffffff"})
vim.api.nvim_set_hl(0, "NavicIconsConstructor", {default = true, bg = "#000000", fg = "#ffffff"})
vim.api.nvim_set_hl(0, "NavicIconsEnum", {default = true, bg = "#000000", fg = "#ffffff"})
vim.api.nvim_set_hl(0, "NavicIconsInterface", {default = true, bg = "#000000", fg = "#ffffff"})
vim.api.nvim_set_hl(0, "NavicIconsFunction", {default = true, bg = "#000000", fg = "#ffffff"})
vim.api.nvim_set_hl(0, "NavicIconsVariable", {default = true, bg = "#000000", fg = "#ffffff"})
vim.api.nvim_set_hl(0, "NavicIconsConstant", {default = true, bg = "#000000", fg = "#ffffff"})
vim.api.nvim_set_hl(0, "NavicIconsString", {default = true, bg = "#000000", fg = "#ffffff"})
vim.api.nvim_set_hl(0, "NavicIconsNumber", {default = true, bg = "#000000", fg = "#ffffff"})
vim.api.nvim_set_hl(0, "NavicIconsBoolean", {default = true, bg = "#000000", fg = "#ffffff"})
vim.api.nvim_set_hl(0, "NavicIconsArray", {default = true, bg = "#000000", fg = "#ffffff"})
vim.api.nvim_set_hl(0, "NavicIconsObject", {default = true, bg = "#000000", fg = "#ffffff"})
vim.api.nvim_set_hl(0, "NavicIconsKey", {default = true, bg = "#000000", fg = "#ffffff"})
vim.api.nvim_set_hl(0, "NavicIconsNull", {default = true, bg = "#000000", fg = "#ffffff"})
vim.api.nvim_set_hl(0, "NavicIconsEnumMember", {default = true, bg = "#000000", fg = "#ffffff"})
vim.api.nvim_set_hl(0, "NavicIconsStruct", {default = true, bg = "#000000", fg = "#ffffff"})
vim.api.nvim_set_hl(0, "NavicIconsEvent", {default = true, bg = "#000000", fg = "#ffffff"})
vim.api.nvim_set_hl(0, "NavicIconsOperator", {default = true, bg = "#000000", fg = "#ffffff"})
vim.api.nvim_set_hl(0, "NavicIconsTypeParameter", {default = true, bg = "#000000", fg = "#ffffff"})
vim.api.nvim_set_hl(0, "NavicText", {default = true, bg = "#000000", fg = "#ffffff"})
vim.api.nvim_set_hl(0, "NavicSeparator", {default = true, bg = "#000000", fg = "#ffffff"})
```
</details>
If you have a font patched with [codicon.ttf](https://github.com/microsoft/vscode-codicons/raw/main/dist/codicon.ttf), you can replicate the look of VSCode breadcrumbs using the following icons
<details>
<summary>VSCode like icons</summary>
```lua
navic.setup {
icons = {
File = ' ',
Module = ' ',
Namespace = ' ',
Package = ' ',
Class = ' ',
Method = ' ',
Property = ' ',
Field = ' ',
Constructor = ' ',
Enum = ' ',
Interface = ' ',
Function = ' ',
Variable = ' ',
Constant = ' ',
String = ' ',
Number = ' ',
Boolean = ' ',
Array = ' ',
Object = ' ',
Key = ' ',
Null = ' ',
EnumMember = ' ',
Struct = ' ',
Event = ' ',
Operator = ' ',
TypeParameter = ' '
}
}
```
</details>
## 🚀 Usage
nvim-navic does not alter your statusline or winbar on its own. Instead, you are provided with these two functions and its left up to you how you want to incorporate this into your setup.
* `is_available(bufnr)` : Returns boolean value indicating whether output can be provided. `bufnr` is optional, default is current.
* `get_location(opts, bufnr)` : Returns a pretty string with context information. Using `opts` table you can override any of the options, format same as the table for `setup` function. You can also provide a `bufnr` value to determine which buffer is used to get the code context information, if not provided the current buffer will be used.
<details>
<summary><h3>Examples</h3></summary>
### Native method
<details>
<summary>Lua</summary>
```lua
vim.o.statusline = "%{%v:lua.require'nvim-navic'.get_location()%}"
-- OR
vim.o.winbar = "%{%v:lua.require'nvim-navic'.get_location()%}"
```
</details>
<details>
<summary>Vimscript</summary>
```vim
set statusline+=%{%v:lua.require'nvim-navic'.get_location()%}
" OR
set winbar+=%{%v:lua.require'nvim-navic'.get_location()%}
```
</details>
### [feline](https://github.com/feline-nvim/feline.nvim)
<details>
<summary>An example feline setup </summary>
```lua
local navic = require("nvim-navic")
table.insert(components.active[1], {
provider = function()
return navic.get_location()
end,
enabled = function()
return navic.is_available()
end
})
require("feline").setup({components = components})
-- OR
require("feline").winbar.setup({components = components})
```
</details>
### [lualine](https://github.com/nvim-lualine/lualine.nvim)
<details>
<summary>An example lualine setup </summary>
```lua
local navic = require("nvim-navic")
require("lualine").setup({
sections = {
lualine_c = {
{
"navic",
-- Component specific options
color_correction = nil, -- Can be nil, "static" or "dynamic". This option is useful only when you have highlights enabled.
-- Many colorschemes don't define same backgroud for nvim-navic as their lualine statusline backgroud.
-- Setting it to "static" will perform a adjustment once when the component is being setup. This should
-- be enough when the lualine section isn't changing colors based on the mode.
-- Setting it to "dynamic" will keep updating the highlights according to the current modes colors for
-- the current section.
navic_opts = nil -- lua table with same format as setup's option. All options except "lsp" options take effect when set here.
}
}
},
-- OR in winbar
winbar = {
lualine_c = {
{
"navic",
color_correction = nil,
navic_opts = nil
}
}
}
})
-- OR a more hands on approach
require("lualine").setup({
sections = {
lualine_c = {
{
function()
return navic.get_location()
end,
cond = function()
return navic.is_available()
end
},
}
},
-- OR in winbar
winbar = {
lualine_c = {
{
function()
return navic.get_location()
end,
cond = function()
return navic.is_available()
end
},
}
}
})
```
</details>
### [galaxyline](https://github.com/glepnir/galaxyline.nvim)
<details>
<summary>An example galaxyline setup </summary>
```lua
local navic = require("nvim-navic")
local gl = require("galaxyline")
gl.section.right[1]= {
nvimNavic = {
provider = function()
return navic.get_location()
end,
condition = function()
return navic.is_available()
end
}
}
```
</details>
</details>
If you have a creative use case and want the raw context data to work with, you can use the following function
* `get_data(bufnr)` : Returns a table of intermediate representation of data. Table of tables that contain 'kind', 'name' and 'icon' for each context. `bufnr` is optional argument, defaults to current buffer.
<details>
<summary>An example output of <code>get_data</code> function: </summary>
```lua
{
{
name = "myclass",
type = "Class",
icon = "󰌗 ",
kind = 5,
scope = {
start = { line = 1, character = 0 },
end = { line = 10, character = 0 }
}
},
{
name = "mymethod",
type = "Method",
icon = "󰆧 ",
kind = 6,
scope = {
start = { line = 2, character = 4 },
end = { line = 5, character = 4 }
}
}
}
```
</details>
If you work with raw context data, you may want to render a modified version of it. In order to ensure a consistent format with `get_location`, you may use the following function:
* `format_data(data, opts)` : Returns a pretty string (with the same format as `get_location`) with the context information provided in `data`. Using `opts` table you can override any of the options, format same as the table for setup function. If the `opts` parameter is omitted, the globally configured options are used.
<details>
<summary>An example usage of <code>format_data</code>:</summary>
Consider the scenario of working in deeply nested namespaces. Typically, just the namespace names will occupy quite some space in your statusline. With the following snippet, nested namespace names are truncated and combined into a single component:
```lua
-- Customized navic.get_location() that combines namespaces into a single string.
-- Example: `adam::bob::charlie > foo` is transformed into `a::b::charlie > foo`
function()
local navic = require("nvim-navic")
local old_data = navic.get_data()
local new_data = {}
local cur_ns = nil
local ns_comps = {}
for _, comp in ipairs(old_data) do
if comp.type == "Namespace" then
cur_ns = comp
table.insert(ns_comps, comp.name)
else
-- On the first non-namespace component $c$, collect
-- previous NS components into a single one and
-- insert it in front of $c$.
if cur_ns ~= nil then
-- Concatenate name and insert
local num_comps = #ns_comps
local comb_name = ""
for idx = 1, num_comps do
local ns_name = ns_comps[idx]
-- No "::" in front of first component
local join = (idx == 1) and "" or "::"
if idx ~= num_comps then
comb_name = comb_name .. join .. ns_name:sub(1, 1)
else
comb_name = comb_name .. join .. ns_name
end
end
cur_ns.name = comb_name
table.insert(new_data, cur_ns)
cur_ns = nil
end
table.insert(new_data, comp)
end
end
return navic.format_data(new_data)
end
```
</details>

View File

@ -0,0 +1,339 @@
*nvim-navic* *navic*
A simple statusline/winbar component that shows your current code context.
Named after the Indian satellite navigation system.
Requires :
- nvim-lspconfig: `https://github.com/neovim/nvim-lspconfig`
- Neovim: 0.7 or above
=============================================================================
CONTENTS *navic-components*
API |navic-api|
Usage |navic-usage|
Variables |navic-variables|
Customisation |navic-customise|
Highlights |navic-highlights|
=============================================================================
API *navic-api*
|nvim-navic| provides the following functions for the user.
*navic.setup* (opts)
Configure |nvim-navic|'s options. See more |navic-configuration|.
*navic.attach* (client, bufnr)
Used to attach |nvim-navic| to lsp server. Pass this function as
on_attach while setting up your desired lsp server.
*navic.is_available* (bufnr)
Returns boolean value indicating whether |nvim-navic| is able to provide
output for current buffer.
'bufnr' is optional argument. If bufnr is not provied, current open
buffer is used.
*navic.get_location* (opts, bufnr)
Returns a pretty string that shows code context and can be used directly
in statusline or winbar.
opts table can be passed to override any of |nvim-navic|'s options.
Follows same table format as |navic-setup|'s opts table. You can pass
|bufnr| value to determine which buffer is used to get code context. If
not provided, the current buffer will be used.
*navic.get_data* (bufnr)
Returns a table of tables representing the current code context. Contains
information about the symbol's name, kind, type, scope and its icon at
each level. Relation between type and kind is defiend on LSP's website.
`https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#symbolKind`
'bufnr' is optional argument. If bufnr is not provied, current open
buffer is used.
*navic.format_data* (data, opts)
Formats data of the type returned by |navic.get_data| for use in the
statusline or winbar. This can be used to modify the raw data before
formatting it.
|opts| table can be passed to override any of |nvim-navic|'s options.
Follows same table format as |navic-setup|'s opts table.
=============================================================================
Usage *navic-usage*
|nvim-navic| needs to be attached to lsp servers of the buffer to work. Use the
|navic.attach| function while setting up lsp servers. You can skip this step
if you have enabled auto_attach option during setup.
NOTE: You can attach to only one lsp server per buffer.
Example: >lua
require("lspconfig").clangd.setup {
on_attach = function(client, bufnr)
navic.attach(client, bufnr)
end
}
<
Next you can use |nvim-navic| in your statusline or winbar with your
favorite statusline/winbar plugins.
Example setup with lualine.nvim `https://github.com/nvim-lualine/lualine.nvim`:
>lua
local navic = require("nvim-navic")
require("lualine").setup({
sections = {
lualine_c = {
"navic",
-- Component specific options
color_correction = nil, -- Can be nil, "static" or "dynamic". This option is useful only when you have highlights enabled.
-- Many colorschemes don't define same backgroud for nvim-navic as their lualine statusline backgroud.
-- Setting it to "static" will perform a adjustment once when the component is being setup. This should
-- be enough when the lualine section isn't changing colors based on the mode.
-- Setting it to "dynamic" will keep updating the highlights according to the current modes colors for
-- the current section.
navic_opts = nil -- lua table with same format as setup's option. All options except "lsp" options take effect when set here.
}
},
-- OR in winbar
winbar = {
lualine_c = {
"navic",
color_correction = nil,
navic_opts = nil
}
}
})
-- OR a more hands on approach
require("lualine").setup({
sections = {
lualine_c = {
{
function()
return navic.get_location()
end,
cond = function()
return navic.is_available()
end
},
}
},
-- OR in winbar
winbar = {
lualine_c = {
{
function()
return navic.get_location()
end,
cond = function()
return navic.is_available()
end
},
}
}
})
<
Example setup with feline.nvim `https://github.com/feline-nvim/feline.nvim`:
Statusline: >lua
local navic = require("nvim-navic")
local components = {
active = {{}, {}, {}},
}
table.insert(components.active[1], {
provider = function()
return navic.get_location()
end,
enabled = function() return navic.is_available() end,
})
require("feline").setup({
components = components
})
<
Winbar: >lua
local navic = require("nvim-navic")
local components = {
active = {{}, {}, {}},
}
table.insert(components.active[1], {
provider = function()
return navic.get_location()
end,
enabled = function() return navic.is_available() end,
})
require("feline").winbar.setup({
components = components
})
<
You can silence warning/error messages thrown by |nvim-navic| by setting
>lua
vim.g.navic_silence = true.
<
at the start of your config. However this is not advisable, the error
messages indicate issues in your setup.
=============================================================================
Variables *navic-variables*
*vim.g.navic_silence*
Set it to true to silence the any warnings/error messages thrown by nvim-navic
*vim.b.navic_lazy_update_context*
Set it to true to update context only on CursorHold event. Could be usefull if
you are facing performance issues on large files. Example usage
>lua
vim.api.nvim_create_autocmd("BufEnter", {
callback = function()
if vim.api.nvim_buf_line_count(0) > 10000 then
vim.b.navic_lazy_update_context = true
end
end,
})
<
=============================================================================
Customisation *navic-customise*
Use |navic.setup| to override any of the default options
icons: table
Icons to show for captured symbols. Default icons assume that you
have nerd-font.
highlight: boolean
Add colors to icons and text as defined by highlight groups
NavicIcons* (NavicIconsFile, NavicIconsModule.. etc.), NavicText and
NavicSeparator.
separator: string
Icon to be used to separate two symbols.
depth_limit: integer
Maximum depth of context to be shown. If the context depth exceeds
this parameter, context information is truncated. default is infinite
depth_limit_indicator: string
Indicator signifing that displayed string is truncated.
safe_output: boolean
Sanitize the output for use in statusline and winbar.
click: boolean
Single click to goto element, double click to open nvim-navbuddy on
the clicked element.
lazy_update_context: boolean
If true, turns off context updates for the "CursorMoved" event,
updates will only happen on the "CursorHold" event. The
difference between this option and the vim.b.navic_lazy_update_context
variable is that this option turns off context updates on the
"CursorMoved" completely for all buffers, whereas the
vim.b.navic_lazy_update_context variable allows you to control that
behavior with more flexibility, like disabling context updates
depending on file size, total lines etc.
lsp :
auto_attach: boolean
Enable to have nvim-navic automatically attach to every LSP for
current buffer. Its disabled by default.
preference: table
Table ranking lsp_servers. Lower the index, higher the priority of
the server. If there are more than one server attached to a
buffer, nvim-navic will refer to this list to make a decision on
which one to use.
For example - In case a buffer is attached to clangd and ccls both
and the preference list is `{ "clangd", "pyright" }`. Then clangd
will be preferred.
Defaults >lua
navic.setup {
icons = {
File = "󰈙 ",
Module = " ",
Namespace = "󰌗 ",
Package = " ",
Class = "󰌗 ",
Method = "󰆧 ",
Property = " ",
Field = " ",
Constructor = " ",
Enum = "󰕘",
Interface = "󰕘",
Function = "󰊕 ",
Variable = "󰆧 ",
Constant = "󰏿 ",
String = "󰀬 ",
Number = "󰎠 ",
Boolean = "◩ ",
Array = "󰅪 ",
Object = "󰅩 ",
Key = "󰌋 ",
Null = "󰟢 ",
EnumMember = " ",
Struct = "󰌗 ",
Event = " ",
Operator = "󰆕 ",
TypeParameter = "󰊄 ",
},
lsp = {
auto_attach = false,
preference = nil,
},
highlight = false,
separator = " > ",
depth_limit = 0,
depth_limit_indicator = "..",
safe_output = true,
lazy_update_context = false,
click = false
}
<
=============================================================================
Highlight *navic-highlights*
|nvim-navic| provides the following highlights which get used when highlight
option is set to `true`.
`NavicIconsFile`
`NavicIconsModule`
`NavicIconsNamespace`
`NavicIconsPackage`
`NavicIconsClass`
`NavicIconsMethod`
`NavicIconsProperty`
`NavicIconsField`
`NavicIconsConstructor`
`NavicIconsEnum`
`NavicIconsInterface`
`NavicIconsFunction`
`NavicIconsVariable`
`NavicIconsConstant`
`NavicIconsString`
`NavicIconsNumber`
`NavicIconsBoolean`
`NavicIconsArray`
`NavicIconsObject`
`NavicIconsKey`
`NavicIconsNull`
`NavicIconsEnumMember`
`NavicIconsStruct`
`NavicIconsEvent`
`NavicIconsOperator`
`NavicIconsTypeParameter`
`NavicText`
`NavicSeparator`
=============================================================================
vim:tw=78:ts=4:ft=help:norl:

View File

@ -0,0 +1,54 @@
local navic = require("nvim-navic")
local navic_lib = require("nvim-navic.lib")
local M = require("lualine.component"):extend()
local utils = require("lualine.utils.utils")
local highlight = require("lualine.highlight")
local default_options = {
cond = function()
return navic.is_available()
end,
color_correction = nil,
navic_opts = nil
}
local function adjust_hl(section)
local lualine_bg = utils.extract_highlight_colors("lualine_" .. section .. highlight.get_mode_suffix(), "bg")
local lualine_fg = utils.extract_highlight_colors("lualine_" .. section .. highlight.get_mode_suffix(), "fg")
local text_hl = utils.extract_highlight_colors("NavicText")
if text_hl ~= nil and (text_hl.bg ~= lualine_bg or text_hl.fg ~= lualine_fg) then
highlight.highlight("NavicText", lualine_fg, lualine_bg)
end
local sep_hl = utils.extract_highlight_colors("NavicSeparator")
if sep_hl ~= nil and (sep_hl.bg ~= lualine_bg or sep_hl.fg ~= lualine_fg) then
highlight.highlight("NavicSeparator", lualine_fg, lualine_bg)
end
for i = 1, 26, 1 do
local hl_name = "NavicIcons"..navic_lib.adapt_lsp_num_to_str(i)
local hl = utils.extract_highlight_colors(hl_name)
if hl ~= nil and hl.bg ~= lualine_bg then
highlight.highlight(hl_name, hl.fg, lualine_bg)
end
end
end
M.init = function(self, options)
M.super.init(self, options)
self.options = vim.tbl_deep_extend("keep", self.options or {}, default_options)
if self.options.color_correction == "static" then
adjust_hl(self.options.self.section)
end
end
M.update_status = function(self)
if self.options.color_correction == "dynamic" then
adjust_hl(self.options.self.section)
end
return navic.get_location(self.options.navic_opts)
end
return M

View File

@ -0,0 +1,401 @@
local lib = require("nvim-navic.lib")
---@class LspOptions
---@field auto_attach boolean
---@field preference table | nil
---@class Options
---@field icons table | nil
---@field highlight boolean | nil
---@field format_text function | nil
---@field depth_limit number | nil
---@field depth_limit_indicator string | nil
---@field lazy_update_context boolean | nil
---@field safe_output boolean | nil
---@field click boolean | nil
---@field lsp LspOptions | nil
-- @Public Methods
local M = {}
---@type Options
local config = {
icons = {
[1] = "󰈙 ", -- File
[2] = "", -- Module
[3] = "󰌗 ", -- Namespace
[4] = "", -- Package
[5] = "󰌗 ", -- Class
[6] = "󰆧 ", -- Method
[7] = "", -- Property
[8] = "", -- Field
[9] = "", -- Constructor
[10] = "󰕘 ", -- Enum
[11] = "󰕘 ", -- Interface
[12] = "󰊕 ", -- Function
[13] = "󰆧 ", -- Variable
[14] = "󰏿 ", -- Constant
[15] = "󰀬 ", -- String
[16] = "󰎠 ", -- Number
[17] = "", -- Boolean
[18] = "󰅪 ", -- Array
[19] = "󰅩 ", -- Object
[20] = "󰌋 ", -- Key
[21] = "󰟢 ", -- Null
[22] = "", -- EnumMember
[23] = "󰌗 ", -- Struct
[24] = "", -- Event
[25] = "󰆕 ", -- Operator
[26] = "󰊄 ", -- TypeParameter
[255] = "󰉨 ", -- Macro
},
highlight = false,
separator = " > ",
depth_limit = 0,
depth_limit_indicator = "..",
safe_output = true,
lazy_update_context = false,
click = false,
lsp = {
auto_attach = false,
preference = nil
},
format_text = function(a) return a end,
}
setmetatable(config.icons, {
__index = function()
return "? "
end,
})
local function setup_auto_attach(opts)
vim.api.nvim_create_autocmd("LspAttach", {
callback = function(args)
local client = vim.lsp.get_client_by_id(args.data.client_id)
if not client.server_capabilities.documentSymbolProvider then
return
end
local prev_client = vim.b[args.buf].navic_client_name
if not prev_client or prev_client == client.name then
return M.attach(client, args.buf)
end
if not opts.lsp.preference then
return vim.notify(
"nvim-navic: Trying to attach "
.. client.name
.. " for current buffer. Already attached to "
.. prev_client
.. ". Please use the preference option to set a higher preference for one of the servers",
vim.log.levels.WARN
)
end
for _, preferred_lsp in ipairs(opts.lsp.preference) do
-- If new client comes first, then remove the previous
-- attached server and attatch the new one
if preferred_lsp == client.name then
vim.b[args.buf].navic_client_id = nil
vim.b[args.buf].navic_client_name = nil
return M.attach(client, args.buf)
elseif preferred_lsp == prev_client then
-- If the previous attached server comes first, it
-- has higher priority over the one trying to attach
return
end
end
end,
})
end
---@param opts Options
function M.setup(opts)
if opts == nil then
return
end
if opts.lsp ~= nil and opts.lsp.auto_attach then
setup_auto_attach(opts)
end
if opts.icons ~= nil then
for k, v in pairs(opts.icons) do
if lib.adapt_lsp_str_to_num(k) then
config.icons[lib.adapt_lsp_str_to_num(k)] = v
end
end
end
if opts.separator ~= nil then
config.separator = opts.separator
end
if opts.depth_limit ~= nil then
config.depth_limit = opts.depth_limit
end
if opts.depth_limit_indicator ~= nil then
config.depth_limit_indicator = opts.depth_limit_indicator
end
if opts.highlight ~= nil then
config.highlight = opts.highlight
end
if opts.safe_output ~= nil then
config.safe_output = opts.safe_output
end
if opts.lazy_update_context then
config.lazy_update_context = opts.lazy_update_context
end
if opts.click then
config.click = opts.click
end
if opts.format_text then
vim.validate({ format_text = { opts.format_text, "f" } })
config.format_text = opts.format_text
end
end
-- returns table of context or nil
function M.get_data(bufnr)
bufnr = bufnr or vim.api.nvim_get_current_buf()
local context_data = lib.get_context_data(bufnr)
if context_data == nil then
return nil
end
local ret = {}
for i, v in ipairs(context_data) do
if i ~= 1 then
table.insert(ret, {
kind = v.kind,
type = lib.adapt_lsp_num_to_str(v.kind),
name = v.name,
icon = config.icons[v.kind],
scope = v.scope,
})
end
end
return ret
end
function M.is_available(bufnr)
bufnr = bufnr or vim.api.nvim_get_current_buf()
return vim.b[bufnr].navic_client_id ~= nil
end
function M.format_data(data, opts)
if data == nil then
return ""
end
local local_config = {}
if opts ~= nil then
local_config = vim.deepcopy(config)
if opts.icons ~= nil then
for k, v in pairs(opts.icons) do
if lib.adapt_lsp_str_to_num(k) then
local_config.icons[lib.adapt_lsp_str_to_num(k)] = v
end
end
end
if opts.separator ~= nil then
local_config.separator = opts.separator
end
if opts.depth_limit ~= nil then
local_config.depth_limit = opts.depth_limit
end
if opts.depth_limit_indicator ~= nil then
local_config.depth_limit_indicator = opts.depth_limit_indicator
end
if opts.highlight ~= nil then
local_config.highlight = opts.highlight
end
if opts.safe_output ~= nil then
local_config.safe_output = opts.safe_output
end
if opts.click ~= nil then
local_config.click = opts.click
end
else
local_config = config
end
local location = {}
local function add_hl(kind, name)
return "%#NavicIcons"
.. lib.adapt_lsp_num_to_str(kind)
.. "#"
.. local_config.icons[kind]
.. "%*%#NavicText#"
.. config.format_text(name)
.. "%*"
end
if local_config.click then
_G.navic_click_handler = function(minwid, cnt, _, _)
vim.cmd("normal! m'")
vim.api.nvim_win_set_cursor(0, {
data[minwid].scope["start"].line,
data[minwid].scope["start"].character
})
if cnt > 1 then
local ok, navbuddy = pcall(require, "nvim-navbuddy")
if ok then
navbuddy.open(bufnr)
else
vim.notify("nvim-navic: Double click requires nvim-navbuddy to be installed.", vim.log.levels.WARN)
end
end
end
end
local function add_click(level, component)
return "%"
.. level
.. "@v:lua.navic_click_handler@"
.. component
.. "%X"
end
for i, v in ipairs(data) do
local name = ""
if local_config.safe_output then
name = string.gsub(v.name, "%%", "%%%%")
name = string.gsub(name, "\n", " ")
else
name = v.name
end
local component
if local_config.highlight then
component = add_hl(v.kind, name)
else
component = v.icon .. name
end
if local_config.click then
component = add_click(i, component)
end
table.insert(location, component)
end
if local_config.depth_limit ~= 0 and #location > local_config.depth_limit then
location = vim.list_slice(location, #location - local_config.depth_limit + 1, #location)
if local_config.highlight then
table.insert(location, 1, "%#NavicSeparator#" .. local_config.depth_limit_indicator .. "%*")
else
table.insert(location, 1, local_config.depth_limit_indicator)
end
end
local ret = ""
if local_config.highlight then
ret = table.concat(location, "%#NavicSeparator#" .. local_config.separator .. "%*")
else
ret = table.concat(location, local_config.separator)
end
return ret
end
function M.get_location(opts, bufnr)
local data = M.get_data(bufnr)
return M.format_data(data, opts)
end
local awaiting_lsp_response = {}
local function lsp_callback(for_buf, symbols)
awaiting_lsp_response[for_buf] = false
lib.update_data(for_buf, symbols)
end
function M.attach(client, bufnr)
if not client.server_capabilities.documentSymbolProvider then
if not vim.g.navic_silence then
vim.notify(
'nvim-navic: Server "' .. client.name .. '" does not support documentSymbols.',
vim.log.levels.ERROR
)
end
return
end
if vim.b[bufnr].navic_client_id ~= nil and vim.b[bufnr].navic_client_name ~= client.name then
local prev_client = vim.b[bufnr].navic_client_name
if not vim.g.navic_silence then
vim.notify(
"nvim-navic: Failed to attach to "
.. client.name
.. " for current buffer. Already attached to "
.. prev_client,
vim.log.levels.WARN
)
end
return
end
vim.b[bufnr].navic_client_id = client.id
vim.b[bufnr].navic_client_name = client.name
local changedtick = 0
local navic_augroup = vim.api.nvim_create_augroup("navic", { clear = false })
vim.api.nvim_clear_autocmds({
buffer = bufnr,
group = navic_augroup,
})
vim.api.nvim_create_autocmd({ "InsertLeave", "BufEnter", "CursorHold" }, {
callback = function()
if not awaiting_lsp_response[bufnr] and changedtick < vim.b[bufnr].changedtick then
awaiting_lsp_response[bufnr] = true
changedtick = vim.b[bufnr].changedtick
lib.request_symbol(bufnr, lsp_callback, client)
end
end,
group = navic_augroup,
buffer = bufnr,
})
vim.api.nvim_create_autocmd("CursorHold", {
callback = function()
lib.update_context(bufnr)
end,
group = navic_augroup,
buffer = bufnr,
})
if not config.lazy_update_context then
vim.api.nvim_create_autocmd("CursorMoved", {
callback = function()
if vim.b.navic_lazy_update_context ~= true then
lib.update_context(bufnr)
end
end,
group = navic_augroup,
buffer = bufnr,
})
end
vim.api.nvim_create_autocmd("BufDelete", {
callback = function()
lib.clear_buffer_data(bufnr)
end,
group = navic_augroup,
buffer = bufnr,
})
-- First call
vim.b[bufnr].navic_awaiting_lsp_response = true
lib.request_symbol(bufnr, lsp_callback, client)
end
return M

View File

@ -0,0 +1,451 @@
-- @Private Methods
-- relation of 'other' with repect to 'symbol'
local function symbol_relation(symbol, other)
local s = symbol.scope
local o = other.scope
if
o["end"].line < s["start"].line
or (o["end"].line == s["start"].line and o["end"].character <= s["start"].character)
then
return "before"
end
if
o["start"].line > s["end"].line
or (o["start"].line == s["end"].line and o["start"].character >= s["end"].character)
then
return "after"
end
if
(
o["start"].line < s["start"].line
or (o["start"].line == s["start"].line and o["start"].character <= s["start"].character)
)
and (
o["end"].line > s["end"].line
or (o["end"].line == s["end"].line and o["end"].character >= s["end"].character)
)
then
return "around"
end
return "within"
end
-- Construct tree structure based on scope information
-- Could be inaccurate ?? Not intended to be used like this...
local function symbolInfo_treemaker(symbols, root_node)
-- convert location to scope
for _, node in ipairs(symbols) do
node.scope = node.location.range
node.scope["start"].line = node.scope["start"].line + 1
node.scope["end"].line = node.scope["end"].line + 1
node.location = nil
node.name_range = node.scope
node.containerName = nil
end
-- sort with repect to node height and location
-- nodes closer to root node come before others
-- nodes and same level are arranged according to scope
table.sort(symbols, function(a, b)
local loc = symbol_relation(a, b)
if loc == "after" or loc == "within" then
return true
end
return false
end)
-- root node
root_node.children = {}
local stack = {}
table.insert(root_node.children, symbols[1])
symbols[1].parent = root_node
table.insert(stack, root_node)
-- build tree
for i = 2, #symbols, 1 do
local prev_chain_node_relation = symbol_relation(symbols[i], symbols[i - 1])
local stack_top_node_relation = symbol_relation(symbols[i], stack[#stack])
if prev_chain_node_relation == "around" then
-- current node is child node of previous chain node
table.insert(stack, symbols[i - 1])
if not symbols[i - 1].children then
symbols[i - 1].children = {}
end
table.insert(symbols[i - 1].children, symbols[i])
symbols[i].parent = symbols[i-1]
elseif prev_chain_node_relation == "before" and stack_top_node_relation == "around" then
-- the previous symbol comes before this one and the current node
-- is child of stack_top node. Add this symbol as child of stack_top
table.insert(stack[#stack].children, symbols[i])
symbols[i].parent = stack[#stack]
elseif stack_top_node_relation == "before" then
-- the stack_top node comes before this symbol; pop nodes off the stack to
-- find the parent of this symbol and add this symbol as its child
while symbol_relation(symbols[i], stack[#stack]) ~= "around" do
stack[#stack] = nil
end
table.insert(stack[#stack].children, symbols[i])
symbols[i].parent = stack[#stack]
end
end
local function dfs_index(node)
if node.children == nil then
return
end
for i = 1, #node.children, 1 do
node.children[i].index = i
dfs_index(node.children[i])
end
-- Set next, prev relations
for i = 1, #node.children, 1 do
local curr_node = node.children[i]
if i ~= 1 then
local prev_node = node.children[i-1]
prev_node.next = curr_node
curr_node.prev = prev_node
end
if node.children[i+1] ~= nil then
local next_node = node.children[i+1]
next_node.prev = curr_node
curr_node.next = next_node
end
end
end
dfs_index(root_node)
end
local function dfs(curr_symbol_layer, parent_node)
if #curr_symbol_layer == 0 then
return
end
parent_node.children = {}
for _, val in ipairs(curr_symbol_layer) do
local scope = val.range
scope["start"].line = scope["start"].line + 1
scope["end"].line = scope["end"].line + 1
local name_range = val.selectionRange
name_range["start"].line = name_range["start"].line + 1
name_range["end"].line = name_range["end"].line + 1
local curr_parsed_symbol = {
name = val.name or "<???>",
scope = scope,
name_range = name_range,
kind = val.kind or 0,
parent = parent_node
}
if val.children then
dfs(val.children, curr_parsed_symbol)
end
table.insert(parent_node.children, curr_parsed_symbol)
end
table.sort(parent_node.children, function(a, b)
if b.scope.start.line == a.scope.start.line then
return b.scope.start.character > a.scope.start.character
end
return b.scope.start.line > a.scope.start.line
end)
for i = 1, #parent_node.children, 1 do
parent_node.children[i].prev = parent_node.children[i-1]
parent_node.children[i].next = parent_node.children[i+1]
parent_node.children[i].index = i
end
end
local function in_range(cursor_pos, range)
-- -1 = behind
-- 0 = in range
-- 1 = ahead
local line = cursor_pos[1]
local char = cursor_pos[2]
if line < range["start"].line then
return -1
elseif line > range["end"].line then
return 1
end
if line == range["start"].line and char < range["start"].character then
return -1
elseif line == range["end"].line and char > range["end"].character then
return 1
end
return 0
end
-- @Public Methods
local M = {}
-- Process raw data from lsp server into Tree structure
-- Node
-- * is_root : boolean
-- * name : string
-- * scope : table { start = {line = ., character = .}, end = {line = ., character = .}}
-- * name_range : table same as scope
-- * kind : int [1-26]
-- * index : int, index among siblings
-- * parent : pointer to parent node
-- * prev : pointer to previous sibling node
-- * next : pointer to next sibling node
function M.parse(symbols)
local root_node = {
is_root = true,
index = 1,
scope = {
start = {
line = -10,
character = 0,
},
["end"] = {
line = 2147483640,
character = 0,
},
}
}
-- detect type
if #symbols >= 1 and symbols[1].range == nil then
symbolInfo_treemaker(symbols, root_node)
else
dfs(symbols, root_node)
end
return root_node
end
-- Make request to lsp server
function M.request_symbol(for_buf, handler, client, file_uri, retry_count)
local textDocument_argument = vim.lsp.util.make_text_document_params()
if retry_count == nil then
retry_count = 10
elseif retry_count == 0 then
handler(for_buf, {})
return
end
if file_uri ~= nil then
textDocument_argument = {
textDocument = {
uri = file_uri
}
}
end
if not vim.api.nvim_buf_is_loaded(for_buf) then
return
end
client.request("textDocument/documentSymbol", { textDocument = textDocument_argument }, function(err, symbols, _)
if symbols == nil then
if vim.api.nvim_buf_is_valid(for_buf) then
handler(for_buf, {})
end
elseif err ~= nil then
if vim.api.nvim_buf_is_valid(for_buf) then
vim.defer_fn(function()
M.request_symbol(for_buf, handler, client, file_uri, retry_count-1)
end, 750)
end
elseif symbols ~= nil then
if vim.api.nvim_buf_is_loaded(for_buf) then
handler(for_buf, symbols)
end
end
end, for_buf)
end
local navic_symbols = {}
local navic_context_data = {}
function M.get_tree(bufnr)
return navic_symbols[bufnr]
end
function M.get_context_data(bufnr)
return navic_context_data[bufnr]
end
function M.clear_buffer_data(bufnr)
navic_context_data[bufnr] = nil
navic_symbols[bufnr] = nil
end
function M.update_data(for_buf, symbols)
navic_symbols[for_buf] = M.parse(symbols)
end
function M.update_context(for_buf, arg_cursor_pos)
local cursor_pos = arg_cursor_pos ~= nil and arg_cursor_pos or vim.api.nvim_win_get_cursor(0)
if navic_context_data[for_buf] == nil then
navic_context_data[for_buf] = {}
end
local old_context_data = navic_context_data[for_buf]
local new_context_data = {}
local curr = navic_symbols[for_buf]
if curr == nil then
return
end
-- Always keep root node
if curr.is_root then
table.insert(new_context_data, curr)
end
-- Find larger context that remained same
for _, context in ipairs(old_context_data) do
if curr == nil then
break
end
if
in_range(cursor_pos, context.scope) == 0
and curr.children ~= nil
and curr.children[context.index] ~= nil
and context.name == curr.children[context.index].name
and context.kind == curr.children[context.index].kind
then
table.insert(new_context_data, curr.children[context.index])
curr = curr.children[context.index]
else
break
end
end
-- Fill out context_data
while curr.children ~= nil do
local go_deeper = false
local l = 1
local h = #curr.children
while l <= h do
local m = bit.rshift(l + h, 1)
local comp = in_range(cursor_pos, curr.children[m].scope)
if comp == -1 then
h = m - 1
elseif comp == 1 then
l = m + 1
else
table.insert(new_context_data, curr.children[m])
curr = curr.children[m]
go_deeper = true
break
end
end
if not go_deeper then
break
end
end
navic_context_data[for_buf] = new_context_data
end
-- stylua: ignore
local lsp_str_to_num = {
File = 1,
Module = 2,
Namespace = 3,
Package = 4,
Class = 5,
Method = 6,
Property = 7,
Field = 8,
Constructor = 9,
Enum = 10,
Interface = 11,
Function = 12,
Variable = 13,
Constant = 14,
String = 15,
Number = 16,
Boolean = 17,
Array = 18,
Object = 19,
Key = 20,
Null = 21,
EnumMember = 22,
Struct = 23,
Event = 24,
Operator = 25,
TypeParameter = 26,
}
setmetatable(lsp_str_to_num, {
__index = function()
return 0
end,
})
function M.adapt_lsp_str_to_num(s)
return lsp_str_to_num[s]
end
-- stylua: ignore
local lsp_num_to_str = {
[1] = "File",
[2] = "Module",
[3] = "Namespace",
[4] = "Package",
[5] = "Class",
[6] = "Method",
[7] = "Property",
[8] = "Field",
[9] = "Constructor",
[10] = "Enum",
[11] = "Interface",
[12] = "Function",
[13] = "Variable",
[14] = "Constant",
[15] = "String",
[16] = "Number",
[17] = "Boolean",
[18] = "Array",
[19] = "Object",
[20] = "Key",
[21] = "Null",
[22] = "EnumMember",
[23] = "Struct",
[24] = "Event",
[25] = "Operator",
[26] = "TypeParameter",
}
setmetatable(lsp_num_to_str, {
__index = function()
return "Text"
end,
})
function M.adapt_lsp_num_to_str(n)
return lsp_num_to_str[n]
end
return M