Files
jj.nvim/lua/jj/diff.lua
T
2025-12-18 22:48:01 -08:00

83 lines
2.3 KiB
Lua

---@class jj.diff
local M = {}
local utils = require("jj.utils")
--- Get the content of a file at a specific revision
--- @param rev string The revision
--- @param path string The file path
--- @return table lines The file content
local function get_file_content(rev, path)
local cmd = string.format("jj file show -r %s %s", vim.fn.shellescape(rev), vim.fn.shellescape(path))
local content = vim.fn.system(cmd)
local success = vim.v.shell_error == 0
if success then
return vim.split(content, "\n", { trimempty = true })
else
-- File does not exist at revision
return {}
end
end
--- Open a read-only buffer for a specific revision of a file
--- @param rev string The revision
--- @param path string The file path
function M.open_revision(rev, path)
local lines = get_file_content(rev, path)
local buf = vim.api.nvim_create_buf(false, true)
local buf_name = string.format("jj://%s/%s", rev, path)
vim.api.nvim_buf_set_name(buf, buf_name)
vim.api.nvim_buf_set_lines(buf, 0, -1, false, lines)
local ft = vim.filetype.match({ filename = path })
if ft then
vim.bo[buf].filetype = ft
end
vim.bo[buf].buftype = "nofile"
vim.bo[buf].bufhidden = "wipe"
vim.bo[buf].readonly = true
vim.bo[buf].swapfile = false
vim.bo[buf].modifiable = true
vim.api.nvim_win_set_buf(0, buf)
end
---@class jj.diff.diff_opts
---@field rev string the revision to diff against
--- Open a diff split for a specific revision of the current file
--- @param split_fun function Split function for the diff
--- @param opts? jj.diff.diff_opts Any passed arguments
function M.open_diff(split_fun, opts)
if not utils.ensure_jj() then
return
end
-- Ensure opts is a table to avoid indexing nil
opts = opts or {}
local rev = opts.rev or "@-"
local path = vim.api.nvim_buf_get_name(0)
vim.cmd.diffthis()
split_fun({ mods = { split = "aboveleft" } })
M.open_revision(rev, path)
vim.cmd.diffthis()
end
-- Open a vertical diff split for a specific revision of the current file
--- @param opts? jj.diff.diff_opts Any passed arguments
function M.open_vdiff(opts)
M.open_diff(vim.cmd.vsplit, opts)
end
-- Open a horizontal diff split for a specific revision of the current file
--- @param opts? jj.diff.diff_opts Any passed arguments
function M.open_hdiff(opts)
M.open_diff(vim.cmd.split, opts)
end
return M