the code
This commit is contained in:
@@ -1,2 +1,32 @@
|
||||
# comment-navigator
|
||||
A simple nvim plugin to jump between comments.
|
||||
|
||||
A simple nvim plugin to jump between (special) comments.
|
||||
|
||||
## Preview
|
||||
|
||||

|
||||
|
||||
## Setup
|
||||
This is my current setup:
|
||||
```lua
|
||||
local comment_navigator = require('comment_navigator')
|
||||
|
||||
local comment_filetypes = {
|
||||
{"*.{odin,c,cc,cpp,cxx}", comment_navigator.regex.c},
|
||||
{"*.lua", comment_navigator.regex.lua},
|
||||
{"*.py", comment_navigator.regex.python}
|
||||
}
|
||||
|
||||
for _, cf in ipairs(comment_filetypes) do
|
||||
local cn = comment_navigator.setup({
|
||||
regex = cf[2]
|
||||
})
|
||||
vim.api.nvim_create_autocmd("BufEnter", {
|
||||
pattern = cf[1],
|
||||
callback = function()
|
||||
vim.keymap.set('n', '<space>c', cn.open, { noremap = true, silent = true })
|
||||
end
|
||||
})
|
||||
end
|
||||
```
|
||||
|
||||
|
||||
@@ -0,0 +1,126 @@
|
||||
local plenary = require("plenary")
|
||||
|
||||
local M = {}
|
||||
|
||||
local function filter_comments(settings, content)
|
||||
local cursor_position = vim.api.nvim_win_get_cursor(0)
|
||||
local new_cursor = {1,0}
|
||||
|
||||
local numbers, values = {}, {}
|
||||
local indentations = {}
|
||||
|
||||
for i, v in ipairs(content) do
|
||||
local indent, line = string.match(v, settings.regex)
|
||||
if line then
|
||||
if settings.keep_indent then
|
||||
numbers[#numbers+1] = i
|
||||
values[#values+1] = indent .. line
|
||||
table.insert(indentations, #indent)
|
||||
else
|
||||
numbers[#numbers+1] = i
|
||||
values[#values+1] = line
|
||||
end
|
||||
end
|
||||
|
||||
-- set the cursor position to the comment under the cursor
|
||||
-- or to the previous comment if not on a comment directly.
|
||||
if new_cursor[1] == 1 then
|
||||
if i == cursor_position[1] then
|
||||
new_cursor = {math.max(#numbers,1), indentations[#indentations] or 0}
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- strip down indentation
|
||||
if settings.keep_indent then
|
||||
local min_indentation = math.huge
|
||||
for _, indent in ipairs(indentations) do
|
||||
min_indentation = min_indentation < indent and min_indentation or indent
|
||||
end
|
||||
for i = 1, #values, 1 do
|
||||
values[i] = string.sub(values[i], min_indentation+1)
|
||||
end
|
||||
end
|
||||
return numbers, values, new_cursor
|
||||
end
|
||||
|
||||
function M.setup(options)
|
||||
-- create a new module to support multiple file types
|
||||
local module = {}
|
||||
|
||||
-- default settings
|
||||
module.settings = {
|
||||
regex = M.regex.c, -- the regex used to extract the comments (c-style default)
|
||||
line_numbers = true, -- show the line numbers in the list
|
||||
width = 100, -- width of the window
|
||||
height = 50, -- height of the window
|
||||
borderchars = { "─", "│", "─", "│", "╭", "╮", "╯", "╰" }, -- the borders, nil means no border
|
||||
keep_indent = true, -- preserve the indentation of the file (shows the values in a hierarchical manner)
|
||||
}
|
||||
|
||||
module.settings = vim.tbl_deep_extend("force", module.settings, options)
|
||||
|
||||
-- main entry point, opens the popup window
|
||||
function module.open()
|
||||
local settings = module.settings
|
||||
|
||||
local content_buffer = vim.api.nvim_buf_get_lines(0, 0, vim.api.nvim_buf_line_count(0), false)
|
||||
local line_numbers, content, cursor_position = filter_comments(settings, content_buffer)
|
||||
|
||||
-- FIXME: this is a hotfix
|
||||
-- removes an empty line at the end of the buffer
|
||||
if content[#content] == "" then
|
||||
table.remove(content, #content)
|
||||
end
|
||||
|
||||
-- TODO: avoid module to be able to open multiple popups at the same time
|
||||
module.state = line_numbers
|
||||
|
||||
-- create the buffer for the popup window
|
||||
local buffer = vim.api.nvim_create_buf(false, true)
|
||||
vim.api.nvim_buf_set_lines(buffer, -2, -1, true, content)
|
||||
vim.api.nvim_buf_set_option(buffer, 'readonly', true)
|
||||
vim.api.nvim_buf_set_keymap(buffer, "n", "<Enter>", "", {
|
||||
callback = function()
|
||||
module.go(buffer)
|
||||
end
|
||||
})
|
||||
vim.api.nvim_buf_set_keymap(buffer, "n", "<Esc>",
|
||||
"<cmd>lua vim.api.nvim_buf_delete(" .. buffer .. ", {})<CR>", {})
|
||||
|
||||
local win, _ = plenary.popup.create(buffer, {
|
||||
title = "comment-navigator",
|
||||
minwidth = settings.width,
|
||||
minheight = settings.height,
|
||||
maxheight = settings.height,
|
||||
maxwidth = settings.width,
|
||||
borderchars = settings.borderchars,
|
||||
})
|
||||
|
||||
if settings.line_numbers then
|
||||
vim.api.nvim_win_set_option(win, "number", true)
|
||||
end
|
||||
|
||||
vim.api.nvim_win_set_cursor(win, cursor_position)
|
||||
end
|
||||
|
||||
-- navigates to the comment under the cursor
|
||||
function module.go(buffer)
|
||||
local idx = vim.api.nvim__buf_stats(buffer).current_lnum
|
||||
vim.api.nvim_buf_delete(buffer, {})
|
||||
|
||||
local line = module.state[idx]
|
||||
vim.api.nvim_win_set_cursor(0,{line,0})
|
||||
end
|
||||
|
||||
return module
|
||||
end
|
||||
|
||||
M.regex = {
|
||||
c = "(%s*)///%s*(.*)%s*", -- /// comment
|
||||
lua = "(%s*)%-%-%-%s*(.*)%s*", -- --- comment
|
||||
python = "(%s*)#:%s*(.*)%s*", -- #: comment (not ## because of autoformatters…)
|
||||
erb = "(%s*)<%%%s?# *(.*) *%%>" -- <%# comment %>
|
||||
}
|
||||
|
||||
return M
|
||||
Reference in New Issue
Block a user