mirror of
https://github.com/lewis6991/gitsigns.nvim
synced 2025-04-21 14:45:59 +00:00
246 lines
5.0 KiB
Lua
Generated
246 lines
5.0 KiB
Lua
Generated
local create_hunk = require("gitsigns.hunks").create_hunk
|
|
local Hunk = require('gitsigns.hunks').Hunk
|
|
|
|
local ffi = require("ffi")
|
|
|
|
ffi.cdef([[
|
|
typedef struct s_mmbuffer { const char *ptr; long size; } mmbuffer_t;
|
|
|
|
typedef struct s_xpparam {
|
|
unsigned long flags;
|
|
|
|
// See Documentation/diff-options.txt.
|
|
char **anchors;
|
|
size_t anchors_nr;
|
|
} xpparam_t;
|
|
|
|
typedef long (__stdcall *find_func_t)(
|
|
const char *line,
|
|
long line_len,
|
|
char *buffer,
|
|
long buffer_size,
|
|
void *priv
|
|
);
|
|
|
|
typedef int (__stdcall *xdl_emit_hunk_consume_func_t)(
|
|
long start_a, long count_a, long start_b, long count_b,
|
|
void *cb_data
|
|
);
|
|
|
|
typedef struct s_xdemitconf {
|
|
long ctxlen;
|
|
long interhunkctxlen;
|
|
unsigned long flags;
|
|
find_func_t find_func;
|
|
void *find_func_priv;
|
|
xdl_emit_hunk_consume_func_t hunk_func;
|
|
} xdemitconf_t;
|
|
|
|
typedef struct s_xdemitcb {
|
|
void *priv;
|
|
int (__stdcall *outf)(void *, mmbuffer_t *, int);
|
|
} xdemitcb_t;
|
|
|
|
int xdl_diff(
|
|
mmbuffer_t *mf1,
|
|
mmbuffer_t *mf2,
|
|
xpparam_t const *xpp,
|
|
xdemitconf_t const *xecfg,
|
|
xdemitcb_t *ecb
|
|
);
|
|
]])
|
|
|
|
local MMBuffer = {}
|
|
|
|
|
|
|
|
|
|
|
|
local function setup_mmbuffer(lines)
|
|
local text = vim.tbl_isempty(lines) and '' or table.concat(lines, '\n') .. '\n'
|
|
return text, #text
|
|
end
|
|
|
|
local XPParam = {}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
local function get_xpparam_flag(diff_algo)
|
|
local daflag = 0
|
|
|
|
if diff_algo == 'minimal' then daflag = 1
|
|
elseif diff_algo == 'patience' then daflag = math.floor(2 ^ 14)
|
|
elseif diff_algo == 'histogram' then daflag = math.floor(2 ^ 15)
|
|
end
|
|
|
|
return daflag
|
|
end
|
|
|
|
local Long = {}
|
|
|
|
|
|
|
|
local XDEmitConf = {}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
local M = {}
|
|
|
|
local DiffResult = {}
|
|
|
|
local mmba = ffi.new('mmbuffer_t')
|
|
local mmbb = ffi.new('mmbuffer_t')
|
|
local xpparam = ffi.new('xpparam_t')
|
|
local emitcb = ffi.new('xdemitcb_t')
|
|
|
|
local function run_diff_xdl(fa, fb, diff_algo)
|
|
mmba.ptr, mmba.size = setup_mmbuffer(fa)
|
|
mmbb.ptr, mmbb.size = setup_mmbuffer(fb)
|
|
xpparam.flags = get_xpparam_flag(diff_algo)
|
|
|
|
local results = {}
|
|
|
|
local hunk_func = ffi.cast('xdl_emit_hunk_consume_func_t', function(
|
|
start_a, count_a, start_b, count_b)
|
|
|
|
local ca = tonumber(count_a)
|
|
local cb = tonumber(count_b)
|
|
local sa = tonumber(start_a)
|
|
local sb = tonumber(start_b)
|
|
|
|
|
|
|
|
if ca > 0 then sa = sa + 1 end
|
|
if cb > 0 then sb = sb + 1 end
|
|
|
|
results[#results + 1] = { sa, ca, sb, cb }
|
|
return 0
|
|
end)
|
|
|
|
local emitconf = ffi.new('xdemitconf_t')
|
|
emitconf.hunk_func = hunk_func
|
|
|
|
local ok = ffi.C.xdl_diff(mmba, mmbb, xpparam, emitconf, emitcb)
|
|
|
|
hunk_func:free()
|
|
|
|
return ok == 0 and results
|
|
end
|
|
|
|
jit.off(run_diff_xdl)
|
|
|
|
function M.run_diff(fa, fb, diff_algo)
|
|
local results = run_diff_xdl(fa, fb, diff_algo)
|
|
|
|
local hunks = {}
|
|
|
|
for _, r in ipairs(results) do
|
|
local rs, rc, as, ac = unpack(r)
|
|
local hunk = create_hunk(rs, rc, as, ac)
|
|
hunk.head = ('@@ -%d%s +%d%s @@'):format(
|
|
rs, rc > 0 and ',' .. rc or '',
|
|
as, ac > 0 and ',' .. ac or '')
|
|
|
|
if rc > 0 then
|
|
for i = rs, rs + rc - 1 do
|
|
table.insert(hunk.lines, '-' .. (fa[i] or ''))
|
|
end
|
|
end
|
|
if ac > 0 then
|
|
for i = as, as + ac - 1 do
|
|
table.insert(hunk.lines, '+' .. (fb[i] or ''))
|
|
end
|
|
end
|
|
table.insert(hunks, hunk)
|
|
end
|
|
|
|
return hunks
|
|
end
|
|
|
|
local Region = {}
|
|
|
|
local gaps_between_regions = 5
|
|
|
|
function M.run_word_diff(hunk_body)
|
|
local removed, added = 0, 0
|
|
for _, line in ipairs(hunk_body) do
|
|
if line:sub(1, 1) == '-' then
|
|
removed = removed + 1
|
|
elseif line:sub(1, 1) == '+' then
|
|
added = added + 1
|
|
end
|
|
end
|
|
|
|
if removed ~= added then
|
|
return {}
|
|
end
|
|
|
|
local ret = {}
|
|
|
|
for i = 1, removed do
|
|
|
|
local rline = hunk_body[i]:sub(2)
|
|
local aline = hunk_body[i + removed]:sub(2)
|
|
|
|
local a, b = vim.split(rline, ''), vim.split(aline, '')
|
|
|
|
local hunks0 = {}
|
|
for _, r in ipairs(run_diff_xdl(a, b)) do
|
|
local rs, rc, as, ac = unpack(r)
|
|
|
|
|
|
if rc == 0 then rs = rs + 1 end
|
|
if ac == 0 then as = as + 1 end
|
|
|
|
|
|
hunks0[#hunks0 + 1] = create_hunk(rs, rc, as, ac)
|
|
end
|
|
|
|
|
|
local hunks = { hunks0[1] }
|
|
for i = 2, #hunks0 do
|
|
local h, n = hunks[#hunks], hunks0[i]
|
|
if not h or not n then break end
|
|
if n.added.start - h.added.start - h.added.count < gaps_between_regions then
|
|
h.added.count = n.added.start + n.added.count - h.added.start
|
|
h.removed.count = n.removed.start + n.removed.count - h.removed.start
|
|
|
|
if h.added.count > 0 or h.removed.count > 0 then
|
|
h.type = 'change'
|
|
end
|
|
else
|
|
hunks[#hunks + 1] = n
|
|
end
|
|
end
|
|
|
|
for _, h in ipairs(hunks) do
|
|
local rem = { i, h.type, h.removed.start, h.removed.start + h.removed.count }
|
|
local add = { i + removed, h.type, h.added.start, h.added.start + h.added.count }
|
|
|
|
ret[#ret + 1] = rem
|
|
ret[#ret + 1] = add
|
|
end
|
|
end
|
|
return ret
|
|
end
|
|
|
|
return M
|