Skip to content

Add TODO's section to status buffer - WIP: #1586

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 6 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -291,6 +291,10 @@ neogit.setup {
folded = true,
hidden = false,
},
todo = {
folded = true,
hidden = false,
},
},
mappings = {
commit_editor = {
Expand Down
9 changes: 9 additions & 0 deletions doc/neogit.txt
Original file line number Diff line number Diff line change
Expand Up @@ -1835,6 +1835,15 @@ Untracked Files *neogit_status_buffer_untracked*
untracked files entirely, "normal" to show files and directories (default),
or "all" to show all files in all directories.

TODOs *neogit_status_buffer_todos*
Requires `ripgrep` and `sort` to be available on your system. By default,
finds all TODO notes in the codebase matching:
- " TODO: "
- " NOTE: "
- " FIXME: "
- " HACK: "

Can be configured to find other/different keywords.
==============================================================================
Editor Buffer *neogit_editor_buffer*

Expand Down
25 changes: 25 additions & 0 deletions lua/neogit/buffers/status/actions.lua
Original file line number Diff line number Diff line change
Expand Up @@ -1124,6 +1124,13 @@ M.n_goto_file = function(self)
return function()
local item = self.buffer.ui:get_item_under_cursor()

-- Goto PLUGIN (TODO, etc...)
if item and item.goto_path and item.goto_cursor then
self:close()
vim.schedule_wrap(open)("edit", item.goto_path, item.goto_cursor)
return
end

-- Goto FILE
if item and item.absolute_path then
local cursor = translate_cursor_location(self, item)
Expand All @@ -1145,6 +1152,12 @@ M.n_tab_open = function(self)
return function()
local item = self.buffer.ui:get_item_under_cursor()

-- Goto PLUGIN (TODO, etc...)
if item and item.goto_path and item.goto_cursor then
open("tabedit", item.goto_path, item.goto_cursor)
return
end

if item and item.absolute_path then
open("tabedit", item.absolute_path, translate_cursor_location(self, item))
end
Expand All @@ -1156,6 +1169,12 @@ M.n_split_open = function(self)
return function()
local item = self.buffer.ui:get_item_under_cursor()

-- Goto PLUGIN (TODO, etc...)
if item and item.goto_path and item.goto_cursor then
open("split", item.goto_path, item.goto_cursor)
return
end

if item and item.absolute_path then
open("split", item.absolute_path, translate_cursor_location(self, item))
end
Expand All @@ -1167,6 +1186,12 @@ M.n_vertical_split_open = function(self)
return function()
local item = self.buffer.ui:get_item_under_cursor()

-- Goto PLUGIN (TODO, etc...)
if item and item.goto_path and item.goto_cursor then
open("vsplit", item.goto_path, item.goto_cursor)
return
end

if item and item.absolute_path then
open("vsplit", item.absolute_path, translate_cursor_location(self, item))
end
Expand Down
131 changes: 116 additions & 15 deletions lua/neogit/buffers/status/ui.lua
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ local row = Ui.row
local text = Ui.text

local map = util.map
local filter_map = util.filter_map

local EmptyLine = common.EmptyLine
local List = common.List
Expand Down Expand Up @@ -158,6 +159,14 @@ local SectionTitleMerge = Component.new(function(props)
end)

local Section = Component.new(function(props)
if not props.visible then
return col {}
end

if type(props.items) == "function" then
props.items = props.items()
end

local count
if props.count then
count = { text(" ("), text.highlight("NeogitSectionHeaderCount")(#props.items), text(")") }
Expand All @@ -176,6 +185,10 @@ local Section = Component.new(function(props)
end)

local SequencerSection = Component.new(function(props)
if not props.visible then
return col {}
end

return col.tag("Section")({
row(util.merge(props.title)),
col(map(props.items, props.render)),
Expand All @@ -189,6 +202,10 @@ local SequencerSection = Component.new(function(props)
end)

local RebaseSection = Component.new(function(props)
if not props.visible then
return col {}
end

return col.tag("Section")({
row(util.merge(props.title, {
text(" ("),
Expand Down Expand Up @@ -430,6 +447,10 @@ local SectionItemBisect = Component.new(function(item)
end)

local BisectDetailsSection = Component.new(function(props)
if not props.visible then
return col {}
end

return col.tag("Section")({
row(util.merge(props.title, { text(" "), text.highlight("NeogitObjectId")(props.commit.oid) })),
row {
Expand Down Expand Up @@ -457,6 +478,36 @@ local BisectDetailsSection = Component.new(function(props)
})
end)

local SectionItemTodo = Component.new(function(item)
local function present_item(item)
return row({
text.highlight(item.highlight)(item.kind),
text(" "),
text(item.message),
}, {
yankable = ("%s:%d"):format(item.path, item.line),
item = {
goto_path = item.path,
goto_cursor = { item.line, item.column },
},
})
end

local grouped_items = map(item, present_item)
table.insert(
grouped_items,
1,
row {
text(item[1].path),
text.highlight("NeogitObjectId")(" ("),
text.highlight("NeogitObjectId")(#item),
text.highlight("NeogitObjectId")(")")
}
)

return col.tag("Section")(grouped_items, { foldable = true, folded = true })
end)

function M.Status(state, config)
-- stylua: ignore start
local show_hint = not config.disable_hint
Expand Down Expand Up @@ -516,6 +567,9 @@ function M.Status(state, config)
local show_recent = #state.recent.items > 0
and not config.sections.recent.hidden

local show_todos = vim.fn.executable("rg") == 1
and not config.sections.todo.hidden

return {
List {
items = {
Expand Down Expand Up @@ -557,7 +611,8 @@ function M.Status(state, config)
},
}, { foldable = true, folded = config.status.HEAD_folded }),
EmptyLine(),
show_merge and SequencerSection {
SequencerSection {
visible = show_merge,
title = SectionTitleMerge {
title = "Merging",
branch = state.merge.branch,
Expand All @@ -568,7 +623,8 @@ function M.Status(state, config)
folded = config.sections.sequencer.folded,
name = "merge",
},
show_rebase and RebaseSection {
RebaseSection {
visible = show_rebase,
title = SectionTitleRebase {
title = "Rebasing",
head = state.rebase.head,
Expand All @@ -583,66 +639,75 @@ function M.Status(state, config)
folded = config.sections.rebase.folded,
name = "rebase",
},
show_cherry_pick and SequencerSection {
SequencerSection {
visible = show_cherry_pick,
title = SectionTitle { title = "Cherry Picking", highlight = "NeogitPicking" },
render = SectionItemSequencer,
items = util.reverse(state.sequencer.items),
folded = config.sections.sequencer.folded,
name = "cherry_pick",
},
show_revert and SequencerSection {
SequencerSection {
visible = show_revert,
title = SectionTitle { title = "Reverting", highlight = "NeogitReverting" },
render = SectionItemSequencer,
items = util.reverse(state.sequencer.items),
folded = config.sections.sequencer.folded,
name = "revert",
},
show_bisect and BisectDetailsSection {
BisectDetailsSection {
visible = show_bisect,
title = SectionTitle { title = "Bisecting at", highlight = "NeogitBisecting" },
commit = state.bisect.current,
folded = config.sections.bisect.folded,
name = "bisect_details",
},
show_bisect and SequencerSection {
SequencerSection {
visible = show_bisect,
title = SectionTitle { title = "Bisecting Log", highlight = "NeogitBisecting" },
render = SectionItemBisect,
items = state.bisect.items,
folded = config.sections.bisect.folded,
name = "bisect",
},
show_untracked and Section {
Section {
visible = show_untracked,
title = SectionTitle { title = "Untracked files", highlight = "NeogitUntrackedfiles" },
count = true,
render = SectionItemFile("untracked", config),
items = state.untracked.items,
folded = config.sections.untracked.folded,
name = "untracked",
},
show_unstaged and Section {
Section {
visible = show_unstaged,
title = SectionTitle { title = "Unstaged changes", highlight = "NeogitUnstagedchanges" },
count = true,
render = SectionItemFile("unstaged", config),
items = state.unstaged.items,
folded = config.sections.unstaged.folded,
name = "unstaged",
},
show_staged and Section {
Section {
visible = show_staged,
title = SectionTitle { title = "Staged changes", highlight = "NeogitStagedchanges" },
count = true,
render = SectionItemFile("staged", config),
items = state.staged.items,
folded = config.sections.staged.folded,
name = "staged",
},
show_stashes and Section {
Section {
visible = show_stashes,
title = SectionTitle { title = "Stashes", highlight = "NeogitStashes" },
count = true,
render = SectionItemStash,
items = state.stashes.items,
folded = config.sections.stashes.folded,
name = "stashes",
},
show_upstream_unmerged and Section {
Section {
visible = show_upstream_unmerged,
title = SectionTitleRemote {
title = "Unmerged into",
ref = state.upstream.ref,
Expand All @@ -654,7 +719,8 @@ function M.Status(state, config)
folded = config.sections.unmerged_upstream.folded,
name = "upstream_unmerged",
},
show_pushRemote_unmerged and Section {
Section {
visible = show_pushRemote_unmerged,
title = SectionTitleRemote {
title = "Unpushed to",
ref = state.pushRemote.ref,
Expand All @@ -666,15 +732,17 @@ function M.Status(state, config)
folded = config.sections.unmerged_pushRemote.folded,
name = "pushRemote_unmerged",
},
not show_upstream_unmerged and show_recent and Section {
Section {
visible = not show_upstream_unmerged and show_recent,
title = SectionTitle { title = "Recent Commits", highlight = "NeogitRecentcommits" },
count = false,
render = SectionItemCommit,
items = state.recent.items,
folded = config.sections.recent.folded,
name = "recent",
},
show_upstream_unpulled and Section {
Section {
visible = show_upstream_unpulled,
title = SectionTitleRemote {
title = "Unpulled from",
ref = state.upstream.ref,
Expand All @@ -686,7 +754,8 @@ function M.Status(state, config)
folded = config.sections.unpulled_upstream.folded,
name = "upstream_unpulled",
},
show_pushRemote_unpulled and Section {
Section {
visible = show_pushRemote_unpulled,
title = SectionTitleRemote {
title = "Unpulled from",
ref = state.pushRemote.ref,
Expand All @@ -698,6 +767,38 @@ function M.Status(state, config)
folded = config.sections.unpulled_pushRemote.folded,
name = "pushRemote_unpulled",
},
Section {
visible = show_todos,
title = SectionTitle { title = "TODOs", highlight = "NeogitRecentcommits" },
render = SectionItemTodo,
folded = true,
name = "todos_plugin",
items = function()
local Collection = require("neogit.lib.collection")

local kinds = table.concat(vim.tbl_keys(config.sections.todo.keywords), "|")
local items = vim.system(
{ "rg", " (" .. kinds .. "): ", "--vimgrep", "--sortr=path" },
{ text = true }
):wait()

items = filter_map(vim.split(items.stdout, "\n"), function(line)
local path, linenr, column, kind, msg = line:match("^([^:]+):(%d+):(%d+):.- (%w+): (.+)$")
if path then
return {
path = path,
line = linenr,
column = column,
message = msg,
kind = kind,
highlight = config.sections.todo.keywords[kind]
}
end
end)

return Collection.new(items):group_by("path")
end
}
},
},
}
Expand Down
Loading
Loading