Mercurial > diff-colorize
comparison diff-colorize.py @ 28:58221373fc6f draft default tip
python3: port to Python 3
Pleasantly few changes required.
| author | Augie Fackler <raf@durin42.com> |
|---|---|
| date | Thu, 14 Jul 2022 10:20:03 -0400 |
| parents | 5f17911c4fe6 |
| children |
comparison
equal
deleted
inserted
replaced
| 27:5f17911c4fe6 | 28:58221373fc6f |
|---|---|
| 1 #!/usr/bin/env python | 1 #!/usr/bin/env python |
| 2 | 2 |
| 3 import sys | 3 import sys |
| 4 import os | 4 import os |
| 5 import fileinput | 5 import fileinput |
| 6 import functools | |
| 6 | 7 |
| 7 has_256_color = (os.environ.get('TERM', None) == 'xterm-256color') | 8 has_256_color = (os.environ.get('TERM', None) == 'xterm-256color') |
| 8 | 9 |
| 9 index_color = int(os.environ.get('DIFF_INDEX_COLOR', | 10 index_color = int(os.environ.get('DIFF_INDEX_COLOR', |
| 10 32 if has_256_color else 36)) | 11 32 if has_256_color else 36)) |
| 46 def interleave(*sequences): | 47 def interleave(*sequences): |
| 47 "Generator that yields one object from each sequence in turn." | 48 "Generator that yields one object from each sequence in turn." |
| 48 | 49 |
| 49 def zip_pad(*iterables, **kw): | 50 def zip_pad(*iterables, **kw): |
| 50 "Downloaded from http://code.activestate.com/recipes/497007/" | 51 "Downloaded from http://code.activestate.com/recipes/497007/" |
| 51 from itertools import izip, chain | 52 from itertools import chain |
| 52 if kw: | 53 if kw: |
| 53 assert len(kw) == 1 | 54 assert len(kw) == 1 |
| 54 pad = kw["pad"] | 55 pad = kw["pad"] |
| 55 else: | 56 else: |
| 56 pad = None | 57 pad = None |
| 60 return | 61 return |
| 61 done[0] -= 1 | 62 done[0] -= 1 |
| 62 while 1: | 63 while 1: |
| 63 yield pad | 64 yield pad |
| 64 iterables = [chain(seq, pad_iter()) for seq in iterables] | 65 iterables = [chain(seq, pad_iter()) for seq in iterables] |
| 65 return izip(*iterables) | 66 return zip(*iterables) |
| 66 | 67 |
| 67 for objects in zip_pad(*sequences): | 68 for objects in zip_pad(*sequences): |
| 68 for obj in objects: | 69 for obj in objects: |
| 69 if obj is not None: | 70 if obj is not None: |
| 70 yield obj | 71 yield obj |
| 71 | 72 |
| 73 @functools.total_ordering | |
| 72 class Substring(object): | 74 class Substring(object): |
| 73 def __init__(self, a, a_start, a_stop, b, b_start, b_stop): | 75 def __init__(self, a, a_start, a_stop, b, b_start, b_stop): |
| 74 self.a = a | 76 self.a = a |
| 75 self.a_start = a_start | 77 self.a_start = a_start |
| 76 self.a_stop = a_stop | 78 self.a_stop = a_stop |
| 91 def after_b_substring(self): | 93 def after_b_substring(self): |
| 92 return self.b[self.b_stop:] | 94 return self.b[self.b_stop:] |
| 93 | 95 |
| 94 def __hash__(self): | 96 def __hash__(self): |
| 95 return hash(self.substring()) | 97 return hash(self.substring()) |
| 96 def __cmp__(self, other): | 98 def __lt__(self, other): |
| 97 return cmp(self.a_start, other.a_start) | 99 return self.a_start < other.a_start |
| 98 def __eq__(self, other): | 100 def __eq__(self, other): |
| 99 return self.substring() == other.substring() | 101 return self.substring() == other.substring() |
| 100 def __str__(self): | 102 def __str__(self): |
| 101 return self.substring() | 103 return self.substring() |
| 102 def __repr__(self): | 104 def __repr__(self): |
| 112 | 114 |
| 113 Clarified and slightly modified (to use a special Substring object) from http://en.wikibooks.org/w/index.php?title=Algorithm_implementation/Strings/Longest_common_substring&oldid=1419225#Python | 115 Clarified and slightly modified (to use a special Substring object) from http://en.wikibooks.org/w/index.php?title=Algorithm_implementation/Strings/Longest_common_substring&oldid=1419225#Python |
| 114 """ | 116 """ |
| 115 a_len = len(a) | 117 a_len = len(a) |
| 116 b_len = len(b) | 118 b_len = len(b) |
| 117 lengths = [[0] * (b_len + 1) for i in xrange(a_len + 1)] | 119 lengths = [[0] * (b_len + 1) for i in range(a_len + 1)] |
| 118 substrings = set() | 120 substrings = set() |
| 119 greatest_length = current_run_length = 0 | 121 greatest_length = current_run_length = 0 |
| 120 for a_idx in xrange(a_len): | 122 for a_idx in range(a_len): |
| 121 for b_idx in xrange(b_len): | 123 for b_idx in range(b_len): |
| 122 if a[a_idx] == b[b_idx]: | 124 if a[a_idx] == b[b_idx]: |
| 123 current_run_length = lengths[a_idx][b_idx] + 1 | 125 current_run_length = lengths[a_idx][b_idx] + 1 |
| 124 lengths[a_idx+1][b_idx+1] = current_run_length | 126 lengths[a_idx+1][b_idx+1] = current_run_length |
| 125 if current_run_length > greatest_length: | 127 if current_run_length > greatest_length: |
| 126 greatest_length = current_run_length | 128 greatest_length = current_run_length |
| 138 | 140 |
| 139 def common_subsequence(a, b): | 141 def common_subsequence(a, b): |
| 140 "Returns all common substrings between a and b, which can be any finite indexable sliceable sequences, as Substring objects. Determines this by recursively calling itself on slices of a and b before and after each longest common substring." | 142 "Returns all common substrings between a and b, which can be any finite indexable sliceable sequences, as Substring objects. Determines this by recursively calling itself on slices of a and b before and after each longest common substring." |
| 141 # Inspired by http://en.wikibooks.org/w/index.php?title=Algorithm_Implementation/Strings/Longest_common_subsequence&oldid=1912924#Python | 143 # Inspired by http://en.wikibooks.org/w/index.php?title=Algorithm_Implementation/Strings/Longest_common_subsequence&oldid=1912924#Python |
| 142 def LCS_length_matrix(a, b): | 144 def LCS_length_matrix(a, b): |
| 143 matrix = [[0] * (len(b) + 1) for i in xrange(len(a) + 1)] | 145 matrix = [[0] * (len(b) + 1) for i in range(len(a) + 1)] |
| 144 for i, a_ch in enumerate(a): | 146 for i, a_ch in enumerate(a): |
| 145 for j, b_ch in enumerate(b): | 147 for j, b_ch in enumerate(b): |
| 146 if a_ch == b_ch: | 148 if a_ch == b_ch: |
| 147 matrix[i + 1][j + 1] = matrix[i][j] + 1 | 149 matrix[i + 1][j + 1] = matrix[i][j] + 1 |
| 148 else: | 150 else: |
