Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Option to ignore case? #161

Open
soumya92 opened this issue Jul 27, 2019 · 2 comments
Open

Option to ignore case? #161

soumya92 opened this issue Jul 27, 2019 · 2 comments

Comments

@soumya92
Copy link

diff provides -i option to ignore case-only differences. It would be great to have that option in icdiff as well.

@jeffkaufman
Copy link
Owner

If anyone wants to add this, go for it!

In the mean time, here's a way to get something similar:

icdiff <(cat a.txt | tr A-Z a-z) <(cat b.txt | tr A-Z a-z) 

@pgdr
Copy link

pgdr commented Jan 6, 2022

I needed this functionality, so I implemented it, but I unfortunately don't have time to create a PR (mainly because I don't have time to write tests). I licence the attached patch under whichever fits best of the following: Python Software Foundation License, BSD, MIT, Apache, GPL 2, GPL 2 and later, GPL 3, LGPL, AGPL.

The first example is case-sensitive, the second example uses the flag -i, or --ignore-case to ignore case differences.

ignore_case

The patch is attached below. Beware that the implementation doesn't immediately scale to --ignore-all-space, but I think it still should be possible with a similar approach.

The idea is that we keep two versions of the original text: the original, and one that is lower-cased. Then we use difflib to create a diff between the two lower-cased versions, and then we "patchback" the text, while simultaneously keeping the annotation from difflib.

diff --git a/icdiff b/icdiff
index 4d92058..054e0ef 100755
--- a/icdiff
+++ b/icdiff
@@ -88,7 +88,9 @@ class ConsoleDiff(object):
                  show_all_spaces=False,
                  highlight=False,
                  truncate=False,
-                 strip_trailing_cr=False):
+                 strip_trailing_cr=False,
+                 ignore_case=False,
+                 ):
         """ConsoleDiff instance initializer
 
         Arguments:
@@ -107,6 +109,7 @@ class ConsoleDiff(object):
         self.highlight = highlight
         self.strip_trailing_cr = strip_trailing_cr
         self.truncate = truncate
+        self.ignore_case = ignore_case
 
         if wrapcolumn is None:
             if not line_numbers:
@@ -347,11 +350,41 @@ class ConsoleDiff(object):
             fromlines = self._strip_trailing_cr(fromlines)
             tolines = self._strip_trailing_cr(tolines)
 
+        fromlines_filtered = fromlines
+        tolines_filtered = tolines
+        if self.ignore_case:
+            fromlines_filtered = [line.lower() for line in fromlines]
+            tolines_filtered = [line.lower() for line in tolines]
+
         # create diffs iterator which generates side by side from/to data
-        diffs = difflib._mdiff(fromlines, tolines, context_lines,
+        diffs = difflib._mdiff(fromlines_filtered, tolines_filtered,
+                               context_lines,
                                linejunk=self._linejunk,
                                charjunk=self._charjunk)
 
+        def patchback(idx, string, diffstring):
+            i = j = 0
+            retval = []
+            while i < len(string):
+                if diffstring[j].lower() != string[i].lower():
+                    retval.append(diffstring[j])
+                    j += 1
+                else:
+                    retval.append(string[i])
+                    i += 1
+                    j += 1
+            return "".join(retval)
+
+        if self.ignore_case:
+            patchdiff = []
+            for (f_idx, f), (t_idx, t), has_change in diffs:
+                if f_idx:
+                    f = patchback(f_idx, fromlines[f_idx - 1], f)
+                if t_idx:
+                    t = patchback(t_idx, tolines[t_idx - 1], t)
+                patchdiff.append(((f_idx, f), (t_idx, t), has_change))
+            diffs = patchdiff
+
         # set up iterator to wrap lines that exceed desired width
         if self._wrapcolumn:
             diffs = self._line_wrapper(diffs)
@@ -528,6 +561,9 @@ def create_option_parser():
                       help="color all non-matching whitespace including "
                       "that which is not needed for drawing the eye to "
                       "changes.  Slow, ugly, displays all changes")
+    parser.add_option("-i", "--ignore-case", default=False,
+                      action="store_true",
+                      help="ignore case differences in file contents")
     parser.add_option("--tabsize", default=8,
                       help="tab stop spacing")
     parser.add_option("-t", "--truncate", default=False,
@@ -779,7 +815,9 @@ def diff_files(options, a, b):
                      line_numbers=options.line_numbers,
                      tabsize=int(options.tabsize),
                      truncate=options.truncate,
-                     strip_trailing_cr=options.strip_trailing_cr)
+                     strip_trailing_cr=options.strip_trailing_cr,
+                     ignore_case=options.ignore_case,
+                     )
     for line in cd.make_table(
             lines_a, lines_b, headers[0], headers[1],
             context=(not options.whole_file),

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants