Created
December 2, 2024 18:11
-
-
Save lopesivan/ff4598e289cb691980813829d3deb0c8 to your computer and use it in GitHub Desktop.
vim.opt_local.foldexpr = "v:lua.vim.lsp.foldexpr()" e vim.opt_local.foldtext = require "config.foldtext"
This file contains hidden or 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
--- @module Foldtext | |
--- Based on https://www.reddit.com/r/neovim/comments/16sqyjz/finally_we_can_have_highlighted_folds/ | |
--- Updated with vim.treesitter._fold.foldtext() | |
-- Função para processar uma linha e extrair os destaques usando Treesitter | |
local function parse_line(linenr) | |
-- Obtém o buffer atual do Neovim | |
local bufnr = vim.api.nvim_get_current_buf() | |
-- Obtém a linha do buffer correspondente ao número da linha | |
local line = vim.api.nvim_buf_get_lines(bufnr, linenr - 1, linenr, false)[1] | |
-- Retorna nil se a linha não existir | |
if not line then | |
return nil | |
end | |
-- Tenta obter o parser do Treesitter para o buffer atual | |
local ok, parser = pcall(vim.treesitter.get_parser, bufnr) | |
-- Retorna nil se o parser não estiver disponível | |
if not ok then | |
return nil | |
end | |
-- Obtém a query de destaques da linguagem do parser | |
local query = vim.treesitter.query.get(parser:lang(), "highlights") | |
-- Retorna nil se não houver query de destaques configurada | |
if not query then | |
return nil | |
end | |
-- Realiza o parsing da linha com o Treesitter | |
local tree = parser:parse({ linenr - 1, linenr })[1] | |
-- Inicializa o resultado que armazenará os trechos destacados | |
local result = {} | |
-- Variável para rastrear a posição atual na linha | |
local line_pos = 0 | |
-- Itera sobre as capturas do Treesitter na linha especificada | |
for id, node, metadata in query:iter_captures(tree:root(), 0, linenr - 1, linenr) do | |
-- Obtém o nome da captura atual | |
local name = query.captures[id] | |
-- Obtém as posições inicial e final do nó capturado | |
local start_row, start_col, end_row, end_col = node:range() | |
-- Define a prioridade do destaque, usando uma prioridade padrão se nenhuma for especificada | |
local priority = tonumber(metadata.priority or vim.highlight.priorities.treesitter) | |
-- Processa apenas capturas que estão inteiramente na linha atual | |
if start_row == linenr - 1 and end_row == linenr - 1 then | |
-- Verifica se há caracteres entre a posição atual e o início da captura | |
if start_col > line_pos then | |
-- Adiciona o trecho ignorado pelo Treesitter ao resultado | |
table.insert(result, { | |
line:sub(line_pos + 1, start_col), -- Texto sem destaque | |
{ { "Folded", priority } }, -- Aplica destaque padrão "Folded" | |
range = { line_pos, start_col }, -- Define a faixa de caracteres | |
}) | |
end | |
-- Atualiza a posição atual para o final da captura | |
line_pos = end_col | |
-- Extrai o texto capturado | |
local text = line:sub(start_col + 1, end_col) | |
-- Adiciona o texto capturado com o destaque correspondente ao resultado | |
table.insert(result, { | |
text, -- Texto capturado | |
{ { "@" .. name, priority } }, -- Destaque baseado no nome da captura | |
range = { start_col, end_col }, -- Define a faixa de caracteres | |
}) | |
end | |
end | |
-- Variável para iterar sobre os resultados processados | |
local i = 1 | |
while i <= #result do | |
-- Encontra capturas que estão dentro do intervalo da captura atual | |
local j = i + 1 | |
while j <= #result and result[j].range[1] >= result[i].range[1] and result[j].range[2] <= result[i].range[2] do | |
-- Adiciona os destaques da captura pai às capturas filhas | |
for k, v in ipairs(result[i][2]) do | |
if not vim.tbl_contains(result[j][2], v) then | |
table.insert(result[j][2], k, v) | |
end | |
end | |
j = j + 1 | |
end | |
-- Remove a captura pai se ela foi dividida em capturas filhas | |
if j > i + 1 then | |
table.remove(result, i) | |
else | |
-- Ordena os destaques por prioridade | |
if #result[i][2] > 1 then | |
table.sort(result[i][2], function(a, b) | |
return a[2] < b[2] | |
end) | |
end | |
-- Simplifica a estrutura de destaque para conter apenas os nomes | |
result[i][2] = vim.tbl_map(function(tbl) | |
return tbl[1] | |
end, result[i][2]) | |
result[i] = { result[i][1], result[i][2] } | |
-- Avança para a próxima captura | |
i = i + 1 | |
end | |
end | |
-- Retorna o resultado processado | |
return result | |
end | |
-- Função principal que monta o texto dobrado com destaques | |
function HighlightedFoldtext() | |
-- Processa a linha inicial do fold | |
local result = parse_line(vim.v.foldstart) | |
-- Retorna o texto padrão do fold se não houver destaques | |
if not result then | |
return vim.fn.foldtext() | |
end | |
-- Adiciona ícones e informações de linhas dobradas ao resultado | |
local folded = { | |
{ " ", "FoldedIcon" }, -- Ícone inicial | |
{ "+" .. vim.v.foldend - vim.v.foldstart .. " lines", "FoldedText" }, -- Contador de linhas | |
{ " ", "FoldedIcon" }, -- Ícone final | |
} | |
-- Insere os elementos adicionais no resultado | |
for _, item in ipairs(folded) do | |
table.insert(result, item) | |
end | |
-- Processa a linha final do fold para capturar destaques adicionais | |
local result2 = parse_line(vim.v.foldend) | |
if result2 then | |
local first = result2[1] | |
if first then -- Verifica se o primeiro item não é nulo | |
result2[1] = { vim.trim(first[1]), first[2] } | |
for _, item in ipairs(result2) do | |
table.insert(result, item) | |
end | |
end | |
end | |
-- Retorna o resultado final com os destaques | |
return result | |
end | |
-- Função para configurar os destaques personalizados de fold | |
local function set_fold_hl() | |
-- Obtém as cores do destaque atual | |
local cl = vim.api.nvim_get_hl(0, { name = "CursorLineNr" }) | |
-- Define a cor do ícone dobrado | |
vim.api.nvim_set_hl(0, "FoldedIcon", { fg = cl.bg }) | |
-- Define a cor e o estilo do texto dobrado | |
vim.api.nvim_set_hl(0, "FoldedText", { bg = cl.bg, fg = cl.fg, italic = true }) | |
end | |
-- Aplica as configurações de destaque | |
set_fold_hl() | |
-- Atualiza as configurações de destaque quando o esquema de cores é alterado | |
vim.api.nvim_create_autocmd("ColorScheme", { | |
callback = set_fold_hl, | |
}) | |
-- Retorna a função que será usada como `foldtext` | |
return 'luaeval("HighlightedFoldtext")()' | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment