[meld] Restrict changes returned by single/pair_changes with range arguments
- From: Kai Willadsen <kaiw src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [meld] Restrict changes returned by single/pair_changes with range arguments
- Date: Tue, 24 Aug 2010 09:51:07 +0000 (UTC)
commit 3c0cd173732a1b8f3e0d65099d7ee99227a929b7
Author: Kai Willadsen <kai willadsen gmail com>
Date: Sun Mar 21 08:00:43 2010 +1000
Restrict changes returned by single/pair_changes with range arguments
The single/pair_changes methods always iterate over all changes, despite
most callers immediately filtering down to a certain subset. With this
commit, these methods accept an optional argument of line ranges to
restrict the set of changes returned.
The semantics of the line range limitation in _range_from_lines() are:
* the starting change is the change that contains the start line, or
the first change that starts after the starting line, or None
* the ending change is the change that contains the end line, or the
the last change that ends before the ending line, or None
meld/diffutil.py | 46 +++++++++++++++++++++++++++++++++++++++-------
meld/filediff.py | 19 ++++---------------
2 files changed, 43 insertions(+), 22 deletions(-)
---
diff --git a/meld/diffutil.py b/meld/diffutil.py
index aa25d99..1a4f598 100644
--- a/meld/diffutil.py
+++ b/meld/diffutil.py
@@ -115,7 +115,8 @@ class Differ(gobject.GObject):
def _update_line_cache(self):
for i, l in enumerate(self.seqlength):
- self._line_cache[i] = [(None, None, None)] * l
+ # seqlength + 1 for after-last-line requests, which we do
+ self._line_cache[i] = [(None, None, None)] * (l + 1)
last_chunk = len(self._merge_cache)
def find_next(diff, seq, current):
@@ -276,33 +277,64 @@ class Differ(gobject.GObject):
for c in self.diffs[which][hiidx:] ]
self.diffs[which][loidx:hiidx] = newdiffs
+ def _range_from_lines(self, textindex, lines):
+ lo_line, hi_line = lines
+ top_chunk = self.locate_chunk(textindex, lo_line)
+ start = top_chunk[0]
+ if start is None:
+ start = top_chunk[2]
+ bottom_chunk = self.locate_chunk(textindex, hi_line)
+ end = bottom_chunk[0]
+ if end is None:
+ end = bottom_chunk[1]
+ return start, end
+
def all_changes(self):
return iter(self._merge_cache)
- def pair_changes(self, fromindex, toindex):
+ def pair_changes(self, fromindex, toindex, lines=(None, None, None, None)):
"""Give all changes between file1 and either file0 or file2.
"""
+ if None not in lines:
+ start1, end1 = self._range_from_lines(fromindex, lines[0:2])
+ start2, end2 = self._range_from_lines(toindex, lines[2:4])
+ if (start1 is None or end1 is None) and \
+ (start2 is None or end2 is None):
+ return
+ start = min([x for x in (start1, start2) if x is not None])
+ end = max([x for x in (end1, end2) if x is not None])
+ merge_cache = self._merge_cache[start:end + 1]
+ else:
+ merge_cache = self._merge_cache
+
if fromindex == 1:
seq = toindex/2
- for c in self._merge_cache:
+ for c in merge_cache:
if c[seq]:
yield c[seq]
else:
seq = fromindex/2
- for c in self._merge_cache:
+ for c in merge_cache:
if c[seq]:
yield reverse_chunk(c[seq])
- def single_changes(self, textindex):
+ def single_changes(self, textindex, lines=(None, None)):
"""Give changes for single file only. do not return 'equal' hunks.
"""
+ if None not in lines:
+ start, end = self._range_from_lines(textindex, lines)
+ if start is None or end is None:
+ return
+ merge_cache = self._merge_cache[start:end + 1]
+ else:
+ merge_cache = self._merge_cache
if textindex in (0,2):
seq = textindex/2
- for cs in self._merge_cache:
+ for cs in merge_cache:
if cs[seq]:
yield reverse_chunk(cs[seq])
else:
- for cs in self._merge_cache:
+ for cs in merge_cache:
yield cs[0] or cs[1]
def sequences_identical(self):
diff --git a/meld/filediff.py b/meld/filediff.py
index f6b68fd..d609685 100644
--- a/meld/filediff.py
+++ b/meld/filediff.py
@@ -932,8 +932,8 @@ class FileDiff(melddoc.MeldDoc, gnomeglade.Component):
return
visible = textview.get_visible_rect()
pane = self.textview.index(textview)
- start_line = self._pixel_to_line(pane, visible.y)
- end_line = 1+self._pixel_to_line(pane, visible.y+visible.height)
+ bounds = (self._pixel_to_line(pane, visible.y),
+ self._pixel_to_line(pane, visible.y + visible.height + 1))
width, height = textview.allocation.width, textview.allocation.height
context = event.window.cairo_create()
@@ -941,12 +941,7 @@ class FileDiff(melddoc.MeldDoc, gnomeglade.Component):
context.clip()
context.set_line_width(1.0)
- for change in self.linediffer.single_changes(pane):
- if change[2] < start_line:
- continue
- if change[1] > end_line:
- break
-
+ for change in self.linediffer.single_changes(pane, bounds):
ypos0 = self._line_to_pixel(pane, change[1]) - visible.y
ypos1 = self._line_to_pixel(pane, change[2]) - visible.y
@@ -1311,13 +1306,7 @@ class FileDiff(melddoc.MeldDoc, gnomeglade.Component):
# For bezier control points
x_steps = [-0.5, (1. / 3) * wtotal, (2. / 3) * wtotal, wtotal + 0.5]
- for c in self.linediffer.pair_changes(which, which + 1):
- assert c[0] != "equal"
- if c[2] < visible[1] and c[4] < visible[3]: # find first visible chunk
- continue
- elif c[1] > visible[2] and c[3] > visible[4]: # we've gone past last visible
- break
-
+ for c in self.linediffer.pair_changes(which, which + 1, visible[1:5]):
# f and t are short for "from" and "to"
f0, f1 = [self._line_to_pixel(which, l) - pix_start[which] + rel_offset[which] for l in c[1:3]]
t0, t1 = [self._line_to_pixel(which + 1, l) - pix_start[which + 1] + rel_offset[which + 1] for l in c[3:5]]
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]