This pull request is an algorithm I've written and tested / developed over the past year to improve the diff mode of neovim, applied as a patch to vim. The following is the description of the algorithm, from the neovim pull request which you can find here:
the description below is still relevant, but I originally had two separate functions to run for the case with two buffers, and three buffers. I've since then written a recursive algorithm (found in the function linematch_nbuffers) which works for any number of diff buffers.
--------------- description -------------
This fork was created to improve the diff mode of neovim to show more useful information when comparing lines between files in diff view. Line comparisons are made in a more useful way to show which lines are actually being added, changed, and deleted.
2 files before:
2 files after:
3 files before:
3 files after:
Fugitive merge conflict before:
Fugitive merge conflict after:
How to use:
enable this enhanced diff mode by using :set diffopt+=linematch:{n}. Where n is the maximum total number of lines of the diff hunk. The line match diff opt is disabled automatically when diffing more than three files at once. A reasonable setting is ":set diffopt+=linematch:50", this will align the most similar lines for a diff hunk in two buffers, 25 lines long in each, or a diff hunk between 3 files, 20 lines, 20 lines, and 10 lines. The limit is placed to prevent lag when a very large diff hunk is present, in the case that the specified line number is exceeded, the default diff behaviour is resumed.
Why is this not a plugin?
This may be able to be converted to a plugin, but doing so would take much more work because the original diff mode would first need to be completely hidden. All the locations with diffs would need to be overwritten with the text from the linematch diff output. This would include writing text over locations which are marked as filler lines, which I don't believe is possible to do. Changing lines would need to be done on different "fake lines", because part of the functionality here moves around the lines to align them between the diff buffers. Additionally, By default the diff mode in vim is very bad compared to other editors like Emacs and vs-code, so by default VIM should have a comparable high quality diff view because other editors do.
How it works:
Before:
After
The 3d case (for 3 buffers) of the algorithm implemented when diffopt 'linematch' is enabled. The algorithm constructs a 3d tensor to compare a diff between 3 buffers. The dimmensions of the tensor are the length of the diff in each buffer plus 1 A path is constructed by moving from one edge of the cube/3d tensor to the opposite edge. Motions from one cell of the cube to the next represent decisions. In a 3d cube, there are a total of 7 decisions that can be made, represented by the enum path3_choice which is defined in buffer_defs.h a comparison of buffer 0 and 1 represents a motion toward the opposite edge of the cube with components along the 0 and 1 axes. a comparison of buffer 0, 1, and 2 represents a motion toward the opposite edge of the cube with components along the 0, 1, and 2 axes. A skip of buffer 0 represents a motion along only the 0 axis. For each action, a point value is awarded, and the path is saved for reference later, if it is found to have been the optimal path. The optimal path has the highest score. The score is calculated as the summation of the total characters matching between all of the lines which were compared. The structure of the algorithm is that of a dynamic programming problem. We can calculate a point i,j,k in the cube as a function of i-1, j-1, and k-1. To find the score and path at point i,j,k, we must determine which path we want to use, this is done by looking at the possibilities and choosing the one which results in the local highest score. The total highest scored path is, then in the end represented by the cell in the opposite corner from the start location. The entire algorithm consits of populating the 3d cube with the optimal paths from which it may have came. However, we cannot apply the general 3d case before first populating the edges and the surfaces of the cube. Therefore, there are several sets of if / else statements inside the main loops which determine which case to evaluate.
Optimizations
As the function to calculate the cell of a tensor at point i,j,k is a function of the cells at i-1, j-1, k-1, the whole tensor doesn't need to be stored in memory at once. In the case of the 3d cube, only two slices (along k and j axis) are stored in memory. For the 2d matrix (for 2 files), only two rows are stored at a time. The next/previous slice (or row) is always calculated from the other, and they alternate at each iteration.
In the 3d case, 3 arrays are populated to memorize the score (matched characters) of the 3 buffers, so a redundant calculation of the scores does not occur
https://github.com/vim/vim/pull/9661
(8 files)
—
Reply to this email directly, view it on GitHub.
Triage notifications on the go with GitHub Mobile for iOS or Android.
You are receiving this because you are subscribed to this thread.
This pull request introduces 3 alerts when merging d4aca2c into f10911e - view on LGTM.com
new alerts:
—
Reply to this email directly, view it on GitHub.
Triage notifications on the go with GitHub Mobile for iOS or Android.
You are receiving this because you are subscribed to this thread.
—
Reply to this email directly, view it on GitHub.
Triage notifications on the go with GitHub Mobile for iOS or Android.
You are receiving this because you are subscribed to this thread.
—
Reply to this email directly, view it on GitHub.
Triage notifications on the go with GitHub Mobile for iOS or Android.
You are receiving this because you are subscribed to this thread.
Thanks for working on this. I've had this annoyance with how diff works for a long time, only recognizing binary change/no-change, while it matters how much changes.
I haven't looked at the code yet, but is there something clever about handling indent? When changing code indent often changes while the rest of the line remains the same, which can be recognized as the same line, and then other lines are inserted or deleted, often the { and } of a block.
—
Reply to this email directly, view it on GitHub.
Triage notifications on the go with GitHub Mobile for iOS or Android.
You are receiving this because you commented.
A quick look at the code shows that you re using C99 syntax, while Vim mostly uses C89. No variable declarations halfway a block, for example (MSVC can't handle them). Thus this patch is fine to discuss functionality, but it can't be included like this.
—
Reply to this email directly, view it on GitHub.
Triage notifications on the go with GitHub Mobile for iOS or Android.
You are receiving this because you commented.
@jamessan commented on this pull request.
> @@ -13,7 +13,21 @@ void ex_diffthis(exarg_T *eap); void diff_win_options(win_T *wp, int addbuf); void ex_diffoff(exarg_T *eap); void diff_clear(tabpage_T *tp); -int diff_check(win_T *wp, linenr_T lnum); +Bool diff_linematch(diff_T *dp);
Use the int TRUE
/FALSE
values instead of Bool
.
-Bool diff_linematch(diff_T *dp); +int diff_linematch(diff_T *dp);
—
Reply to this email directly, view it on GitHub, or unsubscribe.
You are receiving this because you commented.
On 2022-01-29, Jonathon wrote: This pull request is an algorithm I've written and tested / developed over the past year to improve the diff mode of neovim, applied as a patch to vim.
I just started playing with this. I applied your 9661.patch to Vim 8.2.4257. Then, with .../vim/src first in my PATH and "silent! set diffopt+=linematch:60" in my vimrc, I executed "git difftool" in the .../vim directory to see how your algorithm affected the results. The first file opened with these messages. "runtime/doc/options.txt" 9293L, 403236B Error detected while processing command line: E341: Internal error: lalloc(0, ) I realize that I haven't accounted for or tried to minimize my configuration, but I hoped this would be useful anyway. I did this on a system running Ubuntu 20.04.3, remotely over ssh from a Crosh terminal on a Chromebook. Regards, Gary
I'm looking into this. I encountered this error when I first applied the patch to vim. in neovim, there is no error raised when xmalloc is called for a size of 0, but for vim it was raising an error when ALLOC_MULT is called with a size of 0. however, I thought I fixed this so that it should never be called with a size of 0.
I was getting that error when it would allocate a string for a blank line of a file. And it also made me realize I needed at least a size of 1 for a blank line anyway because of the '\0' character.
—
Reply to this email directly, view it on GitHub.
Triage notifications on the go with GitHub Mobile for iOS or Android.
You are receiving this because you commented.
Thanks for working on this. I've had this annoyance with how diff works for a long time, only recognizing binary change/no-change, while it matters how much changes.
I haven't looked at the code yet, but is there something clever about handling indent? When changing code indent often changes while the rest of the line remains the same, which can be recognized as the same line, and then other lines are inserted or deleted, often the { and } of a block.
for the case when you change the indent of a block of code and then remove a few lines above or below it, yes, this would fix that. It would move around the filler places so the lines with a change in indentation are no longer marked as new lines.
—
Reply to this email directly, view it on GitHub.
Triage notifications on the go with GitHub Mobile for iOS or Android.
You are receiving this because you commented.
If your able to give me the content of two files that when you diff them, it produces that error, that would help.
Here is a minimal example:
$ patch -p1 </tmp/patch.txt
$ make clean; make distclean; make
$ ./src/vim -Nu NONE -S /tmp/bug.vim
Here is /tmp/bug.vim
:
set diffopt=linematch:60
call writefile([''], '/tmp/file1')
call writefile(['', ''], '/tmp/file2')
edit /tmp/file1
diffsplit /tmp/file2
And here is /tmp/patch.txt
.
Backtrace:
#0 __GI_raise (sig=sig@entry=6) at ../sysdeps/unix/sysv/linux/raise.c:50
#1 0x00007ffff6f54859 in __GI_abort () at abort.c:79
#2 0x00005555558a566f in iemsg (s=0x555555958800 <e_internal_error_lalloc_zero> "E341: Internal error: lalloc(0, )")
at message.c:833
#3 0x0000555555598b36 in lalloc (size=0, message=1) at alloc.c:231
#4 0x00005555555989e0 in alloc (size=0) at alloc.c:151
#5 0x00005555555d63f7 in allocate_comparison_mem (diff_length=0x5555559f28c0, nDiffs=2) at diff.c:2259
#6 0x00005555555d6e11 in linematch_nbuffers
(diff_block=0x5555559f8820, diff_length=0x5555559f28c0, nDiffs=2, df_comparisonlines=0x5555559f8710, df_arr_col_size=0x5555559f8718, outmap=0x5555559f8870) at diff.c:2502
#7 0x00005555555d73a3 in diff_check (wp=0x5555559eeaa0, lnum=2, linestatus=0x7fffffffc2a8) at diff.c:2618
#8 0x00005555555dddf9 in win_line (wp=0x5555559eeaa0, lnum=2, startrow=1, endrow=14, nochange=1, number_only=0)
at drawline.c:680
#9 0x00005555555e9aa8 in win_update (wp=0x5555559eeaa0) at drawscreen.c:2473
#10 0x00005555555e46aa in update_screen (type_arg=0) at drawscreen.c:317
#11 0x000055555589e351 in main_loop (cmdwin=0, noexmode=0) at main.c:1400
#12 0x000055555589d85c in vim_main2 () at main.c:879
#13 0x000055555589cf51 in main (argc=5, argv=0x7fffffffcb28) at main.c:426
quit
Start of valgrind log:
==200787== Memcheck, a memory error detector
==200787== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==200787== Using Valgrind-3.15.0 and LibVEX; rerun with -h for copyright info
==200787== Command: ./src/vim -Nu NONE -S /tmp/bug.vim
==200787== Parent PID: 199609
==200787==
==200787==
==200787== Process terminating with default action of signal 6 (SIGABRT)
==200787== at 0x573655B: kill (syscall-template.S:78)
==200787== by 0x2B61A6: may_core_dump (os_unix.c:3510)
==200787== by 0x2B6141: mch_exit (os_unix.c:3476)
==200787== by 0x453E24: getout (main.c:1718)
==200787== by 0x276B8D: preserve_exit (misc1.c:2194)
==200787== by 0x2B373B: deathtrap (os_unix.c:1156)
==200787== by 0x573620F: ??? (in /usr/lib/x86_64-linux-gnu/libc-2.31.so)
==200787== by 0x573618A: __libc_signal_restore_set (internal-signals.h:86)
==200787== by 0x573618A: raise (raise.c:48)
==200787== by 0x5715858: abort (abort.c:79)
==200787== by 0x45AACD: iemsg (message.c:833)
==200787== by 0x14CB75: lalloc (alloc.c:231)
==200787== by 0x14CA1F: alloc (alloc.c:151)
==200787== by 0x18A911: allocate_comparison_mem (diff.c:2259)
==200787== by 0x18B32B: linematch_nbuffers (diff.c:2502)
==200787== by 0x18B8BD: diff_check (diff.c:2618)
==200787== by 0x192313: win_line (drawline.c:680)
==200787== by 0x19DFC2: win_update (drawscreen.c:2473)
==200787== by 0x198BC4: update_screen (drawscreen.c:317)
==200787== by 0x4537AF: main_loop (main.c:1400)
==200787== by 0x452CBA: vim_main2 (main.c:879)
==200787== by 0x4523AF: main (main.c:426)
==200787==
==200787== HEAP SUMMARY:
==200787== in use at exit: 767,444 bytes in 3,417 blocks
==200787== total heap usage: 5,629 allocs, 2,212 frees, 1,951,068 bytes allocated
—
Reply to this email directly, view it on GitHub.
Triage notifications on the go with GitHub Mobile for iOS or Android.
You are receiving this because you commented.
@jwhite510 pushed 1 commit.
—
View it on GitHub or unsubscribe.
You are receiving this because you are subscribed to this thread.
That error should now be fixed. I added a check so that ALLOC_MULT is not
called when there is a size of 0
The output of the algorithm has been completely restructured.
( neovim/neovim#14537 )
I will work on porting it from neovim to vim soon.
—
Reply to this email directly, view it on GitHub.
You are receiving this because you commented.
This pull request introduces 3 alerts when merging e4c3f0c into 9dac9b1 - view on LGTM.com
new alerts:
—
Reply to this email directly, view it on GitHub.
You are receiving this because you commented.
@brammool
@jamessan
@lacygoill
This was recently merged to Neovim (neovim/neovim#14537). Are you interested in merging it to vim if I update this pull request?
—
Reply to this email directly, view it on GitHub.
You are receiving this because you commented.
—
Reply to this email directly, view it on GitHub.
You are receiving this because you are subscribed to this thread.
I'd also be interested in it
—
Reply to this email directly, view it on GitHub.
You are receiving this because you commented.
@jwhite510 can you please update this patch?
—
Reply to this email directly, view it on GitHub, or unsubscribe.
You are receiving this because you commented.
@jwhite510 pushed 2 commits.
You are receiving this because you are subscribed to this thread.
@jwhite510 pushed 1 commit.
You are receiving this because you are subscribed to this thread.
still some test failures
—
Reply to this email directly, view it on GitHub.
You are receiving this because you commented.
@jwhite510 pushed 1 commit.
You are receiving this because you are subscribed to this thread.
@jwhite510 pushed 3 commits.
You are receiving this because you are subscribed to this thread.
@benknoble commented on this pull request.
> @@ -2959,6 +2959,19 @@ A jump table for the options with a short description can be found at |Q_op|. diff library. algorithm:{text} Use the specified diff algorithm with the + + linematch:{n} Align and mark changes between the most + similar lines between the buffers. When the + total number of lines in the diff hunk exceeds + {n}, the lines will not be aligned because for + very large diff hunks there will be a + noticeable lag. A reasonable setting is + "linematch:60", as this will enable alignment + for a 2 buffer diff hunk of 30 lines each, + or a 3 buffer diff hunk of 20 lines each. + + algorithm:{text} Use the specified diff algorithm with the
It looks like there’s a copy of this text above that didn’t get deleted
—
Reply to this email directly, view it on GitHub, or unsubscribe.
You are receiving this because you commented.
@jwhite510 pushed 4 commits.
You are receiving this because you are subscribed to this thread.
@jwhite510 pushed 2 commits.
You are receiving this because you are subscribed to this thread.
can someone tell me what I am missing to include 'linematch_nbuffers' from linematch.c in diff.c?
I am getting this
diff.c|2211 col 29| error: implicit declaration of function ‘linematch_nbuffers’ [-Wimplicit-function-declaration]
|| 2211 | size_t decisions_length = linematch_nbuffers(diffbufs, diff_length, ndiffs, &decisions, iwhite);
—
Reply to this email directly, view it on GitHub, or unsubscribe.
You are receiving this because you commented.
Hm, clang throws a bit more information:
error: call to undeclared function 'linematch_nbuffers'; ISO C99 and later do not support implicit function declarations [-Wimplicit-function-declaration]
but I haven't looked into more detail yet.
—
Reply to this email directly, view it on GitHub.
You are receiving this because you commented.
The following patch helped (including @jamessan 's years-old comments):
diff --git i/src/diff.c w/src/diff.c index 74d7e187e..7a4d9ef20 100644 --- i/src/diff.c +++ w/src/diff.c @@ -18,6 +18,7 @@ #include "vim.h" #include "xdiff/xdiff.h" +#include "linematch.pro" #if defined(FEAT_DIFF) || defined(PROTO) @@ -1930,7 +1931,7 @@ diff_clear(tabpage_T *tp) /* * return true if the options are set to use diff linematch */ - Bool + int diff_linematch(diff_T *dp) { if (!(diff_flags & DIFF_LINEMATCH)) { @@ -2017,7 +2018,7 @@ count_filler_lines_and_topline(int *curlinenum_to, int *linesfiller, { const diff_T *curdif = thistopdiff; int ch_virtual_lines = 0; - Bool isfiller = FALSE; + int isfiller = FALSE; while (virtual_lines_passed > 0) { if (ch_virtual_lines) { virtual_lines_passed--; @@ -2207,7 +2208,7 @@ run_linematch_algorithm(diff_T *dp) // we will get the output of the linematch algorithm in the format of an array // of integers (*decisions) and the length of that array (decisions_length) int *decisions = NULL; - const Bool iwhite = (diff_flags & (DIFF_IWHITEALL | DIFF_IWHITE)) > 0; + const int iwhite = (diff_flags & (DIFF_IWHITEALL | DIFF_IWHITE)) > 0; size_t decisions_length = linematch_nbuffers(diffbufs, diff_length, ndiffs, &decisions, iwhite); for (size_t i = 0; i < ndiffs; i++) { diff --git i/src/proto/diff.pro w/src/proto/diff.pro index f566f431d..fb844e1a9 100644 --- i/src/proto/diff.pro +++ w/src/proto/diff.pro @@ -13,7 +13,7 @@ void ex_diffthis(exarg_T *eap); void diff_win_options(win_T *wp, int addbuf); void ex_diffoff(exarg_T *eap); void diff_clear(tabpage_T *tp);
-Bool diff_linematch(diff_T *dp); +int diff_linematch(diff_T *dp);
int count_virtual_lines(win_T *win, linenr_T start, linenr_T endline); int count_virtual_to_real(win_T *win, const linenr_T lnum, const int virtual_lines, int *line_new_virtualp ); long count_n_matched_chars(const char_u **stringps, const int *fromValues, const int n, int ***comparison_mem); diff --git i/src/structs.h w/src/structs.h index 610363329..4225cd12e 100644 --- i/src/structs.h +++ w/src/structs.h @@ -3545,7 +3545,7 @@ struct diffcomparisonpath_flat_S { // diffopt is enabled, it is populated after running linematch_nbuffers typedef struct df_linecompare_S df_linecompare_T; struct df_linecompare_S { - Bool df_newline; // is this line skipped in other buffers? + int df_newline; // is this line skipped in other buffers? int df_filler; // how many filler lines above this? int df_compare[DB_COUNT]; // which line to compare to in other buffer }; @@ -3570,7 +3570,7 @@ struct diffblock_S diff_T *df_next; linenr_T df_lnum[DB_COUNT]; // line number in buffer linenr_T df_count[DB_COUNT]; // nr of inserted/changed lines - Bool is_linematched; // has the linematch algorithm ran on this diff hunk to divide it into + int is_linematched; // has the linematch algorithm ran on this diff hunk to divide it into // smaller diff hunks? }; #endif
Starting make in the src directory.
If there are problems, cd to the src directory and run make there
cd src && /Applications/Xcode.app/Contents/Developer/usr/bin/make first
gcc -c -I. -Iproto -DHAVE_CONFIG_H -DMACOS_X -DMACOS_X_DARWIN -DMACOS_X -DMACOS_X_DARWIN -g -O2 -D_REENTRANT -I/usr/local/Cellar/libsodium/1.0.20/include -U_FORTIFY_SOURCE -D_FORTIFY_SOURCE=1 -o objects/linematch.o linematch.c
linematch.c:32:15: error: implicit declaration of function 'strnchr' is invalid in C99 [-Werror,-Wimplicit-function-declaration]
char *end = strnchr(s, &n, '\n');
^
linematch.c:32:9: warning: incompatible integer to pointer conversion initializing 'char *' with an expression of type 'int' [-Wint-conversion]
char *end = strnchr(s, &n, '\n');
^ ~~~~~~~~~~~~~~~~~~~~
linematch.c:68:10: error: implicit declaration of function 'matching_chars' is invalid in C99 [-Werror,-Wimplicit-function-declaration]
return matching_chars(&sp[0], &sp[1]);
^
linematch.c:84:12: error: static declaration of 'matching_chars' follows non-static declaration
static int matching_chars(const mmfile_t *m1, const mmfile_t *m2)
^
linematch.c:68:10: note: previous implicit declaration is here
return matching_chars(&sp[0], &sp[1]);
^
linematch.c:120:12: error: static declaration of 'count_n_matched_chars' follows non-static declaration
static int count_n_matched_chars(mmfile_t **sp, const size_t n, bool iwhite)
^
proto/diff.pro:19:6: note: previous declaration is here
long count_n_matched_chars(const char_u **stringps, const int *fromValues, const int n, int ***comparison_mem);
^
linematch.c:148:13: error: implicit declaration of function 'strnchr' is invalid in C99 [-Werror,-Wimplicit-function-declaration]
s.ptr = strnchr(s.ptr, &n, '\n');
^
linematch.c:148:11: warning: incompatible integer to pointer conversion assigning to 'char *' from 'int' [-Wint-conversion]
s.ptr = strnchr(s.ptr, &n, '\n');
^ ~~~~~~~~~~~~~~~~~~~~~~~~
linematch.c:170:13: error: static declaration of 'try_possible_paths' follows non-static declaration
static void try_possible_paths(const int *df_iters, const size_t *paths, const int npaths,
^
proto/diff.pro:24:6: note: previous declaration is here
void try_possible_paths(const int *df_iterators, const int *paths, const int nPaths, const int pathIndex, int *choice, diffcomparisonpath_flat_T *diffcomparisonpath_flat, int ***comparison_mem, const int *diff_length, const int nDiffs, const char **diff_block);
^
linematch.c:194:78: error: too few arguments to function call, expected 4, have 3
int matched_chars = count_n_matched_chars(current_lines, ndiffs, iwhite);
~~~~~~~~~~~~~~~~~~~~~ ^
proto/diff.pro:19:6: note: 'count_n_matched_chars' declared here
long count_n_matched_chars(const char_u **stringps, const int *fromValues, const int n, int ***comparison_mem);
^
linematch.c:211:32: warning: incompatible pointer types passing 'const size_t *' (aka 'const unsigned long *') to parameter of type 'const int *' [-Wincompatible-pointer-types]
try_possible_paths(df_iters, paths, npaths, path_idx + 1, choice,
^~~~~
proto/diff.pro:24:61: note: passing argument to parameter 'paths' here
void try_possible_paths(const int *df_iterators, const int *paths, const int nPaths, const int pathIndex, int *choice, diffcomparisonpath_flat_T *diffcomparisonpath_flat, int ***comparison_mem, const int *diff_length, const int nDiffs, const char **diff_block);
^
linematch.c:212:22: warning: incompatible pointer types passing 'diffcmppath_T *' (aka 'struct diffcmppath_S *') to parameter of type 'diffcomparisonpath_flat_T *' (aka 'struct diffcomparisonpath_flat_S *') [-Wincompatible-pointer-types]
diffcmppath, diff_len, ndiffs, diff_blk, iwhite);
^~~~~~~~~~~
proto/diff.pro:24:147: note: passing argument to parameter 'diffcomparisonpath_flat' here
void try_possible_paths(const int *df_iterators, const int *paths, const int nPaths, const int pathIndex, int *choice, diffcomparisonpath_flat_T *diffcomparisonpath_flat, int ***comparison_mem, const int *diff_length, const int nDiffs, const char **diff_block);
^
linematch.c:212:35: warning: incompatible pointer types passing 'const int *' to parameter of type 'int ***' [-Wincompatible-pointer-types]
diffcmppath, diff_len, ndiffs, diff_blk, iwhite);
^~~~~~~~
proto/diff.pro:24:179: note: passing argument to parameter 'comparison_mem' here
void try_possible_paths(const int *df_iterators, const int *paths, const int nPaths, const int pathIndex, int *choice, diffcomparisonpath_flat_T *diffcomparisonpath_flat, int ***comparison_mem, const int *diff_length, const int nDiffs, const char **diff_block);
^
linematch.c:212:45: warning: incompatible integer to pointer conversion passing 'const size_t' (aka 'const unsigned long') to parameter of type 'const int *' [-Wint-conversion]
diffcmppath, diff_len, ndiffs, diff_blk, iwhite);
^~~~~~
proto/diff.pro:24:206: note: passing argument to parameter 'diff_length' here
void try_possible_paths(const int *df_iterators, const int *paths, const int nPaths, const int pathIndex, int *choice, diffcomparisonpath_flat_T *diffcomparisonpath_flat, int ***comparison_mem, const int *diff_length, const int nDiffs, const char **diff_block);
^
linematch.c:212:53: warning: incompatible pointer to integer conversion passing 'const mmfile_t **' (aka 'const struct s_mmfile **') to parameter of type 'int' [-Wint-conversion]
diffcmppath, diff_len, ndiffs, diff_blk, iwhite);
^~~~~~~~
proto/diff.pro:24:229: note: passing argument to parameter 'nDiffs' here
void try_possible_paths(const int *df_iterators, const int *paths, const int nPaths, const int pathIndex, int *choice, diffcomparisonpath_flat_T *diffcomparisonpath_flat, int ***comparison_mem, const int *diff_length, const int nDiffs, const char **diff_block);
^
linematch.c:212:63: warning: incompatible integer to pointer conversion passing 'bool' to parameter of type 'const char **' [-Wint-conversion]
diffcmppath, diff_len, ndiffs, diff_blk, iwhite);
^~~~~~
proto/diff.pro:24:250: note: passing argument to parameter 'diff_block' here
void try_possible_paths(const int *df_iterators, const int *paths, const int nPaths, const int pathIndex, int *choice, diffcomparisonpath_flat_T *diffcomparisonpath_flat, int ***comparison_mem, const int *diff_length, const int nDiffs, const char **diff_block);
^
linematch.c:214:32: warning: incompatible pointer types passing 'const size_t *' (aka 'const unsigned long *') to parameter of type 'const int *' [-Wincompatible-pointer-types]
try_possible_paths(df_iters, paths, npaths, path_idx + 1, choice,
^~~~~
proto/diff.pro:24:61: note: passing argument to parameter 'paths' here
void try_possible_paths(const int *df_iterators, const int *paths, const int nPaths, const int pathIndex, int *choice, diffcomparisonpath_flat_T *diffcomparisonpath_flat, int ***comparison_mem, const int *diff_length, const int nDiffs, const char **diff_block);
^
linematch.c:215:22: warning: incompatible pointer types passing 'diffcmppath_T *' (aka 'struct diffcmppath_S *') to parameter of type 'diffcomparisonpath_flat_T *' (aka 'struct diffcomparisonpath_flat_S *') [-Wincompatible-pointer-types]
diffcmppath, diff_len, ndiffs, diff_blk, iwhite);
^~~~~~~~~~~
proto/diff.pro:24:147: note: passing argument to parameter 'diffcomparisonpath_flat' here
void try_possible_paths(const int *df_iterators, const int *paths, const int nPaths, const int pathIndex, int *choice, diffcomparisonpath_flat_T *diffcomparisonpath_flat, int ***comparison_mem, const int *diff_length, const int nDiffs, const char **diff_block);
^
linematch.c:215:35: warning: incompatible pointer types passing 'const int *' to parameter of type 'int ***' [-Wincompatible-pointer-types]
diffcmppath, diff_len, ndiffs, diff_blk, iwhite);
^~~~~~~~
proto/diff.pro:24:179: note: passing argument to parameter 'comparison_mem' here
void try_possible_paths(const int *df_iterators, const int *paths, const int nPaths, const int pathIndex, int *choice, diffcomparisonpath_flat_T *diffcomparisonpath_flat, int ***comparison_mem, const int *diff_length, const int nDiffs, const char **diff_block);
^
linematch.c:215:45: warning: incompatible integer to pointer conversion passing 'const size_t' (aka 'const unsigned long') to parameter of type 'const int *' [-Wint-conversion]
diffcmppath, diff_len, ndiffs, diff_blk, iwhite);
^~~~~~
proto/diff.pro:24:206: note: passing argument to parameter 'diff_length' here
void try_possible_paths(const int *df_iterators, const int *paths, const int nPaths, const int pathIndex, int *choice, diffcomparisonpath_flat_T *diffcomparisonpath_flat, int ***comparison_mem, const int *diff_length, const int nDiffs, const char **diff_block);
^
linematch.c:215:53: warning: incompatible pointer to integer conversion passing 'const mmfile_t **' (aka 'const struct s_mmfile **') to parameter of type 'int' [-Wint-conversion]
diffcmppath, diff_len, ndiffs, diff_blk, iwhite);
^~~~~~~~
proto/diff.pro:24:229: note: passing argument to parameter 'nDiffs' here
void try_possible_paths(const int *df_iterators, const int *paths, const int nPaths, const int pathIndex, int *choice, diffcomparisonpath_flat_T *diffcomparisonpath_flat, int ***comparison_mem, const int *diff_length, const int nDiffs, const char **diff_block);
^
linematch.c:215:63: warning: incompatible integer to pointer conversion passing 'bool' to parameter of type 'const char **' [-Wint-conversion]
diffcmppath, diff_len, ndiffs, diff_blk, iwhite);
^~~~~~
proto/diff.pro:24:250: note: passing argument to parameter 'diff_block' here
void try_possible_paths(const int *df_iterators, const int *paths, const int nPaths, const int pathIndex, int *choice, diffcomparisonpath_flat_T *diffcomparisonpath_flat, int ***comparison_mem, const int *diff_length, const int nDiffs, const char **diff_block);
^
linematch.c:222:15: error: static declaration of 'unwrap_indexes' follows non-static declaration
static size_t unwrap_indexes(const int *values, const int *diff_len, const size_t ndiffs)
^
proto/diff.pro:23:5: note: previous declaration is here
int unwrap_indexes(const int *values, const int *diff_length, const int nDiffs);
^
linematch.c:248:13: error: static declaration of 'populate_tensor' follows non-static declaration
static void populate_tensor(int *df_iters, const size_t ch_dim, diffcmppath_T *diffcmppath,
^
proto/diff.pro:28:6: note: previous declaration is here
void populate_tensor(int *df_iterators, const int ch_dim, diffcomparisonpath_flat_T *diffcomparisonpath_flat, int ***comparison_mem, const int *diff_length, const int nDiffs, const char **diff_block);
^
linematch.c:265:34: warning: incompatible pointer types passing 'size_t [8]' to parameter of type 'const int *' [-Wincompatible-pointer-types]
try_possible_paths(df_iters, paths, npaths, 0, &choice, diffcmppath,
^~~~~
proto/diff.pro:24:61: note: passing argument to parameter 'paths' here
void try_possible_paths(const int *df_iterators, const int *paths, const int nPaths, const int pathIndex, int *choice, diffcomparisonpath_flat_T *diffcomparisonpath_flat, int ***comparison_mem, const int *diff_length, const int nDiffs, const char **diff_block);
^
linematch.c:265:61: warning: incompatible pointer types passing 'diffcmppath_T *' (aka 'struct diffcmppath_S *') to parameter of type 'diffcomparisonpath_flat_T *' (aka 'struct diffcomparisonpath_flat_S *') [-Wincompatible-pointer-types]
try_possible_paths(df_iters, paths, npaths, 0, &choice, diffcmppath,
^~~~~~~~~~~
proto/diff.pro:24:147: note: passing argument to parameter 'diffcomparisonpath_flat' here
void try_possible_paths(const int *df_iterators, const int *paths, const int nPaths, const int pathIndex, int *choice, diffcomparisonpath_flat_T *diffcomparisonpath_flat, int ***comparison_mem, const int *diff_length, const int nDiffs, const char **diff_block);
^
linematch.c:266:24: warning: incompatible pointer types passing 'const int *' to parameter of type 'int ***' [-Wincompatible-pointer-types]
diff_len, ndiffs, diff_blk, iwhite);
^~~~~~~~
proto/diff.pro:24:179: note: passing argument to parameter 'comparison_mem' here
void try_possible_paths(const int *df_iterators, const int *paths, const int nPaths, const int pathIndex, int *choice, diffcomparisonpath_flat_T *diffcomparisonpath_flat, int ***comparison_mem, const int *diff_length, const int nDiffs, const char **diff_block);
^
linematch.c:266:34: warning: incompatible integer to pointer conversion passing 'const size_t' (aka 'const unsigned long') to parameter of type 'const int *' [-Wint-conversion]
diff_len, ndiffs, diff_blk, iwhite);
^~~~~~
proto/diff.pro:24:206: note: passing argument to parameter 'diff_length' here
void try_possible_paths(const int *df_iterators, const int *paths, const int nPaths, const int pathIndex, int *choice, diffcomparisonpath_flat_T *diffcomparisonpath_flat, int ***comparison_mem, const int *diff_length, const int nDiffs, const char **diff_block);
^
linematch.c:266:42: warning: incompatible pointer to integer conversion passing 'const mmfile_t **' (aka 'const struct s_mmfile **') to parameter of type 'int' [-Wint-conversion]
diff_len, ndiffs, diff_blk, iwhite);
^~~~~~~~
proto/diff.pro:24:229: note: passing argument to parameter 'nDiffs' here
void try_possible_paths(const int *df_iterators, const int *paths, const int nPaths, const int pathIndex, int *choice, diffcomparisonpath_flat_T *diffcomparisonpath_flat, int ***comparison_mem, const int *diff_length, const int nDiffs, const char **diff_block);
^
linematch.c:266:52: warning: incompatible integer to pointer conversion passing 'bool' to parameter of type 'const char **' [-Wint-conversion]
diff_len, ndiffs, diff_blk, iwhite);
^~~~~~
proto/diff.pro:24:250: note: passing argument to parameter 'diff_block' here
void try_possible_paths(const int *df_iterators, const int *paths, const int nPaths, const int pathIndex, int *choice, diffcomparisonpath_flat_T *diffcomparisonpath_flat, int ***comparison_mem, const int *diff_length, const int nDiffs, const char **diff_block);
^
linematch.c:272:43: warning: incompatible pointer types passing 'diffcmppath_T *' (aka 'struct diffcmppath_S *') to parameter of type 'diffcomparisonpath_flat_T *' (aka 'struct diffcomparisonpath_flat_S *') [-Wincompatible-pointer-types]
populate_tensor(df_iters, ch_dim + 1, diffcmppath, diff_len,
^~~~~~~~~~~
proto/diff.pro:28:86: note: passing argument to parameter 'diffcomparisonpath_flat' here
void populate_tensor(int *df_iterators, const int ch_dim, diffcomparisonpath_flat_T *diffcomparisonpath_flat, int ***comparison_mem, const int *diff_length, const int nDiffs, const char **diff_block);
^
linematch.c:272:56: warning: incompatible pointer types passing 'const int *' to parameter of type 'int ***' [-Wincompatible-pointer-types]
populate_tensor(df_iters, ch_dim + 1, diffcmppath, diff_len,
^~~~~~~~
proto/diff.pro:28:118: note: passing argument to parameter 'comparison_mem' here
void populate_tensor(int *df_iterators, const int ch_dim, diffcomparisonpath_flat_T *diffcomparisonpath_flat, int ***comparison_mem, const int *diff_length, const int nDiffs, const char **diff_block);
^
linematch.c:273:21: warning: incompatible integer to pointer conversion passing 'const size_t' (aka 'const unsigned long') to parameter of type 'const int *' [-Wint-conversion]
ndiffs, diff_blk, iwhite);
^~~~~~
proto/diff.pro:28:145: note: passing argument to parameter 'diff_length' here
void populate_tensor(int *df_iterators, const int ch_dim, diffcomparisonpath_flat_T *diffcomparisonpath_flat, int ***comparison_mem, const int *diff_length, const int nDiffs, const char **diff_block);
^
linematch.c:273:29: warning: incompatible pointer to integer conversion passing 'const mmfile_t **' (aka 'const struct s_mmfile **') to parameter of type 'int' [-Wint-conversion]
ndiffs, diff_blk, iwhite);
^~~~~~~~
proto/diff.pro:28:168: note: passing argument to parameter 'nDiffs' here
void populate_tensor(int *df_iterators, const int ch_dim, diffcomparisonpath_flat_T *diffcomparisonpath_flat, int ***comparison_mem, const int *diff_length, const int nDiffs, const char **diff_block);
^
linematch.c:273:39: warning: incompatible integer to pointer conversion passing 'bool' to parameter of type 'const char **' [-Wint-conversion]
ndiffs, diff_blk, iwhite);
^~~~~~
proto/diff.pro:28:189: note: passing argument to parameter 'diff_block' here
void populate_tensor(int *df_iterators, const int ch_dim, diffcomparisonpath_flat_T *diffcomparisonpath_flat, int ***comparison_mem, const int *diff_length, const int nDiffs, const char **diff_block);
^
linematch.c:358:32: warning: incompatible pointer types passing 'diffcmppath_T *' (aka 'struct diffcmppath_S *') to parameter of type 'diffcomparisonpath_flat_T *' (aka 'struct diffcomparisonpath_flat_S *') [-Wincompatible-pointer-types]
populate_tensor(df_iters, 0, diffcmppath, diff_len, ndiffs, diff_blk, iwhite);
^~~~~~~~~~~
proto/diff.pro:28:86: note: passing argument to parameter 'diffcomparisonpath_flat' here
void populate_tensor(int *df_iterators, const int ch_dim, diffcomparisonpath_flat_T *diffcomparisonpath_flat, int ***comparison_mem, const int *diff_length, const int nDiffs, const char **diff_block);
^
linematch.c:358:45: warning: incompatible pointer types passing 'const int *' to parameter of type 'int ***' [-Wincompatible-pointer-types]
populate_tensor(df_iters, 0, diffcmppath, diff_len, ndiffs, diff_blk, iwhite);
^~~~~~~~
proto/diff.pro:28:118: note: passing argument to parameter 'comparison_mem' here
void populate_tensor(int *df_iterators, const int ch_dim, diffcomparisonpath_flat_T *diffcomparisonpath_flat, int ***comparison_mem, const int *diff_length, const int nDiffs, const char **diff_block);
^
linematch.c:358:55: warning: incompatible integer to pointer conversion passing 'const size_t' (aka 'const unsigned long') to parameter of type 'const int *' [-Wint-conversion]
populate_tensor(df_iters, 0, diffcmppath, diff_len, ndiffs, diff_blk, iwhite);
^~~~~~
proto/diff.pro:28:145: note: passing argument to parameter 'diff_length' here
void populate_tensor(int *df_iterators, const int ch_dim, diffcomparisonpath_flat_T *diffcomparisonpath_flat, int ***comparison_mem, const int *diff_length, const int nDiffs, const char **diff_block);
^
linematch.c:358:63: warning: incompatible pointer to integer conversion passing 'const mmfile_t **' (aka 'const struct s_mmfile **') to parameter of type 'int' [-Wint-conversion]
populate_tensor(df_iters, 0, diffcmppath, diff_len, ndiffs, diff_blk, iwhite);
^~~~~~~~
proto/diff.pro:28:168: note: passing argument to parameter 'nDiffs' here
void populate_tensor(int *df_iterators, const int ch_dim, diffcomparisonpath_flat_T *diffcomparisonpath_flat, int ***comparison_mem, const int *diff_length, const int nDiffs, const char **diff_block);
^
linematch.c:358:73: warning: incompatible integer to pointer conversion passing 'bool' to parameter of type 'const char **' [-Wint-conversion]
populate_tensor(df_iters, 0, diffcmppath, diff_len, ndiffs, diff_blk, iwhite);
^~~~~~
proto/diff.pro:28:189: note: passing argument to parameter 'diff_block' here
void populate_tensor(int *df_iterators, const int ch_dim, diffcomparisonpath_flat_T *diffcomparisonpath_flat, int ***comparison_mem, const int *diff_length, const int nDiffs, const char **diff_block);
^
linematch.c:365:3: error: implicit declaration of function 'test_charmatch_paths' is invalid in C99 [-Werror,-Wimplicit-function-declaration]
test_charmatch_paths(startNode, 0);
^
linematch.c:384:15: error: static declaration of 'test_charmatch_paths' follows non-static declaration
static size_t test_charmatch_paths(diffcmppath_T *node, int lastdecision)
^
linematch.c:365:3: note: previous implicit declaration is here
test_charmatch_paths(startNode, 0);
^
30 warnings and 11 errors generated.
make[1]: *** [objects/linematch.o] Error 1
make: *** [first] Error 2
—
Reply to this email directly, view it on GitHub.
You are receiving this because you commented.
@jwhite510 pushed 2 commits.
You are receiving this because you are subscribed to this thread.
@benknoble
thank you for looking into that, I included the .pro file in proto.h, as it looks like most of the .pro files are included there and that fixed the error.
—
Reply to this email directly, view it on GitHub.
You are receiving this because you commented.
@yegappan commented on this pull request.
> @@ -17,6 +17,7 @@ int vim_stricmp(char *s1, char *s2); int vim_strnicmp(char *s1, char *s2, size_t len); int vim_strnicmp_asc(char *s1, char *s2, size_t len); char_u *vim_strchr(char_u *string, int c); +char_u *strnchr(const char_u *p, size_t *n, int c);
To avoid confusion with C stdlib functions, can you add the prefix "vim_" to strnchr?
—
Reply to this email directly, view it on GitHub.
You are receiving this because you commented.
@yegappan commented on this pull request.
In src/structs.h:
> @@ -3533,6 +3533,23 @@ struct file_buffer */ # define DB_COUNT 8 // up to eight buffers can be diff'ed +// struct for running the diff linematch algorithm +typedef struct diffcomparisonpath_flat_S diffcomparisonpath_flat_T; +struct diffcomparisonpath_flat_S { + int *df_decision; // to keep track of this path traveled + int df_lev_score; // to keep track of the total score of this path + int df_path_index; // current index of this path +}; + +// contains the information for how to construct diff views when linematch +// diffopt is enabled, it is populated after running linematch_nbuffers +typedef struct df_linecompare_S df_linecompare_T; +struct df_linecompare_S { + Bool df_newline; // is this line skipped in other buffers?
Can you change "Bool" to "int"?
—
Reply to this email directly, view it on GitHub.
You are receiving this because you commented.
@yegappan requested changes on this pull request.
In src/structs.h:
> @@ -3553,6 +3570,8 @@ struct diffblock_S diff_T *df_next; linenr_T df_lnum[DB_COUNT]; // line number in buffer linenr_T df_count[DB_COUNT]; // nr of inserted/changed lines + Bool is_linematched; // has the linematch algorithm ran on this diff hunk to divide it into
Can you change "Bool" to "int"?
In src/linematch.c:
> +struct diffcmppath_S { + int df_lev_score; // to keep track of the total score of this path + size_t df_path_n; // current index of this path + int df_choice_mem[LN_DECISION_MAX + 1]; + int df_choice[LN_DECISION_MAX]; + diffcmppath_T *df_decision[LN_DECISION_MAX]; // to keep track of this path traveled + size_t df_optimal_choice; +}; + +#ifdef INCLUDE_GENERATED_DECLARATIONS +# include "linematch.c.generated.h" +#endif + +static size_t line_len(const mmfile_t *m) +{ + char_u *s = (char_u *)m->ptr;
The Vim source code uses four spaces for indentation. This file uses 2 spaces for indentation. Can you add a Vim mode line "vi:set ts=8 sts=4 sw=4 noet:" at the beginning of this file?
In src/linematch.c:
> @@ -0,0 +1,406 @@ +#include <assert.h>
Can you add the following header here?
/* vi:set ts=8 sts=4 sw=4 noet:
*
In src/linematch.c:
> + char_u *s = (char_u *)m->ptr; + size_t n = (size_t)m->size; + char_u *end = strnchr(s, &n, '\n'); + if (end) { + return (size_t)(end - s); + } + return (size_t)m->size; +} + +#define MATCH_CHAR_MAX_LEN 800 + +/// Same as matching_chars but ignore whitespace +/// +/// @param s1 +/// @param s2 +static int matching_chars_iwhite(const mmfile_t *s1, const mmfile_t *s2)
Can you move the "static int" to one line above? This comment applies to the other functions also.
In src/linematch.c:
> + mmfile_t sp[2]; + char p[2][MATCH_CHAR_MAX_LEN]; + for (int k = 0; k < 2; k++) { + const mmfile_t *s = k == 0 ? s1 : s2; + size_t pi = 0; + size_t slen = MIN(MATCH_CHAR_MAX_LEN - 1, line_len(s)); + for (size_t i = 0; i <= slen; i++) { + char e = s->ptr[i]; + if (e != ' ' && e != '\t') { + p[k][pi] = e; + pi++; + } + } + + sp[k] = (mmfile_t){ + .ptr = p[k],
I don't think this type of initialization is supported by the older compilers.
—
Reply to this email directly, view it on GitHub.
You are receiving this because you commented.
@yegappan commented on this pull request.
In src/diff.c:
> @@ -1922,6 +1927,298 @@ diff_clear(tabpage_T *tp) tp->tp_first_diff = NULL; } +/* + * return true if the options are set to use diff linematch + */ + Bool +diff_linematch(diff_T *dp) +{ + if (!(diff_flags & DIFF_LINEMATCH)) { + return 0; + } + // are there more than three diff buffers? + int tsize = 0; + for (int i = 0; i < DB_COUNT; i++) {
Can you move the opening curly brace for the "for", "if", "while", etc., statements to a separate line?
—
Reply to this email directly, view it on GitHub.
You are receiving this because you commented.
@jwhite510 pushed 1 commit.
You are receiving this because you are subscribed to this thread.
@jwhite510 commented on this pull request.
In src/structs.h:
> @@ -3533,6 +3533,23 @@ struct file_buffer */ # define DB_COUNT 8 // up to eight buffers can be diff'ed +// struct for running the diff linematch algorithm +typedef struct diffcomparisonpath_flat_S diffcomparisonpath_flat_T; +struct diffcomparisonpath_flat_S { + int *df_decision; // to keep track of this path traveled + int df_lev_score; // to keep track of the total score of this path + int df_path_index; // current index of this path +}; + +// contains the information for how to construct diff views when linematch +// diffopt is enabled, it is populated after running linematch_nbuffers +typedef struct df_linecompare_S df_linecompare_T; +struct df_linecompare_S { + Bool df_newline; // is this line skipped in other buffers?
actually these structs are no longer used, so I should delete them. The way the result of the alignment gets stored was changed, and this is no longer relevant.
—
Reply to this email directly, view it on GitHub.
You are receiving this because you commented.
At this point it compiles and it seems to work when I tested it and diffed some files. Thank you for reviewing @yegappan I will look over those changes soon
—
Reply to this email directly, view it on GitHub.
You are receiving this because you commented.
I am having a look. Please squash in this change:
diff --git a/Filelist b/Filelist index caac66cdb..2fe19fec1 100644 --- a/Filelist +++ b/Filelist @@ -286,6 +286,7 @@ SRC_ALL = \ src/proto/insexpand.pro \ src/proto/job.pro \ src/proto/json.pro \ + src/proto/linematch.pro \ src/proto/list.pro \ src/proto/locale.pro \ src/proto/logfile.pro \
—
Reply to this email directly, view it on GitHub.
You are receiving this because you commented.
@chrisbra commented on this pull request.
In src/Makefile:
> @@ -359,7 +359,7 @@ CClink = $(CC) #CONF_OPT_GUI = --enable-gui=motif --with-motif-lib="-static -lXm -shared" # Uncomment this line to run an individual test with gvim. -#GUI_TESTARG = GUI_FLAG=-g +#GUI_TESTARG = GUI_FLAG=-g
undo this change please
—
Reply to this email directly, view it on GitHub.
You are receiving this because you commented.
@chrisbra commented on this pull request.
In src/globals.h:
> @@ -869,6 +869,7 @@ EXTERN int drag_sep_line INIT(= FALSE); // dragging vert separator #ifdef FEAT_DIFF // Value set from 'diffopt'. EXTERN int diff_context INIT(= 6); // context for folds +EXTERN int linematch_lines INIT(= 0); // number of lines for diff line match
can you please align?
In src/diff.c:
> @@ -753,22 +755,26 @@ clear_diffout(diffout_T *dout) * Return FAIL for failure. */ static int -diff_write_buffer(buf_T *buf, diffin_T *din) +diff_write_buffer(buf_T *buf, mmfile_t *m, linenr_T start, linenr_T end)
is there a reason, we cannot keep the diffin_T struct here?
In src/diff.c:
> + // amount of space and crash + if (dp->df_count[i] < 0) { + return FALSE; + } + tsize += dp->df_count[i]; + } + } + // avoid allocating a huge array because it will lag + return tsize <= linematch_lines; +} + + int +get_max_diff_length(const diff_T *dp) +{ + int maxlength = 0; + for (int k = 0; k < DB_COUNT; k++) {
curly braces style
In src/linematch.c:
> @@ -0,0 +1,402 @@ +#include <assert.h>
this is part of vim.h
In src/linematch.c:
> @@ -0,0 +1,402 @@ +#include <assert.h> +#include <math.h> +#include <stdbool.h> +#include <stddef.h>
that is part of vim.h
In src/linematch.c:
> @@ -0,0 +1,402 @@ +#include <assert.h> +#include <math.h> +#include <stdbool.h>
can we get rid of that and use ints instead?
In src/linematch.c:
> @@ -0,0 +1,402 @@ +#include <assert.h> +#include <math.h> +#include <stdbool.h> +#include <stddef.h> +#include <stdint.h> +#include <string.h>
same here, should be part of vim.h
In src/linematch.c:
> +/// +/// @param s1 +/// @param s2 +int matching_chars_iwhite(const mmfile_t *s1, const mmfile_t *s2) +{ + // the newly processed strings that will be compared + // delete the white space characters + mmfile_t sp[2]; + char p[2][MATCH_CHAR_MAX_LEN]; + for (int k = 0; k < 2; k++) { + const mmfile_t *s = k == 0 ? s1 : s2; + size_t pi = 0; + size_t slen = MIN(MATCH_CHAR_MAX_LEN - 1, line_len(s)); + for (size_t i = 0; i <= slen; i++) { + char e = s->ptr[i]; + if (e != ' ' && e != '\t') {⬇️ Suggested change
- if (e != ' ' && e != '\t') { + if (!VIM_ISWHITE(e)) {
> @@ -13,7 +13,21 @@ void ex_diffthis(exarg_T *eap); void diff_win_options(win_T *wp, int addbuf); void ex_diffoff(exarg_T *eap); void diff_clear(tabpage_T *tp); -int diff_check(win_T *wp, linenr_T lnum); +Bool diff_linematch(diff_T *dp);
this comment is still valid
—
Reply to this email directly, view it on GitHub, or unsubscribe.
You are receiving this because you commented.
unfortunately, there are a bit of style issues (braces, bool, etc). Can you please adjust those to Vims style?
Then can I ask you for a few test cases? Currently the whole linematch.c file is not tested at all and we are adding a bit of changes to diff.c. Would like to make sure this doesn't easily regress.
Check the Test_diff_screen()
function in src/testdir/test_diffmode.vim
how to setup some example test cases.
—
Reply to this email directly, view it on GitHub.
You are receiving this because you commented.
@jwhite510 commented on this pull request.
In src/linematch.c:
> @@ -0,0 +1,406 @@ +#include <assert.h>
added
—
Reply to this email directly, view it on GitHub.
You are receiving this because you commented.
> + char_u *s = (char_u *)m->ptr; + size_t n = (size_t)m->size; + char_u *end = strnchr(s, &n, '\n'); + if (end) { + return (size_t)(end - s); + } + return (size_t)m->size; +} + +#define MATCH_CHAR_MAX_LEN 800 + +/// Same as matching_chars but ignore whitespace +/// +/// @param s1 +/// @param s2 +static int matching_chars_iwhite(const mmfile_t *s1, const mmfile_t *s2)
moved above
—
Reply to this email directly, view it on GitHub.
You are receiving this because you commented.
> + mmfile_t sp[2]; + char p[2][MATCH_CHAR_MAX_LEN]; + for (int k = 0; k < 2; k++) { + const mmfile_t *s = k == 0 ? s1 : s2; + size_t pi = 0; + size_t slen = MIN(MATCH_CHAR_MAX_LEN - 1, line_len(s)); + for (size_t i = 0; i <= slen; i++) { + char e = s->ptr[i]; + if (e != ' ' && e != '\t') { + p[k][pi] = e; + pi++; + } + } + + sp[k] = (mmfile_t){ + .ptr = p[k],
changed
—
Reply to this email directly, view it on GitHub.
You are receiving this because you commented.
@jwhite510 pushed 2 commits.
You are receiving this because you are subscribed to this thread.
@jwhite510 commented on this pull request.
In src/diff.c:
> @@ -1922,6 +1927,298 @@ diff_clear(tabpage_T *tp) tp->tp_first_diff = NULL; } +/* + * return true if the options are set to use diff linematch + */ + Bool +diff_linematch(diff_T *dp) +{ + if (!(diff_flags & DIFF_LINEMATCH)) { + return 0; + } + // are there more than three diff buffers? + int tsize = 0; + for (int i = 0; i < DB_COUNT; i++) {
moved to seperate lines
—
Reply to this email directly, view it on GitHub.
You are receiving this because you commented.
@jwhite510 pushed 1 commit.
You are receiving this because you are subscribed to this thread.
@jwhite510 commented on this pull request.
In src/Makefile:
> @@ -359,7 +359,7 @@ CClink = $(CC) #CONF_OPT_GUI = --enable-gui=motif --with-motif-lib="-static -lXm -shared" # Uncomment this line to run an individual test with gvim. -#GUI_TESTARG = GUI_FLAG=-g +#GUI_TESTARG = GUI_FLAG=-g
fixed
—
Reply to this email directly, view it on GitHub.
You are receiving this because you commented.
@jwhite510 pushed 2 commits.
You are receiving this because you are subscribed to this thread.
@jwhite510 pushed 1 commit.
You are receiving this because you are subscribed to this thread.
@jwhite510 commented on this pull request.
In src/globals.h:
> @@ -869,6 +869,7 @@ EXTERN int drag_sep_line INIT(= FALSE); // dragging vert separator #ifdef FEAT_DIFF // Value set from 'diffopt'. EXTERN int diff_context INIT(= 6); // context for folds +EXTERN int linematch_lines INIT(= 0); // number of lines for diff line match
fixed
—
Reply to this email directly, view it on GitHub.
You are receiving this because you commented.
@jwhite510 pushed 1 commit.
You are receiving this because you are subscribed to this thread.
@jwhite510 pushed 1 commit.
You are receiving this because you are subscribed to this thread.
@jwhite510 commented on this pull request.
In src/diff.c:
> @@ -753,22 +755,26 @@ clear_diffout(diffout_T *dout) * Return FAIL for failure. */ static int -diff_write_buffer(buf_T *buf, diffin_T *din) +diff_write_buffer(buf_T *buf, mmfile_t *m, linenr_T start, linenr_T end)
i put it back to diffin_T
—
Reply to this email directly, view it on GitHub.
You are receiving this because you commented.
@jwhite510 pushed 1 commit.
You are receiving this because you are subscribed to this thread.
> + // amount of space and crash + if (dp->df_count[i] < 0) { + return FALSE; + } + tsize += dp->df_count[i]; + } + } + // avoid allocating a huge array because it will lag + return tsize <= linematch_lines; +} + + int +get_max_diff_length(const diff_T *dp) +{ + int maxlength = 0; + for (int k = 0; k < DB_COUNT; k++) {
fixed
—
Reply to this email directly, view it on GitHub.
You are receiving this because you commented.
@yegappan requested changes on this pull request.
In src/diff.c:
> @@ -501,8 +502,8 @@ diff_mark_adjust_tp( } // check if this block touches the previous one, may merge them. - if (dprev != NULL && dprev->df_lnum[idx] + dprev->df_count[idx] - == dp->df_lnum[idx]) + if ((dprev != NULL) && !dp->is_linematched
Can you remove the parenthesis around "dprev != NULL"?
In src/diff.c:
> @@ -1922,6 +1929,344 @@ diff_clear(tabpage_T *tp) tp->tp_first_diff = NULL; } +/* + * return true if the options are set to use diff linematch + */ + int +diff_linematch(diff_T *dp) +{ + if (!(diff_flags & DIFF_LINEMATCH)) + { + return 0; + } + // are there more than three diff buffers? + int tsize = 0; + for (int i = 0; i < DB_COUNT; i++) + { + if ( curtab->tp_diffbuf[i] != NULL )
Can you remove the extra space after "(" and before ")"?
In src/diff.c:
> + // amount of space and crash + if (dp->df_count[i] < 0) + { + return FALSE; + } + tsize += dp->df_count[i]; + } + } + // avoid allocating a huge array because it will lag + return tsize <= linematch_lines; +} + + int +get_max_diff_length(const diff_T *dp) +{ + int maxlength = 0;
This function uses two spaces for indentation. As the modelines are now added to these files, you can reformat all the new code using "=".
—
Reply to this email directly, view it on GitHub.
You are receiving this because you commented.
I didn't realize that my indentation fixes for diff.c were directly pushed to the PR branch. Sorry about that.
—
Reply to this email directly, view it on GitHub.
You are receiving this because you commented.
@jwhite510 pushed 1 commit.
You are receiving this because you are subscribed to this thread.
@jwhite510 commented on this pull request.
In src/linematch.c:
> @@ -0,0 +1,402 @@ +#include <assert.h>
removed
—
Reply to this email directly, view it on GitHub.
You are receiving this because you commented.
> @@ -0,0 +1,402 @@ +#include <assert.h> +#include <math.h> +#include <stdbool.h> +#include <stddef.h>
removed
—
Reply to this email directly, view it on GitHub.
You are receiving this because you commented.
@jwhite510 commented on this pull request.
In src/linematch.c:
> @@ -0,0 +1,402 @@ +#include <assert.h> +#include <math.h> +#include <stdbool.h>
converted from bool to int
—
Reply to this email directly, view it on GitHub.
You are receiving this because you commented.
@jwhite510 pushed 1 commit.
You are receiving this because you are subscribed to this thread.
> @@ -0,0 +1,402 @@ +#include <assert.h> +#include <math.h> +#include <stdbool.h> +#include <stddef.h> +#include <stdint.h> +#include <string.h>
removed
—
Reply to this email directly, view it on GitHub.
You are receiving this because you commented.
@zeertzjq commented on this pull request.
> @@ -2959,6 +2959,19 @@ A jump table for the options with a short description can be found at |Q_op|. diff library. algorithm:{text} Use the specified diff algorithm with the + + linematch:{n} Align and mark changes between the most + similar lines between the buffers. When the + total number of lines in the diff hunk exceeds + {n}, the lines will not be aligned because for + very large diff hunks there will be a + noticeable lag. A reasonable setting is + "linematch:60", as this will enable alignment + for a 2 buffer diff hunk of 30 lines each, + or a 3 buffer diff hunk of 20 lines each. + + algorithm:{text} Use the specified diff algorithm with the
Also the indent is 16 spaces here, but it should be 2 Tabs.
—
Reply to this email directly, view it on GitHub.
You are receiving this because you commented.
I have fixed all the indentation and coding style issues and the test failures. Also updated the Windows and other platform
Makefiles to include the new linematch.c file. But new tests need to be added for the new code in diff.c and linematch.c
—
Reply to this email directly, view it on GitHub.
You are receiving this because you commented.
@jwhite510 pushed 1 commit.
You are receiving this because you are subscribed to this thread.
@chrisbra
I am having trouble getting these tests to work.
when I run ../vim -u NONE -S runtest.vim test_diffmode.vim Test_diff_screen
I get a running vim instance and seems like it is doing something,
Test_diff_01.dump
Test_diff_02.dump
Test_diff_03.dump
Test_diff_04.dump
Test_diff_05.dump
are all created in src/testdir/failed
So I think that mean the tests are failing?
I added this to testdir/test_diffmode.vim
call term_sendkeys(buf, ":set diffopt+=linematch:30\<cr>")
" write the contents to a screen dump?
call term_dumpwrite(buf, "Test_diff_23")
but seems like it is not reaching that point.
I'm hoping I can then add
call VerifyInternal(buf, 'Test_diff_23', " diffopt+=linematch:30")
—
Reply to this email directly, view it on GitHub.
You are receiving this because you commented.
@yegappan commented on this pull request.
In src/testdir/test_diffmode.vim:
> @@ -1035,6 +1035,13 @@ func Test_diff_screen() call WriteDiffFiles(buf, [], [0]) call VerifyBoth(buf, "Test_diff_22", "") + call WriteDiffFiles(buf, ['?a', '?b', '?c'], ['!b']) + call term_sendkeys(buf, ":set diffopt+=linematch:30\<cr>") + " write the contents to a screen dump? + call term_dumpwrite(buf, "Test_diff_23")
You should remove the calls to the term_sendkeys() and term_dumpwrite() functions above. Uncomment the below call to VerifyInternal() and run the test. The test will fail and the screen dump will be in the testdir/failed directory. You can verify the screen dump by loading it using the term_dumpload() function. Once you have manually verified the screen dump, you can copy that file to the testdir/dumps directory. Now the test should pass.
—
Reply to this email directly, view it on GitHub.
You are receiving this because you commented.
even if I checkout the master branch I am getting all the tests failing
src/testdir/screendump.vim
----------------------
let testdump = ReadAndFilter(testfile, filter)
if refdump == testdump
call delete(testfile)
if did_mkdir
call delete('failed', 'd')
endif
if i > 0
call remove(v:errors, -1)
endif
break
endif
the refdump == testdump check is failing. I compared the contents of
src/testdir/failed/Test_diff_05.dump
| +0#0000e05#a8a8a8255@1|1+0#0000000#ffffff0| @33||+1&&| +0#0000e05#a8a8a8255@1|1+0#0000000#ffffff0| @33
| +0#0000e05#a8a8a8255@1|2+0#0000000#ffffff0| @33||+1&&| +0#0000e05#a8a8a8255@1|2+0#0000000#ffffff0| @33
| +0#0000e05#a8a8a8255@1|3+0#0000000#ffffff0| @33||+1&&| +0#0000e05#a8a8a8255@1|3+0#0000000#ffffff0| @33
| +0#0000e05#a8a8a8255@1|4+0#0000000#ffffff0| @33||+1&&| +0#0000e05#a8a8a8255@1|4+0#0000000#ffffff0| @33
| +0#0000e05#a8a8a8255@1|-+0#4040ff13#afffff255@34||+1#0000000#ffffff0| +0#0000e05#a8a8a8255@1|4+0#0000000#5fd7ff255| @33
| +0#0000e05#a8a8a8255@1|5+0#0000000#ffffff0| @33||+1&&| +0#0000e05#a8a8a8255@1|5+0#0000000#ffffff0| @33
| +0#0000e05#a8a8a8255@1|6+0#0000000#ffffff0| @33||+1&&| +0#0000e05#a8a8a8255@1|6+0#0000000#ffffff0| @33
| +0#0000e05#a8a8a8255@1|7+0#0000000#ffffff0| @33||+1&&| +0#0000e05#a8a8a8255@1|7+0#0000000#ffffff0| @33
| +0#0000e05#a8a8a8255@1|8+0#0000000#ffffff0| @33||+1&&| +0#0000e05#a8a8a8255@1|8+0#0000000#ffffff0| @33
| +0#0000e05#a8a8a8255@1|9+0#0000000#ffffff0| @33||+1&&| +0#0000e05#a8a8a8255@1|9+0#0000000#ffffff0| @33
| +0#0000e05#a8a8a8255@1|1+0#0000000#ffffff0|0| @32||+1&&| +0#0000e05#a8a8a8255@1|1+0#0000000#ffffff0|0| @32
| +0#0000e05#a8a8a8255@1|1+0#0000000#5fd7ff255@1| @32||+1&#ffffff0| +0#0000e05#a8a8a8255@1|-+0#4040ff13#afffff255@34
|~+0&#ffffff0| @35||+1#0000000&|~+0#4040ff13&| @35
|~| @35||+1#0000000&|~+0#4040ff13&| @35
|~| @35||+1#0000000&|~+0#4040ff13&| @35
|~| @35||+1#0000000&|~+0#4040ff13&| @35
|~| @35||+1#0000000&|~+0#4040ff13&| @35
|~| @35||+1#0000000&|~+0#4040ff13&| @35
|X+3#0000000&|d|i|f|i|l|e|1| @29|X+1&&|d|i|f|i|l|e|2| @28
|:+0&&> @73
to
src/testdir/dumps/Test_diff_05.dump
| +0#0000e05#a8a8a8255@1|2+0#0000000#ffffff0| @33||+1&&| +0#0000e05#a8a8a8255@1|2+0#0000000#ffffff0| @33
| +0#0000e05#a8a8a8255@1|3+0#0000000#ffffff0| @33||+1&&| +0#0000e05#a8a8a8255@1|3+0#0000000#ffffff0| @33
| +0#0000e05#a8a8a8255@1|4+0#0000000#ffffff0| @33||+1&&| +0#0000e05#a8a8a8255@1|4+0#0000000#ffffff0| @33
| +0#0000e05#a8a8a8255@1|-+0#4040ff13#afffff255@34||+1#0000000#ffffff0| +0#0000e05#a8a8a8255@1|4+0#0000000#5fd7ff255| @33
| +0#0000e05#a8a8a8255@1|5+0#0000000#ffffff0| @33||+1&&| +0#0000e05#a8a8a8255@1|5+0#0000000#ffffff0| @33
| +0#0000e05#a8a8a8255@1|6+0#0000000#ffffff0| @33||+1&&| +0#0000e05#a8a8a8255@1|6+0#0000000#ffffff0| @33
| +0#0000e05#a8a8a8255@1|7+0#0000000#ffffff0| @33||+1&&| +0#0000e05#a8a8a8255@1|7+0#0000000#ffffff0| @33
| +0#0000e05#a8a8a8255@1|8+0#0000000#ffffff0| @33||+1&&| +0#0000e05#a8a8a8255@1|8+0#0000000#ffffff0| @33
| +0#0000e05#a8a8a8255@1|9+0#0000000#ffffff0| @33||+1&&| +0#0000e05#a8a8a8255@1|9+0#0000000#ffffff0| @33
| +0#0000e05#a8a8a8255@1|1+0#0000000#ffffff0|0| @32||+1&&| +0#0000e05#a8a8a8255@1|1+0#0000000#ffffff0|0| @32
| +0#0000e05#a8a8a8255@1|1+0#0000000#5fd7ff255@1| @32||+1&#ffffff0| +0#0000e05#a8a8a8255@1|-+0#4040ff13#afffff255@34
|~+0&#ffffff0| @35||+1#0000000&|~+0#4040ff13&| @35
|~| @35||+1#0000000&|~+0#4040ff13&| @35
|~| @35||+1#0000000&|~+0#4040ff13&| @35
|~| @35||+1#0000000&|~+0#4040ff13&| @35
|~| @35||+1#0000000&|~+0#4040ff13&| @35
|~| @35||+1#0000000&|~+0#4040ff13&| @35
|X+3#0000000&|d|i|f|i|l|e|1| @10|1|,|1| @11|A|l@1| |X+1&&|d|i|f|i|l|e|2| @10|1|,|1| @11|A|l@1
|:+0&&> @73
that second line to the bottom is different. But when I view the dumps with
./src/vim -u NONE -S src/testdir/viewdumps.vim ./src/testdir/dumps/Test_diff_05.dump
they look identical on the screen. Any idea why that second to last line is different in the dumps?
—
Reply to this email directly, view it on GitHub.
You are receiving this because you commented.
It looks like you have ruler
set? Did this happen when running the test-suite? Or did you manually create those screen-dump files?
—
Reply to this email directly, view it on GitHub.
You are receiving this because you commented.
It looks like you have
ruler
set? Did this happen when running the test-suite? Or did you manually create those screen-dump files?
@chrisbra
this shell script re creates exactly what I am doing. I run this shell script in an empty directory, and I see the failed test
#!/bin/bash
git clone -b master https://github.com/vim/vim.git
cd vim/src
make
cd ./testdir
../vim -u NONE -S runtest.vim test_diffmode.vim Test_diff_screen
diff ./failed/Test_diff_01.dump ./dumps/Test_diff_01.dump
# 19c19
# < |X+3#0000000&|d|i|f|i|l|e|1| @29|X+1&&|d|i|f|i|l|e|2| @28
# ---
# > |X+3#0000000&|d|i|f|i|l|e|1| @10|1|,|1| @11|A|l@1| |X+1&&|d|i|f|i|l|e|2| @10|1|,|1| @11|A|l@1
—
Reply to this email directly, view it on GitHub.
You are receiving this because you commented.
../vim -u NONE -S runtest.vim test_diffmode.vim Test_diff_screen
I never run a test like this. Can you please try: rm -f test_diffmode.res; make test_diffmode.res; cat messages
?
—
Reply to this email directly, view it on GitHub.
You are receiving this because you commented.
../vim -u NONE -S runtest.vim test_diffmode.vim Test_diff_screen
I never run a test like this. Can you please try:
rm -f test_diffmode.res; make test_diffmode.res; cat messages
?
@chrisbra
thank you, that seems to work.
—
Reply to this email directly, view it on GitHub.
You are receiving this because you commented.
@jwhite510 pushed 2 commits.
You are receiving this because you are subscribed to this thread.
@jwhite510 pushed 1 commit.
You are receiving this because you are subscribed to this thread.
@jwhite510 pushed 1 commit.
You are receiving this because you are subscribed to this thread.
@jwhite510 pushed 2 commits.
You are receiving this because you are subscribed to this thread.
@jwhite510 pushed 1 commit.
You are receiving this because you are subscribed to this thread.
Thanks, I checked the coverage heree: https://app.codecov.io/gh/vim/vim/pull/9661
which looks quiet nice already.
diff.c could need some tests for this here: https://app.codecov.io/gh/vim/vim/pull/9661#c00ba4f2032bd4f475214b88ebfa64f3-R2041
linematch.c seems also quiet good already, perhaps if you could try to add some tests for those lines here: https://app.codecov.io/gh/vim/vim/pull/9661#b9b8227973d7830e5b26fb5f1f588442-R61
This PR has gotten quiet lengthy already, so I don't always check the updates here. Once you are satisfied, please squash it into a single commit and rebase (so we can see fresh CI results) and ping me and I'll have another look.
—
Reply to this email directly, view it on GitHub.
You are receiving this because you commented.
@jwhite510 pushed 3 commits.
You are receiving this because you are subscribed to this thread.
@jwhite510 pushed 2 commits.
You are receiving this because you are subscribed to this thread.
@jwhite510 pushed 1 commit.
You are receiving this because you are subscribed to this thread.
@chrisbra it's squashed and rebased, I believe there are now tests for all the features. how does it look?
—
Reply to this email directly, view it on GitHub.
You are receiving this because you commented.
Well, CI is failing on some files not being included in a packaging list ;)
—
Reply to this email directly, view it on GitHub.
You are receiving this because you commented.
I guess the swap files .lmtest.diff1.swl
and .lmtest.diff1.swm
have been erroneously been added? Can you create a test where virtual_lines_passed
is greater than 0?
—
Reply to this email directly, view it on GitHub.
You are receiving this because you commented.
@jwhite510 pushed 1 commit.
You are receiving this because you are subscribed to this thread.
@jwhite510 pushed 1 commit.
You are receiving this because you are subscribed to this thread.
@chrisbra
test is added which scrolls the view, making virtual_lines_passed greater than 0
—
Reply to this email directly, view it on GitHub.
You are receiving this because you commented.