branch todos
This commit is contained in:
parent
8b32f22c49
commit
b8e0dee953
@ -143,6 +143,225 @@ end
|
|||||||
-- Keybind for inserting TODO comment
|
-- Keybind for inserting TODO comment
|
||||||
vim.api.nvim_set_keymap("n", "<leader>t", "<cmd>lua insert_todo_comment()<CR>", { noremap = true, silent = true })
|
vim.api.nvim_set_keymap("n", "<leader>t", "<cmd>lua insert_todo_comment()<CR>", { noremap = true, silent = true })
|
||||||
|
|
||||||
|
local function git_output(args)
|
||||||
|
local output = vim.fn.system(args)
|
||||||
|
if vim.v.shell_error ~= 0 then
|
||||||
|
return nil
|
||||||
|
end
|
||||||
|
return vim.split(output, "\n", { trimempty = true })
|
||||||
|
end
|
||||||
|
|
||||||
|
local function branch_todos_base()
|
||||||
|
if vim.g.branch_todos_base then
|
||||||
|
return vim.g.branch_todos_base
|
||||||
|
end
|
||||||
|
|
||||||
|
for _, ref in ipairs({ "origin/main", "origin/master", "main", "master" }) do
|
||||||
|
if git_output({ "git", "rev-parse", "--verify", ref }) then
|
||||||
|
return ref
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
local function branch_todos_entries()
|
||||||
|
local base = branch_todos_base()
|
||||||
|
if not base then
|
||||||
|
return { "No git base found. Set vim.g.branch_todos_base." }
|
||||||
|
end
|
||||||
|
|
||||||
|
local merge_base = git_output({ "git", "merge-base", base, "HEAD" })
|
||||||
|
if not merge_base or not merge_base[1] then
|
||||||
|
return { "Could not find merge-base against " .. base .. "." }
|
||||||
|
end
|
||||||
|
|
||||||
|
local lines = git_output({ "git", "diff", "--unified=0", merge_base[1] })
|
||||||
|
if not lines then
|
||||||
|
return { "Could not read git diff against " .. base .. "." }
|
||||||
|
end
|
||||||
|
|
||||||
|
local added_lines = {}
|
||||||
|
local file
|
||||||
|
local new_line
|
||||||
|
local todo_keywords = { "TODO", "FIXME", "HACK", "XXX", "BUG", "BUGS" }
|
||||||
|
|
||||||
|
for _, line in ipairs(lines) do
|
||||||
|
local diff_file = line:match("^%+%+%+ b/(.+)$")
|
||||||
|
if diff_file then
|
||||||
|
file = diff_file
|
||||||
|
new_line = nil
|
||||||
|
else
|
||||||
|
local hunk_start = line:match("^@@ %-%d+,?%d* %+(%d+),?%d* @@")
|
||||||
|
if hunk_start then
|
||||||
|
new_line = tonumber(hunk_start)
|
||||||
|
elseif new_line and line:sub(1, 1) == "+" and not line:match("^%+%+%+") then
|
||||||
|
local text = line:sub(2)
|
||||||
|
if file then
|
||||||
|
table.insert(added_lines, { file = file, line = new_line, text = text })
|
||||||
|
end
|
||||||
|
new_line = new_line + 1
|
||||||
|
elseif new_line and line:sub(1, 1) ~= "-" then
|
||||||
|
new_line = new_line + 1
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
local function has_todo_keyword(text)
|
||||||
|
local upper_text = text:upper()
|
||||||
|
for _, keyword in ipairs(todo_keywords) do
|
||||||
|
local start = 1
|
||||||
|
while true do
|
||||||
|
local match_start, match_end = upper_text:find(keyword, start, true)
|
||||||
|
if not match_start then
|
||||||
|
break
|
||||||
|
end
|
||||||
|
|
||||||
|
local before = match_start > 1 and upper_text:sub(match_start - 1, match_start - 1) or ""
|
||||||
|
local after = match_end < #upper_text and upper_text:sub(match_end + 1, match_end + 1) or ""
|
||||||
|
if not before:match("[%w_]") and not after:match("[%w_]") then
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
|
||||||
|
start = match_end + 1
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
|
||||||
|
local function list_depth_delta(text)
|
||||||
|
local _, opens = text:gsub("%[", "")
|
||||||
|
local _, closes = text:gsub("%]", "")
|
||||||
|
return opens - closes
|
||||||
|
end
|
||||||
|
|
||||||
|
local entries = {}
|
||||||
|
local index = 1
|
||||||
|
while index <= #added_lines do
|
||||||
|
local item = added_lines[index]
|
||||||
|
if has_todo_keyword(item.text) then
|
||||||
|
table.insert(entries, string.format("%s:%d", item.file, item.line))
|
||||||
|
table.insert(entries, item.text)
|
||||||
|
|
||||||
|
if item.text:lower():match('todo:%s*"""') and not item.text:match('""".*"""') then
|
||||||
|
index = index + 1
|
||||||
|
while index <= #added_lines do
|
||||||
|
local next_item = added_lines[index]
|
||||||
|
if next_item.file ~= item.file then
|
||||||
|
break
|
||||||
|
end
|
||||||
|
table.insert(entries, next_item.text)
|
||||||
|
if next_item.text:find('"""', 1, true) then
|
||||||
|
break
|
||||||
|
end
|
||||||
|
index = index + 1
|
||||||
|
end
|
||||||
|
elseif item.text:match("[=:]%s*%[") and list_depth_delta(item.text) > 0 then
|
||||||
|
local depth = list_depth_delta(item.text)
|
||||||
|
index = index + 1
|
||||||
|
while index <= #added_lines do
|
||||||
|
local next_item = added_lines[index]
|
||||||
|
if next_item.file ~= item.file then
|
||||||
|
break
|
||||||
|
end
|
||||||
|
|
||||||
|
table.insert(entries, next_item.text)
|
||||||
|
depth = depth + list_depth_delta(next_item.text)
|
||||||
|
if depth <= 0 then
|
||||||
|
break
|
||||||
|
end
|
||||||
|
|
||||||
|
index = index + 1
|
||||||
|
end
|
||||||
|
elseif item.text:match("^%s*#") then
|
||||||
|
index = index + 1
|
||||||
|
while index <= #added_lines do
|
||||||
|
local next_item = added_lines[index]
|
||||||
|
if next_item.file ~= item.file or not next_item.text:match("^%s*#") then
|
||||||
|
break
|
||||||
|
end
|
||||||
|
table.insert(entries, next_item.text)
|
||||||
|
index = index + 1
|
||||||
|
end
|
||||||
|
index = index - 1
|
||||||
|
end
|
||||||
|
|
||||||
|
table.insert(entries, "")
|
||||||
|
end
|
||||||
|
|
||||||
|
index = index + 1
|
||||||
|
end
|
||||||
|
|
||||||
|
if #entries == 0 then
|
||||||
|
return { "No TODOs added on this branch against " .. base .. "." }
|
||||||
|
end
|
||||||
|
|
||||||
|
return entries
|
||||||
|
end
|
||||||
|
|
||||||
|
local function jump_to_branch_todo()
|
||||||
|
local line = vim.api.nvim_get_current_line()
|
||||||
|
local file, linenum = line:match("([^:%s]+):(%d+)")
|
||||||
|
if not file then
|
||||||
|
local cursor = vim.api.nvim_win_get_cursor(0)
|
||||||
|
for row = cursor[1] - 1, 1, -1 do
|
||||||
|
local previous_line = vim.api.nvim_buf_get_lines(0, row - 1, row, false)[1] or ""
|
||||||
|
file, linenum = previous_line:match("([^:%s]+):(%d+)")
|
||||||
|
if file then
|
||||||
|
break
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
if file and linenum then
|
||||||
|
local current_win = vim.api.nvim_get_current_win()
|
||||||
|
vim.cmd("wincmd h")
|
||||||
|
if current_win == vim.api.nvim_get_current_win() then
|
||||||
|
vim.api.nvim_set_current_win(current_win)
|
||||||
|
end
|
||||||
|
|
||||||
|
vim.cmd("edit " .. vim.fn.fnameescape(file))
|
||||||
|
vim.api.nvim_win_set_cursor(0, { tonumber(linenum), 0 })
|
||||||
|
if vim.api.nvim_win_is_valid(current_win) and current_win ~= vim.api.nvim_get_current_win() then
|
||||||
|
vim.api.nvim_set_current_win(current_win)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
local function refresh_branch_todos(buf)
|
||||||
|
local cursor = vim.api.nvim_win_get_cursor(0)
|
||||||
|
vim.bo[buf].modifiable = true
|
||||||
|
vim.api.nvim_buf_set_lines(buf, 0, -1, false, branch_todos_entries())
|
||||||
|
vim.bo[buf].modifiable = false
|
||||||
|
|
||||||
|
local line_count = vim.api.nvim_buf_line_count(buf)
|
||||||
|
vim.api.nvim_win_set_cursor(0, { math.min(cursor[1], line_count), cursor[2] })
|
||||||
|
end
|
||||||
|
|
||||||
|
local function open_branch_todos()
|
||||||
|
local name = "branch-todos"
|
||||||
|
local buf = vim.fn.bufnr(name)
|
||||||
|
if buf == -1 then
|
||||||
|
buf = vim.api.nvim_create_buf(true, false)
|
||||||
|
vim.api.nvim_buf_set_name(buf, name)
|
||||||
|
end
|
||||||
|
|
||||||
|
vim.api.nvim_set_current_buf(buf)
|
||||||
|
vim.bo[buf].buftype = "nofile"
|
||||||
|
vim.bo[buf].bufhidden = "hide"
|
||||||
|
vim.bo[buf].swapfile = false
|
||||||
|
vim.bo[buf].filetype = "branch-todos"
|
||||||
|
|
||||||
|
refresh_branch_todos(buf)
|
||||||
|
|
||||||
|
vim.keymap.set("n", "<CR>", jump_to_branch_todo, { buffer = buf, desc = "Jump to branch TODO" })
|
||||||
|
vim.keymap.set("n", "r", function()
|
||||||
|
refresh_branch_todos(buf)
|
||||||
|
end, { buffer = buf, desc = "Refresh branch TODOs" })
|
||||||
|
vim.keymap.set("n", "q", "<cmd>bdelete<CR>", { buffer = buf, desc = "Close branch TODOs" })
|
||||||
|
end
|
||||||
|
|
||||||
|
vim.api.nvim_create_user_command("BranchTodos", open_branch_todos, {})
|
||||||
|
vim.keymap.set("n", "<leader>xb", open_branch_todos, { desc = "Branch TODOs" })
|
||||||
|
|
||||||
-- floating NOTES
|
-- floating NOTES
|
||||||
function open_notes()
|
function open_notes()
|
||||||
local notes_file = vim.env.HOME .. "/git/notes/todo.md" -- Path to your notes file
|
local notes_file = vim.env.HOME .. "/git/notes/todo.md" -- Path to your notes file
|
||||||
|
|||||||
@ -130,6 +130,11 @@ vim.api.nvim_create_autocmd("FileType", {
|
|||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
|
local rg = vim.system({ "rg", "-q", "--glob", "*.ex", "use ExOf", root }):wait()
|
||||||
|
if rg.code ~= 0 then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
vim.lsp.start({
|
vim.lsp.start({
|
||||||
name = "exofx-lsp",
|
name = "exofx-lsp",
|
||||||
cmd_env = { MIX_ENV = "test" },
|
cmd_env = { MIX_ENV = "test" },
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user