Bookmarks em Neovim
Eu percorro muitos arquivos quando trabalho, principalmente ao resolver bugs ou rastrear comportamentos. Eu criei um sistema de marcadores (bookmarks) no Neovim para navegar mais rápido entre arquivos. Esse sistema difere do sistema padrão do Neovim, pois foca em marcar arquivos e linhas, não apenas posições dentro do mesmo arquivo.
Funcionamento
O sistema registra o caminho do arquivo e a linha atual em um arquivo texto. Eu uso a tecla <leader>o
para abrir todos os arquivos marcados. Eu uso a tecla <leader>m
para marcar um arquivo. Eu também uso o comando :Clearmarks
para limpar todos os marcadores quando termino um trabalho ou inicio outro.
Implementação
A função Mark_point
grava o caminho do arquivo e a linha atual no final de um arquivo texto. Ela cria esse arquivo, se ele não existir.
function Mark_point()
local home = os.getenv("HOME")
local file_marks = home .. "/marks.txt"
local file = vim.fn.expand('%:p') -- caminho completo
local line = vim.fn.line('.') -- número da linha atual
local mark = file .. " +" .. line
local file_handle = io.open(file_marks, "a")
if file_handle then
file_handle:write(mark .. "\n")
file_handle:close()
print("Marked: " .. mark)
return
end
print("Erro ao abrir o arquivo de marcação: " .. file_marks)
end
A função Open_mark
lê o arquivo de marcação, abre o arquivo e salta para a linha marcada. Ela primeiro salta para o início do arquivo com gg
e depois para a linha desejada com G
.
function Open_mark(marks_file)
local file = io.open(marks_file, "r")
if not file then
-- print("Erro ao abrir o arquivo de marcação: " .. marks_file)
return
end
for line in file:lines() do
local file_path, line_number = string.match(
line, "^(.-)%s+%+(%d+)$")
vim.cmd('edit ' .. file_path)
vim.cmd('normal gg')
vim.cmd('normal ' .. line_number .. 'G')
end
file:close()
end
Criei a função Open_marks
para abrir arquivos marcados no diretório do usuário e no diretório atual.
function Open_marks()
local path = os.getenv("HOME")
local marks_file = path .. "/marks.txt"
Open_mark(marks_file)
path = vim.fn.getcwd()
marks_file = path .. "/marks.txt"
Open_mark(marks_file)
end
A função Clear_marks
remove os arquivos de marcação do diretório do usuário e do diretório atual.
function Clear_marks()
local path = os.getenv("HOME")
local marks_file = path .. "/marks.txt"
os.remove(marks_file)
path = vim.fn.getcwd()
marks_file = path .. "/marks.txt"
os.remove(marks_file)
end
Configurei teclas de atalho e um comando do Neovim para chamar as funções.
vim.api.nvim_set_keymap(
'n', '<leader>o', ':lua Open_marks()<CR>',
{ noremap = true, silent = true }
)
vim.api.nvim_set_keymap(
'n', '<leader>m', ':lua Mark_point()<CR>',
{ noremap = true, silent = true }
)
vim.api.nvim_command(
'command! Clearmarks lua Clear_marks()'
)
Arquivo de Marcação
Guardo as marcações em um arquivo texto simples. Dessa forma é simples criar scripts para interagir com esses marcadores, sem precisar abrir o Neovim. Segue um exemplo em Bash:
#!/usr/bin/env bash
INITIAL_QUERY="${*:-}"
MARKS_FILES=("$HOME/marks.txt")
[ -f "./marks.txt" ] && \
MARKS_FILES+=("./marks.txt")
IFS='+' read -r file_path line_number <<< "$(
cat "${MARKS_FILES[@]}" | \
fzf --ansi \
--delimiter '+' \
--preview 'bat --color=always {1} --highlight-line {2}' \
--preview-window 'up,60%,border-bottom,+{2}+3/3,~3' \
--query "$INITIAL_QUERY"
)"
[ -n "$file_path" ] && {
file_path=$(echo "$file_path" | xargs)
line_number=$(echo "$line_number" | xargs)
"$EDITOR" "$file_path" "+$line_number"
echo "$file_path" "+$line_number"
}
Esse script lê o arquivo de bookmarks, permite a seleção de um arquivo e o abre no Neovim na linha marcada. Ele usa o fzf
para interagir com o usuário e o bat
para visualizar o arquivo.
Conclusão
Eu prefiro pequenas ferramentas que executam tarefas específicas de forma eficiente. Elas são fáceis de combinar ou modificar, deixando meu dia a dia mais produtivo e agradável.
Até a próxima!