+ if line.startswith(token):
+ return i
+ return -1
+
+
+def find_complete_lines(lines, sublines, start=0, end=0):
+ """Find first occurence of sequence `sublines` in list `lines`.
+ Return index of first line or -1 on failure.
+
+ Efficient search for a sub-list in a large list. Works for any values.
+
+ >>> find_complete_lines([1, 2, 3, 1, 1, 2], [1, 2])
+ 0
+
+ The `start` and `end` arguments work similar to list.index()
+
+ >>> find_complete_lines([1, 2, 3, 1, 1 ,2], [1, 2], start=1)
+ 4
+ >>> find_complete_lines([1, 2, 3, 1, 1 ,2], [1, 2], start=1, end=4)
+ -1
+
+ The return value can be used to substitute the sub-list.
+ Take care to check before use:
+
+ >>> l = [1, 1, 2]
+ >>> s = find_complete_lines(l, [1, 2])
+ >>> if s != -1:
+ ... l[s:s+2] = [3]; l
+ [1, 3]
+
+ See also del_complete_lines().
+ """
+ if not sublines:
+ return start
+ end = end or len(lines)
+ N = len(sublines)
+ try:
+ while True:
+ for j, value in enumerate(sublines):
+ i = lines.index(value, start, end)
+ if j and i != start:
+ start = i-j
+ break
+ start = i + 1
+ else:
+ return i +1 - N
+ except ValueError: # `sublines` not found
+ return -1
+
+
+def find_across_lines(lines, sub, start=0, end=0):
+ sublines = sub.splitlines()
+ if len(sublines) > 2:
+ # at least 3 lines: the middle one(s) are complete -> use index search
+ i = find_complete_lines(lines, sublines[1:-1], start+1, end-1)
+ if i < start+1:
+ return -1
+ try:
+ if (lines[i-1].endswith(sublines[0]) and
+ lines[i+len(sublines)].startswith(sublines[-1])):
+ return i-1
+ except IndexError:
+ pass
+ elif len(sublines) > 1:
+ # last subline must start a line
+ i = find_token(lines, sublines[-1], start, end)
+ if i < start + 1:
+ return -1
+ if lines[i-1].endswith(sublines[0]):
+ return i-1
+ else: # no line-break, may be in the middle of a line
+ if end == 0 or end > len(lines):
+ end = len(lines)
+ for i in range(start, end):
+ if sub in lines[i]: