Selaa lähdekoodia

Performance enhancement

Matthew Wang 11 vuotta sitten
vanhempi
commit
58bb01b0a7
1 muutettua tiedostoa jossa 31 lisäystä ja 22 poistoa
  1. 31
    22
      cdiff.py

+ 31
- 22
cdiff.py Näytä tiedosto

@@ -70,11 +70,8 @@ VCS_INFO = {
70 70
 }
71 71
 
72 72
 
73
-def ansi_code(color):
74
-    return COLORS.get(color, '')
75
-
76 73
 def colorize(text, start_color, end_color='reset'):
77
-    return ansi_code(start_color) + text + ansi_code(end_color)
74
+    return COLORS[start_color] + text + COLORS[end_color]
78 75
 
79 76
 
80 77
 class Hunk(object):
@@ -217,27 +214,38 @@ class Diff(object):
217 214
 
218 215
     def markup_side_by_side(self, width):
219 216
         """Returns a generator"""
217
+        wrap_char = colorize('>', 'lightmagenta')
220 218
         def _normalize(line):
221 219
             return line.replace('\t', ' '*8).replace('\n', '').replace('\r', '')
222 220
 
223
-        def _fit_width(markup, width, pad=False):
221
+        def _fit_with_marker(text, markup_fn, width, pad=False):
222
+            """Wrap or pad input pure text, then markup"""
223
+            if len(text) > width:
224
+                return markup_fn(text[:width-1]) + wrap_char
225
+            elif pad:
226
+                pad_len = width - len(text)
227
+                return '%s%*s' % (markup_fn(text), pad_len, '')
228
+            else:
229
+                return markup_fn(text)
230
+
231
+        def _fit_markup(markup, width, pad=False):
224 232
             """Fit input markup to given width, pad or wrap accordingly, str len
225
-            does not count correctly if line contains ansi color code.  Only
233
+            does not count correctly if string contains ansi color code.  Only
226 234
             left side need to set `pad`
227 235
             """
228 236
             out = []
229 237
             count = 0
230 238
             ansi_color_regex = r'\x1b\[(1;)?\d{1,2}m'
231
-            patt = re.compile('^(%s)(.*)' % ansi_color_regex)
239
+            patt = re.compile('^((%s)+)(.*)' % ansi_color_regex)
232 240
             repl = re.compile(ansi_color_regex)
233 241
 
234 242
             while markup and count < width:
235 243
                 if patt.match(markup):
236
-                    # Extract the ansi color code seq to target output and
237
-                    # remove the seq from input markup, no update on counter 
244
+                    # Extract longest ansi color code seq to target output and
245
+                    # remove the seq from input markup, no update on counter
238 246
                     #
239 247
                     out.append(patt.sub(r'\1', markup))
240
-                    markup = patt.sub(r'\3', markup)
248
+                    markup = patt.sub(r'\4', markup)
241 249
                 else:
242 250
                     # FIXME: utf-8 wchar might break the rule here, e.g.
243 251
                     # u'\u554a' takes double width of a single letter, also this
@@ -250,7 +258,7 @@ class Diff(object):
250 258
 
251 259
             if count == width and repl.sub('', markup):
252 260
                 # Was stripped: output fulfil and still has ascii in markup
253
-                out[-1] = ansi_code('reset') + colorize('>', 'lightmagenta')
261
+                out[-1] = COLORS['reset'] + wrap_char
254 262
             elif count < width and pad:
255 263
                 pad_len = width - count
256 264
                 out.append('%*s' % (pad_len, ''))
@@ -260,6 +268,7 @@ class Diff(object):
260 268
         # Setup line width and number width
261 269
         if width <= 0:
262 270
             width = 80
271
+
263 272
         (start, offset) = self._hunks[-1].get_old_addr()
264 273
         max1 = start + offset - 1
265 274
         (start, offset) = self._hunks[-1].get_new_addr()
@@ -267,7 +276,7 @@ class Diff(object):
267 276
         num_width = max(len(str(max1)), len(str(max2)))
268 277
         left_num_fmt = colorize('%%(left_num)%ds' % num_width, 'yellow')
269 278
         right_num_fmt = colorize('%%(right_num)%ds' % num_width, 'yellow')
270
-        line_fmt = left_num_fmt + ' %(left)s ' + ansi_code('reset') + \
279
+        line_fmt = left_num_fmt + ' %(left)s ' + COLORS['reset'] + \
271 280
                 right_num_fmt + ' %(right)s\n'
272 281
 
273 282
         # yield header, old path and new path
@@ -299,17 +308,17 @@ class Diff(object):
299 308
                     if not old[0]:
300 309
                         left = '%*s' % (width, ' ')
301 310
                         right = right.lstrip('\x00+').rstrip('\x01')
302
-                        right = _fit_width(self._markup_new(right), width)
311
+                        right = _fit_with_marker(right, self._markup_new, width)
303 312
                     elif not new[0]:
304 313
                         left = left.lstrip('\x00-').rstrip('\x01')
305
-                        left = _fit_width(self._markup_old(left), width)
314
+                        left = _fit_with_marker(left, self._markup_old, width)
306 315
                         right = ''
307 316
                     else:
308
-                        left = _fit_width(self._markup_old_mix(left), width, 1)
309
-                        right = _fit_width(self._markup_new_mix(right), width)
317
+                        left = _fit_markup(self._markup_old_mix(left), width, 1)
318
+                        right = _fit_markup(self._markup_new_mix(right), width)
310 319
                 else:
311
-                    left = _fit_width(self._markup_common(left), width, 1)
312
-                    right = _fit_width(self._markup_common(right), width)
320
+                    left = _fit_with_marker(left, self._markup_common, width, 1)
321
+                    right = _fit_with_marker(right, self._markup_common, width)
313 322
                 yield line_fmt % {
314 323
                     'left_num': left_num,
315 324
                     'left': left,
@@ -342,10 +351,10 @@ class Diff(object):
342 351
         return colorize(line, 'lightgreen')
343 352
 
344 353
     def _markup_mix(self, line, base_color):
345
-        del_code = ansi_code('reverse') + ansi_code(base_color)
346
-        add_code = ansi_code('reverse') + ansi_code(base_color)
347
-        chg_code = ansi_code('underline') + ansi_code(base_color)
348
-        rst_code = ansi_code('reset') + ansi_code(base_color)
354
+        del_code = COLORS['reverse'] + COLORS[base_color]
355
+        add_code = COLORS['reverse'] + COLORS[base_color]
356
+        chg_code = COLORS['underline'] + COLORS[base_color]
357
+        rst_code = COLORS['reset'] + COLORS[base_color]
349 358
         line = line.replace('\x00-', del_code)
350 359
         line = line.replace('\x00+', add_code)
351 360
         line = line.replace('\x00^', chg_code)