diff --git a/ftplugin/gitlog.lua b/ftplugin/gitlog.lua index fa89303..e37f80d 100644 --- a/ftplugin/gitlog.lua +++ b/ftplugin/gitlog.lua @@ -9,7 +9,7 @@ vim.keymap.set("n", "", function() .nvim_get_current_line() :match("^[*|/\\_ ]*(%x%x%x%x%x%x%x+)") if sha then - require("git.show").open_commit(worktree, sha) + require("git.show").open_commit(worktree, sha, { split = false }) else -- "n" mode = no remap, so this doesn't recurse into our mapping. vim.api.nvim_feedkeys(cr, "n", false) diff --git a/lua/git/init.lua b/lua/git/init.lua index 75b0f9f..4be10f8 100644 --- a/lua/git/init.lua +++ b/lua/git/init.lua @@ -28,9 +28,9 @@ end ---@class ow.Git.NewScratchOpts ---@field name string? ---@field bufhidden ("hide"|"wipe")? defaults to "hide" ----@field split ("above"|"below"|"left"|"right")? defaults to splitbelow-aware horizontal +---@field split (false|"above"|"below"|"left"|"right")? defaults to splitbelow-aware horizontal. `false` places the buffer in the current window (drops a `'` mark first so the user can jump back). ----Open a split with a fresh non-modifiable scratch buffer. Default split +---Create a fresh non-modifiable scratch buffer and place it. Default split ---direction is horizontal, honouring `splitbelow`. Caller flips ---`modifiable`, fills the buffer, and sets `filetype` once content lands. ---@param opts ow.Git.NewScratchOpts? @@ -47,6 +47,11 @@ function M.new_scratch(opts) if opts.name then pcall(vim.api.nvim_buf_set_name, buf, opts.name) end + if opts.split == false then + vim.cmd.normal({ "m'", bang = true }) + vim.api.nvim_set_current_buf(buf) + return buf, vim.api.nvim_get_current_win() + end local split = opts.split or (vim.o.splitbelow and "below" or "above") local win = vim.api.nvim_open_win(buf, true, { split = split }) return buf, win diff --git a/lua/git/show.lua b/lua/git/show.lua index c19ff91..acf04fb 100644 --- a/lua/git/show.lua +++ b/lua/git/show.lua @@ -127,9 +127,14 @@ local function show_diff(ctx, section) vim.api.nvim_set_current_win(left_win) end +---@class ow.Git.OpenCommitOpts +---@field split (false|"above"|"below"|"left"|"right")? forwarded to `git.new_scratch`. Default opens a new horizontal split. + ---@param worktree string ---@param ref string -function M.open_commit(worktree, ref) +---@param opts ow.Git.OpenCommitOpts? +function M.open_commit(worktree, ref, opts) + local split = opts and opts.split repo.rev_parse(worktree, ref, true, function(resolved) local sha = resolved or ref local name = "git://" .. sha .. "//" @@ -137,13 +142,18 @@ function M.open_commit(worktree, ref) -- are immutable so the content is stable. local existing = vim.fn.bufnr(name) if existing ~= -1 and vim.api.nvim_buf_is_loaded(existing) then - vim.api.nvim_open_win(existing, true, { - split = vim.o.splitbelow and "below" or "above", - }) + if split == false then + vim.cmd.normal({ "m'", bang = true }) + vim.api.nvim_set_current_buf(existing) + else + vim.api.nvim_open_win(existing, true, { + split = split or (vim.o.splitbelow and "below" or "above"), + }) + end return end - local buf, win = git.new_scratch({ name = name }) + local buf, win = git.new_scratch({ name = name, split = split }) vim.b[buf].git_worktree = worktree vim.b[buf].git_ref = sha @@ -157,10 +167,11 @@ function M.open_commit(worktree, ref) ref, vim.trim(result.stderr or "") ) - -- Tear down the empty placeholder window+buffer so a - -- retry runs a fresh fetch instead of hitting the - -- cached-buffer branch and reopening an empty pane. - if vim.api.nvim_win_is_valid(win) then + -- Drop the empty placeholder so a retry runs a fresh + -- fetch. With `split = false` the window falls back to + -- its alternate buffer (the gitlog); for a real split + -- we close the dedicated window to keep the layout tidy. + if split ~= false and vim.api.nvim_win_is_valid(win) then pcall(vim.api.nvim_win_close, win, true) end if vim.api.nvim_buf_is_valid(buf) then