Criando um Sistema de Bookmarks no Neovim com Lua

Continuando nossa série de artigos que visam diminuir o esforço cognitivo em tarefas de programação, apresento meu pequeno script de bookmarks para o Neovim.

O Neovim é incrivelmente personalizável. Sem a necessidade de criar plugins completos, você pode, com algumas funções Lua, adicionar muitas funcionalidades.

No meu dia a dia, frequentemente preciso retornar aos mesmos arquivos para corrigir e testar problemas. Abrir esses arquivos diretamente na linha correta, sem perder tempo navegando, é essencial.

Para solucionar esse problema, desenvolvi um conjunto de funções Lua que formam meu sistema de bookmarks. Ele salva os bookmarks em um arquivo marks.txt, seguindo um formato específico que uso em outros scripts: uma coluna com o caminho completo e o nome do arquivo, e outra com o número da linha.

Também é possível criar bookmarks específicos para o projeto em que estou, mas quase não uso essa funcionalidade.

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

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

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

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

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()'
)

bookmark.lua

Para utilizar o script, basta adicionar o arquivo bookmark.lua no diretório config/nvim/lua e carregá-lo no início do seu arquivo init.lua.

require "bookmark"

O script adiciona dois atalhos:

  • leader+m: adiciona o arquivo e a linha atual ao bookmark
  • leader+o: abre todos os arquivos no bookmark

O script também adiciona o comando Clearmarks, que limpa todos os bookmarks.

Costumo usar este script da seguinte maneira: ao analisar um código ou discutir uma abordagem, marco os pontos importantes. Dessa forma, consigo retornar rapidamente a esses trechos, o que facilita retomar discussões sobre implementações ou resolver bugs.

Quando um problema está solucionado, apago os bookmarks; não os guardo por muito tempo. Caso precise deles para um projeto mais longo, simplesmente copio o arquivo marks.txt para minhas anotações.

Em conjunto com o script Lua, também tenho um script Bash para abrir os bookmarks direto do terminal.

#!/usr/bin/env bash

MARKS_FILE="$HOME/marks.txt"

[[ ! -f "$MARKS_FILE" ]] && {
    echo "Arquivo de marcações não encontrado: $MARKS_FILE"
    exit 1
}

NVIM_COMMANDS=""

while IFS= read -r line; do
    [[ "$line" =~ ^(.+)\ \+([0-9]+)$ ]] && {
        file="${BASH_REMATCH[1]}"
        lineno="${BASH_REMATCH[2]}"
        NVIM_COMMANDS="$NVIM_COMMANDS +:edit $file +$lineno"
        continue
    }
    echo "Formato inválido na linha: $line"
done < "$MARKS_FILE"

[[ -n "$NVIM_COMMANDS" ]] && {
    nvim $NVIM_COMMANDS
    exit $?
}
echo "Nenhuma marcação válida encontrada para abrir."
exit 1

open_marks

Uso pouco esse script, pois é mais comum entrar no Neovim e rapidamente pressionar leader+o, mas é útil ter a possibilidade de automatizar a abertura dos bookmarks.

Tenho diversas pequenas automações como esta no Neovim. Poder criar funções Lua e vinculá-las a eventos, como teclas de atalho ao salvar arquivos, torna o editor extremamente agradável de usar. Em artigos futuros, compartilharei mais sobre essas automações.

Cesar Gimenes

Última modificação