summaryrefslogtreecommitdiff
path: root/diff.c
diff options
context:
space:
mode:
Diffstat (limited to 'diff.c')
-rw-r--r--diff.c28
1 files changed, 22 insertions, 6 deletions
diff --git a/diff.c b/diff.c
index f598d8a3a0..c50fcc7ea5 100644
--- a/diff.c
+++ b/diff.c
@@ -864,19 +864,31 @@ static int shrink_potential_moved_blocks(struct moved_entry **pmb,
/*
* If o->color_moved is COLOR_MOVED_PLAIN, this function does nothing.
*
- * Otherwise, if the last block has fewer lines than
- * COLOR_MOVED_MIN_BLOCK_LENGTH, unset DIFF_SYMBOL_MOVED_LINE on all lines in
+ * Otherwise, if the last block has fewer alphanumeric characters than
+ * COLOR_MOVED_MIN_ALNUM_COUNT, unset DIFF_SYMBOL_MOVED_LINE on all lines in
* that block.
*
* The last block consists of the (n - block_length)'th line up to but not
* including the nth line.
+ *
+ * NEEDSWORK: This uses the same heuristic as blame_entry_score() in blame.c.
+ * Think of a way to unify them.
*/
static void adjust_last_block(struct diff_options *o, int n, int block_length)
{
- int i;
- if (block_length >= COLOR_MOVED_MIN_BLOCK_LENGTH ||
- o->color_moved == COLOR_MOVED_PLAIN)
+ int i, alnum_count = 0;
+ if (o->color_moved == COLOR_MOVED_PLAIN)
return;
+ for (i = 1; i < block_length + 1; i++) {
+ const char *c = o->emitted_symbols->buf[n - i].line;
+ for (; *c; c++) {
+ if (!isalnum(*c))
+ continue;
+ alnum_count++;
+ if (alnum_count >= COLOR_MOVED_MIN_ALNUM_COUNT)
+ return;
+ }
+ }
for (i = 1; i < block_length + 1; i++)
o->emitted_symbols->buf[n - i].flags &= ~DIFF_SYMBOL_MOVED_LINE;
}
@@ -923,7 +935,6 @@ static void mark_color_as_moved(struct diff_options *o,
}
l->flags |= DIFF_SYMBOL_MOVED_LINE;
- block_length++;
if (o->color_moved == COLOR_MOVED_PLAIN)
continue;
@@ -953,8 +964,13 @@ static void mark_color_as_moved(struct diff_options *o,
}
flipped_block = (flipped_block + 1) % 2;
+
+ adjust_last_block(o, n, block_length);
+ block_length = 0;
}
+ block_length++;
+
if (flipped_block)
l->flags |= DIFF_SYMBOL_MOVED_LINE_ALT;
}