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,21 @@
MIT License
Copyright (c) 2022-2023 Chinmay Dalal
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

View File

@ -0,0 +1,202 @@
![clangd](https://user-images.githubusercontent.com/36493671/152692205-837ec826-54d0-4257-9894-cc1a7ac8a114.svg)
Requires Neovim 0.7+
## Installation
Install this plugin using any plugin/package manager or see [`:h packages`](https://neovim.io/doc/user/repeat.html#packages)
## Configuration:
Set up clangd via lspconfig/vim.lsp.start, as usual.
You don't need to call `require("clangd_extensions").setup` if you like the defaults:
```lua
require("clangd_extensions").setup({
inlay_hints = {
inline = vim.fn.has("nvim-0.10") == 1,
-- Options other than `highlight' and `priority' only work
-- if `inline' is disabled
-- Only show inlay hints for the current line
only_current_line = false,
-- Event which triggers a refresh of the inlay hints.
-- You can make this { "CursorMoved" } or { "CursorMoved,CursorMovedI" } but
-- note that this may cause higher CPU usage.
-- This option is only respected when only_current_line is true.
only_current_line_autocmd = { "CursorHold" },
-- whether to show parameter hints with the inlay hints or not
show_parameter_hints = true,
-- prefix for parameter hints
parameter_hints_prefix = "<- ",
-- prefix for all the other hints (type, chaining)
other_hints_prefix = "=> ",
-- whether to align to the length of the longest line in the file
max_len_align = false,
-- padding from the left if max_len_align is true
max_len_align_padding = 1,
-- whether to align to the extreme right or not
right_align = false,
-- padding from the right if right_align is true
right_align_padding = 7,
-- The color of the hints
highlight = "Comment",
-- The highlight group priority for extmark
priority = 100,
},
ast = {
-- These are unicode, should be available in any font
role_icons = {
type = "🄣",
declaration = "🄓",
expression = "🄔",
statement = ";",
specifier = "🄢",
["template argument"] = "🆃",
},
kind_icons = {
Compound = "🄲",
Recovery = "🅁",
TranslationUnit = "🅄",
PackExpansion = "🄿",
TemplateTypeParm = "🅃",
TemplateTemplateParm = "🅃",
TemplateParamObject = "🅃",
},
--[[ These require codicons (https://github.com/microsoft/vscode-codicons)
role_icons = {
type = "",
declaration = "",
expression = "",
specifier = "",
statement = "",
["template argument"] = "",
},
kind_icons = {
Compound = "",
Recovery = "",
TranslationUnit = "",
PackExpansion = "",
TemplateTypeParm = "",
TemplateTemplateParm = "",
TemplateParamObject = "",
}, ]]
highlights = {
detail = "Comment",
},
},
memory_usage = {
border = "none",
},
symbol_info = {
border = "none",
},
})
```
## Features:
### [Switch between source/header](https://clangd.llvm.org/extensions#switch-between-sourceheader)
### Usage
`:ClangdSwitchSourceHeader`
### [Inlay hints](https://clangd.llvm.org/extensions#inlay-hints)
![image](https://user-images.githubusercontent.com/36493671/152699601-61ad1640-96bf-4082-b553-75d4085c3496.png)
#### Usage
Add this to your nvim-lspconfig / `vim.lsp.start()`'s `on_attach`:
```lua
require("clangd_extensions.inlay_hints").setup_autocmd()
require("clangd_extensions.inlay_hints").set_inlay_hints()
```
You can also enable, disable or toggle the hints with `ClangdSetInlayHints`, `ClangdDisableInlayHints` and `ClangdToggleInlayHints`.
Toggling returns the current state of the hints, this is useful if you want to hook a callback when toggling inlay hints:
```lua
if require("clangd_extensions.inlay_hints").toggle_inlay_hints() then
-- Inlay hints are enabled
else
-- Inlay hints are disabled
end
```
For example if you have autocommands related to Clangd inlay hints you might want to disable/enable them when toggling inlay hints:
```lua
on_attach = function(_, buf)
local group = vim.api.nvim_create_augroup("clangd_no_inlay_hints_in_insert", { clear = true })
vim.keymap.set("n", "<leader>lh", function()
if require("clangd_extensions.inlay_hints").toggle_inlay_hints() then
vim.api.nvim_create_autocmd("InsertEnter", { group = group, buffer = buf,
callback = require("clangd_extensions.inlay_hints").disable_inlay_hints
})
vim.api.nvim_create_autocmd({ "TextChanged", "InsertLeave" }, { group = group, buffer = buf,
callback = require("clangd_extensions.inlay_hints").set_inlay_hints
})
else
vim.api.nvim_clear_autocmds({ group = group, buffer = buf })
end
end, { buffer = buf, desc = "[l]sp [h]ints toggle" })
end,
}
```
### [View AST](https://clangd.llvm.org/extensions#ast)
![image](https://user-images.githubusercontent.com/36493671/255611133-35f397d3-02f8-4d14-b70a-126be6c098fa.gif)
You can fold nodes using `zc` and friends - the AST window has `shiftwidth=2` and `foldmethod=indent`.
#### Usage
`:ClangdAST` to view the ast with the current line as the range, `:'<,'>ClangdAST` with a visual selection to view the ast with the selected lines as range.
See how ranges are handled at https://clangd.llvm.org/extensions#ast
### [Completion scores](https://clangd.llvm.org/extensions#code-completion-scores)
Usage: For nvim-cmp
```lua
local cmp = require "cmp"
cmp.setup {
-- ... rest of your cmp setup ...
sorting = {
comparators = {
cmp.config.compare.offset,
cmp.config.compare.exact,
cmp.config.compare.recently_used,
require("clangd_extensions.cmp_scores"),
cmp.config.compare.kind,
cmp.config.compare.sort_text,
cmp.config.compare.length,
cmp.config.compare.order,
},
},
}
```
### [Symbol info](https://clangd.llvm.org/extensions#symbol-info-request)
![image](https://user-images.githubusercontent.com/36493671/152699367-dc928adf-d3ed-4e8e-a9d0-ca573f01c008.png)
#### Usage
`:ClangdSymbolInfo` with the cursor at the desired symbol.
### [Type hierarchy](https://clangd.llvm.org/extensions#type-hierarchy)
![image](https://user-images.githubusercontent.com/36493671/255609950-80bebd4a-9800-432d-9f0c-5e5519eeba6f.gif)
#### Usage
`:ClangdTypeHierarchy` with the cursor over the desired type or a symbol of that type.
`gd` with the cursor over a type in a window to go to its definition.
### [Memory usage](https://clangd.llvm.org/extensions#memory-usage)
You can fold items using `zc` and friends - the memory usage window has `shiftwidth=2` and `foldmethod=indent`.
![image](https://user-images.githubusercontent.com/36493671/152699322-9e537b1a-8253-45c1-ada3-752effeac39b.png)
#### Usage
`:ClangdMemoryUsage`. Preamble can be large so it is collapsed by default, to expand it use `:ClangdMemoryUsage expand_preamble`
## Implementation status of [extensions](https://clangd.llvm.org/extensions)
☑️ Memory usage
☑️ AST
☑️ Symbol info request
☑️ Type hierarchy
☑️ Inlay hints
☑️ Switch between source/header
☑️ File status (see lsp-status.nvim)
☑️ Compilation commands (can be specified in `vim.lsp.start()`/lspconfig `init_options` and `settings`)
☑️ Code completion scores
⬜ Force diagnostics generation (not sure)
## Credits
[simrat39](https://github.com/simrat39) - the code for inlay hints was taken from [rust-tools.nvim](https://github.com/simrat39/rust-tools.nvim) with very minor changes.

View File

@ -0,0 +1,183 @@
local fmt = string.format
local api = vim.api
local conf = require("clangd_extensions.config").options.ast
local M = {}
--- node_pos[source_buf][ast_buf][linenum] = { start = start, end = end }
--- position of node in `source_buf` corresponding to line no. `linenum` in `ast_buf`
M.node_pos = {}
--- detail_pos[ast_buf][linenum] = { start = start, end = end }
--- position of `detail` in line no. `linenum` of `ast_buf`
M.detail_pos = {}
M.nsid = vim.api.nvim_create_namespace("clangd_extensions")
local function setup_hl_autocmd(source_buf, ast_buf)
local group = api.nvim_create_augroup("ClangdExtensions", {})
api.nvim_create_autocmd("CursorMoved", {
group = group,
buffer = ast_buf,
callback = function() M.update_highlight(source_buf, ast_buf) end,
})
api.nvim_create_autocmd("BufLeave", {
group = group,
buffer = ast_buf,
callback = function() M.clear_highlight(source_buf) end,
})
end
local function icon_prefix(role, kind)
if conf.kind_icons[kind] then
return conf.kind_icons[kind] .. " "
elseif conf.role_icons[role] then
return conf.role_icons[role] .. " "
else
return " "
end
end
local function describe(role, kind, detail)
local str = ""
local icon = icon_prefix(role, kind)
local detailpos = nil
str = str .. kind
if
not (
role == "expression"
or role == "statement"
or role == "declaration"
or role == "template name"
)
then
str = str .. " " .. role
end
if detail then
detailpos = {
start = string.len(str) + vim.fn.strlen(icon) + 1,
["end"] = string.len(str) + vim.fn.strlen(icon) + string.len(
detail
) + 1,
}
str = str .. " " .. detail
end
return (icon .. str), detailpos
end
local function walk_tree(node, visited, result, padding, hl_bufs)
visited[node] = true
local str, detpos = describe(node.role, node.kind, node.detail)
table.insert(result, padding .. str)
if node.detail and detpos then
M.detail_pos[hl_bufs.ast_buf][#result] = {
start = string.len(padding) + detpos.start,
["end"] = string.len(padding) + detpos["end"],
}
end
if node.range then
M.node_pos[hl_bufs.source_buf][hl_bufs.ast_buf][#result] = {
start = { node.range.start.line, node.range.start.character },
["end"] = { node.range["end"].line, node.range["end"].character },
}
end
if node.children then
for _, child in pairs(node.children) do
if not visited[child] then
walk_tree(child, visited, result, padding .. " ", hl_bufs)
end
end
end
return result
end
local function highlight_detail(ast_buf)
for linenum, range in pairs(M.detail_pos[ast_buf]) do
vim.highlight.range(
ast_buf,
M.nsid,
conf.highlights.detail,
{ linenum - 1, range.start },
{ linenum - 1, range["end"] },
"v",
false,
110
)
end
end
local function handler(err, ASTNode)
if err or not ASTNode then
return
else
local source_buf = api.nvim_get_current_buf()
vim.cmd.vsplit(fmt("%s: AST", ASTNode.detail))
local ast_buf = api.nvim_get_current_buf()
api.nvim_set_option_value("filetype", "ClangdAST", { buf = ast_buf })
if not M.node_pos[source_buf] then M.node_pos[source_buf] = {} end
M.node_pos[source_buf][ast_buf] = {}
M.detail_pos[ast_buf] = {}
local lines = walk_tree(
ASTNode,
{},
{},
"",
{ source_buf = source_buf, ast_buf = ast_buf }
)
api.nvim_buf_set_lines(ast_buf, 0, -1, true, lines)
vim.bo.buftype = "nofile"
vim.bo.bufhidden = "wipe"
vim.bo.modifiable = false
vim.bo.shiftwidth = 2
vim.wo.foldmethod = "indent"
api.nvim_set_option_value("number", false, { scope = "local" })
api.nvim_set_option_value("relativenumber", false, { scope = "local" })
api.nvim_set_option_value("spell", false, { scope = "local" })
api.nvim_set_option_value("cursorline", false, { scope = "local" })
setup_hl_autocmd(source_buf, ast_buf)
highlight_detail(ast_buf)
end
end
function M.clear_highlight(source_buf)
api.nvim_buf_clear_namespace(source_buf, M.nsid, 0, -1)
end
function M.update_highlight(source_buf, ast_buf)
M.clear_highlight(source_buf)
if api.nvim_get_current_buf() ~= ast_buf then return end
local curline = vim.fn.getcurpos()[2]
local curline_ranges = M.node_pos[source_buf][ast_buf][curline]
if curline_ranges then
vim.highlight.range(
source_buf,
M.nsid,
"Search",
curline_ranges.start,
curline_ranges["end"],
"v",
false,
110
)
end
end
function M.display_ast(line1, line2)
vim.lsp.buf_request(0, "textDocument/ast", {
textDocument = { uri = vim.uri_from_bufnr(0) },
range = {
start = {
line = line1 - 1,
character = 0,
},
["end"] = {
line = line2,
character = 0,
},
},
}, handler)
end
return M

View File

@ -0,0 +1,10 @@
return function(entry1, entry2)
local diff
if entry1.completion_item.score and entry2.completion_item.score then
diff = (entry2.completion_item.score * entry2.score)
- (entry1.completion_item.score * entry1.score)
else
diff = entry2.score - entry1.score
end
return (diff < 0)
end

View File

@ -0,0 +1,57 @@
local M = {}
M.options = {
inlay_hints = {
inline = vim.fn.has("nvim-0.10") == 1,
only_current_line = false,
only_current_line_autocmd = { "CursorHold" },
show_parameter_hints = true,
parameter_hints_prefix = "<- ",
other_hints_prefix = "=> ",
max_len_align = false,
max_len_align_padding = 1,
right_align = false,
right_align_padding = 7,
highlight = "Comment",
priority = 100,
},
ast = {
role_icons = {
type = "🄣",
declaration = "🄓",
expression = "🄔",
statement = ";",
specifier = "🄢",
["template argument"] = "🆃",
},
kind_icons = {
Compound = "🄲",
Recovery = "🅁",
TranslationUnit = "🅄",
PackExpansion = "🄿",
TemplateTypeParm = "🅃",
TemplateTemplateParm = "🅃",
TemplateParamObject = "🅃",
},
highlights = {
detail = "Comment",
},
},
memory_usage = {
border = "none",
},
symbol_info = {
border = "none",
},
}
function M.setup(options)
M.options = vim.tbl_deep_extend("force", {}, M.options, options or {})
end
return M

View File

@ -0,0 +1,5 @@
return {
setup = function(options)
require("clangd_extensions.config").setup(options)
end,
}

View File

@ -0,0 +1,311 @@
-- MIT License
--
-- Copyright (c) 2020 simrat39
--
-- Permission is hereby granted, free of charge, to any person obtaining a copy
-- of this software and associated documentation files (the "Software"), to deal
-- in the Software without restriction, including without limitation the rights
-- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-- copies of the Software, and to permit persons to whom the Software is
-- furnished to do so, subject to the following conditions:
--
-- The above copyright notice and this permission notice shall be included in all
-- copies or substantial portions of the Software.
--
-- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-- SOFTWARE.
local M = {}
local config = require("clangd_extensions.config")
local api = vim.api
-- Update inlay hints when opening a new buffer and when writing a buffer to a
-- file
-- opts is a string representation of the table of options
function M.setup_autocmd()
local events = { "BufEnter", "BufWinEnter", "TabEnter", "BufWritePost" }
if config.options.inlay_hints.only_current_line then
vim.list_extend(
events,
config.options.inlay_hints.only_current_line_autocmd
)
end
local augroup = vim.api.nvim_create_augroup("ClangdInlayHints", {})
local buffer = api.nvim_get_current_buf()
api.nvim_clear_autocmds({
buffer = buffer,
group = augroup,
})
api.nvim_create_autocmd(events, {
buffer = buffer,
group = augroup,
callback = M.set_inlay_hints,
})
end
local function get_inline_params()
return {
textDocument = vim.lsp.util.make_text_document_params(),
range = {
start = {
line = 0,
character = 0,
},
["end"] = {
line = vim.api.nvim_buf_line_count(0),
character = 0,
},
},
}
end
local namespace = vim.api.nvim_create_namespace("clangd/inlayHints")
-- whether the hints are enabled or not
local enabled = nil
-- parses the result into a easily parsable format
-- example:
-- {
-- ["12"] = { {
-- kind = "TypeHint",
-- label = "String"
-- } },
-- ["13"] = { {
-- kind = "TypeHint",
-- label = "usize"
-- } },
-- ["15"] = { {
-- kind = "ParameterHint",
-- label = "styles"
-- }, {
-- kind = "ParameterHint",
-- label = "len"
-- } },
-- ["7"] = { {
-- kind = "ChainingHint",
-- label = "Result<String, VarError>"
-- }, {
-- kind = "ParameterHint",
-- label = "key"
-- } },
-- ["8"] = { {
-- kind = "ParameterHint",
-- label = "op"
-- } }
-- }
--
local function parseHints(result)
local map = {}
local only_current_line = config.options.inlay_hints.only_current_line
if type(result) ~= "table" then return {} end
for _, value in pairs(result) do
local line = tostring(value.range["end"].line)
local label = value.label
local kind = value.kind
local current_line = vim.api.nvim_win_get_cursor(0)[1]
local function add_line()
if map[line] ~= nil then
table.insert(map[line], { label = label, kind = kind })
else
map[line] = { { label = label, kind = kind } }
end
end
if only_current_line then
if line == tostring(current_line - 1) then add_line() end
else
add_line()
end
end
return map
end
local function handler(err, result, ctx)
if err then return end
local opts = config.options.inlay_hints
local bufnr = ctx.bufnr
if vim.api.nvim_get_current_buf() ~= bufnr then return end
-- clean it up at first
M.disable_inlay_hints()
local ret = parseHints(result)
local max_len = -1
for key, _ in pairs(ret) do
local line = tonumber(key)
local current_line =
vim.api.nvim_buf_get_lines(bufnr, line, line + 1, false)[1]
if current_line then
local current_line_len = string.len(current_line)
max_len = math.max(max_len, current_line_len)
end
end
for key, value in pairs(ret) do
local virt_text = ""
local line = tonumber(key)
local current_line =
vim.api.nvim_buf_get_lines(bufnr, line, line + 1, false)[1]
if current_line then
local current_line_len = string.len(current_line)
local param_hints = {}
local other_hints = {}
-- segregate paramter hints and other hints
for _, value_inner in ipairs(value) do
if value_inner.kind == "parameter" then
table.insert(param_hints, value_inner.label:sub(1, -3))
else
local hint_text = value_inner.label
if hint_text:sub(1, 2) == ": " then
hint_text = hint_text:sub(3)
end
table.insert(other_hints, hint_text)
end
end
-- show parameter hints inside brackets with commas and a thin arrow
if
not vim.tbl_isempty(param_hints) and opts.show_parameter_hints
then
virt_text = virt_text .. opts.parameter_hints_prefix .. "("
for i, value_inner_inner in ipairs(param_hints) do
virt_text = virt_text .. value_inner_inner
if i ~= #param_hints then virt_text = virt_text .. ", " end
end
virt_text = virt_text .. ") "
end
-- show other hints with commas and a thicc arrow
if not vim.tbl_isempty(other_hints) then
virt_text = virt_text .. opts.other_hints_prefix
for i, value_inner_inner in ipairs(other_hints) do
virt_text = virt_text .. value_inner_inner
if i ~= #other_hints then virt_text = virt_text .. ", " end
end
end
if config.options.inlay_hints.right_align then
virt_text = virt_text
.. string.rep(
" ",
config.options.inlay_hints.right_align_padding
)
end
if config.options.inlay_hints.max_len_align then
virt_text = string.rep(
" ",
max_len
- current_line_len
+ config.options.inlay_hints.max_len_align_padding
) .. virt_text
end
-- set the virtual text
vim.api.nvim_buf_set_extmark(bufnr, namespace, line, 0, {
virt_text_pos = config.options.inlay_hints.right_align
and "right_align"
or "eol",
virt_text = {
{ virt_text, config.options.inlay_hints.highlight },
},
hl_mode = "combine",
priority = config.options.inlay_hints.priority,
})
-- update state
enabled = true
end
end
end
local function inline_handler(err, result, ctx)
if err then return end
local bufnr = ctx.bufnr
if vim.api.nvim_get_current_buf() ~= bufnr then return end
local current_line = vim.api.nvim_win_get_cursor(0)[1]
-- clean it up first
M.disable_inlay_hints()
for _, hint in pairs(result) do
local text = hint.label
if hint.paddingLeft then text = " " .. text end
if hint.paddingRight then text = text .. " " end
local line = hint.position.line
if
line == current_line - 1
or not config.options.inlay_hints.only_current_line
then
local col = hint.position.character
vim.api.nvim_buf_set_extmark(bufnr, namespace, line, col, {
virt_text_pos = "inline",
virt_text = {
{ text, config.options.inlay_hints.highlight },
},
hl_mode = "combine",
priority = config.options.inlay_hints.priority,
})
end
end
end
function M.toggle_inlay_hints()
if enabled then
M.disable_inlay_hints()
else
M.set_inlay_hints()
end
enabled = not enabled
return enabled
end
function M.disable_inlay_hints()
-- clear namespace which clears the virtual text as well
vim.api.nvim_buf_clear_namespace(0, namespace, 0, -1)
end
-- Sends the request to clangd to get the inlay hints and handle them
function M.set_inlay_hints()
local buf = vim.api.nvim_get_current_buf()
local clients = vim.lsp.get_clients and vim.lsp.get_clients({ bufnr = buf })
or vim.lsp.buf_get_clients(buf)
-- ensure clangd is running and request doesn't cause error
for _, c in pairs(clients) do
if c.name == "clangd" then
if config.options.inlay_hints.inline then
vim.lsp.buf_request(
0,
"textDocument/inlayHint",
get_inline_params(),
inline_handler
)
else
vim.lsp.buf_request(
0,
"clangd/inlayHints",
{ textDocument = vim.lsp.util.make_text_document_params() },
handler
)
end
break
end
end
end
return M

View File

@ -0,0 +1,112 @@
local api = vim.api
local fmt = string.format
local function display(lines)
for k, line in pairs(lines) do -- Pad lines
if k ~= 1 then lines[k] = " " .. line .. " " end
end
local vim_width = api.nvim_get_option("columns")
local vim_height = api.nvim_get_option("lines")
local height = math.ceil(vim_height * 0.7 - 4)
local width = math.ceil(vim_width * 0.7)
local row = math.ceil((vim_height - height) / 2 - 1)
local col = math.ceil((vim_width - width) / 2)
local buf = api.nvim_create_buf(false, true)
api.nvim_open_win(buf, true, {
style = "minimal",
relative = "editor",
width = width,
height = height,
row = row,
col = col,
border = require("clangd_extensions.config").options.memory_usage.border,
})
vim.bo.shiftwidth = 2
vim.wo.foldmethod = "indent"
api.nvim_buf_set_lines(buf, 0, -1, true, lines)
api.nvim_set_option_value("bufhidden", "wipe", { buf = buf })
api.nvim_set_option_value("modifiable", false, { buf = buf })
api.nvim_set_option_value("buftype", "nofile", { buf = buf })
api.nvim_buf_set_keymap(buf, "n", "q", ":bd<CR>", {
noremap = true,
silent = true,
})
api.nvim_buf_set_keymap(buf, "n", "<ESC>", ":bd<CR>", {
noremap = true,
silent = true,
})
end
local function format_name(name)
if name:sub(1, 7) == "file://" then name = vim.uri_to_fname(name) end
local cwd = vim.fn.getcwd()
if name:sub(1, string.len(cwd)) == cwd then
name = name:sub(string.len(cwd) + 2, -1)
end
return name
end
local function format_tree(
node,
visited,
result,
padding,
prefix,
expand_preamble
)
if padding == "" then
table.insert(
result,
fmt("Total: self = %s, total = %s", node._self, node._total)
)
end
visited[prefix] = true
for child_name, child_node in pairs(node) do
if
child_name ~= "_self"
and child_name ~= "_total"
and not visited[prefix .. child_name]
then
child_name = format_name(child_name)
table.insert(
result,
padding
.. fmt(
"%s: self = %s, total = %s",
child_name,
child_node._self,
child_node._total
)
)
if child_name ~= "preamble" or expand_preamble then
format_tree(
child_node,
visited,
result,
padding .. " ",
prefix .. child_name,
expand_preamble
)
end
end
end
return result
end
local function handler(err, result, expand_preamble)
if err then return end
display(format_tree(result, {}, { "" }, "", "", expand_preamble))
end
local M = {}
function M.show_memory_usage(expand_preamble)
vim.lsp.buf_request(
0,
"$/memoryUsage",
nil,
function(err, result) handler(err, result, expand_preamble) end
)
end
return M

View File

@ -0,0 +1,19 @@
local function handler(_err, uri)
if not uri or uri == "" then
vim.api.nvim_echo({ { "Corresponding file cannot be determined" } }, false, {})
return
end
local file_name = vim.uri_to_fname(uri)
vim.api.nvim_cmd({
cmd = "edit",
args = { file_name },
}, {})
end
return {
switch_source_header = function()
vim.lsp.buf_request(0, "textDocument/switchSourceHeader", {
uri = vim.uri_from_bufnr(0),
}, handler)
end,
}

View File

@ -0,0 +1,29 @@
local function handler(err, result)
if err or (#result == 0) then return end
local name_str = string.format("name: %s", result[1].name)
local container_str =
string.format("container: %s", result[1].containerName)
vim.lsp.util.open_floating_preview({ name_str, container_str }, "", {
height = 2,
width = math.max(string.len(name_str), string.len(container_str)),
focusable = false,
focus = false,
border = require("clangd_extensions.config").options.symbol_info.border,
})
end
local M = {}
function M.show_symbol_info()
vim.lsp.buf_request(0, "textDocument/symbolInfo", {
textDocument = {
uri = vim.uri_from_bufnr(0),
},
position = {
line = vim.fn.getcurpos()[2] - 1,
character = vim.fn.getcurpos()[3] - 1,
},
}, handler)
end
return M

View File

@ -0,0 +1,28 @@
return {
"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",
}

View File

@ -0,0 +1,144 @@
local symbol_kind = require("clangd_extensions.symbol_kind")
local fmt = string.format
local api = vim.api
local type_hierarchy_augroup =
api.nvim_create_augroup("ClangdTypeHierarchy", {})
local M = {}
M.type_to_location = {}
M.offset_encoding = {}
local function format_tree(node, visited, result, padding, type_to_location)
visited[node.data] = true
table.insert(
result,
padding .. fmt(" • %s: %s", node.name, symbol_kind[node.kind])
)
type_to_location[node.name] = { uri = node.uri, range = node.range }
if node.parents then
if #node.parents > 0 then
table.insert(result, padding .. " Parents:")
for _, parent in pairs(node.parents) do
if not visited[parent.data] then
format_tree(
parent,
visited,
result,
padding .. " ",
type_to_location
)
end
end
end
end
if node.children then
if #node.children > 0 then
table.insert(result, padding .. " Children:")
for _, child in pairs(node.children) do
if not visited[child.data] then
format_tree(
child,
visited,
result,
padding .. " ",
type_to_location
)
end
end
end
end
return result
end
local function handler(err, TypeHierarchyItem, ctx)
if err or not TypeHierarchyItem then
return
else
-- Save old state
local source_win = api.nvim_get_current_win()
-- Init
M.offset_encoding[ctx.client_id] =
vim.lsp.get_client_by_id(ctx.client_id).offset_encoding
vim.cmd.split(fmt("%s: type hierarchy", TypeHierarchyItem.name))
local bufnr = vim.api.nvim_get_current_buf()
M.type_to_location[bufnr] = {}
-- Set content
local lines = format_tree(
TypeHierarchyItem,
{},
{},
"",
M.type_to_location[bufnr]
)
api.nvim_buf_set_lines(bufnr, 0, -1, true, lines)
-- Set options
vim.bo.modifiable = false
vim.bo.filetype = "ClangdTypeHierarchy"
vim.bo.buftype = "nofile"
vim.bo.bufhidden = "wipe"
vim.bo.buflisted = true
api.nvim_set_option_value("number", false, { scope = "local" })
api.nvim_set_option_value("relativenumber", false, { scope = "local" })
api.nvim_set_option_value("spell", false, { scope = "local" })
api.nvim_set_option_value("cursorline", false, { scope = "local" })
local winbar = api.nvim_get_option_value("winbar", {})
local numlines = winbar == "" and #lines or #lines + 1
local winheight = math.min(numlines, 15)
api.nvim_win_set_height(0, winheight)
-- Set highlights
vim.cmd([[
syntax clear
syntax match ClangdTypeName "\( \{2,\}• \)\@<=\w\+\(:\)\@="
]])
vim.api.nvim_set_hl(0, "ClangdTypeName", { link = "Underlined" })
-- Set keymap
vim.keymap.set("n", "gd", function()
local word = vim.fn.expand("<cWORD>")
word = string.gsub(word, ":$", "")
local location = M.type_to_location[bufnr][word]
if location ~= nil then
api.nvim_set_current_win(source_win)
vim.lsp.util.jump_to_location(
location,
M.offset_encoding[ctx.client_id]
)
end
end, {
buffer = bufnr,
desc = "go to definition of type under cursor",
})
-- Clear `type_to_location` for this buffer when it is wiped out
api.nvim_create_autocmd("BufWipeOut", {
buffer = bufnr,
group = type_hierarchy_augroup,
callback = function() M.type_to_location[bufnr] = nil end,
})
end
end
function M.show_hierarchy()
vim.lsp.buf_request(0, "textDocument/typeHierarchy", {
textDocument = {
uri = vim.uri_from_bufnr(0),
},
position = {
line = vim.fn.getcurpos()[2] - 1,
character = vim.fn.getcurpos()[3] - 1,
},
-- TODO make these configurable (config + command args)
resolve = 3,
direction = 2,
}, handler)
end
return M

View File

@ -0,0 +1,5 @@
---
base: lua51
globals:
vim:
any: true

View File

@ -0,0 +1,42 @@
local create_command = vim.api.nvim_create_user_command
create_command('ClangdSetInlayHints', function()
require("clangd_extensions.inlay_hints").set_inlay_hints()
end, {})
create_command('ClangdDisableInlayHints', function()
require("clangd_extensions.inlay_hints").disable_inlay_hints()
end, {})
create_command('ClangdToggleInlayHints', function()
require("clangd_extensions.inlay_hints").toggle_inlay_hints()
end, {})
create_command('ClangdAST', function(opts)
require("clangd_extensions.ast").display_ast(opts.line1, opts.line2)
end, { range = true })
create_command('ClangdTypeHierarchy', function()
require("clangd_extensions.type_hierarchy").show_hierarchy()
end, {})
create_command('ClangdSymbolInfo', function()
require("clangd_extensions.symbol_info").show_symbol_info()
end, {})
create_command(
'ClangdMemoryUsage',
function(opts)
require("clangd_extensions.memory_usage").show_memory_usage(opts.args == 'expand_preamble')
end,
{
nargs = '?',
complete = function(_, _, _)
return { 'expand_preamble' }
end
}
)
create_command('ClangdSwitchSourceHeader', function()
require("clangd_extensions.switch_source_header").switch_source_header()
end, {})

View File

@ -0,0 +1 @@
std = "nvim"

View File

@ -0,0 +1,4 @@
indent_width = 4
column_width = 80
indent_type = "Spaces"
collapse_simple_statement = "Always"