git/list[1] front-page[2] threads[3] people[4] search[5] about
 

[PATCH] diff-highlight: Fix broken multibyte string

From
Yi EungJun <semtlenori@gmail.com>
Date
Mar 30, 2015, 15:55 UTC
Message-ID
<1427730933-26189-1-git-send-email-eungjun.yi@navercorp.com>
From: Yi EungJun <eungjun.yi@navercorp.com>

Highlighted string might be broken if the common subsequence is a proper subset of a multibyte character. For example, if the old string is "진" and the new string is "지", then we expect the diff is rendered as follows:

	-진
	+지
but actually it was rendered as follows:
    -<EC><A7><84>
    +<EC><A7><80>
This fixes the bug by splitting the string by multibyte characters.
---
 contrib/diff-highlight/diff-highlight | 25 +++++++++++++++++++++++--
 1 file changed, 23 insertions(+), 2 deletions(-)
diff --git a/contrib/diff-highlight/diff-highlight b/contrib/diff-highlight/diff-highlight
index 08c88bb..2662c1a 100755
--- a/contrib/diff-highlight/diff-highlight
+++ b/contrib/diff-highlight/diff-highlight
@@ -2,6 +2,9 @@
 
 use warnings FATAL => 'all';
 use strict;
+use File::Basename;
+use File::Spec::Functions qw( catdir );
+use String::Multibyte;
 
 # Highlight by reversing foreground and background. You could do
 # other things like bold or underline if you prefer.
@@ -24,6 +27,8 @@ my @removed;
 my @added;
 my $in_hunk;
 
+my $mbcs = get_mbcs();
+
 # Some scripts may not realize that SIGPIPE is being ignored when launching the
 # pager--for instance scripts written in Python.
 $SIG{PIPE} = 'DEFAULT';
@@ -164,8 +169,8 @@ sub highlight_pair {
 
 sub split_line {
 	local $_ = shift;
-	return map { /$COLOR/ ? $_ : (split //) }
-	       split /($COLOR*)/;
+	return map { /$COLOR/ ? $_ : ($mbcs ? $mbcs->strsplit('', $_) : split //) }
+	       split /($COLOR)/;
 }
 
 sub highlight_line {
@@ -211,3 +216,19 @@ sub is_pair_interesting {
 	       $suffix_a !~ /^$BORING*$/ ||
 	       $suffix_b !~ /^$BORING*$/;
 }
+
+# Returns an instance of String::Multibyte based on the charset defined by
+# i18n.commitencoding or UTF-8, or undef if String::Multibyte doesn't support
+# the charset.
+sub get_mbcs {
+	my $dir = catdir(dirname($INC{'String/Multibyte.pm'}), 'Multibyte');
+	opendir my $dh, $dir or return;
+	my @mbcs_charsets = grep s/[.]pm\z//, readdir $dh;
+	close $dh;
+	my $expected_charset = `git config i18n.commitencoding` || "UTF-8";
+	$expected_charset =~ s/-//g;
+	my @matches = grep {/^$expected_charset$/i} @mbcs_charsets;
+	my $charset = shift @matches;
+
+	return eval 'String::Multibyte->new($charset)';
+}
-- 
2.3.2.209.gd67f9d5.dirty
Next: Jeff King
Message 1 of 13 in “diff-highlight: Fix broken multibyte string”
  1. diff-highlight: Fix broken multibyte stringYi EungJun, Mar 30, 2015
  2. Jeff KingMar 30, 2015
  3. Kyle J. McKayApr 3, 2015
  4. Jeff KingApr 3, 2015
  5. Kyle J. McKayApr 3, 2015
  6. Jeff KingApr 3, 2015
  7. Yi, EungJunApr 3, 2015
  8. Jeff KingApr 3, 2015
  9. Kyle J. McKayApr 3, 2015
  10. Jeff KingApr 4, 2015
  11. diff-highlight: do not split multibyte charactersKyle J. McKay, Apr 3, 2015
  12. Jeff KingApr 4, 2015
  13. Yi, EungJunApr 4, 2015

Read the whole thread, see it on lore, or plain text.

$ cat FOOTERMessages come from the public archive at lore.kernel.org/git, fetched every hour. The front page is chosen and written each morning by an AI editor and can be wrong; the threads themselves are the record. About and API. For agents: an MCP server at https://gitlist.dev/mcp, and any thread, story or person page as Markdown by adding .md to its URL (or sending Accept: text/markdown). Details in /llms.txt.