-
-
Notifications
You must be signed in to change notification settings - Fork 5.5k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat:
vim.inspect_pos
, vim.show_pos
, :Inspect
- Loading branch information
Showing
13 changed files
with
385 additions
and
11 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,238 @@ | ||
---@class InspectorFilter | ||
---@field syntax boolean include syntax based highlight groups (defaults to true) | ||
---@field treesitter boolean include treesitter based highlight groups (defaults to true) | ||
---@field extmarks boolean|"all" include extmarks. When `all`, then extmarks without a `hl_group` will also be included (defaults to true) | ||
---@field semantic_tokens boolean include semantic tokens (defaults to true) | ||
local defaults = { | ||
syntax = true, | ||
treesitter = true, | ||
extmarks = true, | ||
semantic_tokens = true, | ||
} | ||
|
||
---Get all the items at a given buffer position. | ||
--- | ||
---Can also be pretty-printed with `:Inspect!`. *:Inspect!* | ||
--- | ||
---@param bufnr? number defaults to the current buffer | ||
---@param row? number row to inspect, 0-based. Defaults to the row of the current cursor | ||
---@param col? number col to inspect, 0-based. Defaults to the col of the current cursor | ||
---@param filter? InspectorFilter (table|nil) a table with key-value pairs to filter the items | ||
--- - syntax (boolean): include syntax based highlight groups (defaults to true) | ||
--- - treesitter (boolean): include treesitter based highlight groups (defaults to true) | ||
--- - extmarks (boolean|"all"): include extmarks. When `all`, then extmarks without a `hl_group` will also be included (defaults to true) | ||
--- - semantic_tokens (boolean): include semantic tokens (defaults to true) | ||
---@return {treesitter:table,syntax:table,extmarks:table,semantic_tokens:table,buffer:number,col:number,row:number} (table) a table with the following key-value pairs. Items are in "traversal order": | ||
--- - treesitter: a list of treesitter captures | ||
--- - syntax: a list of syntax groups | ||
--- - semantic_tokens: a list of semantic tokens | ||
--- - extmarks: a list of extmarks | ||
--- - buffer: the buffer used to get the items | ||
--- - row: the row used to get the items | ||
--- - col: the col used to get the items | ||
function vim.inspect_pos(bufnr, row, col, filter) | ||
filter = vim.tbl_deep_extend('force', defaults, filter or {}) | ||
|
||
bufnr = bufnr or 0 | ||
if row == nil or col == nil then | ||
-- get the row/col from the first window displaying the buffer | ||
local win = bufnr == 0 and vim.api.nvim_get_current_win() or vim.fn.bufwinid(bufnr) | ||
if win == -1 then | ||
error('row/col is required for buffers not visible in a window') | ||
end | ||
local cursor = vim.api.nvim_win_get_cursor(win) | ||
row, col = cursor[1] - 1, cursor[2] | ||
end | ||
bufnr = bufnr == 0 and vim.api.nvim_get_current_buf() or bufnr | ||
|
||
local results = { | ||
treesitter = {}, | ||
syntax = {}, | ||
extmarks = {}, | ||
semantic_tokens = {}, | ||
buffer = bufnr, | ||
row = row, | ||
col = col, | ||
} | ||
|
||
-- resolve hl links | ||
---@private | ||
local function resolve_hl(data) | ||
if data.hl_group then | ||
local hlid = vim.api.nvim_get_hl_id_by_name(data.hl_group) | ||
local name = vim.fn.synIDattr(vim.fn.synIDtrans(hlid), 'name') | ||
data.hl_group_link = name | ||
end | ||
return data | ||
end | ||
|
||
-- treesitter | ||
if filter.treesitter then | ||
for _, capture in pairs(vim.treesitter.get_captures_at_pos(bufnr, row, col)) do | ||
capture.hl_group = '@' .. capture.capture | ||
table.insert(results.treesitter, resolve_hl(capture)) | ||
end | ||
end | ||
|
||
-- syntax | ||
if filter.syntax then | ||
for _, i1 in ipairs(vim.fn.synstack(row + 1, col + 1)) do | ||
table.insert(results.syntax, resolve_hl({ hl_group = vim.fn.synIDattr(i1, 'name') })) | ||
end | ||
end | ||
|
||
-- semantic tokens | ||
if filter.semantic_tokens then | ||
for _, token in ipairs(vim.lsp.semantic_tokens.get_at_pos(bufnr, row, col) or {}) do | ||
token.hl_groups = { | ||
type = resolve_hl({ hl_group = '@' .. token.type }), | ||
modifiers = vim.tbl_map(function(modifier) | ||
return resolve_hl({ hl_group = '@' .. modifier }) | ||
end, token.modifiers or {}), | ||
} | ||
table.insert(results.semantic_tokens, token) | ||
end | ||
end | ||
|
||
-- extmarks | ||
if filter.extmarks then | ||
for ns, nsid in pairs(vim.api.nvim_get_namespaces()) do | ||
if ns:find('vim_lsp_semantic_tokens') ~= 1 then | ||
local extmarks = vim.api.nvim_buf_get_extmarks(bufnr, nsid, 0, -1, { details = true }) | ||
for _, extmark in ipairs(extmarks) do | ||
extmark = { | ||
ns_id = nsid, | ||
ns = ns, | ||
id = extmark[1], | ||
row = extmark[2], | ||
col = extmark[3], | ||
opts = resolve_hl(extmark[4]), | ||
} | ||
local end_row = extmark.opts.end_row or extmark.row -- inclusive | ||
local end_col = extmark.opts.end_col or (extmark.col + 1) -- exclusive | ||
if | ||
(filter.extmarks == 'all' or extmark.opts.hl_group) -- filter hl_group | ||
and (row >= extmark.row and row <= end_row) -- within the rows of the extmark | ||
and (row > extmark.row or col >= extmark.col) -- either not the first row, or in range of the col | ||
and (row < end_row or col < end_col) -- either not in the last row or in range of the col | ||
then | ||
table.insert(results.extmarks, extmark) | ||
end | ||
end | ||
end | ||
end | ||
end | ||
return results | ||
end | ||
|
||
---Show all the items at a given buffer position. | ||
--- | ||
---Can also be shown with `:Inspect`. *:Inspect* | ||
--- | ||
---@param bufnr? number defaults to the current buffer | ||
---@param row? number row to inspect, 0-based. Defaults to the row of the current cursor | ||
---@param col? number col to inspect, 0-based. Defaults to the col of the current cursor | ||
---@param filter? InspectorFilter (table|nil) see |vim.inspect_pos()| | ||
function vim.show_pos(bufnr, row, col, filter) | ||
local items = vim.inspect_pos(bufnr, row, col, filter) | ||
|
||
local lines = { {} } | ||
|
||
---@private | ||
local function append(str, hl) | ||
table.insert(lines[#lines], { str, hl }) | ||
end | ||
|
||
---@private | ||
local function nl() | ||
table.insert(lines, {}) | ||
end | ||
|
||
---@private | ||
local function item(data, comment) | ||
append(' - ') | ||
append(data.hl_group, data.hl_group) | ||
append(' ') | ||
if data.hl_group ~= data.hl_group_link then | ||
append('links to ', 'MoreMsg') | ||
append(data.hl_group_link, data.hl_group_link) | ||
append(' ') | ||
end | ||
if comment then | ||
append(comment, 'Comment') | ||
end | ||
nl() | ||
end | ||
|
||
-- treesitter | ||
if #items.treesitter > 0 then | ||
append('Treesitter', 'Title') | ||
nl() | ||
for _, capture in ipairs(items.treesitter) do | ||
item(capture, capture.lang) | ||
end | ||
nl() | ||
end | ||
|
||
if #items.semantic_tokens > 0 then | ||
append('Semantic Tokens', 'Title') | ||
nl() | ||
for _, token in ipairs(items.semantic_tokens) do | ||
local client = vim.lsp.get_client_by_id(token.client_id) | ||
client = client and (' (' .. client.name .. ')') or '' | ||
item(token.hl_groups.type, 'type' .. client) | ||
for _, modifier in ipairs(token.hl_groups.modifiers) do | ||
item(modifier, 'modifier' .. client) | ||
end | ||
end | ||
nl() | ||
end | ||
|
||
-- syntax | ||
if #items.syntax > 0 then | ||
append('Syntax', 'Title') | ||
nl() | ||
for _, syn in ipairs(items.syntax) do | ||
item(syn) | ||
end | ||
nl() | ||
end | ||
-- extmarks | ||
if #items.extmarks > 0 then | ||
append('Extmarks', 'Title') | ||
nl() | ||
for _, extmark in ipairs(items.extmarks) do | ||
if extmark.opts.hl_group then | ||
item(extmark.opts, extmark.ns) | ||
else | ||
append(' - ') | ||
append(extmark.ns, 'Comment') | ||
nl() | ||
end | ||
end | ||
nl() | ||
end | ||
|
||
if #lines[#lines] == 0 then | ||
table.remove(lines) | ||
end | ||
|
||
local chunks = {} | ||
for _, line in ipairs(lines) do | ||
vim.list_extend(chunks, line) | ||
table.insert(chunks, { '\n' }) | ||
end | ||
if #chunks == 0 then | ||
chunks = { | ||
{ | ||
'No items found at position ' | ||
.. items.row | ||
.. ',' | ||
.. items.col | ||
.. ' in buffer ' | ||
.. items.buffer, | ||
}, | ||
} | ||
end | ||
vim.api.nvim_echo(chunks, false, {}) | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
vim.api.nvim_create_user_command('Inspect', function(cmd) | ||
if cmd.bang then | ||
vim.pretty_print(vim.inspect_pos()) | ||
else | ||
vim.show_pos() | ||
end | ||
end, { desc = 'Inspect highlights and extmarks at the cursor', bang = true }) |
Oops, something went wrong.