Files
jj.nvim/lua/jj/cmd/describe.lua
T
Nicolas GBandGitHub 7f2786ff16 refactor!: Migrate runners cmd from string to argv (#134)
Migrate command execution to structured argv lists across the plugin, replacing shell-string command construction with `vim.system` argv execution. The runner API now exposes argv-based execution as the default path:

   - `runner.execute_command` -> `runner.execute`
   - `runner.execute_command_async` -> `runner.execute_async`
   - `runner.execute_command_raw` -> `runner.execute_raw`
   - `runner.execute_command_raw_async` -> `runner.execute_raw_async`
   - `runner.execute_command_sync` was removed; use `runner.execute` and handle the result directly

BREAKING CHANGES:
   - `cmd.new({ args = ... })` now requires `args` as `string[]` argv tokens, not a single string.
   - `cmd.log({ ... })` now uses `raw_flags` as `string[]` for raw passthrough flags; `raw = "..."` is no longer supported.
   - Direct users of `jj.core.runner` must migrate from the old `execute_command*` string helpers to the new argv-based `execute*` helpers.
2026-07-07 18:25:30 +02:00

135 lines
3.7 KiB
Lua

--- @class jj.cmd.describe
local M = {}
local utils = require("jj.utils")
local runner = require("jj.core.runner")
local terminal = require("jj.ui.terminal")
local editor = require("jj.ui.editor")
--- @class jj.cmd.describe_opts
--- @field with_status boolean: Whether or not `jj st` should be displayed in a buffer while describing the commit
--- @field type? "buffer"|"input" Editor mode for describe command: "buffer" (Git-style editor) or "input" (simple input prompt)
--- @type jj.cmd.describe_opts
local default_describe_opts = {
with_status = true,
}
--- Execute jj describe command with the given description
--- @param description string The description text
--- @param revset? string The revision to describe
--- @param sync? boolean Whether to execute command synchronously
local function execute_describe(description, revset, sync)
local cmd = {
"jj",
"describe",
}
if revset then
table.insert(cmd, "-r")
table.insert(cmd, revset)
end
table.insert(cmd, "--stdin")
-- Use --stdin to properly handle multi-line and special characters
if sync then
runner.execute(cmd, "Failed to describe", description)
utils.notify("Description set.", vim.log.levels.INFO)
return
end
runner.execute_async(cmd, function()
utils.notify("Description set.", vim.log.levels.INFO)
end, "Failed to describe", description)
end
--- Resolve describe editor keymaps from config
--- @return jj.core.buffer.keymap
local function describe_editor_keymaps()
local cmd = require("jj.cmd")
local cfg = cmd.config.describe.editor.keymaps or {}
return cmd.resolve_keymaps_from_specs(cfg, {
close = {
desc = "Close describe editor without saving",
handler = "<cmd>close!<CR>",
modes = { "n" },
},
})
end
--- Jujutsu describe
--- @param description? string Optional description text
--- @param revset? string The revision to describe
--- @param opts? jj.cmd.describe_opts Optional command options
--- @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
-- Check if a description was provided otherwise require for input
if description then
-- Description provided directly
execute_describe(description, revset, false)
return
end
if not revset then
revset = "@"
end
local cmd = require("jj.cmd")
local merged_opts = vim.tbl_deep_extend("force", default_describe_opts, opts or {})
-- Use buffer editor mode (defaults to "buffer" if not configured)
local editor_mode = merged_opts.type or cmd.config.describe.editor.type or "buffer"
if editor_mode == "buffer" then
local text = utils.get_describe_text(revset)
if not text then
return
end
-- Close the terminal buffer before opening editor
terminal.close_terminal_buffer()
editor.open_editor(text, function(buf_lines)
local trimmed_description = utils.extract_description_from_describe(buf_lines)
if not trimmed_description then
trimmed_description = ""
end
execute_describe(trimmed_description, revset, true)
-- Once editing is done, reopen the log if we came from there
end, function()
-- If an on close callback is provided, call it
if on_close then
vim.schedule(function()
on_close()
end)
end
end, describe_editor_keymaps())
else
-- Use input mode
if merged_opts.with_status then
-- Show the status in a terminal buffer
cmd.status()
end
vim.ui.input({
prompt = "Description: ",
default = "",
}, function(input)
-- If the user inputed something, execute the describe command
if input then
execute_describe(input, revset, true)
end
-- Close the current terminal when finished
terminal.close_terminal_buffer()
if on_close then
vim.schedule(function()
on_close()
end)
end
end)
end
end
return M