mirror of
https://github.com/neovim/neovim.git
synced 2025-09-28 05:58:33 +00:00
Enable new diff option linematch (#14537)
Co-authored-by: Lewis Russell <me@lewisr.dev>
This commit is contained in:
@@ -10,12 +10,16 @@
|
||||
#include <string.h>
|
||||
|
||||
#include "nvim/api/private/helpers.h"
|
||||
#include "nvim/linematch.h"
|
||||
#include "nvim/lua/converter.h"
|
||||
#include "nvim/lua/executor.h"
|
||||
#include "nvim/lua/xdiff.h"
|
||||
#include "nvim/vim.h"
|
||||
#include "xdiff/xdiff.h"
|
||||
|
||||
#define COMPARED_BUFFER0 (1 << 0)
|
||||
#define COMPARED_BUFFER1 (1 << 1)
|
||||
|
||||
typedef enum {
|
||||
kNluaXdiffModeUnified = 0,
|
||||
kNluaXdiffModeOnHunkCB,
|
||||
@@ -25,12 +29,72 @@ typedef enum {
|
||||
typedef struct {
|
||||
lua_State *lstate;
|
||||
Error *err;
|
||||
mmfile_t *ma;
|
||||
mmfile_t *mb;
|
||||
bool linematch;
|
||||
bool iwhite;
|
||||
} hunkpriv_t;
|
||||
|
||||
#ifdef INCLUDE_GENERATED_DECLARATIONS
|
||||
# include "lua/xdiff.c.generated.h"
|
||||
#endif
|
||||
|
||||
static void lua_pushhunk(lua_State *lstate, long start_a, long count_a, long start_b, long count_b)
|
||||
{
|
||||
lua_createtable(lstate, 0, 0);
|
||||
lua_pushinteger(lstate, start_a);
|
||||
lua_rawseti(lstate, -2, 1);
|
||||
lua_pushinteger(lstate, count_a);
|
||||
lua_rawseti(lstate, -2, 2);
|
||||
lua_pushinteger(lstate, start_b);
|
||||
lua_rawseti(lstate, -2, 3);
|
||||
lua_pushinteger(lstate, count_b);
|
||||
lua_rawseti(lstate, -2, 4);
|
||||
lua_rawseti(lstate, -2, (signed)lua_objlen(lstate, -2) + 1);
|
||||
}
|
||||
|
||||
static void get_linematch_results(lua_State *lstate, mmfile_t *ma, mmfile_t *mb, long start_a,
|
||||
long count_a, long start_b, long count_b, bool iwhite)
|
||||
{
|
||||
// get the pointer to char of the start of the diff to pass it to linematch algorithm
|
||||
const char *diff_begin[2] = { ma->ptr, mb->ptr };
|
||||
int diff_length[2] = { (int)count_a, (int)count_b };
|
||||
|
||||
fastforward_buf_to_lnum(&diff_begin[0], (size_t)start_a);
|
||||
fastforward_buf_to_lnum(&diff_begin[1], (size_t)start_b);
|
||||
|
||||
int *decisions = NULL;
|
||||
size_t decisions_length = linematch_nbuffers(diff_begin, diff_length, 2, &decisions, iwhite);
|
||||
|
||||
long lnuma = start_a, lnumb = start_b;
|
||||
|
||||
long hunkstarta = lnuma;
|
||||
long hunkstartb = lnumb;
|
||||
long hunkcounta = 0;
|
||||
long hunkcountb = 0;
|
||||
for (size_t i = 0; i < decisions_length; i++) {
|
||||
if (i && (decisions[i - 1] != decisions[i])) {
|
||||
lua_pushhunk(lstate, hunkstarta, hunkcounta, hunkstartb, hunkcountb);
|
||||
|
||||
hunkstarta = lnuma;
|
||||
hunkstartb = lnumb;
|
||||
hunkcounta = 0;
|
||||
hunkcountb = 0;
|
||||
// create a new hunk
|
||||
}
|
||||
if (decisions[i] & COMPARED_BUFFER0) {
|
||||
lnuma++;
|
||||
hunkcounta++;
|
||||
}
|
||||
if (decisions[i] & COMPARED_BUFFER1) {
|
||||
lnumb++;
|
||||
hunkcountb++;
|
||||
}
|
||||
}
|
||||
lua_pushhunk(lstate, hunkstarta, hunkcounta, hunkstartb, hunkcountb);
|
||||
xfree(decisions);
|
||||
}
|
||||
|
||||
static int write_string(void *priv, mmbuffer_t *mb, int nbuf)
|
||||
{
|
||||
luaL_Buffer *buf = (luaL_Buffer *)priv;
|
||||
@@ -61,20 +125,14 @@ static int hunk_locations_cb(long start_a, long count_a, long start_b, long coun
|
||||
if (count_b > 0) {
|
||||
start_b += 1;
|
||||
}
|
||||
|
||||
lua_State *lstate = (lua_State *)cb_data;
|
||||
lua_createtable(lstate, 0, 0);
|
||||
|
||||
lua_pushinteger(lstate, start_a);
|
||||
lua_rawseti(lstate, -2, 1);
|
||||
lua_pushinteger(lstate, count_a);
|
||||
lua_rawseti(lstate, -2, 2);
|
||||
lua_pushinteger(lstate, start_b);
|
||||
lua_rawseti(lstate, -2, 3);
|
||||
lua_pushinteger(lstate, count_b);
|
||||
lua_rawseti(lstate, -2, 4);
|
||||
|
||||
lua_rawseti(lstate, -2, (signed)lua_objlen(lstate, -2) + 1);
|
||||
hunkpriv_t *priv = (hunkpriv_t *)cb_data;
|
||||
lua_State *lstate = priv->lstate;
|
||||
if (priv->linematch) {
|
||||
get_linematch_results(lstate, priv->ma, priv->mb, start_a, count_a, start_b, count_b,
|
||||
priv->iwhite);
|
||||
} else {
|
||||
lua_pushhunk(lstate, start_a, count_a, start_b, count_b);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -149,7 +207,7 @@ static bool check_xdiff_opt(ObjectType actType, ObjectType expType, const char *
|
||||
}
|
||||
|
||||
static NluaXdiffMode process_xdl_diff_opts(lua_State *lstate, xdemitconf_t *cfg, xpparam_t *params,
|
||||
Error *err)
|
||||
bool *linematch, Error *err)
|
||||
{
|
||||
const DictionaryOf(LuaRef) opts = nlua_pop_Dictionary(lstate, true, err);
|
||||
|
||||
@@ -205,6 +263,11 @@ static NluaXdiffMode process_xdl_diff_opts(lua_State *lstate, xdemitconf_t *cfg,
|
||||
goto exit_1;
|
||||
}
|
||||
cfg->interhunkctxlen = v->data.integer;
|
||||
} else if (strequal("linematch", k.data)) {
|
||||
*linematch = api_object_to_bool(*v, "linematch", false, err);
|
||||
if (ERROR_SET(err)) {
|
||||
goto exit_1;
|
||||
}
|
||||
} else {
|
||||
struct {
|
||||
const char *name;
|
||||
@@ -244,10 +307,8 @@ static NluaXdiffMode process_xdl_diff_opts(lua_State *lstate, xdemitconf_t *cfg,
|
||||
|
||||
if (had_on_hunk) {
|
||||
mode = kNluaXdiffModeOnHunkCB;
|
||||
cfg->hunk_func = call_on_hunk_cb;
|
||||
} else if (had_result_type_indices) {
|
||||
mode = kNluaXdiffModeLocations;
|
||||
cfg->hunk_func = hunk_locations_cb;
|
||||
}
|
||||
|
||||
exit_1:
|
||||
@@ -268,6 +329,7 @@ int nlua_xdl_diff(lua_State *lstate)
|
||||
xdemitconf_t cfg;
|
||||
xpparam_t params;
|
||||
xdemitcb_t ecb;
|
||||
bool linematch = false;
|
||||
|
||||
CLEAR_FIELD(cfg);
|
||||
CLEAR_FIELD(params);
|
||||
@@ -280,7 +342,7 @@ int nlua_xdl_diff(lua_State *lstate)
|
||||
return luaL_argerror(lstate, 3, "expected table");
|
||||
}
|
||||
|
||||
mode = process_xdl_diff_opts(lstate, &cfg, ¶ms, &err);
|
||||
mode = process_xdl_diff_opts(lstate, &cfg, ¶ms, &linematch, &err);
|
||||
|
||||
if (ERROR_SET(&err)) {
|
||||
goto exit_0;
|
||||
@@ -288,7 +350,7 @@ int nlua_xdl_diff(lua_State *lstate)
|
||||
}
|
||||
|
||||
luaL_Buffer buf;
|
||||
hunkpriv_t *priv = NULL;
|
||||
hunkpriv_t priv;
|
||||
switch (mode) {
|
||||
case kNluaXdiffModeUnified:
|
||||
luaL_buffinit(lstate, &buf);
|
||||
@@ -296,14 +358,24 @@ int nlua_xdl_diff(lua_State *lstate)
|
||||
ecb.out_line = write_string;
|
||||
break;
|
||||
case kNluaXdiffModeOnHunkCB:
|
||||
priv = xmalloc(sizeof(*priv));
|
||||
priv->lstate = lstate;
|
||||
priv->err = &err;
|
||||
ecb.priv = priv;
|
||||
cfg.hunk_func = call_on_hunk_cb;
|
||||
priv = (hunkpriv_t) {
|
||||
.lstate = lstate,
|
||||
.err = &err,
|
||||
};
|
||||
ecb.priv = &priv;
|
||||
break;
|
||||
case kNluaXdiffModeLocations:
|
||||
cfg.hunk_func = hunk_locations_cb;
|
||||
priv = (hunkpriv_t) {
|
||||
.lstate = lstate,
|
||||
.ma = &ma,
|
||||
.mb = &mb,
|
||||
.linematch = linematch,
|
||||
.iwhite = (params.flags & XDF_IGNORE_WHITESPACE) > 0
|
||||
};
|
||||
ecb.priv = &priv;
|
||||
lua_createtable(lstate, 0, 0);
|
||||
ecb.priv = lstate;
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -314,8 +386,6 @@ int nlua_xdl_diff(lua_State *lstate)
|
||||
}
|
||||
}
|
||||
|
||||
XFREE_CLEAR(priv);
|
||||
|
||||
exit_0:
|
||||
if (ERROR_SET(&err)) {
|
||||
luaL_where(lstate, 1);
|
||||
|
Reference in New Issue
Block a user