feat!(terminal): unify terminal window behavior and centralize sizing config (#102)

- add terminal.window.type support (hsplit, vsplit, floating, tab)
- add terminal.window.split_size for split-based layouts
- rename floating size options to terminal.window.floating_width/floating_height
- validate terminal window ratios during setup
- make terminal.run/run_floating merge default keymaps internally
- remove cmd.split width/height sizing in favor of terminal.window config
- improve floating/log buffer state handling and refresh behavior
- update README examples and configuration docs

BREAKING CHANGE: terminal sizing/config moved to terminal.window.*.
Removed cmd.split.width/cmd.split.height.
Renamed terminal.window.width/height to terminal.window.floating_width/floating_height
This commit is contained in:
Jonas Elhs
2026-04-07 10:31:12 +02:00
committed by GitHub
parent 578c5f15df
commit 46141a282e
8 changed files with 132 additions and 67 deletions
+9 -20
View File
@@ -94,11 +94,7 @@ local split_module = require("jj.cmd.split")
--- @field close? string|string[] Keymaps for the close keybind
--- @field floating? jj.cmd.floating.keymaps Keymaps for the floating buffer
---@class jj.cmd.split.common
---@field height? number Height % for the split buffer (between 0.1 and 1.0)
---@field width? number Width % for the split buffer (between 0.1 and 1.0)
---@class jj.cmd.split.opts: jj.cmd.split.common
---@class jj.cmd.split.opts
---@field rev? string Revision to split
---@field message? string Commit message for the new revision
---@field filesets? string[] Filesets to include in the split
@@ -106,12 +102,9 @@ local split_module = require("jj.cmd.split")
---@field parallel? boolean Run operations in parallel
---@field on_exit? fun(exit_code: number) Callback invoked when command exits
---@class jj.cmd.split: jj.cmd.split.common
--- @class jj.cmd.opts
--- @field describe? jj.cmd.describe
--- @field log? jj.cmd.log
--- @field split? jj.cmd.split
--- @field bookmark? jj.cmd.bookmark
--- @field keymaps? jj.cmd.keymaps Keymaps for the buffers containing the of the commands
---
@@ -149,10 +142,6 @@ M.config = {
log = {
close_on_edit = false,
},
split = {
width = 0.99,
height = 0.95,
},
bookmark = {
prefix = "",
},
@@ -401,7 +390,7 @@ function M.squash()
local cmd = "jj squash"
runner.execute_command_async(cmd, function()
utils.notify("Command `squash` was succesful.", vim.log.levels.INFO)
if terminal.state.buf_cmd == "log" then
if terminal.is_log_buffer_open() then
M.log()
end
end, "Failed to squash")
@@ -650,7 +639,7 @@ function M.undo()
local cmd = "jj undo"
runner.execute_command_async(cmd, function()
utils.notify("Command `undo` was succesful.", vim.log.levels.INFO)
if terminal.state.buf_cmd == "log" then
if terminal.is_log_buffer_open() then
M.log({})
end
end, "Failed to undo")
@@ -665,7 +654,7 @@ function M.redo()
local cmd = "jj redo"
runner.execute_command_async(cmd, function()
utils.notify("Command `redo` was succesful.", vim.log.levels.INFO)
if terminal.state.buf_cmd == "log" then
if terminal.is_log_buffer_open() then
M.log({})
end
end, "Failed to redo")
@@ -701,7 +690,7 @@ function M.fetch()
end
-- Save the lop one state to refresh
local log_open = terminal.state.buf_cmd == "log"
local log_open = terminal.is_log_buffer_open()
-- Get the list of remotes
local remotes = utils.get_remotes()
@@ -751,7 +740,7 @@ function M.push(opts)
opts = opts or {}
-- Save the lop one state to refresh
local log_open = terminal.state.buf_cmd == "log"
local log_open = terminal.is_log_buffer_open()
local cmd = "jj git push"
if opts.bookmark then
@@ -1209,7 +1198,7 @@ function M.j(args)
if #remaining_args == 0 then
M.edit()
else
terminal.run(cmd, M.terminal_keymaps())
terminal.run(cmd)
end
end,
new = function()
@@ -1321,7 +1310,7 @@ function M.j(args)
elseif remaining_args[1] == "track" or remaining_args[1] == "t" then
M.bookmark_track()
else
terminal.run(cmd, M.terminal_keymaps())
terminal.run(cmd)
end
end,
annotate = function()
@@ -1361,7 +1350,7 @@ function M.j(args)
if type(cmd) == "table" and cmd[1] ~= "jj" then
table.insert(cmd, 1, "jj")
end
terminal.run(cmd, M.terminal_keymaps())
terminal.run(cmd)
end
end
+11 -3
View File
@@ -334,7 +334,7 @@ function M.log(opts)
end
-- If a log was already being displayed before this command we will want to maintain the cursor position
if terminal.state.buf_cmd == "log" then
if terminal.is_log_buffer_open() then
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)
@@ -856,9 +856,17 @@ function M.handle_log_split()
on_exit = function(exit_code)
if exit_code == 0 then
utils.notify(string.format("Successfully split `%s`", revset), vim.log.levels.INFO)
M.log({})
vim.schedule(function()
M.log({})
end)
else
utils.notify(string.format("Cancelled splitting `%s`", revset), vim.log.levels.WARN)
-- Since we previously replaced the floating with the split we actually want to re run the log cmd
if require("jj").config.terminal.window.type == "floating" then
vim.schedule(function()
M.log({})
end)
end
end
end,
})
@@ -1197,7 +1205,7 @@ function M.log_keymaps()
desc = "Change the revset(s) being viewed",
handler = M.handle_log_change_revset,
modes = { "n", "v" },
},
},
select_next_revision = {
desc = "Move cursor to the next revision",
handler = M.handle_log_select_next_revision,
-19
View File
@@ -3,21 +3,6 @@ local M = {}
local utils = require("jj.utils")
local terminal = require("jj.ui.terminal")
--- Clamps a ratio value between 0.1 and 1.0, returning a default of 1.0 if the input is invalid.
---@param value? number
---@param field string
---@return number
local function clamp_ratio(value, field)
if type(value) ~= "number" or value < 0.1 or value > 1.0 then
utils.notify(
string.format("Value for field `%s` must be between `0.1` and `1.0`. Defaulted to `1.0`", field),
vim.log.levels.WARN
)
return 1.0
end
return value
end
local function build_split_command(opts)
local args = { "jj", "split" }
@@ -56,8 +41,6 @@ function M.split(opts)
local cmd_mod = require("jj.cmd")
opts = vim.tbl_deep_extend("force", cmd_mod.config.split or {}, opts or {}) --[[@as jj.cmd.split.opts]]
opts.height = clamp_ratio(opts.height, "height")
opts.width = clamp_ratio(opts.width, "width")
-- If it's empty do nothing
if utils.is_change_empty(opts.rev or "@") then
@@ -69,8 +52,6 @@ function M.split(opts)
terminal.run_floating(cmd, nil, {
title = " JJ Split ",
modifiable = true,
height = math.floor(vim.o.lines * opts.height),
width = math.floor(vim.o.columns * opts.width),
keep_modifiable = true,
interactive = true,
on_exit = opts.on_exit or nil,
+6 -4
View File
@@ -50,6 +50,10 @@ function M.handle_status_enter()
return
end
if require("jj").config.terminal.window.type == "floating" then
terminal.close_floating_buffer()
end
local filepath = file_info.new_path
local stat = vim.uv.fs_stat(filepath)
if not stat then
@@ -90,7 +94,7 @@ function M.status(opts)
return
end
local cmd_str = "jj st"
local cmd_str = "jj status"
if opts and opts.notify then
local output, success = runner.execute_command(cmd_str, "Failed to get status")
@@ -99,9 +103,7 @@ function M.status(opts)
end
else
-- Default behavior: show in buffer
local cmd = require("jj.cmd")
local keymaps = cmd.merge_keymaps(M.status_keymaps(), cmd.terminal_keymaps())
terminal.run(cmd_str, keymaps)
terminal.run(cmd_str, M.status_keymaps())
end
end