Parcourir la source

More clear logic with _fit_with_marker_mix()

Matthew Wang il y a 11 ans
Parent
révision
8f24a53487
1 fichiers modifiés avec 32 ajouts et 32 suppressions
  1. 32
    32
      cdiff.py

+ 32
- 32
cdiff.py Voir le fichier

@@ -206,15 +206,16 @@ class Diff(object):
206 206
                     else:
207 207
                         # DEBUG: yield 'CHG: %s %s\n' % (old, new)
208 208
                         yield self._markup_old('-') + \
209
-                            self._markup_old_mix(old[1])
209
+                            self._markup_mix(old[1], 'red')
210 210
                         yield self._markup_new('+') + \
211
-                            self._markup_new_mix(new[1])
211
+                            self._markup_mix(new[1], 'green')
212 212
                 else:
213 213
                     yield self._markup_common(' ' + old[1])
214 214
 
215 215
     def markup_side_by_side(self, width):
216 216
         """Returns a generator"""
217 217
         wrap_char = colorize('>', 'lightmagenta')
218
+
218 219
         def _normalize(line):
219 220
             return line.replace('\t', ' '*8).replace('\n', '').replace('\r', '')
220 221
 
@@ -228,40 +229,45 @@ class Diff(object):
228 229
             else:
229 230
                 return markup_fn(text)
230 231
 
231
-        def _fit_markup(markup, width, pad=False):
232
-            """Fit input markup to given width, pad or wrap accordingly, str len
233
-            does not count correctly if string contains ansi color code.  Only
234
-            left side need to set `pad`
235
-            """
236
-            out = []
232
+        def _fit_with_marker_mix(text, base_color, width, pad=False):
233
+            """Wrap or pad input text which contains mdiff tags, markup at the
234
+            meantime with the markup_fix_fn, note only left side need to set
235
+            `pad`"""
236
+            out = [COLORS[base_color]]
237 237
             count = 0
238
-            ansi_color_regex = r'\x1b\[(1;)?\d{1,2}m'
239
-            patt = re.compile('^((%s)+)(.*)' % ansi_color_regex)
240
-            repl = re.compile(ansi_color_regex)
241
-
242
-            while markup and count < width:
243
-                if patt.match(markup):
244
-                    # Extract longest ansi color code seq to target output and
245
-                    # remove the seq from input markup, no update on counter
246
-                    #
247
-                    out.append(patt.sub(r'\1', markup))
248
-                    markup = patt.sub(r'\4', markup)
238
+            tag_re = re.compile(r'\x00[+^-]|\x01')
239
+
240
+            while text and count < width:
241
+                if text.startswith('\x00-'):    # del
242
+                    out.append(COLORS['reverse'] + COLORS[base_color])
243
+                    text = text[2:]
244
+                elif text.startswith('\x00+'):  # add
245
+                    out.append(COLORS['reverse'] + COLORS[base_color])
246
+                    text = text[2:]
247
+                elif text.startswith('\x00^'):  # change
248
+                    out.append(COLORS['underline'] + COLORS[base_color])
249
+                    text = text[2:]
250
+                elif text.startswith('\x01'):   # reset
251
+                    out.append(COLORS['reset'] + COLORS[base_color])
252
+                    text = text[1:]
249 253
                 else:
250 254
                     # FIXME: utf-8 wchar might break the rule here, e.g.
251 255
                     # u'\u554a' takes double width of a single letter, also this
252 256
                     # depends on your terminal font.  I guess audience of this
253 257
                     # tool never put that kind of symbol in their code :-)
254 258
                     #
255
-                    out.append(markup[0])
259
+                    out.append(text[0])
256 260
                     count += 1
257
-                    markup = markup[1:]
261
+                    text = text[1:]
258 262
 
259
-            if count == width and repl.sub('', markup):
260
-                # Was stripped: output fulfil and still has ascii in markup
263
+            if count == width and tag_re.sub('', text):
264
+                # Was stripped: output fulfil and still has normal char in text
261 265
                 out[-1] = COLORS['reset'] + wrap_char
262 266
             elif count < width and pad:
263 267
                 pad_len = width - count
264
-                out.append('%*s' % (pad_len, ''))
268
+                out.append('%s%*s' % (COLORS['reset'], pad_len, ''))
269
+            else:
270
+                out.append(COLORS['reset'])
265 271
 
266 272
             return ''.join(out)
267 273
 
@@ -314,8 +320,8 @@ class Diff(object):
314 320
                         left = _fit_with_marker(left, self._markup_old, width)
315 321
                         right = ''
316 322
                     else:
317
-                        left = _fit_markup(self._markup_old_mix(left), width, 1)
318
-                        right = _fit_markup(self._markup_new_mix(right), width)
323
+                        left = _fit_with_marker_mix(left, 'red', width, 1)
324
+                        right = _fit_with_marker_mix(right, 'green', width)
319 325
                 else:
320 326
                     left = _fit_with_marker(left, self._markup_common, width, 1)
321 327
                     right = _fit_with_marker(right, self._markup_common, width)
@@ -361,12 +367,6 @@ class Diff(object):
361 367
         line = line.replace('\x01', rst_code)
362 368
         return colorize(line, base_color)
363 369
 
364
-    def _markup_old_mix(self, line):
365
-        return self._markup_mix(line, 'red')
366
-
367
-    def _markup_new_mix(self, line):
368
-        return self._markup_mix(line, 'green')
369
-
370 370
 
371 371
 class Udiff(Diff):
372 372