diff options
author | Lewis Russell <lewis6991@gmail.com> | 2022-10-23 15:08:50 +0100 |
---|---|---|
committer | Lewis Russell <lewis6991@gmail.com> | 2022-10-24 13:57:26 +0100 |
commit | 29f138d5ad9a6609efaee52e053b288c7ac86c8b (patch) | |
tree | 7a19193c8a1a67a2bdc1a18380f5799fc9bc789e /src/nvim/diff.c | |
parent | 267494151bcc6e4fff7b9b8c80b7a5f42e2aa002 (diff) | |
download | rneovim-29f138d5ad9a6609efaee52e053b288c7ac86c8b.tar.gz rneovim-29f138d5ad9a6609efaee52e053b288c7ac86c8b.tar.bz2 rneovim-29f138d5ad9a6609efaee52e053b288c7ac86c8b.zip |
refactor(diff.c): factor out hunk extraction
Diffstat (limited to 'src/nvim/diff.c')
-rw-r--r-- | src/nvim/diff.c | 153 |
1 files changed, 82 insertions, 71 deletions
diff --git a/src/nvim/diff.c b/src/nvim/diff.c index 0efd0e8bf1..9fd9976cbe 100644 --- a/src/nvim/diff.c +++ b/src/nvim/diff.c @@ -101,6 +101,12 @@ typedef struct { int dio_internal; // using internal diff } diffio_T; +typedef enum { + DIFF_ED, + DIFF_UNIFIED, + DIFF_NONE, +} diffstyle_T; + #ifdef INCLUDE_GENERATED_DECLARATIONS # include "diff.c.generated.h" #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. /// /// @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; diffout_T *dout = &dio->dio_diff; int notset = true; // block "*dp" not set yet - enum { - DIFF_ED, - DIFF_UNIFIED, - DIFF_NONE, - } diffstyle = DIFF_NONE; + diffstyle_T diffstyle = DIFF_NONE; - if (dout->dout_fname == NULL) { + if (dio->dio_internal) { diffstyle = DIFF_UNIFIED; } else { 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 (;;) { - if (dio->dio_internal) { - if (line_idx >= dout->dout_ga.ga_len) { - break; // did last line - } - 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) { - // 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 *)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; - } - } + diffhunk_T hunk = { 0 }; + bool eof = dio->dio_internal + ? extract_hunk_internal(dout, &hunk, &line_idx) + : extract_hunk(fd, &hunk, &diffstyle); - 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; - } - } + if (eof) { + break; } // Go over blocks before the change, for which orig and new are equal. |