mirror of
https://github.com/neovim/neovim.git
synced 2025-02-25 18:55:25 -06:00
Merge pull request #20785 from lewis6991/refactor/diff.c_2
This commit is contained in:
commit
6da2271a04
403
src/nvim/diff.c
403
src/nvim/diff.c
@ -26,6 +26,7 @@
|
|||||||
#include "nvim/ex_docmd.h"
|
#include "nvim/ex_docmd.h"
|
||||||
#include "nvim/fileio.h"
|
#include "nvim/fileio.h"
|
||||||
#include "nvim/fold.h"
|
#include "nvim/fold.h"
|
||||||
|
#include "nvim/garray.h"
|
||||||
#include "nvim/mark.h"
|
#include "nvim/mark.h"
|
||||||
#include "nvim/mbyte.h"
|
#include "nvim/mbyte.h"
|
||||||
#include "nvim/memline.h"
|
#include "nvim/memline.h"
|
||||||
@ -74,13 +75,13 @@ static TriState diff_a_works = kNone;
|
|||||||
|
|
||||||
// used for diff input
|
// used for diff input
|
||||||
typedef struct {
|
typedef struct {
|
||||||
char_u *din_fname; // used for external diff
|
char *din_fname; // used for external diff
|
||||||
mmfile_t din_mmfile; // used for internal diff
|
mmfile_t din_mmfile; // used for internal diff
|
||||||
} diffin_T;
|
} diffin_T;
|
||||||
|
|
||||||
// used for diff result
|
// used for diff result
|
||||||
typedef struct {
|
typedef struct {
|
||||||
char_u *dout_fname; // used for external diff
|
char *dout_fname; // used for external diff
|
||||||
garray_T dout_ga; // used for internal diff
|
garray_T dout_ga; // used for internal diff
|
||||||
} diffout_T;
|
} diffout_T;
|
||||||
|
|
||||||
@ -100,6 +101,12 @@ typedef struct {
|
|||||||
int dio_internal; // using internal diff
|
int dio_internal; // using internal diff
|
||||||
} diffio_T;
|
} diffio_T;
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
DIFF_ED,
|
||||||
|
DIFF_UNIFIED,
|
||||||
|
DIFF_NONE,
|
||||||
|
} diffstyle_T;
|
||||||
|
|
||||||
#ifdef INCLUDE_GENERATED_DECLARATIONS
|
#ifdef INCLUDE_GENERATED_DECLARATIONS
|
||||||
# include "diff.c.generated.h"
|
# include "diff.c.generated.h"
|
||||||
#endif
|
#endif
|
||||||
@ -204,13 +211,7 @@ static void diff_buf_clear(void)
|
|||||||
/// @return Its index or DB_COUNT if not found.
|
/// @return Its index or DB_COUNT if not found.
|
||||||
static int diff_buf_idx(buf_T *buf)
|
static int diff_buf_idx(buf_T *buf)
|
||||||
{
|
{
|
||||||
int idx;
|
return diff_buf_idx_tp(buf, curtab);
|
||||||
for (idx = 0; idx < DB_COUNT; idx++) {
|
|
||||||
if (curtab->tp_diffbuf[idx] == buf) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return idx;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Find buffer "buf" in the list of diff buffers for tab page "tp".
|
/// Find buffer "buf" in the list of diff buffers for tab page "tp".
|
||||||
@ -703,16 +704,16 @@ static void clear_diffin(diffin_T *din)
|
|||||||
if (din->din_fname == NULL) {
|
if (din->din_fname == NULL) {
|
||||||
XFREE_CLEAR(din->din_mmfile.ptr);
|
XFREE_CLEAR(din->din_mmfile.ptr);
|
||||||
} else {
|
} else {
|
||||||
os_remove((char *)din->din_fname);
|
os_remove(din->din_fname);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void clear_diffout(diffout_T *dout)
|
static void clear_diffout(diffout_T *dout)
|
||||||
{
|
{
|
||||||
if (dout->dout_fname == NULL) {
|
if (dout->dout_fname == NULL) {
|
||||||
ga_clear_strings(&dout->dout_ga);
|
ga_clear(&dout->dout_ga);
|
||||||
} else {
|
} else {
|
||||||
os_remove((char *)dout->dout_fname);
|
os_remove(dout->dout_fname);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -730,7 +731,7 @@ static int diff_write_buffer(buf_T *buf, diffin_T *din)
|
|||||||
for (linenr_T lnum = 1; lnum <= buf->b_ml.ml_line_count; lnum++) {
|
for (linenr_T lnum = 1; lnum <= buf->b_ml.ml_line_count; lnum++) {
|
||||||
len += (long)strlen(ml_get_buf(buf, lnum, false)) + 1;
|
len += (long)strlen(ml_get_buf(buf, lnum, false)) + 1;
|
||||||
}
|
}
|
||||||
char_u *ptr = try_malloc((size_t)len);
|
char *ptr = try_malloc((size_t)len);
|
||||||
if (ptr == NULL) {
|
if (ptr == NULL) {
|
||||||
// Allocating memory failed. This can happen, because we try to read
|
// Allocating memory failed. This can happen, because we try to read
|
||||||
// the whole buffer text into memory. Set the failed flag, the diff
|
// the whole buffer text into memory. Set the failed flag, the diff
|
||||||
@ -744,12 +745,12 @@ static int diff_write_buffer(buf_T *buf, diffin_T *din)
|
|||||||
}
|
}
|
||||||
return FAIL;
|
return FAIL;
|
||||||
}
|
}
|
||||||
din->din_mmfile.ptr = (char *)ptr;
|
din->din_mmfile.ptr = ptr;
|
||||||
din->din_mmfile.size = len;
|
din->din_mmfile.size = len;
|
||||||
|
|
||||||
len = 0;
|
len = 0;
|
||||||
for (linenr_T lnum = 1; lnum <= buf->b_ml.ml_line_count; lnum++) {
|
for (linenr_T lnum = 1; lnum <= buf->b_ml.ml_line_count; lnum++) {
|
||||||
for (char_u *s = (char_u *)ml_get_buf(buf, lnum, false); *s != NUL;) {
|
for (char *s = ml_get_buf(buf, lnum, false); *s != NUL;) {
|
||||||
if (diff_flags & DIFF_ICASE) {
|
if (diff_flags & DIFF_ICASE) {
|
||||||
int c;
|
int c;
|
||||||
char cbuf[MB_MAXBYTES + 1];
|
char cbuf[MB_MAXBYTES + 1];
|
||||||
@ -758,11 +759,11 @@ static int diff_write_buffer(buf_T *buf, diffin_T *din)
|
|||||||
c = NUL;
|
c = NUL;
|
||||||
} else {
|
} else {
|
||||||
// xdiff doesn't support ignoring case, fold-case the text.
|
// xdiff doesn't support ignoring case, fold-case the text.
|
||||||
c = utf_ptr2char((char *)s);
|
c = utf_ptr2char(s);
|
||||||
c = utf_fold(c);
|
c = utf_fold(c);
|
||||||
}
|
}
|
||||||
const int orig_len = utfc_ptr2len((char *)s);
|
const int orig_len = utfc_ptr2len(s);
|
||||||
if (utf_char2bytes(c, (char *)cbuf) != orig_len) {
|
if (utf_char2bytes(c, cbuf) != orig_len) {
|
||||||
// TODO(Bram): handle byte length difference
|
// TODO(Bram): handle byte length difference
|
||||||
memmove(ptr + len, s, (size_t)orig_len);
|
memmove(ptr + len, s, (size_t)orig_len);
|
||||||
} else {
|
} else {
|
||||||
@ -802,7 +803,7 @@ static int diff_write(buf_T *buf, diffin_T *din)
|
|||||||
// Writing the buffer is an implementation detail of performing the diff,
|
// Writing the buffer is an implementation detail of performing the diff,
|
||||||
// so it shouldn't update the '[ and '] marks.
|
// so it shouldn't update the '[ and '] marks.
|
||||||
cmdmod.cmod_flags |= CMOD_LOCKMARKS;
|
cmdmod.cmod_flags |= CMOD_LOCKMARKS;
|
||||||
int r = buf_write(buf, (char *)din->din_fname, NULL,
|
int r = buf_write(buf, din->din_fname, NULL,
|
||||||
(linenr_T)1, buf->b_ml.ml_line_count,
|
(linenr_T)1, buf->b_ml.ml_line_count,
|
||||||
NULL, false, false, false, true);
|
NULL, false, false, false, true);
|
||||||
cmdmod.cmod_flags = save_cmod_flags;
|
cmdmod.cmod_flags = save_cmod_flags;
|
||||||
@ -820,12 +821,12 @@ static int diff_write(buf_T *buf, diffin_T *din)
|
|||||||
static void diff_try_update(diffio_T *dio, int idx_orig, exarg_T *eap)
|
static void diff_try_update(diffio_T *dio, int idx_orig, exarg_T *eap)
|
||||||
{
|
{
|
||||||
if (dio->dio_internal) {
|
if (dio->dio_internal) {
|
||||||
ga_init(&dio->dio_diff.dout_ga, sizeof(char *), 1000);
|
ga_init(&dio->dio_diff.dout_ga, sizeof(diffhunk_T), 100);
|
||||||
} else {
|
} else {
|
||||||
// We need three temp file names.
|
// We need three temp file names.
|
||||||
dio->dio_orig.din_fname = (char_u *)vim_tempname();
|
dio->dio_orig.din_fname = vim_tempname();
|
||||||
dio->dio_new.din_fname = (char_u *)vim_tempname();
|
dio->dio_new.din_fname = vim_tempname();
|
||||||
dio->dio_diff.dout_fname = (char_u *)vim_tempname();
|
dio->dio_diff.dout_fname = vim_tempname();
|
||||||
if (dio->dio_orig.din_fname == NULL
|
if (dio->dio_orig.din_fname == NULL
|
||||||
|| dio->dio_new.din_fname == NULL
|
|| dio->dio_new.din_fname == NULL
|
||||||
|| dio->dio_diff.dout_fname == NULL) {
|
|| dio->dio_diff.dout_fname == NULL) {
|
||||||
@ -991,7 +992,7 @@ static int check_external_diff(diffio_T *diffio)
|
|||||||
TriState ok = kFalse;
|
TriState ok = kFalse;
|
||||||
for (;;) {
|
for (;;) {
|
||||||
ok = kFalse;
|
ok = kFalse;
|
||||||
FILE *fd = os_fopen((char *)diffio->dio_orig.din_fname, "w");
|
FILE *fd = os_fopen(diffio->dio_orig.din_fname, "w");
|
||||||
|
|
||||||
if (fd == NULL) {
|
if (fd == NULL) {
|
||||||
io_error = true;
|
io_error = true;
|
||||||
@ -1000,7 +1001,7 @@ static int check_external_diff(diffio_T *diffio)
|
|||||||
io_error = true;
|
io_error = true;
|
||||||
}
|
}
|
||||||
fclose(fd);
|
fclose(fd);
|
||||||
fd = os_fopen((char *)diffio->dio_new.din_fname, "w");
|
fd = os_fopen(diffio->dio_new.din_fname, "w");
|
||||||
|
|
||||||
if (fd == NULL) {
|
if (fd == NULL) {
|
||||||
io_error = true;
|
io_error = true;
|
||||||
@ -1011,18 +1012,18 @@ static int check_external_diff(diffio_T *diffio)
|
|||||||
fclose(fd);
|
fclose(fd);
|
||||||
fd = NULL;
|
fd = NULL;
|
||||||
if (diff_file(diffio) == OK) {
|
if (diff_file(diffio) == OK) {
|
||||||
fd = os_fopen((char *)diffio->dio_diff.dout_fname, "r");
|
fd = os_fopen(diffio->dio_diff.dout_fname, "r");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (fd == NULL) {
|
if (fd == NULL) {
|
||||||
io_error = true;
|
io_error = true;
|
||||||
} else {
|
} else {
|
||||||
char_u linebuf[LBUFLEN];
|
char linebuf[LBUFLEN];
|
||||||
|
|
||||||
for (;;) {
|
for (;;) {
|
||||||
// For normal diff there must be a line that contains
|
// For normal diff there must be a line that contains
|
||||||
// "1c1". For unified diff "@@ -1 +1 @@".
|
// "1c1". For unified diff "@@ -1 +1 @@".
|
||||||
if (vim_fgets(linebuf, LBUFLEN, fd)) {
|
if (vim_fgets((char_u *)linebuf, LBUFLEN, fd)) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1033,10 +1034,10 @@ static int check_external_diff(diffio_T *diffio)
|
|||||||
}
|
}
|
||||||
fclose(fd);
|
fclose(fd);
|
||||||
}
|
}
|
||||||
os_remove((char *)diffio->dio_diff.dout_fname);
|
os_remove(diffio->dio_diff.dout_fname);
|
||||||
os_remove((char *)diffio->dio_new.din_fname);
|
os_remove(diffio->dio_new.din_fname);
|
||||||
}
|
}
|
||||||
os_remove((char *)diffio->dio_orig.din_fname);
|
os_remove(diffio->dio_orig.din_fname);
|
||||||
}
|
}
|
||||||
|
|
||||||
// When using 'diffexpr' break here.
|
// When using 'diffexpr' break here.
|
||||||
@ -1114,9 +1115,9 @@ static int diff_file_internal(diffio_T *diffio)
|
|||||||
/// @return OK or FAIL
|
/// @return OK or FAIL
|
||||||
static int diff_file(diffio_T *dio)
|
static int diff_file(diffio_T *dio)
|
||||||
{
|
{
|
||||||
char *tmp_orig = (char *)dio->dio_orig.din_fname;
|
char *tmp_orig = dio->dio_orig.din_fname;
|
||||||
char *tmp_new = (char *)dio->dio_new.din_fname;
|
char *tmp_new = dio->dio_new.din_fname;
|
||||||
char *tmp_diff = (char *)dio->dio_diff.dout_fname;
|
char *tmp_diff = dio->dio_diff.dout_fname;
|
||||||
if (*p_dex != NUL) {
|
if (*p_dex != NUL) {
|
||||||
// Use 'diffexpr' to generate the diff file.
|
// Use 'diffexpr' to generate the diff file.
|
||||||
eval_diff(tmp_orig, tmp_new, tmp_diff);
|
eval_diff(tmp_orig, tmp_new, tmp_diff);
|
||||||
@ -1166,10 +1167,10 @@ static int diff_file(diffio_T *dio)
|
|||||||
/// @param eap
|
/// @param eap
|
||||||
void ex_diffpatch(exarg_T *eap)
|
void ex_diffpatch(exarg_T *eap)
|
||||||
{
|
{
|
||||||
char_u *buf = NULL;
|
char *buf = NULL;
|
||||||
win_T *old_curwin = curwin;
|
win_T *old_curwin = curwin;
|
||||||
char *newname = NULL; // name of patched file buffer
|
char *newname = NULL; // name of patched file buffer
|
||||||
char_u *esc_name = NULL;
|
char *esc_name = NULL;
|
||||||
|
|
||||||
#ifdef UNIX
|
#ifdef UNIX
|
||||||
char *fullname = NULL;
|
char *fullname = NULL;
|
||||||
@ -1177,16 +1178,16 @@ void ex_diffpatch(exarg_T *eap)
|
|||||||
|
|
||||||
// We need two temp file names.
|
// We need two temp file names.
|
||||||
// Name of original temp file.
|
// Name of original temp file.
|
||||||
char_u *tmp_orig = (char_u *)vim_tempname();
|
char *tmp_orig = vim_tempname();
|
||||||
// Name of patched temp file.
|
// Name of patched temp file.
|
||||||
char_u *tmp_new = (char_u *)vim_tempname();
|
char *tmp_new = vim_tempname();
|
||||||
|
|
||||||
if ((tmp_orig == NULL) || (tmp_new == NULL)) {
|
if ((tmp_orig == NULL) || (tmp_new == NULL)) {
|
||||||
goto theend;
|
goto theend;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Write the current buffer to "tmp_orig".
|
// Write the current buffer to "tmp_orig".
|
||||||
if (buf_write(curbuf, (char *)tmp_orig, NULL,
|
if (buf_write(curbuf, tmp_orig, NULL,
|
||||||
(linenr_T)1, curbuf->b_ml.ml_line_count,
|
(linenr_T)1, curbuf->b_ml.ml_line_count,
|
||||||
NULL, false, false, false, true) == FAIL) {
|
NULL, false, false, false, true) == FAIL) {
|
||||||
goto theend;
|
goto theend;
|
||||||
@ -1196,7 +1197,7 @@ void ex_diffpatch(exarg_T *eap)
|
|||||||
// Get the absolute path of the patchfile, changing directory below.
|
// Get the absolute path of the patchfile, changing directory below.
|
||||||
fullname = FullName_save(eap->arg, false);
|
fullname = FullName_save(eap->arg, false);
|
||||||
esc_name =
|
esc_name =
|
||||||
vim_strsave_shellescape((char_u *)(fullname != NULL ? fullname : eap->arg), true, true);
|
(char *)vim_strsave_shellescape((char_u *)(fullname != NULL ? fullname : eap->arg), true, true);
|
||||||
#else
|
#else
|
||||||
esc_name = vim_strsave_shellescape(eap->arg, true, true);
|
esc_name = vim_strsave_shellescape(eap->arg, true, true);
|
||||||
#endif
|
#endif
|
||||||
@ -1204,14 +1205,14 @@ void ex_diffpatch(exarg_T *eap)
|
|||||||
buf = xmalloc(buflen);
|
buf = xmalloc(buflen);
|
||||||
|
|
||||||
#ifdef UNIX
|
#ifdef UNIX
|
||||||
char_u dirbuf[MAXPATHL];
|
char dirbuf[MAXPATHL];
|
||||||
// Temporarily chdir to /tmp, to avoid patching files in the current
|
// Temporarily chdir to /tmp, to avoid patching files in the current
|
||||||
// directory when the patch file contains more than one patch. When we
|
// directory when the patch file contains more than one patch. When we
|
||||||
// have our own temp dir use that instead, it will be cleaned up when we
|
// have our own temp dir use that instead, it will be cleaned up when we
|
||||||
// exit (any .rej files created). Don't change directory if we can't
|
// exit (any .rej files created). Don't change directory if we can't
|
||||||
// return to the current.
|
// return to the current.
|
||||||
if ((os_dirname(dirbuf, MAXPATHL) != OK)
|
if ((os_dirname((char_u *)dirbuf, MAXPATHL) != OK)
|
||||||
|| (os_chdir((char *)dirbuf) != 0)) {
|
|| (os_chdir(dirbuf) != 0)) {
|
||||||
dirbuf[0] = NUL;
|
dirbuf[0] = NUL;
|
||||||
} else {
|
} else {
|
||||||
char *tempdir = vim_gettempdir();
|
char *tempdir = vim_gettempdir();
|
||||||
@ -1226,24 +1227,22 @@ void ex_diffpatch(exarg_T *eap)
|
|||||||
if (*p_pex != NUL) {
|
if (*p_pex != NUL) {
|
||||||
// Use 'patchexpr' to generate the new file.
|
// Use 'patchexpr' to generate the new file.
|
||||||
#ifdef UNIX
|
#ifdef UNIX
|
||||||
eval_patch((char *)tmp_orig,
|
eval_patch(tmp_orig, (fullname != NULL ? fullname : eap->arg), tmp_new);
|
||||||
(fullname != NULL ? fullname : eap->arg),
|
|
||||||
(char *)tmp_new);
|
|
||||||
#else
|
#else
|
||||||
eval_patch((char *)tmp_orig, (char *)eap->arg, (char *)tmp_new);
|
eval_patch(tmp_orig, eap->arg, tmp_new);
|
||||||
#endif
|
#endif
|
||||||
} else {
|
} else {
|
||||||
// Build the patch command and execute it. Ignore errors.
|
// Build the patch command and execute it. Ignore errors.
|
||||||
vim_snprintf((char *)buf, buflen, "patch -o %s %s < %s",
|
vim_snprintf(buf, buflen, "patch -o %s %s < %s",
|
||||||
tmp_new, tmp_orig, esc_name);
|
tmp_new, tmp_orig, esc_name);
|
||||||
block_autocmds(); // Avoid ShellCmdPost stuff
|
block_autocmds(); // Avoid ShellCmdPost stuff
|
||||||
(void)call_shell(buf, kShellOptFilter, NULL);
|
(void)call_shell((char_u *)buf, kShellOptFilter, NULL);
|
||||||
unblock_autocmds();
|
unblock_autocmds();
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef UNIX
|
#ifdef UNIX
|
||||||
if (dirbuf[0] != NUL) {
|
if (dirbuf[0] != NUL) {
|
||||||
if (os_chdir((char *)dirbuf) != 0) {
|
if (os_chdir(dirbuf) != 0) {
|
||||||
emsg(_(e_prev_dir));
|
emsg(_(e_prev_dir));
|
||||||
}
|
}
|
||||||
shorten_fnames(true);
|
shorten_fnames(true);
|
||||||
@ -1253,14 +1252,14 @@ void ex_diffpatch(exarg_T *eap)
|
|||||||
// Delete any .orig or .rej file created.
|
// Delete any .orig or .rej file created.
|
||||||
STRCPY(buf, tmp_new);
|
STRCPY(buf, tmp_new);
|
||||||
STRCAT(buf, ".orig");
|
STRCAT(buf, ".orig");
|
||||||
os_remove((char *)buf);
|
os_remove(buf);
|
||||||
STRCPY(buf, tmp_new);
|
STRCPY(buf, tmp_new);
|
||||||
STRCAT(buf, ".rej");
|
STRCAT(buf, ".rej");
|
||||||
os_remove((char *)buf);
|
os_remove(buf);
|
||||||
|
|
||||||
// Only continue if the output file was created.
|
// Only continue if the output file was created.
|
||||||
FileInfo file_info;
|
FileInfo file_info;
|
||||||
bool info_ok = os_fileinfo((char *)tmp_new, &file_info);
|
bool info_ok = os_fileinfo(tmp_new, &file_info);
|
||||||
uint64_t filesize = os_fileinfo_size(&file_info);
|
uint64_t filesize = os_fileinfo_size(&file_info);
|
||||||
if (!info_ok || filesize == 0) {
|
if (!info_ok || filesize == 0) {
|
||||||
emsg(_("E816: Cannot read patch output"));
|
emsg(_("E816: Cannot read patch output"));
|
||||||
@ -1276,7 +1275,7 @@ void ex_diffpatch(exarg_T *eap)
|
|||||||
if (win_split(0, (diff_flags & DIFF_VERTICAL) ? WSP_VERT : 0) != FAIL) {
|
if (win_split(0, (diff_flags & DIFF_VERTICAL) ? WSP_VERT : 0) != FAIL) {
|
||||||
// Pretend it was a ":split fname" command
|
// Pretend it was a ":split fname" command
|
||||||
eap->cmdidx = CMD_split;
|
eap->cmdidx = CMD_split;
|
||||||
eap->arg = (char *)tmp_new;
|
eap->arg = tmp_new;
|
||||||
do_exedit(eap, old_curwin);
|
do_exedit(eap, old_curwin);
|
||||||
|
|
||||||
// check that split worked and editing tmp_new
|
// check that split worked and editing tmp_new
|
||||||
@ -1301,12 +1300,12 @@ void ex_diffpatch(exarg_T *eap)
|
|||||||
|
|
||||||
theend:
|
theend:
|
||||||
if (tmp_orig != NULL) {
|
if (tmp_orig != NULL) {
|
||||||
os_remove((char *)tmp_orig);
|
os_remove(tmp_orig);
|
||||||
}
|
}
|
||||||
xfree(tmp_orig);
|
xfree(tmp_orig);
|
||||||
|
|
||||||
if (tmp_new != NULL) {
|
if (tmp_new != NULL) {
|
||||||
os_remove((char *)tmp_new);
|
os_remove(tmp_new);
|
||||||
}
|
}
|
||||||
xfree(tmp_new);
|
xfree(tmp_new);
|
||||||
xfree(newname);
|
xfree(newname);
|
||||||
@ -1525,63 +1524,25 @@ void ex_diffoff(exarg_T *eap)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Read the diff output and add each entry to the diff list.
|
static bool extract_hunk_internal(diffout_T *dout, diffhunk_T *hunk, int *line_idx)
|
||||||
///
|
|
||||||
/// @param idx_orig idx of original file
|
|
||||||
/// @param idx_new idx of new file
|
|
||||||
/// @dout diff output
|
|
||||||
static void diff_read(int idx_orig, int idx_new, diffio_T *dio)
|
|
||||||
{
|
{
|
||||||
FILE *fd = NULL;
|
bool eof = *line_idx >= dout->dout_ga.ga_len;
|
||||||
int line_idx = 0;
|
if (!eof) {
|
||||||
diff_T *dprev = NULL;
|
*hunk = ((diffhunk_T *)dout->dout_ga.ga_data)[(*line_idx)++];
|
||||||
diff_T *dp = curtab->tp_first_diff;
|
|
||||||
diffout_T *dout = &dio->dio_diff;
|
|
||||||
int notset = true; // block "*dp" not set yet
|
|
||||||
enum {
|
|
||||||
DIFF_ED,
|
|
||||||
DIFF_UNIFIED,
|
|
||||||
DIFF_NONE,
|
|
||||||
} diffstyle = DIFF_NONE;
|
|
||||||
|
|
||||||
if (dout->dout_fname == NULL) {
|
|
||||||
diffstyle = DIFF_UNIFIED;
|
|
||||||
} else {
|
|
||||||
fd = os_fopen((char *)dout->dout_fname, "r");
|
|
||||||
if (fd == NULL) {
|
|
||||||
emsg(_("E98: Cannot read diff output"));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
diffhunk_T *hunk = NULL;
|
|
||||||
|
|
||||||
if (!dio->dio_internal) {
|
|
||||||
hunk = xmalloc(sizeof(*hunk));
|
|
||||||
}
|
}
|
||||||
|
return eof;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Extract hunk by parsing the diff output from file and calculate the diffstyle.
|
||||||
|
static bool extract_hunk(FILE *fd, diffhunk_T *hunk, diffstyle_T *diffstyle)
|
||||||
|
{
|
||||||
for (;;) {
|
for (;;) {
|
||||||
if (dio->dio_internal) {
|
char line[LBUFLEN]; // only need to hold the diff line
|
||||||
if (line_idx >= dout->dout_ga.ga_len) {
|
if (vim_fgets((char_u *)line, LBUFLEN, fd)) {
|
||||||
break; // did last line
|
return true; // end of file
|
||||||
}
|
|
||||||
hunk = ((diffhunk_T **)dout->dout_ga.ga_data)[line_idx++];
|
|
||||||
} else {
|
|
||||||
char *line;
|
|
||||||
char linebuf[LBUFLEN]; // only need to hold the diff line
|
|
||||||
if (fd == NULL) {
|
|
||||||
if (line_idx >= dout->dout_ga.ga_len) {
|
|
||||||
break; // did last line
|
|
||||||
}
|
|
||||||
line = ((char **)dout->dout_ga.ga_data)[line_idx++];
|
|
||||||
} else {
|
|
||||||
if (vim_fgets((char_u *)linebuf, LBUFLEN, fd)) {
|
|
||||||
break; // end of file
|
|
||||||
}
|
|
||||||
line = linebuf;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (diffstyle == DIFF_NONE) {
|
if (*diffstyle == DIFF_NONE) {
|
||||||
// Determine diff style.
|
// Determine diff style.
|
||||||
// ed like diff looks like this:
|
// ed like diff looks like this:
|
||||||
// {first}[,{last}]c{first}[,{last}]
|
// {first}[,{last}]c{first}[,{last}]
|
||||||
@ -1593,15 +1554,15 @@ static void diff_read(int idx_orig, int idx_new, diffio_T *dio)
|
|||||||
// +++ file2 2018-03-20 13:23:41.183156066 +0100
|
// +++ file2 2018-03-20 13:23:41.183156066 +0100
|
||||||
// @@ -1,3 +1,5 @@
|
// @@ -1,3 +1,5 @@
|
||||||
if (isdigit(*line)) {
|
if (isdigit(*line)) {
|
||||||
diffstyle = DIFF_ED;
|
*diffstyle = DIFF_ED;
|
||||||
} else if ((STRNCMP(line, "@@ ", 3) == 0)) {
|
} else if ((STRNCMP(line, "@@ ", 3) == 0)) {
|
||||||
diffstyle = DIFF_UNIFIED;
|
*diffstyle = DIFF_UNIFIED;
|
||||||
} else if ((STRNCMP(line, "--- ", 4) == 0) // -V501
|
} else if ((STRNCMP(line, "--- ", 4) == 0) // -V501
|
||||||
&& (vim_fgets((char_u *)linebuf, LBUFLEN, fd) == 0) // -V501
|
&& (vim_fgets((char_u *)line, LBUFLEN, fd) == 0) // -V501
|
||||||
&& (STRNCMP(line, "+++ ", 4) == 0)
|
&& (STRNCMP(line, "+++ ", 4) == 0)
|
||||||
&& (vim_fgets((char_u *)linebuf, LBUFLEN, fd) == 0) // -V501
|
&& (vim_fgets((char_u *)line, LBUFLEN, fd) == 0) // -V501
|
||||||
&& (STRNCMP(line, "@@ ", 3) == 0)) {
|
&& (STRNCMP(line, "@@ ", 3) == 0)) {
|
||||||
diffstyle = DIFF_UNIFIED;
|
*diffstyle = DIFF_UNIFIED;
|
||||||
} else {
|
} else {
|
||||||
// Format not recognized yet, skip over this line. Cygwin diff
|
// Format not recognized yet, skip over this line. Cygwin diff
|
||||||
// may put a warning at the start of the file.
|
// may put a warning at the start of the file.
|
||||||
@ -1609,34 +1570,44 @@ static void diff_read(int idx_orig, int idx_new, diffio_T *dio)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (diffstyle == DIFF_ED) {
|
if (*diffstyle == DIFF_ED) {
|
||||||
if (!isdigit(*line)) {
|
if (!isdigit(*line)) {
|
||||||
continue; // not the start of a diff block
|
continue; // not the start of a diff block
|
||||||
}
|
}
|
||||||
if (parse_diff_ed((char_u *)line, hunk) == FAIL) {
|
if (parse_diff_ed(line, hunk) == FAIL) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
assert(diffstyle == DIFF_UNIFIED);
|
assert(*diffstyle == DIFF_UNIFIED);
|
||||||
if (STRNCMP(line, "@@ ", 3) != 0) {
|
if (STRNCMP(line, "@@ ", 3) != 0) {
|
||||||
continue; // not the start of a diff block
|
continue; // not the start of a diff block
|
||||||
}
|
}
|
||||||
if (parse_diff_unified((char_u *)line, hunk) == FAIL) {
|
if (parse_diff_unified(line, hunk) == FAIL) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Successfully parsed diff output, can return
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void process_hunk(diff_T **dpp, diff_T **dprevp, int idx_orig, int idx_new, diffhunk_T *hunk,
|
||||||
|
bool *notsetp)
|
||||||
|
{
|
||||||
|
diff_T *dp = *dpp;
|
||||||
|
diff_T *dprev = *dprevp;
|
||||||
|
|
||||||
// Go over blocks before the change, for which orig and new are equal.
|
// Go over blocks before the change, for which orig and new are equal.
|
||||||
// Copy blocks from orig to new.
|
// Copy blocks from orig to new.
|
||||||
while (dp != NULL
|
while (dp != NULL
|
||||||
&& hunk->lnum_orig > dp->df_lnum[idx_orig] + dp->df_count[idx_orig]) {
|
&& hunk->lnum_orig > dp->df_lnum[idx_orig] + dp->df_count[idx_orig]) {
|
||||||
if (notset) {
|
if (*notsetp) {
|
||||||
diff_copy_entry(dprev, dp, idx_orig, idx_new);
|
diff_copy_entry(dprev, dp, idx_orig, idx_new);
|
||||||
}
|
}
|
||||||
dprev = dp;
|
dprev = dp;
|
||||||
dp = dp->df_next;
|
dp = dp->df_next;
|
||||||
notset = true;
|
*notsetp = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((dp != NULL)
|
if ((dp != NULL)
|
||||||
@ -1663,7 +1634,7 @@ static void diff_read(int idx_orig, int idx_new, diffio_T *dio)
|
|||||||
}
|
}
|
||||||
dp->df_lnum[idx_new] = hunk->lnum_new;
|
dp->df_lnum[idx_new] = hunk->lnum_new;
|
||||||
dp->df_count[idx_new] = (linenr_T)hunk->count_new;
|
dp->df_count[idx_new] = (linenr_T)hunk->count_new;
|
||||||
} else if (notset) {
|
} else if (*notsetp) {
|
||||||
// new block inside existing one, adjust new block
|
// new block inside existing one, adjust new block
|
||||||
dp->df_lnum[idx_new] = hunk->lnum_new + off;
|
dp->df_lnum[idx_new] = hunk->lnum_new + off;
|
||||||
dp->df_count[idx_new] = (linenr_T)hunk->count_new - off;
|
dp->df_count[idx_new] = (linenr_T)hunk->count_new - off;
|
||||||
@ -1684,7 +1655,7 @@ static void diff_read(int idx_orig, int idx_new, diffio_T *dio)
|
|||||||
if (off < 0) {
|
if (off < 0) {
|
||||||
// new change ends in existing block, adjust the end if not
|
// new change ends in existing block, adjust the end if not
|
||||||
// done already
|
// done already
|
||||||
if (notset) {
|
if (*notsetp) {
|
||||||
dp->df_count[idx_new] += -off;
|
dp->df_count[idx_new] += -off;
|
||||||
}
|
}
|
||||||
off = 0;
|
off = 0;
|
||||||
@ -1724,7 +1695,45 @@ static void diff_read(int idx_orig, int idx_new, diffio_T *dio)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
notset = false; // "*dp" has been set
|
*notsetp = false; // "*dp" has been set
|
||||||
|
*dpp = dp;
|
||||||
|
*dprevp = dprev;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Read the diff output and add each entry to the diff list.
|
||||||
|
///
|
||||||
|
/// @param idx_orig idx of original file
|
||||||
|
/// @param idx_new idx of new file
|
||||||
|
/// @dout diff output
|
||||||
|
static void diff_read(int idx_orig, int idx_new, diffio_T *dio)
|
||||||
|
{
|
||||||
|
FILE *fd = NULL;
|
||||||
|
int line_idx = 0;
|
||||||
|
diff_T *dprev = NULL;
|
||||||
|
diff_T *dp = curtab->tp_first_diff;
|
||||||
|
diffout_T *dout = &dio->dio_diff;
|
||||||
|
bool notset = true; // block "*dp" not set yet
|
||||||
|
diffstyle_T diffstyle = DIFF_NONE;
|
||||||
|
|
||||||
|
if (!dio->dio_internal) {
|
||||||
|
fd = os_fopen(dout->dout_fname, "r");
|
||||||
|
if (fd == NULL) {
|
||||||
|
emsg(_("E98: Cannot read diff output"));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (;;) {
|
||||||
|
diffhunk_T hunk = { 0 };
|
||||||
|
bool eof = dio->dio_internal
|
||||||
|
? extract_hunk_internal(dout, &hunk, &line_idx)
|
||||||
|
: extract_hunk(fd, &hunk, &diffstyle);
|
||||||
|
|
||||||
|
if (eof) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
process_hunk(&dp, &dprev, idx_orig, idx_new, &hunk, ¬set);
|
||||||
}
|
}
|
||||||
|
|
||||||
// for remaining diff blocks orig and new are equal
|
// for remaining diff blocks orig and new are equal
|
||||||
@ -1737,10 +1746,6 @@ static void diff_read(int idx_orig, int idx_new, diffio_T *dio)
|
|||||||
notset = true;
|
notset = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!dio->dio_internal) {
|
|
||||||
xfree(hunk);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (fd != NULL) {
|
if (fd != NULL) {
|
||||||
fclose(fd);
|
fclose(fd);
|
||||||
}
|
}
|
||||||
@ -1934,24 +1939,24 @@ static bool diff_equal_entry(diff_T *dp, int idx1, int idx2)
|
|||||||
|
|
||||||
// Compare the characters at "p1" and "p2". If they are equal (possibly
|
// Compare the characters at "p1" and "p2". If they are equal (possibly
|
||||||
// ignoring case) return true and set "len" to the number of bytes.
|
// ignoring case) return true and set "len" to the number of bytes.
|
||||||
static bool diff_equal_char(const char_u *const p1, const char_u *const p2, int *const len)
|
static bool diff_equal_char(const char *const p1, const char *const p2, int *const len)
|
||||||
{
|
{
|
||||||
const int l = utfc_ptr2len((char *)p1);
|
const int l = utfc_ptr2len(p1);
|
||||||
|
|
||||||
if (l != utfc_ptr2len((char *)p2)) {
|
if (l != utfc_ptr2len(p2)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (l > 1) {
|
if (l > 1) {
|
||||||
if (STRNCMP(p1, p2, l) != 0
|
if (STRNCMP(p1, p2, l) != 0
|
||||||
&& (!(diff_flags & DIFF_ICASE)
|
&& (!(diff_flags & DIFF_ICASE)
|
||||||
|| utf_fold(utf_ptr2char((char *)p1)) != utf_fold(utf_ptr2char((char *)p2)))) {
|
|| utf_fold(utf_ptr2char(p1)) != utf_fold(utf_ptr2char(p2)))) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
*len = l;
|
*len = l;
|
||||||
} else {
|
} else {
|
||||||
if ((*p1 != *p2)
|
if ((*p1 != *p2)
|
||||||
&& (!(diff_flags & DIFF_ICASE)
|
&& (!(diff_flags & DIFF_ICASE)
|
||||||
|| TOLOWER_LOC(*p1) != TOLOWER_LOC(*p2))) {
|
|| TOLOWER_LOC((uint8_t)(*p1)) != TOLOWER_LOC((uint8_t)(*p2)))) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
*len = 1;
|
*len = 1;
|
||||||
@ -1978,7 +1983,7 @@ static int diff_cmp(char *s1, char *s2)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if ((diff_flags & DIFF_ICASE) && !(diff_flags & ALL_WHITE_DIFF)) {
|
if ((diff_flags & DIFF_ICASE) && !(diff_flags & ALL_WHITE_DIFF)) {
|
||||||
return mb_stricmp((const char *)s1, (const char *)s2);
|
return mb_stricmp(s1, s2);
|
||||||
}
|
}
|
||||||
|
|
||||||
char *p1 = s1;
|
char *p1 = s1;
|
||||||
@ -1994,7 +1999,7 @@ static int diff_cmp(char *s1, char *s2)
|
|||||||
p2 = skipwhite(p2);
|
p2 = skipwhite(p2);
|
||||||
} else {
|
} else {
|
||||||
int l;
|
int l;
|
||||||
if (!diff_equal_char((char_u *)p1, (char_u *)p2, &l)) {
|
if (!diff_equal_char(p1, p2, &l)) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
p1 += l;
|
p1 += l;
|
||||||
@ -2334,7 +2339,7 @@ bool diff_find_change(win_T *wp, linenr_T lnum, int *startp, int *endp)
|
|||||||
si_new = (int)(skipwhite(line_new + si_new) - line_new);
|
si_new = (int)(skipwhite(line_new + si_new) - line_new);
|
||||||
} else {
|
} else {
|
||||||
int l;
|
int l;
|
||||||
if (!diff_equal_char((char_u *)line_org + si_org, (char_u *)line_new + si_new, &l)) {
|
if (!diff_equal_char(line_org + si_org, line_new + si_new, &l)) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
si_org += l;
|
si_org += l;
|
||||||
@ -2374,11 +2379,11 @@ bool diff_find_change(win_T *wp, linenr_T lnum, int *startp, int *endp)
|
|||||||
ei_new--;
|
ei_new--;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
const char_u *p1 = (char_u *)line_org + ei_org;
|
const char *p1 = line_org + ei_org;
|
||||||
const char_u *p2 = (char_u *)line_new + ei_new;
|
const char *p2 = line_new + ei_new;
|
||||||
|
|
||||||
p1 -= utf_head_off(line_org, (char *)p1);
|
p1 -= utf_head_off(line_org, p1);
|
||||||
p2 -= utf_head_off(line_new, (char *)p2);
|
p2 -= utf_head_off(line_new, p2);
|
||||||
|
|
||||||
int l;
|
int l;
|
||||||
if (!diff_equal_char(p1, p2, &l)) {
|
if (!diff_equal_char(p1, p2, &l)) {
|
||||||
@ -2499,8 +2504,6 @@ static bool valid_diff(diff_T *diff)
|
|||||||
/// @param eap
|
/// @param eap
|
||||||
void ex_diffgetput(exarg_T *eap)
|
void ex_diffgetput(exarg_T *eap)
|
||||||
{
|
{
|
||||||
linenr_T off = 0;
|
|
||||||
aco_save_T aco;
|
|
||||||
int idx_other;
|
int idx_other;
|
||||||
|
|
||||||
// Find the current buffer in the list of diff buffers.
|
// Find the current buffer in the list of diff buffers.
|
||||||
@ -2600,15 +2603,9 @@ void ex_diffgetput(exarg_T *eap)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int idx_from;
|
aco_save_T aco;
|
||||||
int idx_to;
|
|
||||||
if (eap->cmdidx == CMD_diffget) {
|
|
||||||
idx_from = idx_other;
|
|
||||||
idx_to = idx_cur;
|
|
||||||
} else {
|
|
||||||
idx_from = idx_cur;
|
|
||||||
idx_to = idx_other;
|
|
||||||
|
|
||||||
|
if (eap->cmdidx != CMD_diffget) {
|
||||||
// Need to make the other buffer the current buffer to be able to make
|
// Need to make the other buffer the current buffer to be able to make
|
||||||
// changes in it.
|
// changes in it.
|
||||||
|
|
||||||
@ -2616,6 +2613,9 @@ void ex_diffgetput(exarg_T *eap)
|
|||||||
aucmd_prepbuf(&aco, curtab->tp_diffbuf[idx_other]);
|
aucmd_prepbuf(&aco, curtab->tp_diffbuf[idx_other]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const int idx_from = eap->cmdidx == CMD_diffget ? idx_other : idx_cur;
|
||||||
|
const int idx_to = eap->cmdidx == CMD_diffget ? idx_cur : idx_other;
|
||||||
|
|
||||||
// May give the warning for a changed buffer here, which can trigger the
|
// May give the warning for a changed buffer here, which can trigger the
|
||||||
// FileChangedRO autocommand, which may do nasty things and mess
|
// FileChangedRO autocommand, which may do nasty things and mess
|
||||||
// everything up.
|
// everything up.
|
||||||
@ -2627,10 +2627,55 @@ void ex_diffgetput(exarg_T *eap)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
diffgetput(eap->addr_count, idx_cur, idx_from, idx_to, eap->line1, eap->line2);
|
||||||
|
|
||||||
|
// restore curwin/curbuf and a few other things
|
||||||
|
if (eap->cmdidx != CMD_diffget) {
|
||||||
|
// Syncing undo only works for the current buffer, but we change
|
||||||
|
// another buffer. Sync undo if the command was typed. This isn't
|
||||||
|
// 100% right when ":diffput" is used in a function or mapping.
|
||||||
|
if (KeyTyped) {
|
||||||
|
u_sync(false);
|
||||||
|
}
|
||||||
|
aucmd_restbuf(&aco);
|
||||||
|
}
|
||||||
|
|
||||||
|
theend:
|
||||||
|
diff_busy = false;
|
||||||
|
|
||||||
|
if (diff_need_update) {
|
||||||
|
ex_diffupdate(NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check that the cursor is on a valid character and update its
|
||||||
|
// position. When there were filler lines the topline has become
|
||||||
|
// invalid.
|
||||||
|
check_cursor();
|
||||||
|
changed_line_abv_curs();
|
||||||
|
|
||||||
|
if (diff_need_update) {
|
||||||
|
// redraw already done by ex_diffupdate()
|
||||||
|
diff_need_update = false;
|
||||||
|
} else {
|
||||||
|
// Also need to redraw the other buffers.
|
||||||
|
diff_redraw(false);
|
||||||
|
apply_autocmds(EVENT_DIFFUPDATED, NULL, NULL, false, curbuf);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Apply diffget/diffput to buffers and diffblocks
|
||||||
|
///
|
||||||
|
/// @param idx_cur index of "curbuf" before aucmd_prepbuf() in the list of diff buffers
|
||||||
|
/// @param idx_from index of the buffer to read from in the list of diff buffers
|
||||||
|
/// @param idx_to index of the buffer to modify in the list of diff buffers
|
||||||
|
static void diffgetput(const int addr_count, const int idx_cur, const int idx_from,
|
||||||
|
const int idx_to, const linenr_T line1, const linenr_T line2)
|
||||||
|
{
|
||||||
|
linenr_T off = 0;
|
||||||
diff_T *dprev = NULL;
|
diff_T *dprev = NULL;
|
||||||
|
|
||||||
for (diff_T *dp = curtab->tp_first_diff; dp != NULL;) {
|
for (diff_T *dp = curtab->tp_first_diff; dp != NULL;) {
|
||||||
if (dp->df_lnum[idx_cur] > eap->line2 + off) {
|
if (dp->df_lnum[idx_cur] > line2 + off) {
|
||||||
// past the range that was specified
|
// past the range that was specified
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -2638,15 +2683,15 @@ void ex_diffgetput(exarg_T *eap)
|
|||||||
linenr_T lnum = dp->df_lnum[idx_to];
|
linenr_T lnum = dp->df_lnum[idx_to];
|
||||||
linenr_T count = dp->df_count[idx_to];
|
linenr_T count = dp->df_count[idx_to];
|
||||||
|
|
||||||
if ((dp->df_lnum[idx_cur] + dp->df_count[idx_cur] > eap->line1 + off)
|
if ((dp->df_lnum[idx_cur] + dp->df_count[idx_cur] > line1 + off)
|
||||||
&& (u_save(lnum - 1, lnum + count) != FAIL)) {
|
&& (u_save(lnum - 1, lnum + count) != FAIL)) {
|
||||||
// Inside the specified range and saving for undo worked.
|
// Inside the specified range and saving for undo worked.
|
||||||
linenr_T start_skip = 0;
|
linenr_T start_skip = 0;
|
||||||
linenr_T end_skip = 0;
|
linenr_T end_skip = 0;
|
||||||
|
|
||||||
if (eap->addr_count > 0) {
|
if (addr_count > 0) {
|
||||||
// A range was specified: check if lines need to be skipped.
|
// A range was specified: check if lines need to be skipped.
|
||||||
start_skip = eap->line1 + off - dp->df_lnum[idx_cur];
|
start_skip = line1 + off - dp->df_lnum[idx_cur];
|
||||||
if (start_skip > 0) {
|
if (start_skip > 0) {
|
||||||
// range starts below start of current diff block
|
// range starts below start of current diff block
|
||||||
if (start_skip > count) {
|
if (start_skip > count) {
|
||||||
@ -2661,7 +2706,7 @@ void ex_diffgetput(exarg_T *eap)
|
|||||||
}
|
}
|
||||||
|
|
||||||
end_skip = dp->df_lnum[idx_cur] + dp->df_count[idx_cur] - 1
|
end_skip = dp->df_lnum[idx_cur] + dp->df_count[idx_cur] - 1
|
||||||
- (eap->line2 + off);
|
- (line2 + off);
|
||||||
|
|
||||||
if (end_skip > 0) {
|
if (end_skip > 0) {
|
||||||
// range ends above end of current/from diff block
|
// range ends above end of current/from diff block
|
||||||
@ -2786,38 +2831,6 @@ void ex_diffgetput(exarg_T *eap)
|
|||||||
dp = dp->df_next;
|
dp = dp->df_next;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// restore curwin/curbuf and a few other things
|
|
||||||
if (eap->cmdidx != CMD_diffget) {
|
|
||||||
// Syncing undo only works for the current buffer, but we change
|
|
||||||
// another buffer. Sync undo if the command was typed. This isn't
|
|
||||||
// 100% right when ":diffput" is used in a function or mapping.
|
|
||||||
if (KeyTyped) {
|
|
||||||
u_sync(false);
|
|
||||||
}
|
|
||||||
aucmd_restbuf(&aco);
|
|
||||||
}
|
|
||||||
|
|
||||||
theend:
|
|
||||||
diff_busy = false;
|
|
||||||
if (diff_need_update) {
|
|
||||||
ex_diffupdate(NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check that the cursor is on a valid character and update its
|
|
||||||
// position. When there were filler lines the topline has become
|
|
||||||
// invalid.
|
|
||||||
check_cursor();
|
|
||||||
changed_line_abv_curs();
|
|
||||||
|
|
||||||
if (diff_need_update) {
|
|
||||||
// redraw already done by ex_diffupdate()
|
|
||||||
diff_need_update = false;
|
|
||||||
} else {
|
|
||||||
// Also need to redraw the other buffers.
|
|
||||||
diff_redraw(false);
|
|
||||||
apply_autocmds(EVENT_DIFFUPDATED, NULL, NULL, false, curbuf);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Update folds for all diff buffers for entry "dp".
|
/// Update folds for all diff buffers for entry "dp".
|
||||||
@ -3041,7 +3054,7 @@ linenr_T diff_lnum_win(linenr_T lnum, win_T *wp)
|
|||||||
/// Handle an ED style diff line.
|
/// Handle an ED style diff line.
|
||||||
/// Return FAIL if the line does not contain diff info.
|
/// Return FAIL if the line does not contain diff info.
|
||||||
///
|
///
|
||||||
static int parse_diff_ed(char_u *line, diffhunk_T *hunk)
|
static int parse_diff_ed(char *line, diffhunk_T *hunk)
|
||||||
{
|
{
|
||||||
long l1, l2;
|
long l1, l2;
|
||||||
|
|
||||||
@ -3049,7 +3062,7 @@ static int parse_diff_ed(char_u *line, diffhunk_T *hunk)
|
|||||||
// change: {first}[,{last}]c{first}[,{last}]
|
// change: {first}[,{last}]c{first}[,{last}]
|
||||||
// append: {first}a{first}[,{last}]
|
// append: {first}a{first}[,{last}]
|
||||||
// delete: {first}[,{last}]d{first}
|
// delete: {first}[,{last}]d{first}
|
||||||
char *p = (char *)line;
|
char *p = line;
|
||||||
linenr_T f1 = getdigits_int32(&p, true, 0);
|
linenr_T f1 = getdigits_int32(&p, true, 0);
|
||||||
if (*p == ',') {
|
if (*p == ',') {
|
||||||
p++;
|
p++;
|
||||||
@ -3093,11 +3106,11 @@ static int parse_diff_ed(char_u *line, diffhunk_T *hunk)
|
|||||||
/// Parses unified diff with zero(!) context lines.
|
/// Parses unified diff with zero(!) context lines.
|
||||||
/// Return FAIL if there is no diff information in "line".
|
/// Return FAIL if there is no diff information in "line".
|
||||||
///
|
///
|
||||||
static int parse_diff_unified(char_u *line, diffhunk_T *hunk)
|
static int parse_diff_unified(char *line, diffhunk_T *hunk)
|
||||||
{
|
{
|
||||||
// Parse unified diff hunk header:
|
// Parse unified diff hunk header:
|
||||||
// @@ -oldline,oldcount +newline,newcount @@
|
// @@ -oldline,oldcount +newline,newcount @@
|
||||||
char *p = (char *)line;
|
char *p = line;
|
||||||
if (*p++ == '@' && *p++ == '@' && *p++ == ' ' && *p++ == '-') {
|
if (*p++ == '@' && *p++ == '@' && *p++ == ' ' && *p++ == '-') {
|
||||||
long oldcount;
|
long oldcount;
|
||||||
long newline;
|
long newline;
|
||||||
@ -3149,13 +3162,11 @@ static int parse_diff_unified(char_u *line, diffhunk_T *hunk)
|
|||||||
static int xdiff_out(long start_a, long count_a, long start_b, long count_b, void *priv)
|
static int xdiff_out(long start_a, long count_a, long start_b, long count_b, void *priv)
|
||||||
{
|
{
|
||||||
diffout_T *dout = (diffout_T *)priv;
|
diffout_T *dout = (diffout_T *)priv;
|
||||||
diffhunk_T *p = xmalloc(sizeof(*p));
|
GA_APPEND(diffhunk_T, &(dout->dout_ga), ((diffhunk_T){
|
||||||
|
.lnum_orig = (linenr_T)start_a + 1,
|
||||||
ga_grow(&dout->dout_ga, 1);
|
.count_orig = count_a,
|
||||||
p->lnum_orig = (linenr_T)start_a + 1;
|
.lnum_new = (linenr_T)start_b + 1,
|
||||||
p->count_orig = count_a;
|
.count_new = count_b,
|
||||||
p->lnum_new = (linenr_T)start_b + 1;
|
}));
|
||||||
p->count_new = count_b;
|
|
||||||
((diffhunk_T **)dout->dout_ga.ga_data)[dout->dout_ga.ga_len++] = p;
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user