refactor(git): introduce Revision class, normalize naming, slim docs
This commit is contained in:
+7
-72
@@ -1,54 +1,9 @@
|
||||
local M = {}
|
||||
|
||||
local URI_PREFIX = "git://"
|
||||
|
||||
---@param revspec string
|
||||
---@return string
|
||||
function M.uri(revspec)
|
||||
return URI_PREFIX .. revspec
|
||||
end
|
||||
|
||||
---Extract the revspec from a `git://<revspec>` buffer name. Returns
|
||||
---nil if the name doesn't carry the scheme.
|
||||
---@param name string
|
||||
---@return string?
|
||||
function M.parse_uri(name)
|
||||
return name:match("^" .. URI_PREFIX .. "(.+)$")
|
||||
end
|
||||
|
||||
---@class ow.Git.ParsedRevspec
|
||||
---@field stage 0|1|2|3? index stage when the revspec is `:<path>` / `:0:<path>` / `:N:<path>`, nil otherwise
|
||||
---@field path string? path component when the revspec carries one, nil for bare object refs
|
||||
|
||||
---Classify a `git://<revspec>` revspec into its stage / path components.
|
||||
---Recognised forms:
|
||||
--- * `:<path>` and `:0:<path>` -> stage 0 (the resolved index entry)
|
||||
--- * `:1:<path>` / `:2:<path>` / `:3:<path>` -> merge stages base / ours / theirs
|
||||
--- * `<commit-ref>:<path>` -> stage = nil, path set
|
||||
--- * bare object ref (no `:`) -> stage = nil, path = nil
|
||||
---@param revspec string
|
||||
---@return ow.Git.ParsedRevspec
|
||||
function M.parse_revspec(revspec)
|
||||
local stage, path = revspec:match("^:([0123]):(.+)$")
|
||||
if stage then
|
||||
return {
|
||||
stage = tonumber(stage) --[[@as (0|1|2|3)?]],
|
||||
path = path,
|
||||
}
|
||||
end
|
||||
path = revspec:match("^:([^:]+)$")
|
||||
if path then
|
||||
return { stage = 0, path = path }
|
||||
end
|
||||
path = (revspec:match("^[^:]+:(.+)$"))
|
||||
return { stage = nil, path = path }
|
||||
end
|
||||
|
||||
---@class ow.Git.ScratchOpts
|
||||
---@field name string?
|
||||
---@field bufhidden ("hide"|"wipe")? defaults to "wipe"
|
||||
---@field bufhidden ("hide"|"wipe")?
|
||||
|
||||
---Configure a fresh buffer as a read-only scratch and optionally name it.
|
||||
---@param buf integer
|
||||
---@param opts ow.Git.ScratchOpts
|
||||
local function setup_scratch(buf, opts)
|
||||
@@ -62,8 +17,6 @@ local function setup_scratch(buf, opts)
|
||||
end
|
||||
end
|
||||
|
||||
---Set a buffer's name and re-run filetype detection from it. Wrapped
|
||||
---in `pcall` because a buffer with that name may already exist (E95).
|
||||
---@param buf integer
|
||||
---@param name string
|
||||
function M.set_buf_name(buf, name)
|
||||
@@ -74,10 +27,6 @@ function M.set_buf_name(buf, name)
|
||||
end
|
||||
end
|
||||
|
||||
---Place a buffer in the current window or a new split per `split`.
|
||||
---`false` replaces the current buffer, dropping a `'` mark first so
|
||||
---`''` jumps back. A direction string opens a split on that side. Nil
|
||||
---falls back to `'splitbelow'` for the direction.
|
||||
---@param buf integer
|
||||
---@param split (false|"above"|"below"|"left"|"right")?
|
||||
---@return integer win
|
||||
@@ -95,11 +44,8 @@ function M.place_buf(buf, split)
|
||||
end
|
||||
|
||||
---@class ow.Git.NewScratchOpts : ow.Git.ScratchOpts
|
||||
---@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).
|
||||
---@field split (false|"above"|"below"|"left"|"right")?
|
||||
|
||||
---Create a fresh read-only 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?
|
||||
---@return integer buf
|
||||
---@return integer win
|
||||
@@ -134,9 +80,6 @@ function M.debug(fmt, ...)
|
||||
vim.notify(fmt:format(...), vim.log.levels.DEBUG)
|
||||
end
|
||||
|
||||
---Split a string on newlines, dropping the trailing empty element that an
|
||||
---input ending in `\n` produces. Convenient for slicing subprocess stdout
|
||||
---into a list of lines without a phantom blank at the end.
|
||||
---@param content string
|
||||
---@return string[]
|
||||
function M.split_lines(content)
|
||||
@@ -164,9 +107,9 @@ function M.debounce(fn, delay)
|
||||
local fired_gen = 0
|
||||
|
||||
local cb_main = vim.schedule_wrap(function()
|
||||
-- Identity check: the libuv fire may have been superseded by a
|
||||
-- re-arm or a cancel between the timer firing and this scheduled
|
||||
-- callback running.
|
||||
-- Identity check: the libuv fire may have been superseded by
|
||||
-- a re-arm or a cancel between the timer firing and this
|
||||
-- scheduled callback running.
|
||||
if fired_gen ~= gen or args == nil then
|
||||
return
|
||||
end
|
||||
@@ -217,17 +160,9 @@ end
|
||||
---@class ow.Git.ExecOpts
|
||||
---@field cwd string?
|
||||
---@field stdin string?
|
||||
---@field silent boolean? suppress the auto-log on non-zero exit
|
||||
---@field on_done fun(stdout: string?)? if set, run async and deliver stdout (or nil on failure) here on the main loop instead of returning sync
|
||||
---@field silent boolean?
|
||||
---@field on_done fun(stdout: string?)?
|
||||
|
||||
---Run a system command. Default is sync: returns stdout on success or
|
||||
---nil on failure (logging stderr unless `opts.silent`). When
|
||||
---`opts.on_done` is set, runs async via `vim.schedule_wrap` and
|
||||
---delivers the same stdout-or-nil value to that callback instead.
|
||||
---
|
||||
---Async mode returns nil immediately. Callers that need access to the
|
||||
---raw stderr / exit code in the failure path should opt out of this
|
||||
---helper and use `vim.system` directly.
|
||||
---@param cmd string[]
|
||||
---@param opts ow.Git.ExecOpts?
|
||||
---@return string?
|
||||
|
||||
Reference in New Issue
Block a user