Skip to content
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

Rework how commit editor handles closing/saving/aborting #1038

Merged
merged 5 commits into from
Dec 16, 2023
Merged
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
2 changes: 0 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -70,8 +70,6 @@ neogit.setup {
disable_context_highlighting = false,
-- Disables signs for sections/items/hunks
disable_signs = false,
-- Do not ask to confirm the commit - just do it when the buffer is closed.
disable_commit_confirmation = false,
-- Changes what mode the Commit Editor starts in. `true` will leave nvim in normal mode, `false` will change nvim to
-- insert mode, and `"auto"` will change nvim to insert mode IF the commit message is empty, otherwise leaving it in
-- normal mode.
Expand Down
75 changes: 51 additions & 24 deletions lua/neogit/buffers/commit_editor/init.lua
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
local Buffer = require("neogit.lib.buffer")
local config = require("neogit.config")
local input = require("neogit.lib.input")
local util = require("neogit.lib.util")

local pad = util.pad_right

local M = {}

Expand Down Expand Up @@ -30,7 +33,9 @@ function M.new(filename, on_unload)
end

function M:open()
local should_commit = false
local mapping = config.get_reversed_commit_editor_maps()
local aborted = false

self.buffer = Buffer.create {
name = self.filename,
filetype = "NeogitCommitMessage",
Expand All @@ -39,38 +44,60 @@ function M:open()
kind = config.values.commit_editor.kind,
modifiable = true,
readonly = false,
autocmds = {
["BufUnload"] = function(o)
local buf = Buffer.create {
name = o.buf,
}
if not should_commit and buf:get_option("modified") then
if
not config.values.disable_commit_confirmation
and not input.get_confirmation("Are you sure you want to commit?")
then
-- Clear the buffer, without filling the register
buf:clear()
buf:write()
end
after = function(buffer)
local padding = util.max_length(util.flatten(vim.tbl_values(mapping)))
local pad_mapping = function(name)
return pad(mapping[name][1], padding)
end

-- stylua: ignore
local help_lines = {
"# Neogit Commands:",
string.format("# %s close", pad_mapping("Close")),
string.format("# %s tell Git to make it happen", pad_mapping("Submit")),
string.format("# %s tell Git that you changed your mind, i.e. abort", pad_mapping("Abort")),
"#"
}

help_lines = util.filter_map(help_lines, function(line)
if not line:match("<NOP>") then -- mapping will be <NOP> if user unbinds key
return line
end
end)

if self.on_unload and not should_commit then
self.on_unload(0)
local line = vim.fn.search("# Changes to be committed:") - 2
buffer:set_lines(line, line, false, help_lines)
buffer:write()
buffer:move_cursor(1)
end,
autocmds = {
["BufUnload"] = function()
if self.on_unload then
self.on_unload(aborted and 1 or 0)
end

require("neogit.process").defer_show_preview_buffers()
if not aborted then
require("neogit.process").defer_show_preview_buffers()
end
end,
},
mappings = {
n = {
["q"] = function(buffer)
if not buffer:get_option("modified") then
buffer:close(true)
elseif input.get_confirmation("Commit message hasn't been saved. Abort?") then
should_commit = true
buffer:close(true)
[mapping["Close"]] = function(buffer)
if buffer:get_option("modified") and input.get_confirmation("Save changes?") then
buffer:write()
end

buffer:close(true)
end,
[mapping["Submit"]] = function(buffer)
buffer:write()
buffer:close(true)
end,
[mapping["Abort"]] = function(buffer)
aborted = true
buffer:write()
buffer:close(true)
end,
},
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,10 @@ local config = require("neogit.config")

local M = {}

function M.new(filename, on_close)
function M.new(filename, on_unload)
local instance = {
filename = filename,
on_close = on_close,
on_unload = on_unload,
buffer = nil,
}

Expand All @@ -26,7 +26,7 @@ function M:open()
readonly = false,
autocmds = {
["BufUnload"] = function()
self.on_close()
self.on_unload()
vim.cmd("silent w!")
require("neogit.process").defer_show_preview_buffers()
end,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,10 @@ local config = require("neogit.config")

local M = {}

function M.new(filename, on_close)
function M.new(filename, on_unload)
local instance = {
filename = filename,
on_close = on_close,
on_unload = on_unload,
buffer = nil,
}

Expand All @@ -26,7 +26,7 @@ function M:open()
readonly = false,
autocmds = {
["BufUnload"] = function()
self.on_close()
self.on_unload()
vim.cmd("silent w!")
require("neogit.process").defer_show_preview_buffers()
end,
Expand Down
8 changes: 4 additions & 4 deletions lua/neogit/buffers/rebase_editor/init.lua
Original file line number Diff line number Diff line change
Expand Up @@ -31,10 +31,10 @@ local function line_action(action)
end
end

function M.new(filename, on_close)
function M.new(filename, on_unload)
local instance = {
filename = filename,
on_close = on_close,
on_unload = on_unload,
buffer = nil,
}

Expand Down Expand Up @@ -99,8 +99,8 @@ function M:open()
end,
autocmds = {
["BufUnload"] = function()
if self.on_close then
self.on_close(aborted and 1 or 0)
if self.on_unload then
self.on_unload(aborted and 1 or 0)
end

if not aborted then
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,10 @@ local config = require("neogit.config")

local M = {}

function M.new(filename, on_close)
function M.new(filename, on_unload)
local instance = {
filename = filename,
on_close = on_close,
on_unload = on_unload,
buffer = nil,
}

Expand All @@ -26,7 +26,7 @@ function M:open()
readonly = false,
autocmds = {
["BufUnload"] = function()
self.on_close()
self.on_unload()
vim.cmd("silent w!")
require("neogit.process").defer_show_preview_buffers()
end,
Expand Down
65 changes: 59 additions & 6 deletions lua/neogit/config.lua
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,18 @@ function M.get_reversed_rebase_editor_maps()

return reversed_rebase_editor_maps
end

local reversed_commit_editor_maps
---@return table<string, string[]>
--- Returns a map of commands, mapped to the list of keys which trigger them.
function M.get_reversed_commit_editor_maps()
if not reversed_commit_editor_maps then
reversed_commit_editor_maps = get_reversed_maps(M.values.mappings.commit_editor)
end

return reversed_commit_editor_maps
end

---@alias WindowKind
---|"split" Open in a split
---| "vsplit" Open in a vertical split
Expand Down Expand Up @@ -106,13 +118,16 @@ end

---@alias NeogitConfigMappingsPopup "HelpPopup" | "DiffPopup" | "PullPopup" | "RebasePopup" | "MergePopup" | "PushPopup" | "CommitPopup" | "LogPopup" | "RevertPopup" | "StashPopup" | "IgnorePopup" | "CherryPickPopup" | "BranchPopup" | "FetchPopup" | "ResetPopup" | "RemotePopup" | "TagPopup" | false

---@alias NeogitConfigMappingsRebaseEditor "Pick" | "Reword" | "Edit" | "Squash" | "Fixup" | "Execute" | "Drop" | "Break" | "MoveUp" | "MoveDown" | "Close" | "OpenCommit" | "Submit" | "Abort" | false
---@alias NeogitConfigMappingsRebaseEditor "Pick" | "Reword" | "Edit" | "Squash" | "Fixup" | "Execute" | "Drop" | "Break" | "MoveUp" | "MoveDown" | "Close" | "OpenCommit" | "Submit" | "Abort" | false | fun()
---
---@alias NeogitConfigMappingsCommitEditor "Close" | "Submit" | "Abort" | false | fun()

---@class NeogitConfigMappings Consult the config file or documentation for values
---@field finder? { [string]: NeogitConfigMappingsFinder } A dictionary that uses finder commands to set multiple keybinds
---@field status? { [string]: NeogitConfigMappingsStatus } A dictionary that uses status commands to set a single keybind
---@field popup? { [string]: NeogitConfigMappingsPopup } A dictionary that uses popup commands to set a single keybind
---@field rebase_editor? { [string]: NeogitConfigMappingsRebaseEditor } A dictionary that uses Rebase editor commands to set a single keybind
---@field commit_editor? { [string]: NeogitConfigMappingsCommitEditor } A dictionary that uses Commit editor commands to set a single keybind

---@alias NeogitGraphStyle "ascii" | "unicode"

Expand All @@ -123,7 +138,6 @@ end
---@field disable_context_highlighting? boolean Disable context highlights based on cursor position
---@field disable_signs? boolean Special signs to draw for sections etc. in Neogit
---@field git_services? table Templartes to use when opening a pull request for a branch
---@field disable_commit_confirmation? boolean Disable commit confirmations
---@field fetch_after_checkout? boolean Perform a fetch if the newly checked out branch has an upstream or pushRemote set
---@field telescope_sorter? function The sorter telescope will use
---@field disable_insert_on_commit? boolean|"auto" Disable automatically entering insert mode in commit dialogues
Expand Down Expand Up @@ -163,7 +177,6 @@ function M.get_default_values()
disable_hint = false,
disable_context_highlighting = false,
disable_signs = false,
disable_commit_confirmation = false,
graph_style = "ascii",
filewatcher = {
interval = 1000,
Expand All @@ -177,7 +190,7 @@ function M.get_default_values()
["bitbucket.org"] = "https://bitbucket.org/${owner}/${repository}/pull-requests/new?source=${branch_name}&t=1",
["gitlab.com"] = "https://gitlab.com/${owner}/${repository}/merge_requests/new?merge_request[source_branch]=${branch_name}",
},
disable_insert_on_commit = true,
disable_insert_on_commit = "auto",
use_per_project_settings = true,
remember_settings = true,
fetch_after_checkout = false,
Expand Down Expand Up @@ -290,6 +303,11 @@ function M.get_default_values()
"NeogitCommitPopup--allow-empty",
},
mappings = {
commit_editor = {
["q"] = "Close",
["<c-c><c-c>"] = "Submit",
["<c-c><c-k>"] = "Abort",
},
rebase_editor = {
["p"] = "Pick",
["r"] = "Reword",
Expand Down Expand Up @@ -673,7 +691,7 @@ function M.validate_config()
and validate_type(
command,
string.format("mappings.rebase_editor['%s']", key),
{ "string", "boolean" }
{ "string", "boolean", "function" }
)
then
if type(command) == "string" and not vim.tbl_contains(valid_rebase_editor_commands, command) then
Expand All @@ -693,13 +711,48 @@ function M.validate_config()
end
end
end

local valid_commit_editor_commands = {
false,
}

for _, cmd in pairs(M.get_default_values().mappings.commit_editor) do
table.insert(valid_commit_editor_commands, cmd)
end

if validate_type(config.mappings.commit_editor, "mappings.commit_editor", "table") then
for key, command in pairs(config.mappings.commit_editor) do
if
validate_type(key, "mappings.commit_editor -> " .. vim.inspect(key), "string")
and validate_type(
command,
string.format("mappings.commit_editor['%s']", key),
{ "string", "boolean", "function" }
)
then
if type(command) == "string" and not vim.tbl_contains(valid_commit_editor_commands, command) then
local valid_commit_editor_commands = util.map(valid_commit_editor_commands, function(command)
return vim.inspect(command)
end)

err(
string.format("mappings.commit_editor['%s']", key),
string.format(
"Expected a valid commit_editor command, got '%s'. Valid commit_editor commands: { %s }",
command,
table.concat(valid_commit_editor_commands, ", ")
)
)
end
end
end
end
end

if validate_type(config, "base config", "table") then
validate_type(config.disable_hint, "disable_hint", "boolean")
validate_type(config.disable_context_highlighting, "disable_context_highlighting", "boolean")
validate_type(config.disable_signs, "disable_signs", "boolean")
validate_type(config.disable_commit_confirmation, "disable_commit_confirmation", "boolean")
validate_type(config.telescope_sorter, "telescope_sorter", "function")
validate_type(config.use_per_project_settings, "use_per_project_settings", "boolean")
validate_type(config.remember_settings, "remember_settings", "boolean")
Expand Down