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,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