mirror of
https://github.com/zoriya/jj.nvim.git
synced 2026-08-14 07:08:32 +00:00
feat(log): Implement squash and quick squash from the log buffer.
- Squash: behaves like rebase, the user can select 1 or more
revisions to squash and then a destination
- Quick squash: `-r {rev} -u --ignore-immutable` flag from jj allowing
for quick visuall squashes
This commit is contained in:
@@ -19,6 +19,7 @@
|
||||
- [Abandon changes from the log buffer](#abandon-changes-from-the-log-buffer)
|
||||
- [Fetch and push from the log buffer](#fetch-and-push-from-the-log-buffer)
|
||||
- [Manage bookmarks from the log buffer](#manage-bookmarks-from-the-log-buffer)
|
||||
- [Squash changes from the log buffer](#squash-changes-from-the-log-buffer)
|
||||
- [Rebase changes from the log buffer](#rebase-changes-from-the-log-buffer)
|
||||
- [Open a PR/MR from the log buffer](#open-a-prmr-from-the-log-buffer)
|
||||
- [Open a changed file](#open-a-changed-file)
|
||||
@@ -53,7 +54,7 @@
|
||||
- `diff` - Show changes with optional filtering by current file
|
||||
- `new` - Create a new change with optional parent selection
|
||||
- `edit` - Edit a change
|
||||
- `squash` - Squash the current diff to it's parent
|
||||
- `squash` - Squash the current diff to its parent or interactive squash mode from the log buffer
|
||||
- `rebase` - Rebase changes to a destination
|
||||
- `bookmark create/delete` - Create and delete bookmarks
|
||||
- `undo` - Undo the last operation
|
||||
@@ -119,6 +120,31 @@ You can fetch and push directly from the log buffer:
|
||||
- Select from existing bookmarks to move them
|
||||
- Or create a new bookmark at that revision
|
||||
|
||||
### Squash changes from the log buffer
|
||||
|
||||
Enter an interactive squash mode to squash one or more changes into a destination:
|
||||
|
||||
- `s` - Enter squash mode targeting the revision under cursor (in normal mode) or selected revisions (in visual mode)
|
||||
- `<S-s>` - Quick squash the revision under cursor into its parent
|
||||
|
||||
Once in squash mode, the interface highlights your selection and the current squash destination:
|
||||
|
||||
- Selected changes are highlighted in your configured `selected_hl` color (default: dark magenta)
|
||||
- The cursor position (potential squash destination) is highlighted in your configured `targeted_hl` color (default: green)
|
||||
- Move the cursor to preview different squash destinations with live highlighting
|
||||
|
||||
From squash mode, choose how to squash:
|
||||
|
||||
- `<CR>` - Squash into (`-t`) the revision under cursor
|
||||
- `<S-CR>` - Squash into (`-t`) ignoring immutability
|
||||
- `<Esc>` or `<C-c>` - Exit squash mode without making changes
|
||||
|
||||
**Visual mode selection:** Select multiple revisions in visual mode before pressing `s` to squash them all at once. The plugin extracts each selected revision and squashes them together.
|
||||
|
||||
**Quick squash:** In normal mode, press `<S-s>` to quickly squash the current revision into its parent. This ignores immutability.
|
||||
|
||||

|
||||
|
||||
### Rebase changes from the log buffer
|
||||
|
||||
Enter an interactive rebase mode directly from the log buffer to rebase one or more changes:
|
||||
@@ -311,6 +337,13 @@ The plugin also provides `:Jdiff`, `:Jvdiff`, and `:Jhdiff` commands for diffing
|
||||
before_immutable = "<S-b>", -- Rebase before revision under cursor (ignore immutability)
|
||||
exit_mode = { "<Esc>", "<C-c>" }, -- Exit rebase mode
|
||||
},
|
||||
squash = "s", -- Enter squash mode targeting revision under cursor or selected revisions
|
||||
squash_mode = {
|
||||
into = "<CR>", -- Squash into revision under cursor
|
||||
into_immutable = "<S-CR>", -- Squash into revision under cursor (ignore immutability)
|
||||
exit_mode = { "<Esc>", "<C-c>" }, -- Exit squash mode
|
||||
},
|
||||
quick_squash = "<S-s>", -- Quick squash revision under cursor into its parent (ignore immutability)
|
||||
},
|
||||
-- Status buffer keymaps (set to nil to disable)
|
||||
status = {
|
||||
@@ -320,8 +353,8 @@ The plugin also provides `:Jdiff`, `:Jvdiff`, and `:Jhdiff` commands for diffing
|
||||
-- Close keymaps (shared across all buffers)
|
||||
close = { "q", "<Esc>" },
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
}}
|
||||
|
||||
```
|
||||
|
||||
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 1.8 MiB |
@@ -46,7 +46,11 @@ local status_module = require("jj.cmd.status")
|
||||
--- @field open_pr? string|string[]
|
||||
--- @field open_pr_list? string|string[]
|
||||
--- @field bookmark? string|string[]
|
||||
--- @field rebase? string|string[]
|
||||
--- @field rebase_mode? jj.cmd.rebase.keymaps
|
||||
--- @field squash? string|string[]
|
||||
--- @field squash_mode? jj.cmd.squash.keymaps
|
||||
--- @field quick_squash? string|string[]
|
||||
|
||||
--- @class jj.cmd.rebase.keymaps
|
||||
--- @field onto? string|string[]
|
||||
@@ -57,6 +61,11 @@ local status_module = require("jj.cmd.status")
|
||||
--- @field before_immutable? string|string[]
|
||||
--- @field exit_mode? string|string[]
|
||||
|
||||
--- @class jj.cmd.squash.keymaps
|
||||
--- @field into? string|string[]
|
||||
--- @field into_immutable? string|string[]
|
||||
--- @field exit_mode? string|string[]
|
||||
|
||||
--- @class jj.cmd.bookmark
|
||||
--- @field prefix? string Prefix to append when creating a bookmark
|
||||
|
||||
@@ -138,6 +147,13 @@ M.config = {
|
||||
before_immutable = "<S-b>",
|
||||
exit_mode = { "<Esc>", "<C-c>" },
|
||||
},
|
||||
squash = "s",
|
||||
squash_mode = {
|
||||
into = "<CR>",
|
||||
into_immutable = "<S-CR>",
|
||||
exit_mode = { "<Esc>", "<C-c>" },
|
||||
},
|
||||
quick_squash = "<S-s>",
|
||||
},
|
||||
status = {
|
||||
open_file = "<CR>",
|
||||
|
||||
+196
-63
@@ -8,8 +8,8 @@ local terminal = require("jj.ui.terminal")
|
||||
|
||||
local log_selected_hl_group = "JJLogSelectedHlGroup"
|
||||
local log_selected_ns_id = vim.api.nvim_create_namespace(log_selected_hl_group)
|
||||
local log_rebase_target_hl_group = "JJLogRebaseTargetHlGroup"
|
||||
local log_rebase_target_ns_id = vim.api.nvim_create_namespace(log_rebase_target_hl_group)
|
||||
local log_special_mode_target_hl_group = "JJLogSpecialModeTargetHlGroup"
|
||||
local log_special_mode_target_ns_id = vim.api.nvim_create_namespace(log_special_mode_target_hl_group)
|
||||
local rebase_mode_autocmd_id = nil
|
||||
local last_rebase_target_line = nil
|
||||
local HIGHLIGHT_RANGE = 2 -- Revision line + description line
|
||||
@@ -33,7 +33,7 @@ function M.init_log_highlights()
|
||||
end
|
||||
|
||||
vim.api.nvim_set_hl(0, log_selected_hl_group, cfg.selected)
|
||||
vim.api.nvim_set_hl(0, log_rebase_target_hl_group, cfg.targeted)
|
||||
vim.api.nvim_set_hl(0, log_special_mode_target_hl_group, cfg.targeted)
|
||||
end
|
||||
|
||||
--- Find the revision line under cursor, handling description lines
|
||||
@@ -124,7 +124,7 @@ end
|
||||
local function apply_target_highlight(buf, revset_line, hl_group)
|
||||
vim.api.nvim_buf_set_extmark(
|
||||
buf,
|
||||
log_rebase_target_ns_id,
|
||||
log_special_mode_target_ns_id,
|
||||
revset_line,
|
||||
0,
|
||||
{ end_line = revset_line + HIGHLIGHT_RANGE, end_col = 0, hl_group = hl_group }
|
||||
@@ -137,7 +137,7 @@ local function clear_target_highlight(buf)
|
||||
if last_rebase_target_line ~= nil then
|
||||
vim.api.nvim_buf_clear_namespace(
|
||||
buf,
|
||||
log_rebase_target_ns_id,
|
||||
log_special_mode_target_ns_id,
|
||||
last_rebase_target_line,
|
||||
last_rebase_target_line + HIGHLIGHT_RANGE
|
||||
)
|
||||
@@ -146,7 +146,7 @@ local function clear_target_highlight(buf)
|
||||
end
|
||||
|
||||
--- Update rebase target highlight on cursor movement
|
||||
local function update_rebase_target_highlight()
|
||||
local function update_special_mode_target_highlight()
|
||||
local buf = terminal.state.buf
|
||||
if not buf then
|
||||
return
|
||||
@@ -162,7 +162,71 @@ local function update_rebase_target_highlight()
|
||||
-- Only highlight if rev is not in selection
|
||||
local is_in_selection = vim.b.jj_rebase_revsets and string.find(vim.b.jj_rebase_revsets, rev, 1, true)
|
||||
if not is_in_selection then
|
||||
apply_target_highlight(buf, revset_line, log_rebase_target_hl_group)
|
||||
apply_target_highlight(buf, revset_line, log_special_mode_target_hl_group)
|
||||
end
|
||||
end
|
||||
|
||||
--- Extracts the revsets from either the current line or the selected lines in visual mode
|
||||
--- @return string|nil The revsets string or nil if none found
|
||||
local function extract_revsets_from_terminal_buffer()
|
||||
local buf = terminal.state.buf
|
||||
if not buf then
|
||||
utils.notify("No open log buffer", vim.log.levels.ERROR)
|
||||
return nil
|
||||
end
|
||||
|
||||
local revsets_str = nil
|
||||
local mode = vim.fn.mode()
|
||||
|
||||
-- Get revsets based on mode
|
||||
if mode == "n" then
|
||||
revsets_str = get_revset()
|
||||
elseif mode == "v" or mode == "V" then
|
||||
local start_line = vim.fn.line("v")
|
||||
local end_line = vim.fn.line(".")
|
||||
if start_line > end_line then
|
||||
start_line, end_line = end_line, start_line
|
||||
end
|
||||
|
||||
local lines = vim.api.nvim_buf_get_lines(buf, start_line - 1, end_line, false)
|
||||
local revsets = parser.get_all_revsets(lines)
|
||||
if not revsets or #revsets == 0 then
|
||||
utils.notify("No valid revisions found in selected lines", vim.log.levels.ERROR)
|
||||
return nil
|
||||
end
|
||||
|
||||
revsets_str = table.concat(revsets, " | ")
|
||||
-- Exit visual mode after extracting revsets
|
||||
vim.api.nvim_feedkeys(vim.api.nvim_replace_termcodes("<Esc>", true, false, true), "n", true)
|
||||
else
|
||||
return nil
|
||||
end
|
||||
|
||||
return revsets_str
|
||||
end
|
||||
|
||||
--- Setup highlights for selected revisions in the log buffer
|
||||
local function setup_selected_highlights()
|
||||
local buf = terminal.state.buf
|
||||
if not buf then
|
||||
return
|
||||
end
|
||||
|
||||
-- Set highlights
|
||||
local marks = get_highlight_marks()
|
||||
if not marks or #marks == 0 then
|
||||
utils.notify("No valid revisions found to highlight", vim.log.levels.ERROR)
|
||||
return
|
||||
end
|
||||
|
||||
for _, mark in ipairs(marks) do
|
||||
vim.api.nvim_buf_set_extmark(
|
||||
buf,
|
||||
log_selected_ns_id,
|
||||
mark.line,
|
||||
mark.col,
|
||||
{ end_line = mark.end_line, end_col = mark.end_col, hl_group = log_selected_hl_group }
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
@@ -178,7 +242,7 @@ function M.log(opts)
|
||||
terminal.store_cursor_position()
|
||||
-- Make sure to clear highlights before rerunning since the previous log buffer might have some
|
||||
vim.api.nvim_buf_clear_namespace(terminal.state.buf, log_selected_ns_id, 0, -1)
|
||||
vim.api.nvim_buf_clear_namespace(terminal.state.buf, log_rebase_target_ns_id, 0, -1)
|
||||
vim.api.nvim_buf_clear_namespace(terminal.state.buf, log_special_mode_target_ns_id, 0, -1)
|
||||
end
|
||||
|
||||
local jj_cmd = "jj log"
|
||||
@@ -528,65 +592,49 @@ end
|
||||
|
||||
--- Rebase bookmark(s)
|
||||
function M.handle_log_rebase()
|
||||
local buf = terminal.state.buf
|
||||
if not buf then
|
||||
utils.notify("No open log buffer", vim.log.levels.ERROR)
|
||||
local revsets_str = extract_revsets_from_terminal_buffer()
|
||||
-- Validate revsets
|
||||
if not revsets_str or revsets_str == "" then
|
||||
return
|
||||
end
|
||||
vim.b.jj_rebase_revsets = revsets_str
|
||||
|
||||
local revsets_str = nil
|
||||
local mode = vim.fn.mode()
|
||||
-- Set highlights
|
||||
setup_selected_highlights()
|
||||
|
||||
-- Get revsets based on mode
|
||||
if mode == "n" then
|
||||
revsets_str = get_revset()
|
||||
elseif mode == "v" or mode == "V" then
|
||||
local start_line = vim.fn.line("v")
|
||||
local end_line = vim.fn.line(".")
|
||||
if start_line > end_line then
|
||||
start_line, end_line = end_line, start_line
|
||||
end
|
||||
|
||||
local lines = vim.api.nvim_buf_get_lines(buf, start_line - 1, end_line, false)
|
||||
local revsets = parser.get_all_revsets(lines)
|
||||
if not revsets or #revsets == 0 then
|
||||
utils.notify("No valid revisions found in selected lines", vim.log.levels.ERROR)
|
||||
return
|
||||
end
|
||||
|
||||
revsets_str = table.concat(revsets, " | ")
|
||||
-- Exit visual mode before transition
|
||||
vim.api.nvim_feedkeys(vim.api.nvim_replace_termcodes("<Esc>", true, false, true), "n", true)
|
||||
else
|
||||
return
|
||||
end
|
||||
M.transition_mode("rebase")
|
||||
utils.notify("Rebase `started`.", vim.log.levels.INFO, 500)
|
||||
end
|
||||
|
||||
--- Squash bookmarks(s)
|
||||
function M.handle_log_squash()
|
||||
local revsets_str = extract_revsets_from_terminal_buffer()
|
||||
-- Validate revsets
|
||||
if not revsets_str or revsets_str == "" then
|
||||
return
|
||||
end
|
||||
|
||||
vim.b.jj_rebase_revsets = revsets_str
|
||||
|
||||
vim.b.jj_squash_revsets = revsets_str
|
||||
-- Set highlights
|
||||
local marks = get_highlight_marks()
|
||||
if not marks or #marks == 0 then
|
||||
utils.notify("No valid revisions found to highlight during rebase", vim.log.levels.ERROR)
|
||||
setup_selected_highlights()
|
||||
|
||||
M.transition_mode("squash")
|
||||
utils.notify("Squash `started`.", vim.log.levels.INFO, 500)
|
||||
end
|
||||
|
||||
--- Quick squash the bookmark under the cursor into it's parent
|
||||
function M.handle_log_quick_squash()
|
||||
local revset = get_revset()
|
||||
if not revset or revset == "" then
|
||||
return
|
||||
end
|
||||
|
||||
for _, mark in ipairs(marks) do
|
||||
vim.api.nvim_buf_set_extmark(
|
||||
buf,
|
||||
log_selected_ns_id,
|
||||
mark.line,
|
||||
mark.col,
|
||||
{ end_line = mark.end_line, end_col = mark.end_col, hl_group = log_selected_hl_group }
|
||||
)
|
||||
end
|
||||
|
||||
M.transition_mode("rebase")
|
||||
utils.notify("Rebase `started`.", vim.log.levels.INFO, 500)
|
||||
local cmd = string.format("jj squash -r %s -u --ignore-immutable", revset)
|
||||
utils.notify(string.format("Squashing `%s` into it's parent...", revset), vim.log.levels.INFO)
|
||||
runner.execute_command_async(cmd, function()
|
||||
utils.notify(string.format("Successfully squashed `%s` into it's parent", revset), vim.log.levels.INFO)
|
||||
M.log({})
|
||||
end, string.format("Error squashing `%s` into it's parent", revset))
|
||||
end
|
||||
|
||||
--- Resolve log keymaps from config, filtering out nil values
|
||||
@@ -698,6 +746,16 @@ function M.log_keymaps()
|
||||
handler = M.handle_log_rebase,
|
||||
modes = { "n", "v" },
|
||||
},
|
||||
squash = {
|
||||
desc = "Squash bookmark(s)",
|
||||
handler = M.handle_log_squash,
|
||||
modes = { "n", "v" },
|
||||
},
|
||||
quick_squash = {
|
||||
desc = "Squash the bookmark under the cursor into it's parent (-r) keeping parent's message (-u), alwas ignores immutability",
|
||||
handler = M.handle_log_quick_squash,
|
||||
modes = { "n" },
|
||||
},
|
||||
}
|
||||
|
||||
return cmd.merge_keymaps(cmd.resolve_keymaps_from_specs(keymaps, specs), cmd.terminal_keymaps())
|
||||
@@ -749,7 +807,37 @@ function M.rebase_keymaps()
|
||||
},
|
||||
exit_mode = {
|
||||
desc = "Exit rebase to normal mode",
|
||||
handler = M.handle_rebase_mode_exit,
|
||||
handler = M.handle_special_mode_exit,
|
||||
modes = { "n" },
|
||||
},
|
||||
}
|
||||
|
||||
return cmd.resolve_keymaps_from_specs(keymaps, spec)
|
||||
end
|
||||
|
||||
--- Squash mode keymaps
|
||||
--- @return jj.core.buffer.keymap[]
|
||||
function M.squash_keymaps()
|
||||
local cmd = require("jj.cmd")
|
||||
local keymaps = cmd.config.keymaps.log.squash_mode or {}
|
||||
|
||||
--- @type jj.cmd.keymap_specs
|
||||
local spec = {
|
||||
into = {
|
||||
desc = "Squash into (-t) the revision under cursor",
|
||||
handler = M.handle_squash_execute,
|
||||
args = { "into" },
|
||||
modes = { "n" },
|
||||
},
|
||||
into_immutable = {
|
||||
desc = "Squash onto (-i) the revision under cursor (ignores immutability)",
|
||||
handler = M.handle_squash_execute,
|
||||
args = { "into", true },
|
||||
modes = { "n" },
|
||||
},
|
||||
exit_mode = {
|
||||
desc = "Exit squash to normal mode",
|
||||
handler = M.handle_special_mode_exit,
|
||||
modes = { "n" },
|
||||
},
|
||||
}
|
||||
@@ -765,12 +853,14 @@ function M.get_keymaps_for_mode(mode)
|
||||
return M.log_keymaps()
|
||||
elseif mode == "rebase" then
|
||||
return M.rebase_keymaps()
|
||||
elseif mode == "squash" then
|
||||
return M.squash_keymaps()
|
||||
end
|
||||
return {}
|
||||
end
|
||||
|
||||
--- Transition between buffer modes by swapping keymaps
|
||||
--- @param target_mode string Target mode name (e.g., "normal", "rebase")
|
||||
--- @param target_mode "normal"|"rebase"|"squash" Target mode name (e.g., "normal", "rebase")
|
||||
function M.transition_mode(target_mode)
|
||||
-- Get the mode keymaps
|
||||
if target_mode == vim.b.jj_mode then
|
||||
@@ -782,19 +872,19 @@ function M.transition_mode(target_mode)
|
||||
terminal.replace_terminal_keymaps(new_keymaps)
|
||||
|
||||
-- Set up or tear down rebase mode autocmd
|
||||
if target_mode == "rebase" then
|
||||
if target_mode ~= "normal" then
|
||||
rebase_mode_autocmd_id = vim.api.nvim_create_autocmd("CursorMoved", {
|
||||
buffer = terminal.state.buf,
|
||||
callback = update_rebase_target_highlight,
|
||||
callback = update_special_mode_target_highlight,
|
||||
})
|
||||
-- Highlight initial position
|
||||
update_rebase_target_highlight()
|
||||
update_special_mode_target_highlight()
|
||||
elseif rebase_mode_autocmd_id then
|
||||
vim.api.nvim_del_autocmd(rebase_mode_autocmd_id)
|
||||
rebase_mode_autocmd_id = nil
|
||||
-- Clear target highlight
|
||||
local buf = terminal.state.buf or 0
|
||||
vim.api.nvim_buf_clear_namespace(buf, log_rebase_target_ns_id, 0, -1)
|
||||
vim.api.nvim_buf_clear_namespace(buf, log_special_mode_target_ns_id, 0, -1)
|
||||
last_rebase_target_line = nil
|
||||
end
|
||||
|
||||
@@ -802,8 +892,8 @@ function M.transition_mode(target_mode)
|
||||
vim.b.jj_mode = target_mode
|
||||
end
|
||||
|
||||
--- Handle rebase mode exit
|
||||
function M.handle_rebase_mode_exit()
|
||||
--- Handle special mode exit
|
||||
function M.handle_special_mode_exit()
|
||||
-- Clear stored revsets
|
||||
vim.b.jj_rebase_revsets = nil
|
||||
|
||||
@@ -811,7 +901,7 @@ function M.handle_rebase_mode_exit()
|
||||
-- Clear highlights
|
||||
local buf = terminal.state.buf or 0
|
||||
vim.api.nvim_buf_clear_namespace(buf, log_selected_ns_id, 0, -1)
|
||||
vim.api.nvim_buf_clear_namespace(buf, log_rebase_target_ns_id, 0, -1)
|
||||
vim.api.nvim_buf_clear_namespace(buf, log_special_mode_target_ns_id, 0, -1)
|
||||
|
||||
utils.notify("Rebase `canceled`", vim.log.levels.INFO, 500)
|
||||
end
|
||||
@@ -853,7 +943,7 @@ function M.handle_rebase_execute(mode, ignore_immut)
|
||||
-- Clear all highlighting before transitioning
|
||||
local buf = terminal.state.buf or 0
|
||||
vim.api.nvim_buf_clear_namespace(buf, log_selected_ns_id, 0, -1)
|
||||
vim.api.nvim_buf_clear_namespace(buf, log_rebase_target_ns_id, 0, -1)
|
||||
vim.api.nvim_buf_clear_namespace(buf, log_special_mode_target_ns_id, 0, -1)
|
||||
|
||||
M.transition_mode("normal")
|
||||
-- Refresh log
|
||||
@@ -861,4 +951,47 @@ function M.handle_rebase_execute(mode, ignore_immut)
|
||||
end, "Error during rebase onto")
|
||||
end
|
||||
|
||||
--- Handle squash execution
|
||||
--- @param mode "into" Squash mode
|
||||
--- @param ignore_immut boolean? Wether or not to ignore immutability
|
||||
function M.handle_squash_execute(mode, ignore_immut)
|
||||
-- Get all revsets in the format "xx xy xz"
|
||||
local revsets = vim.b.jj_squash_revsets
|
||||
local destination_revset = get_revset()
|
||||
if not destination_revset or destination_revset == "" then
|
||||
return
|
||||
end
|
||||
|
||||
utils.notify(string.format("Squashing...", revsets, mode, destination_revset), vim.log.levels.INFO, 500)
|
||||
-- U flag to keep destination's message
|
||||
local cmd = string.format("jj squash -f '%s' -u", revsets)
|
||||
|
||||
if mode == "into" then
|
||||
cmd = cmd .. string.format(" -t %s", destination_revset)
|
||||
end
|
||||
|
||||
-- If ignore_immut is true, add the flag
|
||||
-- This is not currently exposed in keymaps but could be in the future
|
||||
if ignore_immut then
|
||||
cmd = cmd .. " --ignore-immutable"
|
||||
end
|
||||
|
||||
runner.execute_command_async(cmd, function()
|
||||
utils.notify(
|
||||
string.format("Squashed `%s` into `%s` successfully", revsets, destination_revset),
|
||||
vim.log.levels.INFO
|
||||
)
|
||||
vim.b.jj_squash_revsets = nil
|
||||
|
||||
-- Clear all highlighting before transitioning
|
||||
local buf = terminal.state.buf or 0
|
||||
vim.api.nvim_buf_clear_namespace(buf, log_selected_ns_id, 0, -1)
|
||||
vim.api.nvim_buf_clear_namespace(buf, log_special_mode_target_ns_id, 0, -1)
|
||||
|
||||
M.transition_mode("normal")
|
||||
-- Refresh log
|
||||
M.log({})
|
||||
end, "Error during squash into")
|
||||
end
|
||||
|
||||
return M
|
||||
|
||||
+63
-52
@@ -52,30 +52,32 @@ end
|
||||
|
||||
--- Help for terminal buffer
|
||||
function M.keymap_help()
|
||||
-- get the normal mode keys defined for the current buffer
|
||||
local keys = vim.api.nvim_buf_get_keymap(0, "n")
|
||||
-- get the normal mode keys defined for the current buffer
|
||||
local keys = vim.api.nvim_buf_get_keymap(0, "n")
|
||||
|
||||
-- sort the keys table by desc
|
||||
table.sort(keys, function(a, b) return (a.desc or "") < (b.desc or "") end)
|
||||
-- sort the keys table by desc
|
||||
table.sort(keys, function(a, b)
|
||||
return (a.desc or "") < (b.desc or "")
|
||||
end)
|
||||
|
||||
-- Figure out the width of the longest key for later formatting
|
||||
-- Ignore keys for entries without a desc
|
||||
local max_key_width = 0
|
||||
for _, mapping in ipairs(keys) do
|
||||
local desc = mapping["desc"]
|
||||
if desc ~= nil then
|
||||
local key = mapping["lhs"]
|
||||
local key_width = vim.api.nvim_strwidth(key)
|
||||
if key_width > max_key_width then
|
||||
max_key_width = key_width
|
||||
end
|
||||
end
|
||||
end
|
||||
-- Figure out the width of the longest key for later formatting
|
||||
-- Ignore keys for entries without a desc
|
||||
local max_key_width = 0
|
||||
for _, mapping in ipairs(keys) do
|
||||
local desc = mapping["desc"]
|
||||
if desc ~= nil then
|
||||
local key = mapping["lhs"]
|
||||
local key_width = vim.api.nvim_strwidth(key)
|
||||
if key_width > max_key_width then
|
||||
max_key_width = key_width
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- create a buffer and floating window to show the key mappings
|
||||
local buf, win = buffer.create_float({
|
||||
title = " Key mappings ",
|
||||
title_pos = "left",
|
||||
-- create a buffer and floating window to show the key mappings
|
||||
local buf, win = buffer.create_float({
|
||||
title = " Key mappings ",
|
||||
title_pos = "left",
|
||||
enter = true,
|
||||
bufhidden = "hide",
|
||||
win_options = {
|
||||
@@ -85,41 +87,38 @@ function M.keymap_help()
|
||||
cursorline = false,
|
||||
signcolumn = "no",
|
||||
},
|
||||
})
|
||||
})
|
||||
|
||||
-- helper function to pad a given key with spaces if necessary such that
|
||||
-- its size will match max_key_width calculated above.
|
||||
local function space_pad(key)
|
||||
local key_width = vim.api.nvim_strwidth(key)
|
||||
local delta = max_key_width - key_width
|
||||
if delta > 0 then
|
||||
return key .. string.rep(" ", delta)
|
||||
end
|
||||
return key
|
||||
end
|
||||
-- helper function to pad a given key with spaces if necessary such that
|
||||
-- its size will match max_key_width calculated above.
|
||||
local function space_pad(key)
|
||||
local key_width = vim.api.nvim_strwidth(key)
|
||||
local delta = max_key_width - key_width
|
||||
if delta > 0 then
|
||||
return key .. string.rep(" ", delta)
|
||||
end
|
||||
return key
|
||||
end
|
||||
|
||||
-- create formated entries for items with a non-nil desc
|
||||
local lines = {}
|
||||
for _, entry in ipairs(keys) do
|
||||
if entry["desc"] ~= nil then
|
||||
local line = string.format(" %s %s",
|
||||
space_pad(entry["lhs"]),
|
||||
entry["desc"])
|
||||
table.insert(lines, line)
|
||||
end
|
||||
-- create formated entries for items with a non-nil desc
|
||||
local lines = {}
|
||||
for _, entry in ipairs(keys) do
|
||||
if entry["desc"] ~= nil then
|
||||
local line = string.format(" %s %s", space_pad(entry["lhs"]), entry["desc"])
|
||||
table.insert(lines, line)
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
-- add some helper text at the end
|
||||
table.insert(lines, "")
|
||||
table.insert(lines, ' Use "q" or ESC to close this window')
|
||||
|
||||
-- add some helper text at the end
|
||||
table.insert(lines, "")
|
||||
table.insert(lines, ' Use "q" or ESC to close this window')
|
||||
-- add the formatted lines to the buffer
|
||||
vim.api.nvim_buf_set_lines(buf, 3, -1, false, lines)
|
||||
|
||||
-- add the formatted lines to the buffer
|
||||
vim.api.nvim_buf_set_lines(buf, 3, -1, false, lines)
|
||||
|
||||
-- Use q or ESC to close the buffer
|
||||
vim.keymap.set("n", "q", "<cmd>close<CR>", { buffer = buf })
|
||||
vim.keymap.set("n", "<Esc>", "<cmd>close<CR>", { buffer = buf })
|
||||
-- Use q or ESC to close the buffer
|
||||
vim.keymap.set("n", "q", "<cmd>close<CR>", { buffer = buf })
|
||||
vim.keymap.set("n", "<Esc>", "<cmd>close<CR>", { buffer = buf })
|
||||
end
|
||||
|
||||
--- Close the current terminal buffer if it exists
|
||||
@@ -282,6 +281,12 @@ function M.run_floating(cmd, keymaps)
|
||||
end
|
||||
end
|
||||
|
||||
-- Remove prompt keymaps
|
||||
buffer.remove_keymaps(state.floating_buf, {
|
||||
{ modes = { "n", "v" }, lhs = "[[", rhs = function() end },
|
||||
{ modes = { "n", "v" }, lhs = "]]", rhs = function() end },
|
||||
})
|
||||
|
||||
buffer.set_keymaps(state.floating_buf, default_keymaps)
|
||||
vim.b[state.floating_buf].jj_keymaps_set = true
|
||||
end
|
||||
@@ -410,7 +415,7 @@ function M.run(cmd, keymaps)
|
||||
-- Set base keymaps only if they haven't been set for this buffer yet
|
||||
if not vim.b[state.buf].jj_keymaps_set then
|
||||
buffer.set_keymaps(state.buf, {
|
||||
{ modes = { "n" }, lhs = "g?", rhs = M.keymap_help },
|
||||
{ modes = { "n" }, lhs = "g?", rhs = M.keymap_help },
|
||||
-- Disable insert, command and append modes
|
||||
{ modes = { "n", "v" }, lhs = "i", rhs = function() end },
|
||||
{ modes = { "n", "v" }, lhs = "c", rhs = function() end },
|
||||
@@ -421,6 +426,12 @@ function M.run(cmd, keymaps)
|
||||
vim.b[state.buf].jj_keymaps_set = true
|
||||
end
|
||||
|
||||
-- Remove prompt keymaps
|
||||
buffer.remove_keymaps(state.buf, {
|
||||
{ modes = { "n", "v" }, lhs = "[[", rhs = function() end },
|
||||
{ modes = { "n", "v" }, lhs = "]]", rhs = function() end },
|
||||
})
|
||||
|
||||
-- Remove command-specific keymaps from previous runs
|
||||
if vim.b[state.buf].jj_command_keymaps then
|
||||
buffer.remove_keymaps(state.buf, vim.b[state.buf].jj_command_keymaps)
|
||||
|
||||
Reference in New Issue
Block a user