mirror of
https://github.com/zoriya/jj.nvim.git
synced 2026-08-14 23:23:20 +00:00
refactor: Restructure keymaps and event handlers into centralized config-driven system
- Add M.setup() to cmd module for configuration
- Move describe editor config to M.config.describe.editor with nested structure
- Add keymaps config with separate log, status, and close sections
- Implement resolve_keymaps_from_specs() helper to build keymap lists from config
- Extract editor.open_editor() keymaps parameter support
- Move status/log event handlers from terminal.lua to cmd.lua
- Convert log/status buffer keymaps to config-driven approach with handler specs
This commit is contained in:
+1
-234
@@ -1,10 +1,7 @@
|
||||
--- @class jj.ui.terminal
|
||||
local M = {}
|
||||
|
||||
local utils = require("jj.utils")
|
||||
local parser = require("jj.core.parser")
|
||||
local buffer = require("jj.core.buffer")
|
||||
local runner = require("jj.core.runner")
|
||||
|
||||
--- @class jj.ui.terminal.state
|
||||
local state = {
|
||||
@@ -54,174 +51,6 @@ local function hide_floating_window()
|
||||
end
|
||||
end
|
||||
|
||||
local function handle_status_enter()
|
||||
local file_info = parser.parse_file_info_from_status_line(vim.api.nvim_get_current_line())
|
||||
|
||||
if not file_info then
|
||||
return
|
||||
end
|
||||
|
||||
local filepath = file_info.new_path
|
||||
local stat = vim.uv.fs_stat(filepath)
|
||||
if not stat then
|
||||
utils.notify("File not found: " .. filepath, vim.log.levels.ERROR)
|
||||
return
|
||||
end
|
||||
|
||||
-- Go to the previous window (split above)
|
||||
vim.cmd("wincmd p")
|
||||
|
||||
-- Open the file in that window, replacing current buffer
|
||||
vim.cmd("edit " .. vim.fn.fnameescape(filepath))
|
||||
end
|
||||
|
||||
local function handle_status_restore()
|
||||
local file_info = parser.parse_file_info_from_status_line(vim.api.nvim_get_current_line())
|
||||
if not file_info then
|
||||
return
|
||||
end
|
||||
|
||||
if file_info.is_rename then
|
||||
-- For renamed files, remove the new file and restore the old one from parent revision
|
||||
local rm_cmd = "rm " .. vim.fn.shellescape(file_info.new_path)
|
||||
local restore_cmd = "jj restore --from @- " .. vim.fn.shellescape(file_info.old_path)
|
||||
|
||||
local _, rm_success = runner.execute_command(rm_cmd, "Failed to remove renamed file")
|
||||
if rm_success then
|
||||
local _, restore_success = runner.execute_command(restore_cmd, "Failed to restore original file")
|
||||
if restore_success then
|
||||
utils.notify(
|
||||
"Reverted rename: " .. file_info.new_path .. " -> " .. file_info.old_path,
|
||||
vim.log.levels.INFO
|
||||
)
|
||||
require("jj.cmd").status()
|
||||
end
|
||||
end
|
||||
else
|
||||
-- For non-renamed files, use regular restore
|
||||
local restore_cmd = "jj restore " .. vim.fn.shellescape(file_info.old_path)
|
||||
|
||||
local _, success = runner.execute_command(restore_cmd, "Failed to restore")
|
||||
if success then
|
||||
utils.notify("Restored: " .. file_info.old_path, vim.log.levels.INFO)
|
||||
require("jj.cmd").status()
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
--- Handle keypress enter on `jj log` buffer to edit a revision.
|
||||
--- If ignore_immut is true, adds --ignore-immutable to the command.
|
||||
--- Silently returns if no revision is found or the jj command fails.
|
||||
--- On success, notifies and refreshes the log buffer.
|
||||
--- @param ignore_immut? boolean Pass --ignore-immutable to jj edit when true.
|
||||
local function handle_log_enter(ignore_immut)
|
||||
local line = vim.api.nvim_get_current_line()
|
||||
local revset = parser.get_rev_from_log_line(line)
|
||||
if not revset or revset == "" then
|
||||
return
|
||||
end
|
||||
|
||||
-- If we found a revision, edit it.
|
||||
|
||||
-- Build command parts.
|
||||
local cmd_parts = { "jj", "edit" }
|
||||
if ignore_immut then
|
||||
table.insert(cmd_parts, "--ignore-immutable")
|
||||
end
|
||||
|
||||
table.insert(cmd_parts, revset)
|
||||
|
||||
-- Build cmd string
|
||||
local cmd = table.concat(cmd_parts, " ")
|
||||
|
||||
-- Try to execute cmd
|
||||
local _, success = runner.execute_command(cmd, "Error editing change")
|
||||
if not success then
|
||||
return
|
||||
end
|
||||
|
||||
utils.notify(string.format("Editing change: `%s`", revset), vim.log.levels.INFO)
|
||||
-- Close the terminal buffer
|
||||
M.close_terminal_buffer()
|
||||
end
|
||||
|
||||
--- Create a new change relative to the revision under the cursor in a jj log buffer.
|
||||
--- Behavior:
|
||||
--- flag == nil -> branch off the current revision
|
||||
--- flag == "after" -> create a new change after the current revision (-A)
|
||||
--- If ignore_immut is true, adds --ignore-immutable to the command.
|
||||
--- Silently returns if no revision is found or the jj command fails.
|
||||
--- On success, notifies and refreshes the log buffer.
|
||||
--- @param flag? 'after' Position relative to the current revision; nil to branch off.
|
||||
--- @param ignore_immut? boolean Pass --ignore-immutable to jj when true.
|
||||
local function handle_log_new(flag, ignore_immut)
|
||||
local line = vim.api.nvim_get_current_line()
|
||||
local revset = parser.get_rev_from_log_line(line)
|
||||
if not revset or revset == "" then
|
||||
return
|
||||
end
|
||||
|
||||
-- Mapping for flag-specific options and messages.
|
||||
local flag_map = {
|
||||
after = {
|
||||
opt = "-A",
|
||||
err = "Error creating new change after: `%s`",
|
||||
ok = "Successfully created change after: `%s`",
|
||||
},
|
||||
default = {
|
||||
opt = "",
|
||||
err = "Error creating new change branching off `%s`",
|
||||
ok = "Successfully created change branching off `%s`",
|
||||
},
|
||||
}
|
||||
|
||||
local cfg = flag_map[flag] or flag_map.default
|
||||
|
||||
-- Build command parts
|
||||
local cmd_parts = { "jj", "new" }
|
||||
if cfg.opt ~= "" then
|
||||
table.insert(cmd_parts, cfg.opt)
|
||||
end
|
||||
table.insert(cmd_parts, revset)
|
||||
if ignore_immut then
|
||||
table.insert(cmd_parts, "--ignore-immutable")
|
||||
end
|
||||
|
||||
local cmd = table.concat(cmd_parts, " ")
|
||||
local _, success = runner.execute_command(cmd, string.format(cfg.err, revset))
|
||||
if not success then
|
||||
return
|
||||
end
|
||||
|
||||
utils.notify(string.format(cfg.ok, revset), vim.log.levels.INFO)
|
||||
-- Refresh the log buffer after creating the change.
|
||||
require("jj.cmd").log()
|
||||
end
|
||||
|
||||
--- Handle diffing a log line
|
||||
local function handle_log_diff()
|
||||
local line = vim.api.nvim_get_current_line()
|
||||
local revset = parser.get_rev_from_log_line(line)
|
||||
|
||||
if revset then
|
||||
local cmd = string.format("jj show %s", revset)
|
||||
M.run_floating(cmd)
|
||||
else
|
||||
utils.notify("No valid revision found in the log line", vim.log.levels.ERROR)
|
||||
end
|
||||
end
|
||||
|
||||
--- Handle describing a log line
|
||||
local function handle_log_describe()
|
||||
local line = vim.api.nvim_get_current_line()
|
||||
local revset = parser.get_rev_from_log_line(line)
|
||||
if revset then
|
||||
require("jj.cmd").describe(nil, revset)
|
||||
else
|
||||
utils.notify("No valid revision found in the log line", vim.log.levels.ERROR)
|
||||
end
|
||||
end
|
||||
|
||||
--- Run the command in a floating window
|
||||
--- @param cmd string The command to run in the floating window
|
||||
function M.run_floating(cmd)
|
||||
@@ -491,6 +320,7 @@ function M.run(cmd, keymaps)
|
||||
local new_command_keymaps = {}
|
||||
|
||||
-- Append the given keymaps
|
||||
-- Add a debug
|
||||
if keymaps and #keymaps > 0 then
|
||||
for _, km in ipairs(keymaps) do
|
||||
table.insert(new_command_keymaps, km)
|
||||
@@ -503,69 +333,6 @@ function M.run(cmd, keymaps)
|
||||
{ modes = "n", lhs = "<CR>", rhs = handle_status_enter, opts = { desc = "Open file under cursor" } },
|
||||
{ modes = "n", lhs = "X", rhs = handle_status_restore, opts = { desc = "Restore file under cursor" } },
|
||||
}
|
||||
elseif cmd[2] == "log" then
|
||||
new_command_keymaps = {
|
||||
-- Edit
|
||||
{
|
||||
modes = "n",
|
||||
lhs = "<CR>",
|
||||
rhs = function()
|
||||
handle_log_enter(false)
|
||||
end,
|
||||
opts = { desc = "Edit change under cursor" },
|
||||
},
|
||||
{
|
||||
modes = "n",
|
||||
lhs = "<S-CR>",
|
||||
rhs = function()
|
||||
handle_log_enter(true)
|
||||
end,
|
||||
opts = { desc = "Edit change under cursor ignoring immutability" },
|
||||
},
|
||||
-- Diff
|
||||
{ modes = "n", lhs = "d", rhs = handle_log_diff, opts = { desc = "Diff change under cursor" } },
|
||||
-- New
|
||||
{
|
||||
modes = "n",
|
||||
lhs = "n",
|
||||
rhs = handle_log_new,
|
||||
opts = { desc = "New change off the change under cursor" },
|
||||
},
|
||||
{
|
||||
modes = "n",
|
||||
lhs = "<C-n>",
|
||||
rhs = function()
|
||||
handle_log_new("after")
|
||||
end,
|
||||
opts = { desc = "New change after the change under cursor" },
|
||||
},
|
||||
{
|
||||
modes = "n",
|
||||
lhs = "<S-n>",
|
||||
rhs = function()
|
||||
handle_log_new("after", true)
|
||||
end,
|
||||
opts = { desc = "New change after the change under cursor ignoring immutability" },
|
||||
},
|
||||
-- Undo/Redo
|
||||
{
|
||||
modes = "n",
|
||||
lhs = "u",
|
||||
rhs = function()
|
||||
require("jj.cmd").undo()
|
||||
end,
|
||||
opts = { desc = "Undo last operation" },
|
||||
},
|
||||
{
|
||||
modes = "n",
|
||||
lhs = "r",
|
||||
rhs = function()
|
||||
require("jj.cmd").redo()
|
||||
end,
|
||||
opts = { desc = "Redo last operation" },
|
||||
},
|
||||
{ modes = "n", lhs = "D", rhs = handle_log_describe, opts = { desc = "Describe change under cursor" } },
|
||||
}
|
||||
end
|
||||
|
||||
if #new_command_keymaps > 0 then
|
||||
|
||||
Reference in New Issue
Block a user