From 43d65b1d1bd844b1af0e05eddbc90fbb2ec703f8 Mon Sep 17 00:00:00 2001 From: Corey Kaylor Date: Wed, 4 Nov 2026 18:47:13 -0500 Subject: [PATCH 1/2] Close views with q everywhere and swap views in one tab q in the commit panel now closes the whole view, the same as q in the diff panes, and :DiffBanditClose does it from the command line. gzp toggles the panel in 2-way diffs, and the session close key is configurable via navigation.close_key. Closing a view saves an unfinished commit message for the repository; the next panel opened there restores it, and committing clears it. Closed hosts delete their panel buffers so a modified commit buffer no longer blocks :qa with E37. Moving the panel selection between a merge conflict and a changed file now closes the previous view instead of leaving its tab behind. Fixes #20 Fixes #22 --- README.md | 20 +++++++- doc/diffbandit.txt | 23 ++++++++- lua/diffbandit/config.lua | 2 + lua/diffbandit/init.lua | 24 +++++++++ lua/diffbandit/merge/init.lua | 6 +++ lua/diffbandit/panel/commit_host.lua | 2 + lua/diffbandit/panel/init.lua | 73 ++++++++++++++++++++++++++-- lua/diffbandit/session/init.lua | 65 +++++++++++++++++++++++-- lua/diffbandit/state.lua | 3 ++ plugin/diffbandit.lua | 6 +++ tests/specs/15_running.lua | 41 ++++++++++++++++ tests/specs/20_git_merge.lua | 57 ++++++++++++++++++++-- tests/specs/25_launcher.lua | 6 +-- 13 files changed, 310 insertions(+), 18 deletions(-) diff --git a/README.md b/README.md index b8be135..88c4228 100644 --- a/README.md +++ b/README.md @@ -182,6 +182,12 @@ Resolve a Git conflict: :DiffBanditMerge path/to/conflicted-file ``` +Close the DiffBandit view in the current tab (same as `q`): + +```vim +:DiffBanditClose +``` + ## Editor Integration DiffBandit uses real editable buffers for the right-side target in file, @@ -277,11 +283,12 @@ Inside a diff view: | `]d` | Align both panes to the bottom of the documents | | `]s` | Snap the other pane to the cursor line | | `C` | Open or focus the commit panel for the current Git file | +| `gzp` | Show or hide the commit panel | | `` | Toggle stage for the active Git hunk | | `>>` | Apply the left side to the right target | | `<<` | Apply the right side to the left target | | `u` | Undo the last DiffBandit hunk action | -| `q` | Close the diff session | +| `q` | Close the diff session (`navigation.close_key`) | At a file boundary, `]c` and `[c` first notify that the next press will move to the next or previous file. This keeps hunk navigation deliberate while still @@ -332,7 +339,16 @@ opened by `:DiffBanditGit`. | `` in the commit message window | Toggle amend mode | | `:w` in the commit message window | Commit staged changes | | `R` | Refresh the panel | -| `q` | Close the panel | +| `gzp` | Hide the panel, keeping the diff open | +| `q` | Close the whole view (diff, merge resolver, or standalone panel) | + +`q` closes the view the same way from the panel and the diff panes, as does +`:DiffBanditClose`. An unfinished commit message is kept: closing the view +saves it for the repository, and the next commit panel opened there restores +it. Committing clears it. + +Moving the panel selection between a merge conflict and a changed file swaps +the view in place, in the same tab. The panel validates empty commit messages and missing staged changes before committing, and rejects commits while merge conflicts remain unresolved. In diff --git a/doc/diffbandit.txt b/doc/diffbandit.txt index 58b0f77..00b8c29 100644 --- a/doc/diffbandit.txt +++ b/doc/diffbandit.txt @@ -125,6 +125,12 @@ COMMANDS *diffbandit-commands* Open a three-pane resolver for an unmerged Git conflict. If [path] is omitted, the current buffer path is used. + *:DiffBanditClose* +:DiffBanditClose + Close the DiffBandit view in the current tab: a diff, merge, or folder + session together with its tab page, or a standalone commit panel. + Equivalent to pressing `q`. + *:DiffBanditLaunch* :DiffBanditLaunch Entry point for the `bin/diffbandit` launcher; see @@ -204,7 +210,11 @@ Diff view mappings: u Undo the last DiffBandit hunk action for the current file. *diffbandit-q* - q Close the diff session. + *diffbandit-gzp* + gzp Show or hide the commit panel for a Git diff. + + q Close the diff session. Set by `navigation.close_key`; + false disables it. At a file boundary, |diffbandit-]c| and |diffbandit-[c| first notify that the next press will move to the next or previous file. This keeps file navigation @@ -329,7 +339,14 @@ Panel mappings: a Open file actions for the selected file. cc Focus the commit message window. R Refresh the panel. - q Close the panel. + gzp Hide the panel, keeping the diff open. + q Close the whole view: the diff or merge resolver with its + tab page, or the standalone panel. Same as |:DiffBanditClose|. + +Closing a view keeps an unfinished commit message: it is saved for the +repository and restored by the next commit panel opened there. Committing +clears it. Moving the panel selection between a merge conflict and a changed +file swaps the view in place, in the same tab page. Commit message window mappings: @@ -414,6 +431,7 @@ Common configuration: bottom = "]d", }, snap_key = "]s", + close_key = "q", }, git = { default_mode = "all", @@ -435,6 +453,7 @@ Common configuration: file_actions = "a", toggle_amend = "", refresh = "R", + toggle_panel = "gzp", close = "q", }, }, diff --git a/lua/diffbandit/config.lua b/lua/diffbandit/config.lua index ced44bd..2b977bf 100644 --- a/lua/diffbandit/config.lua +++ b/lua/diffbandit/config.lua @@ -120,6 +120,7 @@ local defaults = { bottom = "]d", }, snap_key = "]s", + close_key = "q", prompt_message = "Reached final change in this diff. Open next file with changes?", on_request_next_file = nil, }, @@ -155,6 +156,7 @@ local defaults = { file_actions = "a", toggle_amend = "", refresh = "R", + toggle_panel = "gzp", close = "q", }, }, diff --git a/lua/diffbandit/init.lua b/lua/diffbandit/init.lua index 52a8ac3..43f7bad 100644 --- a/lua/diffbandit/init.lua +++ b/lua/diffbandit/init.lua @@ -598,4 +598,28 @@ function M.undo() return call_current_session("undo_action") end +-- Close the DiffBandit view in the current tab: a diff, merge, or folder +-- session (with its tabpage) and/or a standalone commit panel. Under the +-- bin/diffbandit launcher this quits nvim, matching the panel's close key. +function M.close() + local tab = vim.api.nvim_get_current_tabpage() + local session = live_session(tab) + local panel = live_panel(tab) + if not session and not panel then + nvim.notify_info("no DiffBandit view in this tab") + return false + end + if state.quit_on_close then + pcall(vim.cmd, "confirm qall") + return true + end + if panel then + panel:close() + end + if session then + session:close() + end + return true +end + return M diff --git a/lua/diffbandit/merge/init.lua b/lua/diffbandit/merge/init.lua index 376e13b..9fc8e34 100644 --- a/lua/diffbandit/merge/init.lua +++ b/lua/diffbandit/merge/init.lua @@ -1919,6 +1919,11 @@ function Merge:goto_queue_file(index, chunk_position, opts) return false end state.register(session) + -- Replace this merge view rather than stacking a tab per switch (issue #20). + self:close() + if session.tabpage and vim.api.nvim_tabpage_is_valid(session.tabpage) then + pcall(vim.api.nvim_set_current_tabpage, session.tabpage) + end return true end @@ -2157,6 +2162,7 @@ function Merge:close(from_autocmd) if self.disposed then return end + panel_mod.save_draft(self) self.disposed = true kitty.detach(self) self:clear_keymaps() diff --git a/lua/diffbandit/panel/commit_host.lua b/lua/diffbandit/panel/commit_host.lua index 90d255e..065a7fe 100644 --- a/lua/diffbandit/panel/commit_host.lua +++ b/lua/diffbandit/panel/commit_host.lua @@ -77,8 +77,10 @@ function CommitPanel:close() if self.disposed then return end + panel_mod.save_draft(self) self:hide_commit_panel() self.disposed = true + panel_mod.delete_buffers(self) state.unregister_panel(self.tabpage) end diff --git a/lua/diffbandit/panel/init.lua b/lua/diffbandit/panel/init.lua index 646a68c..7f1e1f9 100644 --- a/lua/diffbandit/panel/init.lua +++ b/lua/diffbandit/panel/init.lua @@ -281,6 +281,41 @@ function M.capture_message_lines(session) return panel.message_lines or { "" } end +local function has_text(lines) + return vim.trim(table.concat(lines or {}, "\n")) ~= "" +end + +local function draft_root(session) + if is_review_panel(session) then + return nil + end + local queue = (session or {}).file_queue + return queue and queue.kind == "git" and queue.root or nil +end + +-- Remember an unfinished commit message per repository, so closing the view +-- (q, :DiffBanditClose, :tabclose) never throws it away; the next panel +-- opened for that repository restores it. A panel that never rendered its +-- message (and carries none) leaves the saved draft alone, and so does amend +-- mode, whose message is the amended commit's rather than a draft. +function M.save_draft(session) + local panel = (session or {}).panel + local root = draft_root(session) + if not (panel and root) or panel.amend then + return + end + local lines + if panel.message_initialized and panel.commit_buf and vim.api.nvim_buf_is_valid(panel.commit_buf) then + lines = commit_message_lines_from_buffer(panel.commit_buf) + else + lines = panel.message_lines + if not has_text(lines) then + return + end + end + state.commit_drafts[root] = has_text(lines) and vim.deepcopy(lines) or nil +end + function M.clear_amend_opts(opts) local clean = vim.tbl_extend("force", {}, opts or {}) clean.stage_base = nil @@ -671,6 +706,11 @@ function M.render_commit(session) end if not panel.message_initialized then panel.message_initialized = true + local root = draft_root(session) + local draft = root and state.commit_drafts[root] + if draft and not panel.amend and not has_text(panel.message_lines) then + panel.message_lines = vim.deepcopy(draft) + end if #(panel.message_lines or {}) == 0 then panel.message_lines = { "" } end @@ -929,6 +969,10 @@ function M.commit(session) nvim.notify_warn(panel.validation_message) return false, err end + local root = draft_root(session) + if root then + state.commit_drafts[root] = nil + end panel.message_lines = { "" } panel.message_initialized = false panel.validation_message = nil @@ -943,11 +987,25 @@ function M.commit(session) return true, nil end -function M.close(session) - if is_review_panel(session) and panel_api.has(session, "close") then - panel_api.close(session) +-- Delete a closed host's panel buffers. The commit buffer is an acwrite +-- buffer that is usually modified, so leaving it loaded would make :qa fail +-- with E37; its text is already saved as a draft by save_draft(). +function M.delete_buffers(session) + local panel = (session or {}).panel + if not panel then return end + for _, buf in ipairs({ panel.nav_buf, panel.commit_buf }) do + if buf and vim.api.nvim_buf_is_valid(buf) then + pcall(vim.api.nvim_set_option_value, "modified", false, { buf = buf }) + pcall(vim.api.nvim_buf_delete, buf, { force = true }) + end + end +end + +-- Hide the panel windows. Closing the whole view is the host's close(), which +-- the panel's close key calls directly. +function M.close(session) local panel = session.panel if not panel then return @@ -1011,7 +1069,14 @@ function M.setup_keymaps(session) pcall(vim.cmd, "confirm qall") return end - M.close(session) + -- q closes the whole view (diff, merge, or standalone panel), the same + -- as q in the diff panes and :DiffBanditClose; the toggle_panel key + -- hides only the panel. + if panel_api.has(session, "close") then + panel_api.close(session) + else + M.close(session) + end end -- lhs = nil/false skips the map (unset config key or failed condition); diff --git a/lua/diffbandit/session/init.lua b/lua/diffbandit/session/init.lua index ef15014..d905dbc 100644 --- a/lua/diffbandit/session/init.lua +++ b/lua/diffbandit/session/init.lua @@ -558,9 +558,11 @@ function Session:setup_keymaps() map(buf, "[c", function() self:goto_prev_chunk() end) - map(buf, "q", function() - self:close() - end) + if navigation.close_key then + map(buf, navigation.close_key, function() + self:close() + end) + end if document_keys.top then map(buf, document_keys.top, function() self:goto_document_edge("top") @@ -627,6 +629,14 @@ function Session:setup_keymaps() self:focus_commit_panel_for_current_file() end) end + if self.file_queue and self.file_queue.kind == "git" and panel_keys.toggle_panel then + for _, buf in ipairs({ self.left_buf, self.right_buf }) do + map(buf, panel_keys.toggle_panel, function() + self:toggle_commit_panel() + end) + end + self:map_panel_toggle() + end map(self.left_buf, "l", function() if self.right_win and vim.api.nvim_win_is_valid(self.right_win) then vim.api.nvim_set_current_win(self.right_win) @@ -1002,9 +1012,11 @@ function Session:dispose() if self.disposed then return end + panel_mod.save_draft(self) self.disposed = true kitty.detach(self) self:clear_keymaps() + panel_mod.delete_buffers(self) -- Editable right reuses the user's buffer; without this, band/intraline -- extmarks stay visible after q returns to that buffer (issue #5). self:clear_buffer_paint_namespaces(self.right_buf) @@ -1051,6 +1063,22 @@ function Session:close() end end +-- Switching the panel between a changed file and a merge conflict starts a +-- different host in its own tab; close this one so the switch replaces the +-- view instead of stacking a tab per move (issue #20). Unlike close(), this +-- never returns to a parent view: the replacement is where focus belongs. +function Session:close_for_replacement(next_host) + if self.tabpage and vim.api.nvim_tabpage_is_valid(self.tabpage) then + pcall(vim.api.nvim_set_current_tabpage, self.tabpage) + pcall(vim.cmd, "tabclose") + end + self:dispose() + local next_tab = next_host and next_host.tabpage + if next_tab and vim.api.nvim_tabpage_is_valid(next_tab) then + pcall(vim.api.nvim_set_current_tabpage, next_tab) + end +end + function Session:reset_pending_file_boundary() self.pending_file_boundary = nil end @@ -1486,6 +1514,7 @@ function Session:open_merge_file(index, opts) nvim.notify_error(tostring(start_err)) return false end + self:close_for_replacement(session) if opts.navigate_change == "prev" then session:goto_prev_conflict() elseif opts.navigate_change == "next" then @@ -1622,6 +1651,7 @@ function Session:show_commit_panel(opts) else panel_mod.attach(self) end + self:map_panel_toggle() self:resize_layout() panel_mod.focus_nav(self) return true @@ -1644,12 +1674,41 @@ function Session:focus_commit_panel_for_current_file() return self:show_commit_panel({ select_current_file = true }) end +-- The toggle key also hides the panel while focused in it (as in merge). +-- Panel buffers can be created after setup_keymaps, so show_commit_panel +-- re-runs this. +function Session:map_panel_toggle() + local key = config_mod.section(self.config, "git", "panel", "keys").toggle_panel + local panel = self.panel + if not (key and panel and self.file_queue and self.file_queue.kind == "git") then + return + end + for _, buf in ipairs({ panel.nav_buf, panel.commit_buf }) do + if buf and vim.api.nvim_buf_is_valid(buf) then + self:set_buffer_keymap("n", buf, key, function() + self:toggle_commit_panel() + end, { nowait = true, noremap = true, silent = true }) + end + end +end + function Session:hide_commit_panel() if not self.panel then return false end + local current = vim.api.nvim_get_current_win() + local in_panel = current == self.panel.nav_win or current == self.panel.commit_win panel_mod.close(self) self:resize_layout() + if in_panel then + local target = self.last_source_win + if not (target and vim.api.nvim_win_is_valid(target)) then + target = self.right_win + end + if target and vim.api.nvim_win_is_valid(target) then + pcall(vim.api.nvim_set_current_win, target) + end + end return true end diff --git a/lua/diffbandit/state.lua b/lua/diffbandit/state.lua index a0bd492..7326c74 100644 --- a/lua/diffbandit/state.lua +++ b/lua/diffbandit/state.lua @@ -12,6 +12,9 @@ local State = { -- Set by the standalone launcher (bin/diffbandit): the panel's close key -- quits nvim instead of only hiding the panel. quit_on_close = false, + -- Unfinished commit messages by repository root, saved when a view with a + -- commit panel closes and restored the next time a panel opens there. + commit_drafts = {}, } function State.set_config(user) diff --git a/plugin/diffbandit.lua b/plugin/diffbandit.lua index 215c7f2..3802128 100644 --- a/plugin/diffbandit.lua +++ b/plugin/diffbandit.lua @@ -246,6 +246,12 @@ end, { desc = "Open DiffBandit folder diff view", }) +vim.api.nvim_create_user_command("DiffBanditClose", function() + diffbandit.close() +end, { + desc = "Close the DiffBandit view in the current tab", +}) + vim.api.nvim_create_user_command("DiffBanditLaunch", function() require("diffbandit.launcher").main() end, { diff --git a/tests/specs/15_running.lua b/tests/specs/15_running.lua index fcd1230..6e0a6fc 100644 --- a/tests/specs/15_running.lua +++ b/tests/specs/15_running.lua @@ -77,3 +77,44 @@ do state_mod.sessions = saved_sessions state_mod.panels = saved_panels end + +-- Suite: :DiffBanditClose closes the current tab's view (issue #22) +do + local diffbandit = require("diffbandit") + if vim.fn.exists(":DiffBanditClose") ~= 2 then + dofile(root .. "/plugin/diffbandit.lua") + end + + local origin = vim.api.nvim_get_current_tabpage() + local session = assert(diffbandit.buffers( + (function() + local b = vim.api.nvim_create_buf(false, true) + vim.api.nvim_buf_set_lines(b, 0, -1, false, { "left" }) + return b + end)(), + (function() + local b = vim.api.nvim_create_buf(false, true) + vim.api.nvim_buf_set_lines(b, 0, -1, false, { "right" }) + return b + end)())) + local session_tab = session.tabpage + assert_ne(session_tab, origin, "Session opens in its own tab") + vim.cmd("DiffBanditClose") + assert_eq(session.disposed, true, ":DiffBanditClose disposes the current-tab session") + assert_eq(vim.api.nvim_tabpage_is_valid(session_tab), false, ":DiffBanditClose closes the session tab") + assert_eq(vim.api.nvim_get_current_tabpage(), origin, ":DiffBanditClose returns to the origin tab") + + local closed = 0 + state_mod.panels[origin] = { + disposed = false, + close = function(self) + closed = closed + 1 + self.disposed = true + end, + } + assert_eq(diffbandit.close(), true, "close() reports closing a standalone panel") + assert_eq(closed, 1, "close() closes the standalone commit panel in this tab") + state_mod.panels[origin] = nil + + assert_eq(diffbandit.close(), false, "close() is a no-op without a DiffBandit view in this tab") +end diff --git a/tests/specs/20_git_merge.lua b/tests/specs/20_git_merge.lua index 9efd91a..3f501e3 100644 --- a/tests/specs/20_git_merge.lua +++ b/tests/specs/20_git_merge.lua @@ -1430,8 +1430,57 @@ if vim.fn.executable("git") == 1 then "Panel preview should keep focus in the panel navigation window") assert_eq(merge_session.panel.message_lines[1], "draft merge commit", "Panel preview should carry commit message text into the merge resolver") - merge_session:close() - session:close() + assert_eq(session.disposed, true, + "Switching to a conflict should close the changed-file view instead of keeping its tab (issue #20)") + local tab_count = #vim.api.nvim_list_tabpages() + + assert_eq(merge_session:goto_queue_file(1, "top"), true, + "Panel preview should switch from a conflict back to a changed file") + local back = state_mod.sessions[vim.api.nvim_get_current_tabpage()] + assert_eq(back ~= nil and back ~= merge_session and back.left_buf ~= nil, true, + "Switching back should land on the new changed-file view") + assert_eq(merge_session.disposed, true, + "Switching away from a conflict should close the merge view (issue #20)") + assert_eq(#vim.api.nvim_list_tabpages(), tab_count, + "Switching between conflicts and changes should reuse one tab, not stack them (issue #20)") + + -- gzp hides and re-shows the panel without closing the diff. + vim.api.nvim_set_current_win(back.right_win) + buffer_keymap_callback(back.right_buf, "n", "gzp")() + assert_eq(back.panel.visible, false, "gzp in a diff pane should hide the commit panel") + assert_eq(back.disposed, false, "Hiding the panel should keep the diff open") + buffer_keymap_callback(back.right_buf, "n", "gzp")() + assert_eq(back.panel.visible, true, "gzp should show the commit panel again") + buffer_keymap_callback(back.panel.nav_buf, "n", "gzp")() + assert_eq(back.panel.visible, false, "gzp in the panel should hide the panel") + local focused = vim.api.nvim_get_current_win() + assert_eq(focused == back.left_win or focused == back.right_win, true, + "Hiding the focused panel should return focus to a diff pane") + back:show_commit_panel() + + -- q in the panel closes the whole view and keeps the unfinished message. + assert_eq(vim.api.nvim_buf_get_lines(back.panel.commit_buf, 2, 3, false)[1], "draft merge commit", + "The message should survive both view switches") + local back_tab = back.tabpage + buffer_keymap_callback(back.panel.nav_buf, "n", "q")() + assert_eq(back.disposed, true, "q in the commit panel should close the whole diff view") + assert_eq(vim.api.nvim_tabpage_is_valid(back_tab), false, "q in the commit panel should close the view's tab") + assert_eq((state_mod.commit_drafts[queue.root] or {})[1], "draft merge commit", + "Closing a view should save the unfinished commit message for the repository") + + local reloaded = assert((queue.load(1))) + local reopened = assert((Session.start({ left = reloaded.left, right = reloaded.right }, config, { + queue = queue, + panel = true, + panel_initial_selection = 1, + }))) + state_mod.register(reopened) + assert_eq(vim.api.nvim_buf_get_lines(reopened.panel.commit_buf, 2, 3, false)[1], "draft merge commit", + "The next panel for the repository should restore the saved draft") + vim.api.nvim_buf_set_lines(reopened.panel.commit_buf, 2, -1, false, { "" }) + reopened:close() + assert_eq(state_mod.commit_drafts[queue.root], nil, + "Closing with a cleared message should drop the saved draft") end do @@ -2267,8 +2316,8 @@ do self.closed = true end panel_mod.close(fake) - assert_eq(fake.closed, true, - "Closing a review panel should close the owning diff session") + assert_eq(fake.closed, false, + "Hiding a review panel should not close the owning diff session (q calls the host's close)") end -- Document-navigation keymaps survive LspAttach handlers that install diff --git a/tests/specs/25_launcher.lua b/tests/specs/25_launcher.lua index b80a0e1..6bf1d29 100644 --- a/tests/specs/25_launcher.lua +++ b/tests/specs/25_launcher.lua @@ -88,7 +88,7 @@ do session:close() assert_eq(launcher.has_live_view(), false, "Closing the session leaves no live view") - -- Launcher mode: the panel's q quits nvim instead of only hiding the panel. + -- Launcher mode: the panel's q quits nvim; otherwise it closes the view. do local state = require("diffbandit.state") local panel_q = function(launched) @@ -107,8 +107,8 @@ do local launched = assert((launcher.launch({}, { cwd = repo }))) local commands = panel_q(launched) - assert_eq(commands[1], nil, "Without launcher mode, panel q does not quit") - assert_eq(launched.panel.visible, false, "Without launcher mode, panel q hides the panel") + assert_eq(commands[1], "tabclose", "Without launcher mode, panel q closes the view's tab") + assert_eq(vim.tbl_contains(commands, "confirm qall"), false, "Without launcher mode, panel q does not quit") launched:close() launched = assert((launcher.launch({}, { cwd = repo }))) From 4fe6824f313aa0bade37000c26ffa64e753b492a Mon Sep 17 00:00:00 2001 From: Corey Kaylor Date: Wed, 4 Nov 2026 18:48:16 -0500 Subject: [PATCH 2/2] Regenerate help tags for :DiffBanditClose and gzp --- doc/tags | 2 ++ 1 file changed, 2 insertions(+) diff --git a/doc/tags b/doc/tags index bcd5089..a164349 100644 --- a/doc/tags +++ b/doc/tags @@ -2,6 +2,7 @@ :DiffBanditApplyLeftHunk diffbandit.txt /*:DiffBanditApplyLeftHunk* :DiffBanditApplyRightHunk diffbandit.txt /*:DiffBanditApplyRightHunk* :DiffBanditBuffers diffbandit.txt /*:DiffBanditBuffers* +:DiffBanditClose diffbandit.txt /*:DiffBanditClose* :DiffBanditCommitPanel diffbandit.txt /*:DiffBanditCommitPanel* :DiffBanditDiscardHunk diffbandit.txt /*:DiffBanditDiscardHunk* :DiffBanditFolderDiff diffbandit.txt /*:DiffBanditFolderDiff* @@ -35,6 +36,7 @@ diffbandit-commit-panel diffbandit.txt /*diffbandit-commit-panel* diffbandit-configuration diffbandit.txt /*diffbandit-configuration* diffbandit-folder-diff diffbandit.txt /*diffbandit-folder-diff* diffbandit-git diffbandit.txt /*diffbandit-git* +diffbandit-gzp diffbandit.txt /*diffbandit-gzp* diffbandit-hunk-actions diffbandit.txt /*diffbandit-hunk-actions* diffbandit-installation diffbandit.txt /*diffbandit-installation* diffbandit-launcher diffbandit.txt /*diffbandit-launcher*