Skip to content

Add restrict option #220

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

Open
wants to merge 4 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 15 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,8 @@ Show differences between files in a two column view.
changes
-L LABELS, --label=LABELS
override file labels with arbitrary tags. Use twice,
one for each file
one for each file. You may include the formatting
strings '{path}' and '{basename}'
-N, --line-numbers generate output with line numbers. Not compatible with
the 'exclude-lines' option.
--no-bold use non-bold colors; recommended for solarized
Expand All @@ -66,6 +67,7 @@ Show differences between files in a two column view.
--show-all-spaces color all non-matching whitespace including that which
is not needed for drawing the eye to changes. Slow,
ugly, displays all changes
--show-no-spaces don't color whitespace-only changes
--tabsize=TABSIZE tab stop spacing
-t, --truncate truncate long lines instead of wrapping them
-u, --patch generate patch. This is always true, and only exists
Expand All @@ -75,14 +77,23 @@ Show differences between files in a two column view.
with --whole-file
-W, --whole-file show the whole file instead of just changed lines and
context
-P, --permissions compare the file permissions as well as the content of
the file
--strip-trailing-cr strip any trailing carriage return at the end of an
input line
--color-map=COLOR_MAP
choose which colors are used for which items. Default
is --color-map='add:green_bold,change:yellow_bold,desc
ription:blue,meta:magenta,separator:blue,subtract:red_
bold'. You don't have to override all of them:
'--color-map=separator:white,description:cyan
ription:blue,line-numbers:white,meta:magenta,permissio
ns:yellow,separator:blue,subtract:red_bold'. You
don't have to override all of them: '--color-
map=separator:white,description:cyan
--is-git-diff Show the real file name when displaying git-diff
result
-x PATH, --exclude=PATH
exclude files that match PATH
-R RESTRICT, --restrict=RESTRICT
Only color text that matches this regex
```

## Using with Git
Expand Down
86 changes: 78 additions & 8 deletions icdiff
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,7 @@ class ConsoleDiff(object):
highlight=False,
truncate=False,
strip_trailing_cr=False,
restrict=False,
):
"""ConsoleDiff instance initializer

Expand All @@ -123,6 +124,7 @@ class ConsoleDiff(object):
self.highlight = highlight
self.strip_trailing_cr = strip_trailing_cr
self.truncate = truncate
self.restrict = restrict

if wrapcolumn is None:
if not line_numbers:
Expand Down Expand Up @@ -182,7 +184,57 @@ class ConsoleDiff(object):

return sum(width(c) for c in s)

def _split_line(self, data_list, line_num, text):
def _mark_clipper(self, origin, marked):
xranges = [
(i.start(), i.end()) for i in re.finditer(self.restrict, origin)
]
result = ""
c0 = 0

def wipe_all(s):
return replace_all({"\0+": "", "\0-": "", "\0^": "", "\1": ""}, s)

if not xranges:
return wipe_all(marked)

# we can interpolate restricted and marked text from left to right.
# See https://docs.python.org/3/library/re.html#re.finditer
rex = re.escape("\0") + "[^" + re.escape("\0") + "]+" + re.escape("\1")
for i, m in enumerate(re.finditer(rex, marked)):
m0, m1, m2, m3 = m.start(), m.start() + 2, m.end() - 1, m.end()
offset = i * 3 + 2
c1 = c0

for xstart, xend in xranges:
x1, x2 = xstart + offset, xend + offset
restricted = range(x1, x2 + 1) # include the last

if m1 >= x1 and m2 <= x2:
result += marked[c0:m3]
elif m1 < x1 and m2 in restricted:
result += marked[c0:m0] + marked[m1:x1]
result += marked[m0:m1] + marked[x1:m3]
elif m1 in restricted and m2 > x2:
result += marked[c0:x2] + marked[m2:m3]
result += marked[x2:m2]
elif m1 < x1 and m2 > x2:
result += marked[c0:m0] + marked[m1:x1]
result += marked[m0:m1] + marked[x1:x2]
result += marked[m2:m3] + marked[x2:m2]
else:
continue

c0 = m3
break

if c0 == c1:
result += wipe_all(marked[c0:m3])
c0 = m3

result += marked[c0:]
return result

def _split_line(self, orig_list, data_list, line_num, text):
"""Builds list of text lines by splitting text lines at wrap point

This function will determine if the input text line needs to be
Expand All @@ -192,6 +244,7 @@ class ConsoleDiff(object):
the second part of the split line to further split it.
"""

i = 0
while True:
# if blank line or context separator, just add it to the output
# list
Expand All @@ -205,6 +258,11 @@ class ConsoleDiff(object):
self._display_len(text) - (text.count("\0") * 3)
<= self._wrapcolumn
):
if self.restrict:
orig_text = orig_list[line_num - 1]
text = self._mark_clipper(orig_text[i:], text)

line_num = line_num if not i else ">"
data_list.append((line_num, text))
return

Expand Down Expand Up @@ -236,17 +294,20 @@ class ConsoleDiff(object):
line1 = line1 + "\1"
line2 = "\0" + mark + line2

if self.restrict:
orig_text = orig_list[line_num - 1]
line1 = self._mark_clipper(orig_text[:i], line1)

# tack on first line onto the output list
data_list.append((line_num, line1))

# use this routine again to wrap the remaining text
# unless truncate is set
if self.truncate:
return
line_num = ">"
text = line2

def _line_wrapper(self, diffs):
def _line_wrapper(self, fromlines, tolines, diffs):
"""Returns iterator that splits (wraps) mdiff text lines"""

# pull from/to data and flags from mdiff iterator
Expand All @@ -259,8 +320,8 @@ class ConsoleDiff(object):
# for each from/to line split it at the wrap column to form
# list of text lines.
fromlist, tolist = [], []
self._split_line(fromlist, fromline, fromtext)
self._split_line(tolist, toline, totext)
self._split_line(fromlines, fromlist, fromline, fromtext)
self._split_line(tolines, tolist, toline, totext)
# yield from/to line in pairs inserting blank lines as
# necessary when one side has more wrapped lines
while fromlist or tolist:
Expand Down Expand Up @@ -392,7 +453,7 @@ class ConsoleDiff(object):

# set up iterator to wrap lines that exceed desired width
if self._wrapcolumn:
diffs = self._line_wrapper(diffs)
diffs = self._line_wrapper(fromlines, tolines, diffs)
diffs = self._collect_lines(diffs)

for left, right in self._generate_table(
Expand Down Expand Up @@ -726,10 +787,18 @@ def create_option_parser():
parser.add_option(
"-x",
"--exclude",
metavar="PAT",
metavar="PATH",
action="append",
default=[],
help="exclude files that match PAT",
help="exclude files that match PATH",
)
parser.add_option(
"-R",
"--restrict",
action="store",
type="string",
dest="restrict",
help="Only color text that matches this regex",
)
return parser

Expand Down Expand Up @@ -1012,6 +1081,7 @@ def diff_files(options, a, b):
tabsize=int(options.tabsize),
truncate=options.truncate,
strip_trailing_cr=options.strip_trailing_cr,
restrict=options.restrict,
)
for line in cd.make_table(
lines_a,
Expand Down
7 changes: 5 additions & 2 deletions test.sh
Original file line number Diff line number Diff line change
Expand Up @@ -102,11 +102,10 @@ function check_git_diff() {
FIRST_TIME_CHECK_GIT_DIFF=false
# Set default args when first time check git diff
yes | git difftool --extcmd icdiff > /dev/null
git config --global icdiff.options '--cols=80'
export PATH="$(pwd)":$PATH
fi
local tmp=/tmp/git-icdiff.output
git icdiff $1 $2 &> $tmp
git -c icdiff.options='--cols=80' icdiff $1 $2 &> $tmp
if ! diff $tmp $gitdiff; then
echo "Got: ($tmp)"
cat $tmp
Expand Down Expand Up @@ -162,6 +161,10 @@ check_gold 2 gold-bad-encoding.txt tests/input-{1,2}.txt --encoding=nonexistend_
check_gold 0 gold-recursive-with-exclude.txt --recursive -x c tests/{a,b} --cols=80
check_gold 1 gold-recursive-with-exclude2.txt --recursive -x 'excl*' tests/test-with-exclude/{a,b} --cols=80
check_gold 0 gold-exit-process-sub tests/input-1.txt <(cat tests/input-1.txt) --no-headers --cols=80
check_gold 1 gold-restrict-clip-none.txt tests/input-restrict-0{1,2}.txt --restrict="(%|A).*(%|A)?" --cols=100
check_gold 1 gold-restrict-clip-lhs.txt tests/input-restrict-0{1,2}.txt --restrict="(;|O).+;" --cols=100
check_gold 1 gold-restrict-clip-rhs.txt tests/input-restrict-0{1,2}.txt --restrict=":.+(:|O)" --cols=100
check_gold 1 gold-restrict-clip-both.txt tests/input-restrict-0{1,2}.txt --restrict="Q.+Q" --cols=100

rm -f tests/permissions-{a,b}
touch tests/permissions-{a,b}
Expand Down
7 changes: 7 additions & 0 deletions tests/gold-restrict-clip-both.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
tests/input-restrict-01.txt tests/input-restrict-02.txt
__________%______________________%___________ __________%________AXXXXXA_______%___________
___________________%_____%___________________ ___________________AAAAAAA___________________
______________________%______________________ ______________________A______________________
______________________;__________;___________ ___________________XXXOXXX_______;___________
__________:___________:______________________ __________:________XXXOXXX___________________
_____________________________________________ __________ QQQ ___________
7 changes: 7 additions & 0 deletions tests/gold-restrict-clip-lhs.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
tests/input-restrict-01.txt tests/input-restrict-02.txt
__________%______________________%___________ __________%________AXXXXXA_______%___________
___________________%_____%___________________ ___________________AAAAAAA___________________
______________________%______________________ ______________________A______________________
______________________;__________;___________ ___________________XXXOXXX_______;___________
__________:___________:______________________ __________:________XXXOXXX___________________
_____________________________________________ __________ QQQ ___________
7 changes: 7 additions & 0 deletions tests/gold-restrict-clip-none.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
tests/input-restrict-01.txt tests/input-restrict-02.txt
__________%______________________%___________ __________%________AXXXXXA_______%___________
___________________%_____%___________________ ___________________AAAAAAA___________________
______________________%______________________ ______________________A______________________
______________________;__________;___________ ___________________XXXOXXX_______;___________
__________:___________:______________________ __________:________XXXOXXX___________________
_____________________________________________ __________ QQQ ___________
7 changes: 7 additions & 0 deletions tests/gold-restrict-clip-rhs.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
tests/input-restrict-01.txt tests/input-restrict-02.txt
__________%______________________%___________ __________%________AXXXXXA_______%___________
___________________%_____%___________________ ___________________AAAAAAA___________________
______________________%______________________ ______________________A______________________
______________________;__________;___________ ___________________XXXOXXX_______;___________
__________:___________:______________________ __________:________XXXOXXX___________________
_____________________________________________ __________ QQQ ___________
6 changes: 6 additions & 0 deletions tests/input-restrict-01.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
__________%______________________%___________
___________________%_____%___________________
______________________%______________________
______________________;__________;___________
__________:___________:______________________
_____________________________________________
6 changes: 6 additions & 0 deletions tests/input-restrict-02.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
__________%________AXXXXXA_______%___________
___________________AAAAAAA___________________
______________________A______________________
___________________XXXOXXX_______;___________
__________:________XXXOXXX___________________
__________ QQQ ___________