From c474bc63f214c4174489d1dbfdfd67ca04f0d1e9 Mon Sep 17 00:00:00 2001 From: NicolasGB Date: Tue, 8 Jul 2025 11:13:35 +0200 Subject: [PATCH] feat(log): Pressing "Enter" on mutable log lines runs `jj edit` to seamlessly navigate repisotory commit history --- lua/jj/cmd.lua | 56 ++++++++++++++++++++++++++++++++++++++++ lua/jj/picker/snacks.lua | 2 +- 2 files changed, 57 insertions(+), 1 deletion(-) diff --git a/lua/jj/cmd.lua b/lua/jj/cmd.lua index 591b1ea..a974f67 100644 --- a/lua/jj/cmd.lua +++ b/lua/jj/cmd.lua @@ -68,6 +68,60 @@ local function handle_status_enter() vim.cmd("edit " .. vim.fn.fnameescape(filepath)) end +--- Extract revision ID from a jujutsu log line +--- @param line string The log line to parse +--- @return string|nil The revision ID if found, nil otherwise +local function get_rev_from_log_line(line) + -- Define jujutsu symbols with their UTF-8 byte sequences + local jj_symbols = { + diamond = "\226\151\134", -- ◆ + circle = "\226\151\139", -- ○ + } + + local revset + + -- Try each symbol pattern + for _, symbol in pairs(jj_symbols) do + -- Pattern: Lines starting with symbol + revset = line:match("^%s*" .. symbol .. "%s+(%w+)") + if revset then + return revset + end + + -- Pattern: Lines with │ followed by symbol (this are the branches) + revset = line:match("^│%s*" .. symbol .. "%s+(%w+)") + if revset then + return revset + end + end + + -- Pattern for simple ASCII symbols + revset = line:match("^%s*[@]%s+(%w+)") + if revset then + return revset + end + + return nil +end + +--- Handle keypress enter on `jj log` buffer to edit a previous revision +local function handle_log_enter() + local line = vim.api.nvim_get_current_line() + + local revset = get_rev_from_log_line(line) + + if revset then + -- If we found a revision, edit it + local cmd = string.format("jj edit %s", revset) + local _, success = utils.execute_command(cmd, "Error editing change") + if not success then + return + end + -- Close the terminal buffer + close_terminal_buffer() + end +end + --- Run a command and show it's output in a terminal buffer --- If a previous command already existed it smartly reuses the buffer cleaning the previous output ---@param cmd string @@ -173,6 +227,8 @@ local function run(cmd) local cmd_parts = vim.split(cmd, " ") if cmd_parts[2] == "st" or cmd_parts[2] == "status" then vim.keymap.set({ "n" }, "", handle_status_enter, { buffer = state.buf, noremap = true, silent = true }) + elseif cmd_parts[2] == "log" then + vim.keymap.set({ "n" }, "", handle_log_enter, { buffer = state.buf, noremap = true, silent = true }) end vim.b[state.buf].jj_keymaps_set = true diff --git a/lua/jj/picker/snacks.lua b/lua/jj/picker/snacks.lua index 7fa34b6..545c49a 100644 --- a/lua/jj/picker/snacks.lua +++ b/lua/jj/picker/snacks.lua @@ -75,7 +75,7 @@ local function format_jj_log(item, picker) end if item.commit_id then - ret[#ret + 1] = { a(item.commit_id, 4, { truncate = true }), "SnacksPickerGitCommit" } + ret[#ret + 1] = { a(item.commit_id, 10, { truncate = true }), "SnacksPickerGitCommit" } if #item.commit_id >= 4 then ret[#ret + 1] = { " " } end