Skip to content

Commit f0b8fb6

Browse files
jonathantanmygitster
authored andcommitted
diff: define block by number of alphanumeric chars
The existing behavior of diff --color-moved=zebra does not define the minimum size of a block at all, instead relying on a heuristic applied later to filter out sets of adjacent moved lines that are shorter than 3 lines long. This can be confusing, because a block could thus be colored as moved at the source but not at the destination (or vice versa), depending on its neighbors. Instead, teach diff that the minimum size of a block is 20 alphanumeric characters, the same heuristic used by "git blame". This allows diff to still exclude uninteresting lines appearing on their own (such as those solely consisting of one or a few closing braces), as was the intention of the adjacent-moved-line heuristic. This requires a change in some tests in that some of their lines are no longer considered to be part of a block, because they are too short. Signed-off-by: Jonathan Tan <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent 0915327 commit f0b8fb6

File tree

4 files changed

+183
-81
lines changed

4 files changed

+183
-81
lines changed

Documentation/diff-options.txt

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -254,13 +254,11 @@ plain::
254254
moved line, but it is not very useful in a review to determine
255255
if a block of code was moved without permutation.
256256
zebra::
257-
Blocks of moved code are detected greedily. The detected blocks are
257+
Blocks of moved text of at least 20 alphanumeric characters
258+
are detected greedily. The detected blocks are
258259
painted using either the 'color.diff.{old,new}Moved' color or
259260
'color.diff.{old,new}MovedAlternative'. The change between
260-
the two colors indicates that a new block was detected. If there
261-
are fewer than 3 adjacent moved lines, they are not marked up
262-
as moved, but the regular colors 'color.diff.{old,new}' will be
263-
used.
261+
the two colors indicates that a new block was detected.
264262
dimmed_zebra::
265263
Similar to 'zebra', but additional dimming of uninteresting parts
266264
of moved code is performed. The bordering lines of two adjacent

diff.c

Lines changed: 22 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -864,19 +864,31 @@ static int shrink_potential_moved_blocks(struct moved_entry **pmb,
864864
/*
865865
* If o->color_moved is COLOR_MOVED_PLAIN, this function does nothing.
866866
*
867-
* Otherwise, if the last block has fewer lines than
868-
* COLOR_MOVED_MIN_BLOCK_LENGTH, unset DIFF_SYMBOL_MOVED_LINE on all lines in
867+
* Otherwise, if the last block has fewer alphanumeric characters than
868+
* COLOR_MOVED_MIN_ALNUM_COUNT, unset DIFF_SYMBOL_MOVED_LINE on all lines in
869869
* that block.
870870
*
871871
* The last block consists of the (n - block_length)'th line up to but not
872872
* including the nth line.
873+
*
874+
* NEEDSWORK: This uses the same heuristic as blame_entry_score() in blame.c.
875+
* Think of a way to unify them.
873876
*/
874877
static void adjust_last_block(struct diff_options *o, int n, int block_length)
875878
{
876-
int i;
877-
if (block_length >= COLOR_MOVED_MIN_BLOCK_LENGTH ||
878-
o->color_moved == COLOR_MOVED_PLAIN)
879+
int i, alnum_count = 0;
880+
if (o->color_moved == COLOR_MOVED_PLAIN)
879881
return;
882+
for (i = 1; i < block_length + 1; i++) {
883+
const char *c = o->emitted_symbols->buf[n - i].line;
884+
for (; *c; c++) {
885+
if (!isalnum(*c))
886+
continue;
887+
alnum_count++;
888+
if (alnum_count >= COLOR_MOVED_MIN_ALNUM_COUNT)
889+
return;
890+
}
891+
}
880892
for (i = 1; i < block_length + 1; i++)
881893
o->emitted_symbols->buf[n - i].flags &= ~DIFF_SYMBOL_MOVED_LINE;
882894
}
@@ -923,7 +935,6 @@ static void mark_color_as_moved(struct diff_options *o,
923935
}
924936

925937
l->flags |= DIFF_SYMBOL_MOVED_LINE;
926-
block_length++;
927938

928939
if (o->color_moved == COLOR_MOVED_PLAIN)
929940
continue;
@@ -953,8 +964,13 @@ static void mark_color_as_moved(struct diff_options *o,
953964
}
954965

955966
flipped_block = (flipped_block + 1) % 2;
967+
968+
adjust_last_block(o, n, block_length);
969+
block_length = 0;
956970
}
957971

972+
block_length++;
973+
958974
if (flipped_block)
959975
l->flags |= DIFF_SYMBOL_MOVED_LINE_ALT;
960976
}

diff.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -195,7 +195,7 @@ struct diff_options {
195195
COLOR_MOVED_ZEBRA_DIM = 3,
196196
} color_moved;
197197
#define COLOR_MOVED_DEFAULT COLOR_MOVED_ZEBRA
198-
#define COLOR_MOVED_MIN_BLOCK_LENGTH 3
198+
#define COLOR_MOVED_MIN_ALNUM_COUNT 20
199199
};
200200

201201
void diff_emit_submodule_del(struct diff_options *o, const char *line);

0 commit comments

Comments
 (0)