feat: Adds syntax highlighting in the telescope picker (#386)

* Add telescope highlighting

* Fix no TS language parser edge case

* Fix language detection for non-matching languages

* Remove nvim-treesitter dependency, streamline logic

* Change to show_columns option

* Update README
This commit is contained in:
Sergey Tarasov 2024-07-17 01:12:17 +03:00 committed by GitHub
parent e4de1a4b3f
commit 4e77964569
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 81 additions and 8 deletions

View file

@ -613,6 +613,8 @@ require("telescope").setup({
json = true, -- You can set the option for specific filetypes
yaml = true,
},
-- Available modes: symbols, lines, both
show_columns = "both",
},
},
})

View file

@ -5,7 +5,8 @@ local pickers = require("telescope.pickers")
local telescope = require("telescope")
local ext_config = {
show_lines = true,
-- show_lines = true, -- deprecated in favor of show_columns
show_columns = "both", -- { "symbols", "lines", "both" }
show_nesting = {
["_"] = false,
json = true,
@ -26,6 +27,19 @@ local function aerial_picker(opts)
local filename = vim.api.nvim_buf_get_name(0)
local filetype = vim.bo[bufnr].filetype
local show_nesting = ext_config.show_nesting[filetype]
local show_columns = opts.show_columns or conf.show_columns
local show_lines = opts.show_lines or conf.show_lines -- show_lines is deprecated
if show_columns == nil then
if show_lines == true then
show_columns = "both"
elseif show_lines == false then
show_columns = "symbols"
else
show_columns = ext_config.show_columns
end
end
if show_nesting == nil then
show_nesting = ext_config.show_nesting["_"]
end
@ -39,7 +53,7 @@ local function aerial_picker(opts)
end
local layout
if ext_config.show_lines then
if show_columns == "both" then
layout = {
{ width = 4 },
{ width = 30 },
@ -57,8 +71,55 @@ local function aerial_picker(opts)
items = layout,
})
local function collect_buf_highlights()
local parser = vim.treesitter.get_parser(bufnr)
if not parser then
return {}
end
local lang = parser:lang()
local root = parser:trees()[1]:root() -- get root of already parsed cached tree
local highlights = {}
local query = vim.treesitter.query.get(lang, "highlights")
if query then
for _, captures, _ in query:iter_matches(root, bufnr, 0, -1) do
for id, node in pairs(captures) do
local start_row, start_col, _, end_col = node:range()
highlights[start_row] = highlights[start_row] or {}
table.insert(highlights[start_row], { start_col, end_col, query.captures[id] })
end
end
end
return highlights
end
local buf_highlights = {}
if show_columns == "lines" or show_columns == "both" then
buf_highlights = collect_buf_highlights() -- collect buffer highlights only if needed
end
local function highlights_for_row(row, offset)
offset = offset or 0
local row_highlights = buf_highlights[row] or {}
local highlights = {}
for _, value in ipairs(row_highlights) do
local start_col, end_col, hl_type = unpack(value)
hl_type = hl_type:match("^[^.]+") -- strip subtypes after dot
table.insert(highlights, { { start_col + offset, end_col + offset }, hl_type })
end
return highlights
end
local function make_display(entry)
local item = entry.value
local row = item.lnum - 1
if show_columns == "lines" then
local text = vim.api.nvim_buf_get_lines(bufnr, row, row + 1, false)[1] or ""
return text, highlights_for_row(row)
end
local icon = config.get_icon(bufnr, item.kind)
local icon_hl = highlight.get_highlight(item, true, false) or "NONE"
local name_hl = highlight.get_highlight(item, false, false) or "NONE"
@ -66,12 +127,21 @@ local function aerial_picker(opts)
{ icon, icon_hl },
{ entry.name, name_hl },
}
if ext_config.show_lines then
local text = vim.api.nvim_buf_get_lines(bufnr, item.lnum - 1, item.lnum, false)[1] or ""
text = vim.trim(text)
table.insert(columns, text)
local highlights = {}
if show_columns == "both" then
local text = vim.api.nvim_buf_get_lines(bufnr, row, row + 1, false)[1] or ""
table.insert(columns, vim.trim(text))
local leading_spaces = text:match("^%s*")
local offset = layout[1].width + layout[2].width - #leading_spaces + #icon
if #entry.name > layout[2].width then
offset = offset + 2 -- '...' symbol
end
highlights = highlights_for_row(row, offset)
end
return displayer(columns)
return displayer(columns), highlights
end
local function make_entry(item)
@ -114,7 +184,8 @@ local function aerial_picker(opts)
end
-- Reverse the symbols so they have the same top-to-bottom order as in the file
if conf.sorting_strategy == "descending" then
local sorting_strategy = opts.sorting_strategy or conf.sorting_strategy
if sorting_strategy == "descending" then
util.tbl_reverse(results)
default_selection_index = #results - (default_selection_index - 1)
end