diff --git a/README.md b/README.md index 4f664bb..c241724 100644 --- a/README.md +++ b/README.md @@ -61,6 +61,7 @@ - `redo` - Redo the last undone operation - `open_pr` - Open a PR/MR on your remote (GitHub, GitLab, Gitea, Forgejo, etc.) - `annotate` / `annotate_line` - View file blame and line history with change ID, author, and timestamp + - `commit` - Describe the current change and create a new one after - Diff commands - `:Jdiff [revision]` - Vertical split diff against a jj revision - `:Jhdiff [revision]` - Horizontal split diff @@ -234,6 +235,8 @@ The plugin provides a `:J` command that accepts jj subcommands: :J bookmark create/move/delete :J # This will use your defined default command :J +:J commit " Opens your configured editor describes @ and then creates a new change -A immediately +:J commit " Automatically describes @ and creates a new change -A immediately ``` ### Diff Commands diff --git a/lua/jj/cmd/describe.lua b/lua/jj/cmd/describe.lua index 25184f2..e7899c9 100644 --- a/lua/jj/cmd/describe.lua +++ b/lua/jj/cmd/describe.lua @@ -18,7 +18,8 @@ local default_describe_opts = { --- Execute jj describe command with the given description --- @param description string The description text --- @param revset? string The revision to describe -local function execute_describe(description, revset) +--- @param on_close function|nil The function to run on success +local function execute_describe(description, revset, on_close) if not description or description == "" then utils.notify("Description cannot be empty", vim.log.levels.ERROR) return @@ -33,6 +34,12 @@ local function execute_describe(description, revset) -- Use --stdin to properly handle multi-line and special characters runner.execute_command_async(cmd, function() utils.notify("Description set.", vim.log.levels.INFO) + -- If an on close callback is provided, call it + if on_close then + vim.schedule(function() + on_close() + end) + end end, "Failed to describe", description) end @@ -53,7 +60,8 @@ end --- @param description? string Optional description text --- @param revset? string The revision to describe --- @param opts? jj.cmd.describe_opts Optional command options -function M.describe(description, revset, opts) +--- @param on_close function|nil Optional callback when editor is closed +function M.describe(description, revset, opts, on_close) if not utils.ensure_jj() then return end @@ -61,7 +69,7 @@ function M.describe(description, revset, opts) -- Check if a description was provided otherwise require for input if description then -- Description provided directly - execute_describe(description, revset) + execute_describe(description, revset, on_close) return end @@ -105,9 +113,6 @@ function M.describe(description, revset, opts) table.insert(text, "JJ:") -- blank line table.insert(text, 'JJ: Lines starting with "JJ:" (like this one) will be removed') - -- Check if we're coming from the log view so we can reopen it after editing - local open_log_on_close = terminal.state.buf_cmd == "log" - -- Close the terminal buffer before opening editor terminal.close_terminal_buffer() @@ -123,9 +128,10 @@ function M.describe(description, revset, opts) execute_describe(trimmed_description, revset) -- Once editing is done, reopen the log if we came from there end, function() - if open_log_on_close then + -- If an on close callback is provided, call it + if on_close then vim.schedule(function() - cmd.log({}) + on_close() end) end end, describe_editor_keymaps()) @@ -142,7 +148,7 @@ function M.describe(description, revset, opts) }, function(input) -- If the user inputed something, execute the describe command if input then - execute_describe(input, revset) + execute_describe(input, revset, on_close) end -- Close the current terminal when finished terminal.close_terminal_buffer() @@ -151,4 +157,3 @@ function M.describe(description, revset, opts) end return M - diff --git a/lua/jj/cmd/init.lua b/lua/jj/cmd/init.lua index d63f83a..5b59d5f 100644 --- a/lua/jj/cmd/init.lua +++ b/lua/jj/cmd/init.lua @@ -682,6 +682,19 @@ function M.open_pr(opts) utils.open_pr_for_bookmark(bookmark) end +-- Jujutsu commit +--- @param description string|nil Commit changes in the current change +function M.commit(description) + if not utils.ensure_jj() then + return + end + + M.describe(description, nil, nil, function() + -- Opinionated -A flag since it seems more intuitive when editing and commiting past changes and has no effect on top changes + M.new({ args = "-A @" }) + end) +end + --- @param args string|string[] jj command arguments function M.j(args) if not utils.ensure_jj() then @@ -795,6 +808,9 @@ function M.j(args) annotate_line = function() require("jj.annotate").line() end, + commit = function() + M.commit(remaining_args_str ~= "" and remaining_args_str or nil) + end, } if handlers[subcommand] then @@ -841,6 +857,7 @@ function M.register_command() "open_pr", "annotate", "annotate_line", + "commit", } local matches = {} for _, cmd in ipairs(subcommands) do diff --git a/lua/jj/cmd/log.lua b/lua/jj/cmd/log.lua index 4d7d081..f4be33b 100644 --- a/lua/jj/cmd/log.lua +++ b/lua/jj/cmd/log.lua @@ -343,9 +343,16 @@ end --- Handle describing a log line function M.handle_log_describe() + -- Store the cursor pos for when we exit the describe + terminal.store_cursor_position() local revset = get_revset() if revset then - require("jj.cmd").describe(nil, revset) + require("jj.cmd").describe(nil, revset, nil, function() + -- Execute log + M.log() + -- Restore previous cursor pos + terminal.restore_cursor_position() + end) else utils.notify("No valid revision found in the log line", vim.log.levels.ERROR) end