浏览代码

Merge pull request #72 from dimonomid/wrap

Implement --wrap flag
Matt Wang 6 年前
父节点
当前提交
05209aa5b2
没有帐户链接到提交者的电子邮件

+ 146
- 44
cdiff.py 查看文件

@@ -59,7 +59,6 @@ COLORS = {
59 59
     'lightcyan'     : '\x1b[1;36m',
60 60
 }
61 61
 
62
-
63 62
 # Keys for revision control probe, diff and log with diff
64 63
 VCS_INFO = {
65 64
     'Git': {
@@ -84,6 +83,87 @@ def colorize(text, start_color, end_color='reset'):
84 83
     return COLORS[start_color] + text + COLORS[end_color]
85 84
 
86 85
 
86
+def strsplit(text, width):
87
+    r"""strsplit() splits a given string into two substrings, respecting the
88
+    escape sequences (in a global var COLORS).
89
+
90
+    It returns 3-tuple: (first string, second string, number of visible chars
91
+    in the first string).
92
+
93
+    If some color was active at the splitting point, then the first string is
94
+    appended with the resetting sequence, and the second string is prefixed
95
+    with all active colors.
96
+    """
97
+    first = ''
98
+    second = ''
99
+    found_colors = []
100
+    chars_cnt = 0
101
+    bytes_cnt = 0
102
+    while len(text) > 0:
103
+        # First of all, check if current string begins with any escape
104
+        # sequence.
105
+        append_len = 0
106
+        for color in COLORS:
107
+            if text.startswith(COLORS[color]):
108
+                if color == 'reset':
109
+                    found_colors = []
110
+                else:
111
+                    found_colors.append(color)
112
+                append_len = len(COLORS[color])
113
+                break
114
+
115
+        if append_len == 0:
116
+            # Current string does not start with any escape sequence, so,
117
+            # either add one more visible char to the "first" string, or
118
+            # break if that string is already large enough.
119
+            if chars_cnt >= width:
120
+                break
121
+            chars_cnt += 1
122
+            append_len = 1
123
+
124
+        first += text[:append_len]
125
+        text = text[append_len:]
126
+        bytes_cnt += append_len
127
+
128
+    second = text
129
+
130
+    # If the first string has some active colors at the splitting point,
131
+    # reset it and append the same colors to the second string
132
+    if len(found_colors) > 0:
133
+        first += COLORS['reset']
134
+        for color in found_colors:
135
+            second = COLORS[color] + second
136
+
137
+    return (first, second, chars_cnt)
138
+
139
+
140
+def strtrim(text, width, wrap_char, pad):
141
+    r"""strtrim() trims given string respecting the escape sequences (using
142
+    strsplit), so that if text is larger than width, it's trimmed to have
143
+    width-1 chars plus wrap_char. Additionally, if pad is True, short strings
144
+    are padded with space to have exactly needed width.
145
+
146
+    Returns resulting string.
147
+    """
148
+    text, _, tlen = strsplit(text, width + 1)
149
+    if tlen > width:
150
+        text, _, _ = strsplit(text, width - 1)
151
+
152
+        # Old code always added trailing 'reset' sequence, but strsplit is
153
+        # smarter and only adds it when there is something to reset. However,
154
+        # in order not to distract with changed test data, here's workaround
155
+        # which keeps output exactly the same. TODO: remove it; it doesn't add
156
+        # any practical value for the user.
157
+        if not text.endswith(COLORS['reset']):
158
+            text += COLORS['reset']
159
+
160
+        text += wrap_char
161
+    elif pad:
162
+        # The string is short enough, but it might need to be padded.
163
+        text = "%s%*s" % (text, width - tlen, '')
164
+    return text
165
+
166
+
87 167
 class Hunk(object):
88 168
 
89 169
     def __init__(self, hunk_headers, hunk_meta, old_addr, new_addr):
@@ -398,11 +478,13 @@ class DiffParser(object):
398 478
 
399 479
 class DiffMarker(object):
400 480
 
401
-    def markup(self, diffs, side_by_side=False, width=0, tab_width=8):
481
+    def markup(self, diffs, side_by_side=False, width=0, tab_width=8,
482
+               wrap=False):
402 483
         """Returns a generator"""
403 484
         if side_by_side:
404 485
             for diff in diffs:
405
-                for line in self._markup_side_by_side(diff, width, tab_width):
486
+                for line in self._markup_side_by_side(diff, width, tab_width,
487
+                                                      wrap):
406 488
                     yield line
407 489
         else:
408 490
             for diff in diffs:
@@ -442,33 +524,21 @@ class DiffMarker(object):
442 524
                 else:
443 525
                     yield self._markup_common(' ' + old[1])
444 526
 
445
-    def _markup_side_by_side(self, diff, width, tab_width):
527
+    def _markup_side_by_side(self, diff, width, tab_width, wrap):
446 528
         """Returns a generator"""
447
-        wrap_char = colorize('>', 'lightmagenta')
448 529
 
449 530
         def _normalize(line):
450 531
             return line.replace(
451 532
                 '\t', ' ' * tab_width).replace('\n', '').replace('\r', '')
452 533
 
453
-        def _fit_with_marker(text, markup_fn, width, pad=False):
454
-            """Wrap or pad input pure text, then markup"""
455
-            if len(text) > width:
456
-                return markup_fn(text[:(width - 1)]) + wrap_char
457
-            elif pad:
458
-                pad_len = width - len(text)
459
-                return '%s%*s' % (markup_fn(text), pad_len, '')
460
-            else:
461
-                return markup_fn(text)
462
-
463
-        def _fit_with_marker_mix(text, base_color, width, pad=False):
464
-            """Wrap or pad input text which contains mdiff tags, markup at the
465
-            meantime, note only left side need to set `pad`
534
+        def _fit_with_marker_mix(text, base_color, width):
535
+            """Wrap input text which contains mdiff tags, markup at the
536
+            meantime
466 537
             """
467 538
             out = [COLORS[base_color]]
468
-            count = 0
469 539
             tag_re = re.compile(r'\x00[+^-]|\x01')
470 540
 
471
-            while text and count < width:
541
+            while text:
472 542
                 if text.startswith('\x00-'):    # del
473 543
                     out.append(COLORS['reverse'] + COLORS[base_color])
474 544
                     text = text[2:]
@@ -479,6 +549,9 @@ class DiffMarker(object):
479 549
                     out.append(COLORS['underline'] + COLORS[base_color])
480 550
                     text = text[2:]
481 551
                 elif text.startswith('\x01'):   # reset
552
+                    # TODO: Append resetting sequence if only there is some
553
+                    # text after that. That is, call out.append(...) if only
554
+                    # len(text) > 1.
482 555
                     out.append(COLORS['reset'] + COLORS[base_color])
483 556
                     text = text[1:]
484 557
                 else:
@@ -488,17 +561,9 @@ class DiffMarker(object):
488 561
                     # this tool never put that kind of symbol in their code :-)
489 562
                     #
490 563
                     out.append(text[0])
491
-                    count += 1
492 564
                     text = text[1:]
493 565
 
494
-            if count == width and tag_re.sub('', text):
495
-                # Was stripped: output fulfil and still has normal char in text
496
-                out[-1] = COLORS['reset'] + wrap_char
497
-            elif count < width and pad:
498
-                pad_len = width - count
499
-                out.append('%s%*s' % (COLORS['reset'], pad_len, ''))
500
-            else:
501
-                out.append(COLORS['reset'])
566
+            out.append(COLORS['reset'])
502 567
 
503 568
             return ''.join(out)
504 569
 
@@ -558,31 +623,64 @@ class DiffMarker(object):
558 623
 
559 624
                 if changed:
560 625
                     if not old[0]:
561
-                        left = '%*s' % (width, ' ')
626
+                        left = ''
562 627
                         right = right.rstrip('\x01')
563 628
                         if right.startswith('\x00+'):
564 629
                             right = right[2:]
565
-                        right = _fit_with_marker(
566
-                            right, self._markup_new, width)
630
+                        right = self._markup_new(right)
567 631
                     elif not new[0]:
568 632
                         left = left.rstrip('\x01')
569 633
                         if left.startswith('\x00-'):
570 634
                             left = left[2:]
571
-                        left = _fit_with_marker(left, self._markup_old, width)
635
+                        left = self._markup_old(left)
572 636
                         right = ''
573 637
                     else:
574
-                        left = _fit_with_marker_mix(left, 'red', width, 1)
638
+                        left = _fit_with_marker_mix(left, 'red', width)
575 639
                         right = _fit_with_marker_mix(right, 'green', width)
576 640
                 else:
577
-                    left = _fit_with_marker(
578
-                        left, self._markup_common, width, 1)
579
-                    right = _fit_with_marker(right, self._markup_common, width)
580
-                yield line_fmt % {
581
-                    'left_num': left_num,
582
-                    'left': left,
583
-                    'right_num': right_num,
584
-                    'right': right
585
-                }
641
+                    left = self._markup_common(left)
642
+                    right = self._markup_common(right)
643
+
644
+                if wrap:
645
+                    # Need to wrap long lines, so here we'll iterate,
646
+                    # shaving off `width` chars from both left and right
647
+                    # strings, until both are empty. Also, line number needs to
648
+                    # be printed only for the first part.
649
+                    lncur = left_num
650
+                    rncur = right_num
651
+                    while len(left) > 0 or len(right) > 0:
652
+                        # Split both left and right lines, preserving escaping
653
+                        # sequences correctly.
654
+                        lcur, left, llen = strsplit(left, width)
655
+                        rcur, right, rlen = strsplit(right, width)
656
+
657
+                        # Pad left line with spaces if needed
658
+                        if llen < width:
659
+                            lcur = "%s%*s" % (lcur, width - llen, '')
660
+
661
+                        yield line_fmt % {
662
+                            'left_num': lncur,
663
+                            'left': lcur,
664
+                            'right_num': rncur,
665
+                            'right': rcur
666
+                        }
667
+
668
+                        # Clean line numbers for further iterations
669
+                        lncur = ''
670
+                        rncur = ''
671
+                else:
672
+                    # Don't need to wrap long lines; instead, a trailing '>'
673
+                    # char needs to be appended.
674
+                    wrap_char = colorize('>', 'lightmagenta')
675
+                    left = strtrim(left, width, wrap_char, len(right) > 0)
676
+                    right = strtrim(right, width, wrap_char, False)
677
+
678
+                    yield line_fmt % {
679
+                        'left_num': left_num,
680
+                        'left': left,
681
+                        'right_num': right_num,
682
+                        'right': right
683
+                    }
586 684
 
587 685
     def _markup_header(self, line):
588 686
         return colorize(line, 'cyan')
@@ -642,7 +740,8 @@ def markup_to_pager(stream, opts):
642 740
     diffs = DiffParser(stream).get_diff_generator()
643 741
     marker = DiffMarker()
644 742
     color_diff = marker.markup(diffs, side_by_side=opts.side_by_side,
645
-                               width=opts.width, tab_width=opts.tab_width)
743
+                               width=opts.width, tab_width=opts.tab_width,
744
+                               wrap=opts.wrap)
646 745
 
647 746
     for line in color_diff:
648 747
         pager.stdin.write(line.encode('utf-8'))
@@ -754,6 +853,9 @@ def main():
754 853
     parser.add_option(
755 854
         '-t', '--tab-width', type='int', default=8, metavar='N',
756 855
         help="""convert tab characters to this many spcaes (default: 8)""")
856
+    parser.add_option(
857
+        '', '--wrap', action='store_true',
858
+        help='wrap long lines in side-by-side view')
757 859
 
758 860
     # Hack: use OptionGroup text for extra help message after option list
759 861
     option_group = OptionGroup(

+ 37
- 0
tests/context/out.w70.wrap 查看文件

@@ -0,0 +1,37 @@
1
+--- a/Lib/test/test_minidom.py	Fri Sep 30 08:46:25 2011 +0300
2
++++ b/Lib/test/test_minidom.py	Sat Oct 01 21:02:49 2011 +0300
3
+@@ -467,6 +467,13 @@
4
+467         dom.unlink()                                                   467         dom.unlink()
5
+468         self.confirm(domstr == str.replace("\n", "\r\n"))              468         self.confirm(domstr == str.replace("\n", "\r\n"))
6
+                                                                           469 
7
+                                                                           470     def testPrettyTextNode(self):
8
+                                                                           471         str = '<A>B</A>'
9
+                                                                           472         dom = parseString(str)
10
+                                                                           473         dom2 = parseString(dom.toprettyxml())
11
+                                                                           474         self.confirm(dom.childNodes[0].childNodes[0].toxml()==
12
+                                                                           475                      dom2.childNodes[0].childNodes[0].toxml())
13
+469                                                                        476 
14
+470     def testProcessingInstruction(self):                               477     def testProcessingInstruction(self):
15
+471         dom = parseString('<e><?mypi \t\n data \t\n ?></e>')           478         dom = parseString('<e><?mypi \t\n data \t\n ?></e>')
16
+472         pi = dom.documentElement.firstChild                            479         pi = dom.documentElement.firstChild
17
+--- a/Lib/xml/dom/minidom.py	Fri Sep 30 08:46:25 2011 +0300
18
++++ b/Lib/xml/dom/minidom.py	Sat Oct 01 21:02:49 2011 +0300
19
+@@ -836,7 +836,9 @@
20
+ 836             _write_data(writer, attrs[a_name].value)                    836             _write_data(writer, attrs[a_name].value)
21
+ 837             writer.write("\"")                                          837             writer.write("\"")
22
+ 838         if self.childNodes:                                             838         if self.childNodes:
23
+ 839             writer.write(">%s"%(newl))                                  839             writer.write(">")
24
+                                                                             840             if self.childNodes[0].nodeType != Node.TEXT_NODE:     # St
25
+                                                                                 rict check
26
+                                                                             841                 writer.write(newl)
27
+ 840             for node in self.childNodes:                                842             for node in self.childNodes:
28
+ 841                 node.writexml(writer,indent+addindent,addindent,newl)   843                 node.writexml(writer,indent+addindent,addindent,newl)
29
+ 842             writer.write("%s</%s>%s" % (indent,self.tagName,newl))      844             writer.write("%s</%s>%s" % (indent,self.tagName,newl))
30
+@@ -1061,7 +1063,7 @@
31
+1061         return newText                                                 1063         return newText
32
+1062                                                                        1064 
33
+1063     def writexml(self, writer, indent="", addindent="", newl=""):      1065     def writexml(self, writer, indent="", addindent="", newl=""):
34
+1064         _write_data(writer, "%s%s%s"%(indent, self.data, newl))        1066         _write_data(writer, self.data)
35
+1065                                                                        1067 
36
+1066     # DOM Level 3 (WD 9 April 2002)                                    1068     # DOM Level 3 (WD 9 April 2002)
37
+1067                                                                        1069 

+ 35
- 0
tests/crlf/out.w70.wrap 查看文件

@@ -0,0 +1,35 @@
1
+Index: README.md
2
+===================================================================
3
+--- README.md	(revision 41)
4
++++ README.md	(working copy)
5
+@@ -3,7 +3,6 @@
6
+  3 ## About                                                                 3 ## About
7
+  4                                                                          4 
8
+  5 Coderev is a toolkit generates static side-by-side html pages for code   5 Coderev is a toolkit generates static side-by-side html pages for code
9
+     review.                                                                    review.
10
+  6 Typical use case is to generate diff pages for local modification in s     
11
+    vn/cvs                                                                     
12
+  7 workspace and send page link to teammates for code review.               6 workspace and send page link to teammates for code review.
13
+  8                                                                          7 
14
+  9 See [joyus.org/pub/coderev-demo](http://joyus.org/pub/coderev-demo) fo   8 See [joyus.org/pub/coderev-demo](http://joyus.org/pub/coderev-demo) fo
15
+    r a demo.                                                                  r a demo.
16
+@@ -18,9 +17,10 @@
17
+ 18                                                                         17 
18
+ 19 ## Usage of coderev.sh                                                  18 ## Usage of coderev.sh
19
+ 20                                                                         19 
20
+ 21 Just type `./coderev.sh -h` to see the usage.                           20 Just type `./coderev.sh --help` to see the usage.
21
+ 22                                                                         21 
22
+ 23     Usage:                                                              22     Usage:
23
+                                                                            23 
24
+ 24         coderev.sh [-r revision] [-w width] [-o outdir] [-y] [-d name]  24         coderev.sh [-r revision] [-w width] [-o outdir] [-y] [-d name]
25
+     \                                                                          \
26
+ 25                 [-F comment-file | -m 'comment...'] [file...]           25                 [-F comment-file | -m 'comment...'] [file...]
27
+ 26                                                                         26 
28
+@@ -145,3 +145,5 @@
29
+145                             specify column number where lines are brok 145                             specify column number where lines are brok
30
+    en and                                                                     en and
31
+146                             wrapped for sdiff, default is no line wrap 146                             wrapped for sdiff, default is no line wrap
32
+    ping                                                                       ping
33
+147     -y, --yes             do not prompt for overwriting                147     -y, --yes             do not prompt for overwriting
34
+                                                                           148 
35
+                                                                           149 # EOF

+ 34
- 0
tests/diff-of-diff/out.w70.wrap 查看文件

@@ -0,0 +1,34 @@
1
+Index: patch-Alias.xs
2
+===================================================================
3
+--- patch-Alias.xs	(revision 384635)
4
++++ patch-Alias.xs	(revision 384636)
5
+@@ -140,17 +140,21 @@
6
+140          tmp = kLISTOP->op_first;                                      140          tmp = kLISTOP->op_first;
7
+141          if (inside)                                                   141          if (inside)
8
+142                  op_null(tmp);                                         142                  op_null(tmp);
9
+143 @@ -2001,6 +2035,9 @@ STATIC OP *da_ck_entersub(pTHX_ OP *o) {         143 @@ -2001,6 +2035,13 @@ STATIC OP *da_ck_entersub(pTHX_ OP *o) {
10
+144          while (kid->op_sibling != last)                               144          while (kid->op_sibling != last)
11
+145                  kid = kid->op_sibling;                                145                  kid = kid->op_sibling;
12
+146          kid->op_sibling = Nullop;                                     146          kid->op_sibling = Nullop;
13
+147 +#ifdef op_sibling_splice                                              147 +#ifdef op_sibling_splice
14
+                                                                           148 +#if (PERL_COMBI_VERSION >= 5021011)
15
+                                                                           149 +        kid->op_moresib = 0;
16
+                                                                           150 +#else
17
+148 +        kid->op_lastsib = 1;                                          151 +        kid->op_lastsib = 1;
18
+                                                                           152 +#endif
19
+149 +#endif                                                                153 +#endif
20
+150          cLISTOPx(cUNOPo->op_first)->op_last = kid;                    154          cLISTOPx(cUNOPo->op_first)->op_last = kid;
21
+151          if (kid->op_type == OP_NULL && inside)                        155          if (kid->op_type == OP_NULL && inside)
22
+152                  kid->op_flags &= ~OPf_SPECIAL;                        156                  kid->op_flags &= ~OPf_SPECIAL;
23
+153 @@ -2008,6 +2045,14 @@ STATIC OP *da_ck_entersub(pTHX_ OP *o) {        157 @@ -2008,6 +2049,14 @@ STATIC OP *da_ck_entersub(pTHX_ OP *o) {
24
+154          return o;                                                     158          return o;
25
+155  }                                                                     159  }
26
+156                                                                        160  
27
+@@ -165,7 +169,7 @@
28
+165                                                                        169  
29
+166  MODULE = Data::Alias  PACKAGE = Data::Alias                           170  MODULE = Data::Alias  PACKAGE = Data::Alias
30
+167                                                                        171  
31
+168 @@ -2025,6 +2070,10 @@ BOOT:                                           172 @@ -2025,6 +2074,10 @@ BOOT:
32
+169                  PL_check[OP_RV2CV] = da_ck_rv2cv;                     173                  PL_check[OP_RV2CV] = da_ck_rv2cv;
33
+170                  da_old_ck_entersub = PL_check[OP_ENTERSUB];           174                  da_old_ck_entersub = PL_check[OP_ENTERSUB];
34
+171                  PL_check[OP_ENTERSUB] = da_ck_entersub;               175                  PL_check[OP_ENTERSUB] = da_ck_entersub;

+ 19
- 0
tests/diff-ru-bin/out.w70.wrap 查看文件

@@ -0,0 +1,19 @@
1
+diff -ru a/README b/README
2
+--- a/README	2013-02-23 19:51:41.000000000 +0800
3
++++ b/README	2013-02-23 19:52:06.000000000 +0800
4
+@@ -1,6 +1,6 @@
5
+1 # To generate expected output, chdir to a subdir and use following com 1 # To generate expected output, cd to a subdir and use following comman
6
+  mand, then                                                               d, then
7
+2 # review with `less -R`                                                2 # review with `less -R`
8
+3 #                                                                        
9
+4 ../../cdiff.py -c always < in.diff > out.normal                        3 ../../cdiff.py -c always < in.diff > out.normal
10
+5 ../../cdiff.py -c always -s < in.diff > out.side-by-side               4 ../../cdiff.py -c always -s < in.diff > out.side-by-side
11
+6 ../../cdiff.py -c always -s < in.diff -w70 > out.w70                   5 ../../cdiff.py -c always -s < in.diff -w70 > out.w70
12
+                                                                         6 # EOF
13
+Binary files a/foo.pdf and b/foo.pdf differ
14
+diff -ru a/foo.txt b/foo.txt
15
+--- a/foo.txt	2013-02-23 19:55:03.000000000 +0800
16
++++ b/foo.txt	2013-02-23 19:55:10.000000000 +0800
17
+@@ -1,2 +1,2 @@
18
+1 Hello                                                                  1 hella
19
+2 world                                                                  2 world

+ 22
- 0
tests/diff-ru/out.w70.wrap 查看文件

@@ -0,0 +1,22 @@
1
+diff -ru a/README b/README
2
+--- a/README	2013-02-22 20:26:43.000000000 +0800
3
++++ b/README	2013-02-22 20:27:51.000000000 +0800
4
+@@ -1,6 +1,6 @@
5
+1 # To generate expected output, chdir to a subdir and use following com 1 # To generate expected output, cd to a subdir and use following comman
6
+  mand, then                                                               d, then
7
+2 # review with `less -R`                                                2 # review with `less -R`
8
+3 #                                                                        
9
+4 ../../cdiff.py -c always in.diff > out.normal                          3 ../../cdiff.py -c always in.diff > out.normal 
10
+5 ../../cdiff.py -c always -s in.diff > out.side-by-side                 4 ../../cdiff.py -c always -s in.diff > out.side-by-side
11
+6 ../../cdiff.py -c always -s in.diff -w70 > out.w70                     5 ../../cdiff.py -c always -s in.diff -w70 > out.w70
12
+                                                                         6 # EOF
13
+Only in a: a1
14
+Only in b: b1
15
+diff -ru a/common/foo.txt b/common/foo.txt
16
+--- a/common/foo.txt	2013-02-22 20:28:32.000000000 +0800
17
++++ b/common/foo.txt	2013-02-22 20:30:18.000000000 +0800
18
+@@ -1 +1 @@
19
+1 Hello                                                                  1 world
20
+Only in b: date.txt
21
+Only in a: time.txt
22
+

+ 15
- 0
tests/evil-udiff/out.w70.wrap 查看文件

@@ -0,0 +1,15 @@
1
+--- evil.orig   2013-06-01 16:36:29.676003599 -0500
2
++++ evil.new    2013-06-01 16:36:28.280056137 -0500
3
+@@ -1,12 +1,12 @@
4
+ 1 blah blah blah                                                          1 blah blah blah
5
+ 2 humbug                                                                  2 bah humbug
6
+ 3 one two three                                                           3 one two three
7
+ 4 four five six                                                           4 four five six
8
+ 5 -- vim73/src/ui.c      2013-06-01 14:48:45.012467754 -0500              5 ++ vim73/src/ui.c      2013-06-01 14:48:45.012467754 -0500
9
+ 6 @@ -1,6 +1,6 @@                                                         6 @@ -1,6 +1,6 @@
10
+ 7 blah blah blah                                                          7 blah blah blah
11
+ 8 humbug                                                                  8 humbug
12
+ 9 one two three                                                           9 one two three
13
+10 four five six                                                          10 four five six
14
+11 eight nine ten                                                         11 seven eight nine ten
15
+12 zero                                                                   12 zero

+ 27
- 0
tests/git-bin/out.w70.wrap 查看文件

@@ -0,0 +1,27 @@
1
+diff --git a/2pdf.sh b/2pdf.sh
2
+index 529d8a3..ad71911 100755
3
+--- a/2pdf.sh
4
++++ b/2pdf.sh
5
+@@ -13,3 +13,5 @@ INPUT=${1:-foo.html}
6
+13 OUTPUT=${INPUT%.html}.pdf                                              13 OUTPUT=${INPUT%.html}.pdf
7
+14                                                                        14 
8
+15 wkhtmltopdf --page-size A4 $INPUT $OUTPUT  # very very long comments e 15 wkhtmltopdf --page-size A4 $INPUT $OUTPUT  # very very long comments e
9
+   nds here                                                                  nds here
10
+                                                                          16 
11
+                                                                          17 # EOF
12
+diff --git a/example.pdf b/example.pdf
13
+index 1eacfd8..3696851 100644
14
+Binary files a/example.pdf and b/example.pdf differ
15
+diff --git a/foo.html b/foo.html
16
+index d2fd3fb..13afa6e 100644
17
+--- a/foo.html
18
++++ b/foo.html
19
+@@ -1,4 +1,4 @@
20
+1 <!doctype html>                                                        1 <!DOCTYPE html>
21
+2 <html>                                                                 2 <html>
22
+3                                                                        3 
23
+4 <head>                                                                 4 <head>
24
+diff --git a/foo.pdf b/foo.pdf
25
+index 0e90017..3c3b90d 100644
26
+Binary files a/foo.pdf and b/foo.pdf differ
27
+

+ 38
- 0
tests/git-log/out.w70.wrap 查看文件

@@ -0,0 +1,38 @@
1
+commit 65f33a326fb1d81e9b56cfa9dbe3af887ed91c8d
2
+Author: Steven Myint
3
+Date:   Fri Mar 22 14:59:34 2013 -0700
4
+
5
+    Remove unused imports
6
+
7
+diff --git a/libmodernize/fixes/__init__.py b/libmodernize/fixes/__init__.py
8
+index f8628f1..2e06052 100644
9
+--- a/libmodernize/fixes/__init__.py
10
++++ b/libmodernize/fixes/__init__.py
11
+@@ -1,7 +1,3 @@
12
+1 import sys                                                               
13
+2 from lib2to3 import refactor                                             
14
+3                                                                          
15
+4                                                                          
16
+5 lib2to3_fix_names = set([                                              1 lib2to3_fix_names = set([
17
+6     'lib2to3.fixes.fix_apply',                                         2     'lib2to3.fixes.fix_apply',
18
+7     'lib2to3.fixes.fix_except',                                        3     'lib2to3.fixes.fix_except',
19
+
20
+commit 2e80837bf815d0686138beec9a5bb94e3282204d
21
+Author: Steven Myint
22
+Date:   Fri Mar 22 14:33:55 2013 -0700
23
+
24
+    Format docstring
25
+
26
+diff --git a/libmodernize/main.py b/libmodernize/main.py
27
+index caf847d..b24db29 100644
28
+--- a/libmodernize/main.py
29
++++ b/libmodernize/main.py
30
+@@ -14,6 +14,7 @@ def main(args=None):
31
+14     """Main program.                                                   14     """Main program.
32
+15                                                                        15 
33
+16     Returns a suggested exit status (0, 1, 2).                         16     Returns a suggested exit status (0, 1, 2).
34
+                                                                          17 
35
+17     """                                                                18     """
36
+18     # Set up option parser                                             19     # Set up option parser
37
+19     parser = optparse.OptionParser(usage="modernize [options] file|dir 20     parser = optparse.OptionParser(usage="modernize [options] file|dir
38
+    ...")                                                                     ...")

+ 7
- 0
tests/git-perm/out.w70.wrap 查看文件

@@ -0,0 +1,7 @@
1
+diff --git a/cdiff b/cdiff
2
+old mode 100755
3
+new mode 100644
4
+diff --git a/cdiff.py b/cdiff.py
5
+old mode 100755
6
+new mode 100644
7
+

+ 45
- 0
tests/git/out.w70.wrap 查看文件

@@ -0,0 +1,45 @@
1
+commit 15bfa564b9db08fb277a343a3d0a01d377800606
2
+Author: Matthew Wang <XXXXXXX@gmail.com>
3
+Date:   Thu Jan 31 15:27:17 2013 +0800
4
+
5
+    Default width is now 80
6
+
7
+diff --git a/src/cdiff.py b/src/cdiff.py
8
+index 13f725f..bf15ef1 100755
9
+--- a/src/cdiff.py
10
++++ b/src/cdiff.py
11
+@@ -128,9 +128,7 @@ class Diff(object):
12
+128                     yield self._markup_common(' ' + old[1])            128                     yield self._markup_common(' ' + old[1])
13
+129                                                                        129 
14
+130     def markup_side_by_side(self, width):                              130     def markup_side_by_side(self, width):
15
+131         """width of 0 means infinite width, None means auto detect. Re 131         """Returns a generator"""
16
+    turns a                                                                    
17
+132         generator                                                          
18
+133         """                                                                
19
+134         def _normalize(line):                                          132         def _normalize(line):
20
+135             return line.replace('\t', ' ' * 8).replace('\n', '')       133             return line.replace('\t', ' ' * 8).replace('\n', '')
21
+136                                                                        134 
22
+@@ -147,7 +145,8 @@ class Diff(object):
23
+147                 return markup                                          145                 return markup
24
+148                                                                        146 
25
+149         # Setup line width and number width                            147         # Setup line width and number width
26
+150         if not width: width = 80                                       148         if width <= 0:
27
+                                                                           149             width = 80
28
+151         (start, offset) = self._hunks[-1].get_old_addr()               150         (start, offset) = self._hunks[-1].get_old_addr()
29
+152         max1 = start + offset - 1                                      151         max1 = start + offset - 1
30
+153         (start, offset) = self._hunks[-1].get_new_addr()               152         (start, offset) = self._hunks[-1].get_new_addr()
31
+@@ -430,13 +429,10 @@ if __name__ == '__main__':
32
+430     parser = optparse.OptionParser(usage)                              429     parser = optparse.OptionParser(usage)
33
+431     parser.add_option('-s', '--side-by-side', action='store_true',     430     parser.add_option('-s', '--side-by-side', action='store_true',
34
+432             help=('show in side-by-side mode'))                        431             help=('show in side-by-side mode'))
35
+433     parser.add_option('-w', '--width', type='int', default=None,       432     parser.add_option('-w', '--width', type='int', default=80,
36
+434             help='set line width (side-by-side mode only)')            433             help='set line width (side-by-side mode only), default is 
37
+                                                                               80')
38
+435     opts, args = parser.parse_args()                                   434     opts, args = parser.parse_args()
39
+436                                                                            
40
+437     if opts.width and opts.width < 0:                                      
41
+438         opts.width = 0                                                     
42
+439                                                                        435 
43
+440     if len(args) >= 1:                                                 436     if len(args) >= 1:
44
+441         diff_hdl = open(args[0], 'r')                                  437         diff_hdl = open(args[0], 'r')
45
+442     elif sys.stdin.isatty():                                           438     elif sys.stdin.isatty():

+ 51
- 0
tests/hg-log/out.w70.wrap 查看文件

@@ -0,0 +1,51 @@
1
+# HG changeset patch
2
+# User Dan Kenigsberg <danken@redhat.com>
3
+# Date 1317492169 -10800
4
+# Node ID a9a87f0e7c509ec6768379c08a0cf56f43d71b4a
5
+# Parent  b0ef6a5a6dccab0089d287bf6b9bcb8132bdbd0d
6
+xml.dom.minidom toprettyxml: omit whitespace for Text nodes
7
+
8
+http://bugs.python.org/issue4147
9
+
10
+This patch was very lightly tested, but I think it is nicer than the former one,
11
+as Text.writexml() should better know not to wrap its data with whitespace.
12
+Ever.
13
+
14
+diff -r b0ef6a5a6dcc -r a9a87f0e7c50 Lib/test/test_minidom.py
15
+--- a/Lib/test/test_minidom.py	Fri Sep 30 08:46:25 2011 +0300
16
++++ b/Lib/test/test_minidom.py	Sat Oct 01 21:02:49 2011 +0300
17
+@@ -467,6 +467,13 @@
18
+467         dom.unlink()                                                   467         dom.unlink()
19
+468         self.confirm(domstr == str.replace("\n", "\r\n"))              468         self.confirm(domstr == str.replace("\n", "\r\n"))
20
+                                                                           469 
21
+                                                                           470     def testPrettyTextNode(self):
22
+                                                                           471         str = '<A>B</A>'
23
+                                                                           472         dom = parseString(str)
24
+                                                                           473         dom2 = parseString(dom.toprettyxml())
25
+                                                                           474         self.confirm(dom.childNodes[0].childNodes[0].toxml()==
26
+                                                                           475                      dom2.childNodes[0].childNodes[0].toxml())
27
+469                                                                        476 
28
+470     def testProcessingInstruction(self):                               477     def testProcessingInstruction(self):
29
+471         dom = parseString('<e><?mypi \t\n data \t\n ?></e>')           478         dom = parseString('<e><?mypi \t\n data \t\n ?></e>')
30
+472         pi = dom.documentElement.firstChild                            479         pi = dom.documentElement.firstChild
31
+diff -r b0ef6a5a6dcc -r a9a87f0e7c50 Lib/xml/dom/minidom.py
32
+--- a/Lib/xml/dom/minidom.py	Fri Sep 30 08:46:25 2011 +0300
33
++++ b/Lib/xml/dom/minidom.py	Sat Oct 01 21:02:49 2011 +0300
34
+@@ -836,7 +836,9 @@
35
+ 836             _write_data(writer, attrs[a_name].value)                    836             _write_data(writer, attrs[a_name].value)
36
+ 837             writer.write("\"")                                          837             writer.write("\"")
37
+ 838         if self.childNodes:                                             838         if self.childNodes:
38
+ 839             writer.write(">%s"%(newl))                                  839             writer.write(">")
39
+                                                                             840             if self.childNodes[0].nodeType != Node.TEXT_NODE:
40
+                                                                             841                 writer.write(newl)
41
+ 840             for node in self.childNodes:                                842             for node in self.childNodes:
42
+ 841                 node.writexml(writer,indent+addindent,addindent,newl)   843                 node.writexml(writer,indent+addindent,addindent,newl)
43
+ 842             writer.write("%s</%s>%s" % (indent,self.tagName,newl))      844             writer.write("%s</%s>%s" % (indent,self.tagName,newl))
44
+@@ -1061,7 +1063,7 @@
45
+1061         return newText                                                 1063         return newText
46
+1062                                                                        1064 
47
+1063     def writexml(self, writer, indent="", addindent="", newl=""):      1065     def writexml(self, writer, indent="", addindent="", newl=""):
48
+1064         _write_data(writer, "%s%s%s"%(indent, self.data, newl))        1066         _write_data(writer, self.data)
49
+1065                                                                        1067 
50
+1066     # DOM Level 3 (WD 9 April 2002)                                    1068     # DOM Level 3 (WD 9 April 2002)
51
+1067                                                                        1069 

+ 9
- 0
tests/latin1/out.w70.wrap 查看文件

@@ -0,0 +1,9 @@
1
+diff --git a/test/latin1.cc b/test/latin1.cc
2
+index a556e5c..d81bb0c 100644
3
+--- a/test/latin1.cc
4
++++ b/test/latin1.cc
5
+@@ -1,4 +1,3 @@
6
+1 // é                                                                     
7
+2 int latin1()                                                           1 int latin1()
8
+3 {                                                                      2 {
9
+4         static int x;                                                  3         static int x;

+ 20
- 0
tests/strange/out.w70.wrap 查看文件

@@ -0,0 +1,20 @@
1
+commit 57263369bd810ba3a2c2dfd32a905f1e7d59cc6d
2
+Author: Matthew Wang <XXXXXXX@gmail.com>
3
+Date:   Sun Jan 6 21:56:54 2013 +0800
4
+
5
+    simplify with seperate node.py
6
+
7
+diff --git a/.gitignore b/.gitignore
8
+new file mode 100644
9
+index 0000000..0d20b64
10
+--- /dev/null
11
++++ b/.gitignore
12
+@@ -0,0 +1 @@
13
+                                                                           1 *.pyc
14
+diff --git a/README b/README
15
+index 7e70850..b5eb369 100644
16
+--- a/README
17
++++ b/README
18
+@@ -1 +1,2 @@
19
+1 Sun Feb  3 13:57:05 CST 2013                                           1 Sun Feb  3 13:57:05 CST 2013
20
+                                                                         2 Sun Feb  3 13:57:15 CST 2013

+ 50
- 0
tests/svn-log/out.w70.wrap 查看文件

@@ -0,0 +1,50 @@
1
+------------------------------------------------------------------------
2
+r1235 | ymattw | 2011-09-01 17:00:02 +0800 (Thu, 01 Sep 2011) | 3 lines
3
+
4
+Interpreter fix
5
+
6
+
7
+Index: src/share/example.sh
8
+===================================================================
9
+--- src/share/example.sh	(revision 1234)
10
++++ src/share/example.sh	(revision 1235)
11
+@@ -1,3 +1,3 @@
12
+1 #!/bin/sh                                                              1 #!/bin/bash
13
+2 #                                                                      2 #
14
+3 # Test program, also try run me as yroot (sudo ./example.sh)           3 # Test program, also try run me as yroot (sudo ./example.sh)
15
+
16
+------------------------------------------------------------------------
17
+r1234 | ymattw | 2011-09-01 16:00:02 +0800 (Thu, 01 Sep 2011) | 3 lines
18
+
19
+Implement common tool to run command as headless account
20
+
21
+
22
+Index: ChangeLog
23
+===================================================================
24
+--- ChangeLog	(revision 1233)
25
++++ ChangeLog	(revision 1234)
26
+@@ -1,3 +1,6 @@
27
+                                                                         1 Version 0.0.4
28
+                                                                         2     * Add prototype of perl module
29
+                                                                         3 
30
+1 Version 0.0.3                                                          4 Version 0.0.3
31
+2     * Implement '-d' option                                            5     * Implement '-d' option
32
+3     * Add configfile to set global debug flag                          6     * Add configfile to set global debug flag
33
+Index: src/share/example.sh
34
+===================================================================
35
+--- src/share/example.sh	(revision 0)
36
++++ src/share/example.sh	(revision 1234)
37
+@@ -0,0 +1,4 @@
38
+                                                                           1 #!/bin/sh
39
+                                                                           2 #
40
+                                                                           3 # Test program, also try run me as yroot (sudo ./example.sh)
41
+                                                                           4 #
42
+
43
+Property changes on: src/share/example.sh
44
+___________________________________________________________________
45
+Added: svn:executable
46
+## -0,0 +1 ##
47
+                                                                           1 *
48
+Added: svn:keywords
49
+## -0,0 +1 ##
50
+                                                                           1 Id

+ 11
- 0
tests/svn-merge/out.w70.wrap 查看文件

@@ -0,0 +1,11 @@
1
+Index: .
2
+==================================================================
3
+--- .   (revision 10)
4
++++ .   (working copy)
5
+
6
+Property changes on: .
7
+___________________________________________________________________
8
+Modified: svn:mergeinfo
9
+   Merged /repository/foo/branches/foo-bar:r4-9
10
+   Merged /repository/foo/trunk/foo:r2-3
11
+

+ 5
- 0
tests/svn-property/out.w70.wrap 查看文件

@@ -0,0 +1,5 @@
1
+Index: foo
2
+===================================================================
3
+Cannot display: file marked as a binary type.
4
+svn:mime-type = application/octet-stream
5
+

+ 35
- 0
tests/svn/out.w70.wrap 查看文件

@@ -0,0 +1,35 @@
1
+Index: README.md
2
+===================================================================
3
+--- README.md	(revision 41)
4
++++ README.md	(working copy)
5
+@@ -3,7 +3,6 @@
6
+  3 ## About                                                                 3 ## About
7
+  4                                                                          4 
8
+  5 Coderev is a toolkit generates static side-by-side html pages for code   5 Coderev is a toolkit generates static side-by-side html pages for code
9
+     review.                                                                    review.
10
+  6 Typical use case is to generate diff pages for local modification in s     
11
+    vn/cvs                                                                     
12
+  7 workspace and send page link to teammates for code review.               6 workspace and send page link to teammates for code review.
13
+  8                                                                          7 
14
+  9 See [joyus.org/pub/coderev-demo](http://joyus.org/pub/coderev-demo) fo   8 See [joyus.org/pub/coderev-demo](http://joyus.org/pub/coderev-demo) fo
15
+    r a demo.                                                                  r a demo.
16
+@@ -18,9 +17,10 @@
17
+ 18                                                                         17 
18
+ 19 ## Usage of coderev.sh                                                  18 ## Usage of coderev.sh
19
+ 20                                                                         19 
20
+ 21 Just type `./coderev.sh -h` to see the usage.                           20 Just type `./coderev.sh --help` to see the usage.
21
+ 22                                                                         21 
22
+ 23     Usage:                                                              22     Usage:
23
+                                                                            23 
24
+ 24         coderev.sh [-r revision] [-w width] [-o outdir] [-y] [-d name]  24         coderev.sh [-r revision] [-w width] [-o outdir] [-y] [-d name]
25
+     \                                                                          \
26
+ 25                 [-F comment-file | -m 'comment...'] [file...]           25                 [-F comment-file | -m 'comment...'] [file...]
27
+ 26                                                                         26 
28
+@@ -145,3 +145,5 @@
29
+145                             specify column number where lines are brok 145                             specify column number where lines are brok
30
+    en and                                                                     en and
31
+146                             wrapped for sdiff, default is no line wrap 146                             wrapped for sdiff, default is no line wrap
32
+    ping                                                                       ping
33
+147     -y, --yes             do not prompt for overwriting                147     -y, --yes             do not prompt for overwriting
34
+                                                                           148 
35
+                                                                           149 # EOF

+ 9
- 8
tests/test_cdiff.py 查看文件

@@ -214,7 +214,7 @@ class DiffMarkupTest(unittest.TestCase):
214 214
         diff = self._init_diff()
215 215
         marker = cdiff.DiffMarker()
216 216
 
217
-        out = list(marker._markup_side_by_side(diff, 7, 8))
217
+        out = list(marker._markup_side_by_side(diff, 7, 8, False))
218 218
         self.assertEqual(len(out), 11)
219 219
 
220 220
         sys.stdout.write('\n')
@@ -261,13 +261,13 @@ class DiffMarkupTest(unittest.TestCase):
261 261
             '\x1b[33m5\x1b[0m '
262 262
             '\x1b[31m\x1b[7m\x1b[31m      \x1b[0m\x1b[1;35m>\x1b[0m '
263 263
             '\x1b[0m\x1b[33m5\x1b[0m '
264
-            '\x1b[32m\x1b[7m\x1b[32m spaced\x1b[0m\n')
264
+            '\x1b[32m\x1b[7m\x1b[32m spaced\x1b[0m\x1b[32m\x1b[0m\n')
265 265
 
266 266
     # This test is not valid anymore
267 267
     def __test_markup_side_by_side_neg_width(self):
268 268
         diff = self._init_diff()
269 269
         marker = cdiff.DiffMarker()
270
-        out = list(marker._markup_side_by_side(diff, -1, 8))
270
+        out = list(marker._markup_side_by_side(diff, -1, 8, False))
271 271
         self.assertEqual(len(out), 11)
272 272
 
273 273
         self.assertEqual(out[0], '\x1b[36mheader\n\x1b[0m')
@@ -311,7 +311,7 @@ class DiffMarkupTest(unittest.TestCase):
311 311
     def test_markup_side_by_side_off_by_one(self):
312 312
         diff = self._init_diff()
313 313
         marker = cdiff.DiffMarker()
314
-        out = list(marker._markup_side_by_side(diff, 6, 8))
314
+        out = list(marker._markup_side_by_side(diff, 6, 8, False))
315 315
         self.assertEqual(len(out), 11)
316 316
 
317 317
         sys.stdout.write('\n')
@@ -325,10 +325,11 @@ class DiffMarkupTest(unittest.TestCase):
325 325
         self.assertEqual(out[4], '\x1b[1;34m@@ -1,5 +1,5 @@\n\x1b[0m')
326 326
         self.assertEqual(
327 327
             out[5],
328
+
328 329
             '\x1b[33m1\x1b[0m '
329 330
             '\x1b[31m\x1b[7m\x1b[31mh\x1b[0m\x1b[31mhello\x1b[0m '
330 331
             '\x1b[0m\x1b[33m1\x1b[0m '
331
-            '\x1b[32mhello\x1b[7m\x1b[32mo\x1b[0m\n')
332
+            '\x1b[32mhello\x1b[7m\x1b[32mo\x1b[0m\x1b[32m\x1b[0m\n')
332 333
         self.assertEqual(
333 334
             out[6],
334 335
             '\x1b[33m \x1b[0m        '
@@ -362,7 +363,7 @@ class DiffMarkupTest(unittest.TestCase):
362 363
     def test_markup_side_by_side_wrapped(self):
363 364
         diff = self._init_diff()
364 365
         marker = cdiff.DiffMarker()
365
-        out = list(marker._markup_side_by_side(diff, 5, 8))
366
+        out = list(marker._markup_side_by_side(diff, 5, 8, False))
366 367
         self.assertEqual(len(out), 11)
367 368
 
368 369
         sys.stdout.write('\n')
@@ -414,7 +415,7 @@ class DiffMarkupTest(unittest.TestCase):
414 415
     def test_markup_side_by_side_tabbed(self):
415 416
         diff = self._init_diff()
416 417
         marker = cdiff.DiffMarker()
417
-        out = list(marker._markup_side_by_side(diff, 8, 2))
418
+        out = list(marker._markup_side_by_side(diff, 8, 2, False))
418 419
         self.assertEqual(len(out), 11)
419 420
 
420 421
         sys.stdout.write('\n')
@@ -459,7 +460,7 @@ class DiffMarkupTest(unittest.TestCase):
459 460
         self.assertEqual(
460 461
             out[10],
461 462
             '\x1b[33m5\x1b[0m '
462
-            '\x1b[31m\x1b[7m\x1b[31m  tabbed\x1b[0m '
463
+            '\x1b[31m\x1b[7m\x1b[31m  tabbed\x1b[0m\x1b[31m\x1b[0m '
463 464
             '\x1b[0m\x1b[33m5\x1b[0m '
464 465
             '\x1b[32m\x1b[7m\x1b[32m spaced\x1b[0m\x1b[32m\x1b[0m\n')
465 466