mirror of
https://github.com/neovim/neovim.git
synced 2025-02-25 18:55:25 -06:00
refactor(diff.c): factor out hunk extraction
This commit is contained in:
parent
267494151b
commit
29f138d5ad
153
src/nvim/diff.c
153
src/nvim/diff.c
@ -101,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
|
||||||
@ -1524,6 +1530,74 @@ void ex_diffoff(exarg_T *eap)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool extract_hunk_internal(diffout_T *dout, diffhunk_T *hunk, int *line_idx)
|
||||||
|
{
|
||||||
|
bool eof = *line_idx >= dout->dout_ga.ga_len;
|
||||||
|
if (!eof) {
|
||||||
|
*hunk = ((diffhunk_T *)dout->dout_ga.ga_data)[(*line_idx)++];
|
||||||
|
}
|
||||||
|
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 (;;) {
|
||||||
|
char line[LBUFLEN]; // only need to hold the diff line
|
||||||
|
if (vim_fgets((char_u *)line, LBUFLEN, fd)) {
|
||||||
|
return true; // end of file
|
||||||
|
}
|
||||||
|
|
||||||
|
if (*diffstyle == DIFF_NONE) {
|
||||||
|
// Determine diff style.
|
||||||
|
// ed like diff looks like this:
|
||||||
|
// {first}[,{last}]c{first}[,{last}]
|
||||||
|
// {first}a{first}[,{last}]
|
||||||
|
// {first}[,{last}]d{first}
|
||||||
|
//
|
||||||
|
// unified diff looks like this:
|
||||||
|
// --- file1 2018-03-20 13:23:35.783153140 +0100
|
||||||
|
// +++ file2 2018-03-20 13:23:41.183156066 +0100
|
||||||
|
// @@ -1,3 +1,5 @@
|
||||||
|
if (isdigit(*line)) {
|
||||||
|
*diffstyle = DIFF_ED;
|
||||||
|
} else if ((STRNCMP(line, "@@ ", 3) == 0)) {
|
||||||
|
*diffstyle = DIFF_UNIFIED;
|
||||||
|
} else if ((STRNCMP(line, "--- ", 4) == 0) // -V501
|
||||||
|
&& (vim_fgets((char_u *)line, LBUFLEN, fd) == 0) // -V501
|
||||||
|
&& (STRNCMP(line, "+++ ", 4) == 0)
|
||||||
|
&& (vim_fgets((char_u *)line, LBUFLEN, fd) == 0) // -V501
|
||||||
|
&& (STRNCMP(line, "@@ ", 3) == 0)) {
|
||||||
|
*diffstyle = DIFF_UNIFIED;
|
||||||
|
} else {
|
||||||
|
// Format not recognized yet, skip over this line. Cygwin diff
|
||||||
|
// may put a warning at the start of the file.
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (*diffstyle == DIFF_ED) {
|
||||||
|
if (!isdigit(*line)) {
|
||||||
|
continue; // not the start of a diff block
|
||||||
|
}
|
||||||
|
if (parse_diff_ed(line, hunk) == FAIL) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
assert(*diffstyle == DIFF_UNIFIED);
|
||||||
|
if (STRNCMP(line, "@@ ", 3) != 0) {
|
||||||
|
continue; // not the start of a diff block
|
||||||
|
}
|
||||||
|
if (parse_diff_unified(line, hunk) == FAIL) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Successfully parsed diff output, can return
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Read the diff output and add each entry to the diff list.
|
/// Read the diff output and add each entry to the diff list.
|
||||||
///
|
///
|
||||||
/// @param idx_orig idx of original file
|
/// @param idx_orig idx of original file
|
||||||
@ -1537,13 +1611,9 @@ static void diff_read(int idx_orig, int idx_new, diffio_T *dio)
|
|||||||
diff_T *dp = curtab->tp_first_diff;
|
diff_T *dp = curtab->tp_first_diff;
|
||||||
diffout_T *dout = &dio->dio_diff;
|
diffout_T *dout = &dio->dio_diff;
|
||||||
int notset = true; // block "*dp" not set yet
|
int notset = true; // block "*dp" not set yet
|
||||||
enum {
|
diffstyle_T diffstyle = DIFF_NONE;
|
||||||
DIFF_ED,
|
|
||||||
DIFF_UNIFIED,
|
|
||||||
DIFF_NONE,
|
|
||||||
} diffstyle = DIFF_NONE;
|
|
||||||
|
|
||||||
if (dout->dout_fname == NULL) {
|
if (dio->dio_internal) {
|
||||||
diffstyle = DIFF_UNIFIED;
|
diffstyle = DIFF_UNIFIED;
|
||||||
} else {
|
} else {
|
||||||
fd = os_fopen(dout->dout_fname, "r");
|
fd = os_fopen(dout->dout_fname, "r");
|
||||||
@ -1553,73 +1623,14 @@ static void diff_read(int idx_orig, int idx_new, diffio_T *dio)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
diffhunk_T hunk;
|
|
||||||
|
|
||||||
for (;;) {
|
for (;;) {
|
||||||
if (dio->dio_internal) {
|
diffhunk_T hunk = { 0 };
|
||||||
if (line_idx >= dout->dout_ga.ga_len) {
|
bool eof = dio->dio_internal
|
||||||
break; // did last line
|
? extract_hunk_internal(dout, &hunk, &line_idx)
|
||||||
}
|
: extract_hunk(fd, &hunk, &diffstyle);
|
||||||
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 (eof) {
|
||||||
// Determine diff style.
|
break;
|
||||||
// ed like diff looks like this:
|
|
||||||
// {first}[,{last}]c{first}[,{last}]
|
|
||||||
// {first}a{first}[,{last}]
|
|
||||||
// {first}[,{last}]d{first}
|
|
||||||
//
|
|
||||||
// unified diff looks like this:
|
|
||||||
// --- file1 2018-03-20 13:23:35.783153140 +0100
|
|
||||||
// +++ file2 2018-03-20 13:23:41.183156066 +0100
|
|
||||||
// @@ -1,3 +1,5 @@
|
|
||||||
if (isdigit(*line)) {
|
|
||||||
diffstyle = DIFF_ED;
|
|
||||||
} else if ((STRNCMP(line, "@@ ", 3) == 0)) {
|
|
||||||
diffstyle = DIFF_UNIFIED;
|
|
||||||
} else if ((STRNCMP(line, "--- ", 4) == 0) // -V501
|
|
||||||
&& (vim_fgets((char_u *)linebuf, LBUFLEN, fd) == 0) // -V501
|
|
||||||
&& (STRNCMP(line, "+++ ", 4) == 0)
|
|
||||||
&& (vim_fgets((char_u *)linebuf, LBUFLEN, fd) == 0) // -V501
|
|
||||||
&& (STRNCMP(line, "@@ ", 3) == 0)) {
|
|
||||||
diffstyle = DIFF_UNIFIED;
|
|
||||||
} else {
|
|
||||||
// Format not recognized yet, skip over this line. Cygwin diff
|
|
||||||
// may put a warning at the start of the file.
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (diffstyle == DIFF_ED) {
|
|
||||||
if (!isdigit(*line)) {
|
|
||||||
continue; // not the start of a diff block
|
|
||||||
}
|
|
||||||
if (parse_diff_ed(line, &hunk) == FAIL) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
assert(diffstyle == DIFF_UNIFIED);
|
|
||||||
if (STRNCMP(line, "@@ ", 3) != 0) {
|
|
||||||
continue; // not the start of a diff block
|
|
||||||
}
|
|
||||||
if (parse_diff_unified(line, &hunk) == FAIL) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 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.
|
||||||
|
Loading…
Reference in New Issue
Block a user