22 patch as patchmod, |
22 patch as patchmod, |
23 pycompat, |
23 pycompat, |
24 scmutil, |
24 scmutil, |
25 util, |
25 util, |
26 ) |
26 ) |
27 from .utils import ( |
27 from .utils import stringutil |
28 stringutil, |
28 |
29 ) |
|
30 stringio = util.stringio |
29 stringio = util.stringio |
31 |
30 |
32 # patch comments based on the git one |
31 # patch comments based on the git one |
33 diffhelptext = _("""# To remove '-' lines, make them ' ' lines (context). |
32 diffhelptext = _( |
|
33 """# To remove '-' lines, make them ' ' lines (context). |
34 # To remove '+' lines, delete them. |
34 # To remove '+' lines, delete them. |
35 # Lines starting with # will be removed from the patch. |
35 # Lines starting with # will be removed from the patch. |
36 """) |
36 """ |
37 |
37 ) |
38 hunkhelptext = _("""# |
38 |
|
39 hunkhelptext = _( |
|
40 """# |
39 # If the patch applies cleanly, the edited hunk will immediately be |
41 # If the patch applies cleanly, the edited hunk will immediately be |
40 # added to the record list. If it does not apply cleanly, a rejects file |
42 # added to the record list. If it does not apply cleanly, a rejects file |
41 # will be generated. You can use that when you try again. If all lines |
43 # will be generated. You can use that when you try again. If all lines |
42 # of the hunk are removed, then the edit is aborted and the hunk is left |
44 # of the hunk are removed, then the edit is aborted and the hunk is left |
43 # unchanged. |
45 # unchanged. |
44 """) |
46 """ |
45 |
47 ) |
46 patchhelptext = _("""# |
48 |
|
49 patchhelptext = _( |
|
50 """# |
47 # If the patch applies cleanly, the edited patch will immediately |
51 # If the patch applies cleanly, the edited patch will immediately |
48 # be finalised. If it does not apply cleanly, rejects files will be |
52 # be finalised. If it does not apply cleanly, rejects files will be |
49 # generated. You can use those when you try again. |
53 # generated. You can use those when you try again. |
50 """) |
54 """ |
|
55 ) |
51 |
56 |
52 try: |
57 try: |
53 import curses |
58 import curses |
|
59 |
54 curses.error |
60 curses.error |
55 except ImportError: |
61 except ImportError: |
56 # I have no idea if wcurses works with crecord... |
62 # I have no idea if wcurses works with crecord... |
57 try: |
63 try: |
58 import wcurses as curses |
64 import wcurses as curses |
|
65 |
59 curses.error |
66 curses.error |
60 except ImportError: |
67 except ImportError: |
61 # wcurses is not shipped on Windows by default, or python is not |
68 # wcurses is not shipped on Windows by default, or python is not |
62 # compiled with curses |
69 # compiled with curses |
63 curses = False |
70 curses = False |
64 |
71 |
|
72 |
65 class fallbackerror(error.Abort): |
73 class fallbackerror(error.Abort): |
66 """Error that indicates the client should try to fallback to text mode.""" |
74 """Error that indicates the client should try to fallback to text mode.""" |
|
75 |
67 # Inherits from error.Abort so that existing behavior is preserved if the |
76 # Inherits from error.Abort so that existing behavior is preserved if the |
68 # calling code does not know how to fallback. |
77 # calling code does not know how to fallback. |
|
78 |
69 |
79 |
70 def checkcurses(ui): |
80 def checkcurses(ui): |
71 """Return True if the user wants to use curses |
81 """Return True if the user wants to use curses |
72 |
82 |
73 This method returns True if curses is found (and that python is built with |
83 This method returns True if curses is found (and that python is built with |
74 it) and that the user has the correct flag for the ui. |
84 it) and that the user has the correct flag for the ui. |
75 """ |
85 """ |
76 return curses and ui.interface("chunkselector") == "curses" |
86 return curses and ui.interface("chunkselector") == "curses" |
|
87 |
77 |
88 |
78 class patchnode(object): |
89 class patchnode(object): |
79 """abstract class for patch graph nodes |
90 """abstract class for patch graph nodes |
80 (i.e. patchroot, header, hunk, hunkline) |
91 (i.e. patchroot, header, hunk, hunkline) |
81 """ |
92 """ |
165 # try previous sibling's last child's last child, |
176 # try previous sibling's last child's last child, |
166 # else try previous sibling's last child, else try previous sibling |
177 # else try previous sibling's last child, else try previous sibling |
167 prevsibling = self.prevsibling() |
178 prevsibling = self.prevsibling() |
168 if prevsibling is not None: |
179 if prevsibling is not None: |
169 prevsiblinglastchild = prevsibling.lastchild() |
180 prevsiblinglastchild = prevsibling.lastchild() |
170 if ((prevsiblinglastchild is not None) and |
181 if (prevsiblinglastchild is not None) and not prevsibling.folded: |
171 not prevsibling.folded): |
|
172 prevsiblinglclc = prevsiblinglastchild.lastchild() |
182 prevsiblinglclc = prevsiblinglastchild.lastchild() |
173 if ((prevsiblinglclc is not None) and |
183 if ( |
174 not prevsiblinglastchild.folded): |
184 prevsiblinglclc is not None |
|
185 ) and not prevsiblinglastchild.folded: |
175 return prevsiblinglclc |
186 return prevsiblinglclc |
176 else: |
187 else: |
177 return prevsiblinglastchild |
188 return prevsiblinglastchild |
178 else: |
189 else: |
179 return prevsibling |
190 return prevsibling |
180 |
191 |
181 # try parent (or None) |
192 # try parent (or None) |
182 return self.parentitem() |
193 return self.parentitem() |
183 |
194 |
184 class patch(patchnode, list): # todo: rename patchroot |
195 |
|
196 class patch(patchnode, list): # todo: rename patchroot |
185 """ |
197 """ |
186 list of header objects representing the patch. |
198 list of header objects representing the patch. |
187 """ |
199 """ |
|
200 |
188 def __init__(self, headerlist): |
201 def __init__(self, headerlist): |
189 self.extend(headerlist) |
202 self.extend(headerlist) |
190 # add parent patch object reference to each header |
203 # add parent patch object reference to each header |
191 for header in self: |
204 for header in self: |
192 header.patch = self |
205 header.patch = self |
|
206 |
193 |
207 |
194 class uiheader(patchnode): |
208 class uiheader(patchnode): |
195 """patch header |
209 """patch header |
196 |
210 |
197 xxx shouldn't we move this to mercurial/patch.py ? |
211 xxx shouldn't we move this to mercurial/patch.py ? |
371 "return a list of all of the direct children of this node" |
389 "return a list of all of the direct children of this node" |
372 return self.changedlines |
390 return self.changedlines |
373 |
391 |
374 def countchanges(self): |
392 def countchanges(self): |
375 """changedlines -> (n+,n-)""" |
393 """changedlines -> (n+,n-)""" |
376 add = len([l for l in self.changedlines if l.applied |
394 add = len( |
377 and l.prettystr().startswith('+')]) |
395 [ |
378 rem = len([l for l in self.changedlines if l.applied |
396 l |
379 and l.prettystr().startswith('-')]) |
397 for l in self.changedlines |
|
398 if l.applied and l.prettystr().startswith('+') |
|
399 ] |
|
400 ) |
|
401 rem = len( |
|
402 [ |
|
403 l |
|
404 for l in self.changedlines |
|
405 if l.applied and l.prettystr().startswith('-') |
|
406 ] |
|
407 ) |
380 return add, rem |
408 return add, rem |
381 |
409 |
382 def getfromtoline(self): |
410 def getfromtoline(self): |
383 # calculate the number of removed lines converted to context lines |
411 # calculate the number of removed lines converted to context lines |
384 removedconvertedtocontext = self.originalremoved - self.removed |
412 removedconvertedtocontext = self.originalremoved - self.removed |
385 |
413 |
386 contextlen = (len(self.before) + len(self.after) + |
414 contextlen = ( |
387 removedconvertedtocontext) |
415 len(self.before) + len(self.after) + removedconvertedtocontext |
|
416 ) |
388 if self.after and self.after[-1] == '\\ No newline at end of file\n': |
417 if self.after and self.after[-1] == '\\ No newline at end of file\n': |
389 contextlen -= 1 |
418 contextlen -= 1 |
390 fromlen = contextlen + self.removed |
419 fromlen = contextlen + self.removed |
391 tolen = contextlen + self.added |
420 tolen = contextlen + self.added |
392 |
421 |
475 elif text.startswith('+'): |
508 elif text.startswith('+'): |
476 dels.append(text[1:]) |
509 dels.append(text[1:]) |
477 adds.append(text[1:]) |
510 adds.append(text[1:]) |
478 hunk = ['-%s' % l for l in dels] + ['+%s' % l for l in adds] |
511 hunk = ['-%s' % l for l in dels] + ['+%s' % l for l in adds] |
479 h = self._hunk |
512 h = self._hunk |
480 return patchmod.recordhunk(h.header, h.toline, h.fromline, h.proc, |
513 return patchmod.recordhunk( |
481 h.before, hunk, h.after) |
514 h.header, h.toline, h.fromline, h.proc, h.before, hunk, h.after |
|
515 ) |
482 |
516 |
483 def __getattr__(self, name): |
517 def __getattr__(self, name): |
484 return getattr(self._hunk, name) |
518 return getattr(self._hunk, name) |
485 |
519 |
486 def __repr__(self): |
520 def __repr__(self): |
487 return r'<hunk %r@%d>' % (self.filename(), self.fromline) |
521 return r'<hunk %r@%d>' % (self.filename(), self.fromline) |
|
522 |
488 |
523 |
489 def filterpatch(ui, chunks, chunkselector, operation=None): |
524 def filterpatch(ui, chunks, chunkselector, operation=None): |
490 """interactively filter patch chunks into applied-only chunks""" |
525 """interactively filter patch chunks into applied-only chunks""" |
491 chunks = list(chunks) |
526 chunks = list(chunks) |
492 # convert chunks list into structure suitable for displaying/modifying |
527 # convert chunks list into structure suitable for displaying/modifying |
500 # let user choose headers/hunks/lines, and mark their applied flags |
535 # let user choose headers/hunks/lines, and mark their applied flags |
501 # accordingly |
536 # accordingly |
502 ret = chunkselector(ui, uiheaders, operation=operation) |
537 ret = chunkselector(ui, uiheaders, operation=operation) |
503 appliedhunklist = [] |
538 appliedhunklist = [] |
504 for hdr in uiheaders: |
539 for hdr in uiheaders: |
505 if (hdr.applied and |
540 if hdr.applied and ( |
506 (hdr.special() or len([h for h in hdr.hunks if h.applied]) > 0)): |
541 hdr.special() or len([h for h in hdr.hunks if h.applied]) > 0 |
|
542 ): |
507 appliedhunklist.append(hdr) |
543 appliedhunklist.append(hdr) |
508 fixoffset = 0 |
544 fixoffset = 0 |
509 for hnk in hdr.hunks: |
545 for hnk in hdr.hunks: |
510 if hnk.applied: |
546 if hnk.applied: |
511 appliedhunklist.append(hnk) |
547 appliedhunklist.append(hnk) |
512 # adjust the 'to'-line offset of the hunk to be correct |
548 # adjust the 'to'-line offset of the hunk to be correct |
513 # after de-activating some of the other hunks for this file |
549 # after de-activating some of the other hunks for this file |
514 if fixoffset: |
550 if fixoffset: |
515 #hnk = copy.copy(hnk) # necessary?? |
551 # hnk = copy.copy(hnk) # necessary?? |
516 hnk.toline += fixoffset |
552 hnk.toline += fixoffset |
517 else: |
553 else: |
518 fixoffset += hnk.removed - hnk.added |
554 fixoffset += hnk.removed - hnk.added |
519 |
555 |
520 return (appliedhunklist, ret) |
556 return (appliedhunklist, ret) |
|
557 |
521 |
558 |
522 def chunkselector(ui, headerlist, operation=None): |
559 def chunkselector(ui, headerlist, operation=None): |
523 """ |
560 """ |
524 curses interface to get selection of chunks, and mark the applied flags |
561 curses interface to get selection of chunks, and mark the applied flags |
525 of the chosen chunks. |
562 of the chosen chunks. |
540 finally: |
577 finally: |
541 if origsigtstp is not sentinel: |
578 if origsigtstp is not sentinel: |
542 signal.signal(signal.SIGTSTP, origsigtstp) |
579 signal.signal(signal.SIGTSTP, origsigtstp) |
543 return chunkselector.opts |
580 return chunkselector.opts |
544 |
581 |
|
582 |
545 def testdecorator(testfn, f): |
583 def testdecorator(testfn, f): |
546 def u(*args, **kwargs): |
584 def u(*args, **kwargs): |
547 return f(testfn, *args, **kwargs) |
585 return f(testfn, *args, **kwargs) |
|
586 |
548 return u |
587 return u |
|
588 |
549 |
589 |
550 def testchunkselector(testfn, ui, headerlist, operation=None): |
590 def testchunkselector(testfn, ui, headerlist, operation=None): |
551 """ |
591 """ |
552 test interface to get selection of chunks, and mark the applied flags |
592 test interface to get selection of chunks, and mark the applied flags |
553 of the chosen chunks. |
593 of the chosen chunks. |
568 while True: |
609 while True: |
569 if chunkselector.handlekeypressed(testcommands.pop(0), test=True): |
610 if chunkselector.handlekeypressed(testcommands.pop(0), test=True): |
570 break |
611 break |
571 return chunkselector.opts |
612 return chunkselector.opts |
572 |
613 |
573 _headermessages = { # {operation: text} |
614 |
|
615 _headermessages = { # {operation: text} |
574 'apply': _('Select hunks to apply'), |
616 'apply': _('Select hunks to apply'), |
575 'discard': _('Select hunks to discard'), |
617 'discard': _('Select hunks to discard'), |
576 'keep': _('Select hunks to keep'), |
618 'keep': _('Select hunks to keep'), |
577 None: _('Select hunks to record'), |
619 None: _('Select hunks to record'), |
578 } |
620 } |
|
621 |
579 |
622 |
580 class curseschunkselector(object): |
623 class curseschunkselector(object): |
581 def __init__(self, headerlist, ui, operation=None): |
624 def __init__(self, headerlist, ui, operation=None): |
582 # put the headers into a patch object |
625 # put the headers into a patch object |
583 self.headerlist = patch(headerlist) |
626 self.headerlist = patch(headerlist) |
689 most-indented level. for example, if a hunk is selected, select |
732 most-indented level. for example, if a hunk is selected, select |
690 the first hunkline of the selected hunk. or, if the last hunkline of |
733 the first hunkline of the selected hunk. or, if the last hunkline of |
691 a hunk is currently selected, then select the next hunk, if one exists, |
734 a hunk is currently selected, then select the next hunk, if one exists, |
692 or if not, the next header if one exists. |
735 or if not, the next header if one exists. |
693 """ |
736 """ |
694 #self.startprintline += 1 #debug |
737 # self.startprintline += 1 #debug |
695 currentitem = self.currentselecteditem |
738 currentitem = self.currentselecteditem |
696 |
739 |
697 nextitem = currentitem.nextitem() |
740 nextitem = currentitem.nextitem() |
698 # if there's no next item, keep the selection as-is |
741 # if there's no next item, keep the selection as-is |
699 if nextitem is None: |
742 if nextitem is None: |
870 siblingappliedstatus = [hnk.applied for hnk in item.header.hunks] |
913 siblingappliedstatus = [hnk.applied for hnk in item.header.hunks] |
871 allsiblingsapplied = not (False in siblingappliedstatus) |
914 allsiblingsapplied = not (False in siblingappliedstatus) |
872 nosiblingsapplied = not (True in siblingappliedstatus) |
915 nosiblingsapplied = not (True in siblingappliedstatus) |
873 |
916 |
874 siblingspartialstatus = [hnk.partial for hnk in item.header.hunks] |
917 siblingspartialstatus = [hnk.partial for hnk in item.header.hunks] |
875 somesiblingspartial = (True in siblingspartialstatus) |
918 somesiblingspartial = True in siblingspartialstatus |
876 |
919 |
877 #cases where applied or partial should be removed from header |
920 # cases where applied or partial should be removed from header |
878 |
921 |
879 # if no 'sibling' hunks are applied (including this hunk) |
922 # if no 'sibling' hunks are applied (including this hunk) |
880 if nosiblingsapplied: |
923 if nosiblingsapplied: |
881 if not item.header.special(): |
924 if not item.header.special(): |
882 item.header.applied = False |
925 item.header.applied = False |
883 item.header.partial = False |
926 item.header.partial = False |
884 else: # some/all parent siblings are applied |
927 else: # some/all parent siblings are applied |
885 item.header.applied = True |
928 item.header.applied = True |
886 item.header.partial = (somesiblingspartial or |
929 item.header.partial = ( |
887 not allsiblingsapplied) |
930 somesiblingspartial or not allsiblingsapplied |
|
931 ) |
888 |
932 |
889 elif isinstance(item, uihunkline): |
933 elif isinstance(item, uihunkline): |
890 siblingappliedstatus = [ln.applied for ln in item.hunk.changedlines] |
934 siblingappliedstatus = [ln.applied for ln in item.hunk.changedlines] |
891 allsiblingsapplied = not (False in siblingappliedstatus) |
935 allsiblingsapplied = not (False in siblingappliedstatus) |
892 nosiblingsapplied = not (True in siblingappliedstatus) |
936 nosiblingsapplied = not (True in siblingappliedstatus) |
896 item.hunk.applied = False |
940 item.hunk.applied = False |
897 item.hunk.partial = False |
941 item.hunk.partial = False |
898 elif allsiblingsapplied: |
942 elif allsiblingsapplied: |
899 item.hunk.applied = True |
943 item.hunk.applied = True |
900 item.hunk.partial = False |
944 item.hunk.partial = False |
901 else: # some siblings applied |
945 else: # some siblings applied |
902 item.hunk.applied = True |
946 item.hunk.applied = True |
903 item.hunk.partial = True |
947 item.hunk.partial = True |
904 |
948 |
905 parentsiblingsapplied = [hnk.applied for hnk |
949 parentsiblingsapplied = [ |
906 in item.hunk.header.hunks] |
950 hnk.applied for hnk in item.hunk.header.hunks |
|
951 ] |
907 noparentsiblingsapplied = not (True in parentsiblingsapplied) |
952 noparentsiblingsapplied = not (True in parentsiblingsapplied) |
908 allparentsiblingsapplied = not (False in parentsiblingsapplied) |
953 allparentsiblingsapplied = not (False in parentsiblingsapplied) |
909 |
954 |
910 parentsiblingspartial = [hnk.partial for hnk |
955 parentsiblingspartial = [ |
911 in item.hunk.header.hunks] |
956 hnk.partial for hnk in item.hunk.header.hunks |
912 someparentsiblingspartial = (True in parentsiblingspartial) |
957 ] |
|
958 someparentsiblingspartial = True in parentsiblingspartial |
913 |
959 |
914 # if all parent hunks are not applied, un-apply header |
960 # if all parent hunks are not applied, un-apply header |
915 if noparentsiblingsapplied: |
961 if noparentsiblingsapplied: |
916 if not item.hunk.header.special(): |
962 if not item.hunk.header.special(): |
917 item.hunk.header.applied = False |
963 item.hunk.header.applied = False |
918 item.hunk.header.partial = False |
964 item.hunk.header.partial = False |
919 # set the applied and partial status of the header if needed |
965 # set the applied and partial status of the header if needed |
920 else: # some/all parent siblings are applied |
966 else: # some/all parent siblings are applied |
921 item.hunk.header.applied = True |
967 item.hunk.header.applied = True |
922 item.hunk.header.partial = (someparentsiblingspartial or |
968 item.hunk.header.partial = ( |
923 not allparentsiblingsapplied) |
969 someparentsiblingspartial or not allparentsiblingsapplied |
|
970 ) |
924 |
971 |
925 def toggleall(self): |
972 def toggleall(self): |
926 "toggle the applied flag of all items." |
973 "toggle the applied flag of all items." |
927 if self.waslasttoggleallapplied: # then unapply them this time |
974 if self.waslasttoggleallapplied: # then unapply them this time |
928 for item in self.headerlist: |
975 for item in self.headerlist: |
929 if item.applied: |
976 if item.applied: |
930 self.toggleapply(item) |
977 self.toggleapply(item) |
931 else: |
978 else: |
932 for item in self.headerlist: |
979 for item in self.headerlist: |
983 self.currentselecteditem = item = item.parentitem() |
1032 self.currentselecteditem = item = item.parentitem() |
984 elif item.neverunfolded: |
1033 elif item.neverunfolded: |
985 item.neverunfolded = False |
1034 item.neverunfolded = False |
986 |
1035 |
987 # also fold any foldable children of the parent/current item |
1036 # also fold any foldable children of the parent/current item |
988 if isinstance(item, uiheader): # the original or 'new' item |
1037 if isinstance(item, uiheader): # the original or 'new' item |
989 for child in item.allchildren(): |
1038 for child in item.allchildren(): |
990 child.folded = not item.folded |
1039 child.folded = not item.folded |
991 |
1040 |
992 if isinstance(item, (uiheader, uihunk)): |
1041 if isinstance(item, (uiheader, uihunk)): |
993 item.folded = not item.folded |
1042 item.folded = not item.folded |
1002 y, xstart = window.getyx() |
1051 y, xstart = window.getyx() |
1003 width = self.xscreensize |
1052 width = self.xscreensize |
1004 # turn tabs into spaces |
1053 # turn tabs into spaces |
1005 instr = instr.expandtabs(4) |
1054 instr = instr.expandtabs(4) |
1006 strwidth = encoding.colwidth(instr) |
1055 strwidth = encoding.colwidth(instr) |
1007 numspaces = (width - ((strwidth + xstart) % width)) |
1056 numspaces = width - ((strwidth + xstart) % width) |
1008 return instr + " " * numspaces |
1057 return instr + " " * numspaces |
1009 |
1058 |
1010 def printstring(self, window, text, fgcolor=None, bgcolor=None, pair=None, |
1059 def printstring( |
1011 pairname=None, attrlist=None, towin=True, align=True, showwhtspc=False): |
1060 self, |
|
1061 window, |
|
1062 text, |
|
1063 fgcolor=None, |
|
1064 bgcolor=None, |
|
1065 pair=None, |
|
1066 pairname=None, |
|
1067 attrlist=None, |
|
1068 towin=True, |
|
1069 align=True, |
|
1070 showwhtspc=False, |
|
1071 ): |
1012 """ |
1072 """ |
1013 print the string, text, with the specified colors and attributes, to |
1073 print the string, text, with the specified colors and attributes, to |
1014 the specified curses window object. |
1074 the specified curses window object. |
1015 |
1075 |
1016 the foreground and background colors are of the form |
1076 the foreground and background colors are of the form |
1028 if showwhtspc == True, trailing whitespace of a string is highlighted. |
1088 if showwhtspc == True, trailing whitespace of a string is highlighted. |
1029 """ |
1089 """ |
1030 # preprocess the text, converting tabs to spaces |
1090 # preprocess the text, converting tabs to spaces |
1031 text = text.expandtabs(4) |
1091 text = text.expandtabs(4) |
1032 # strip \n, and convert control characters to ^[char] representation |
1092 # strip \n, and convert control characters to ^[char] representation |
1033 text = re.sub(br'[\x00-\x08\x0a-\x1f]', |
1093 text = re.sub( |
1034 lambda m:'^' + chr(ord(m.group()) + 64), text.strip('\n')) |
1094 br'[\x00-\x08\x0a-\x1f]', |
|
1095 lambda m: '^' + chr(ord(m.group()) + 64), |
|
1096 text.strip('\n'), |
|
1097 ) |
1035 |
1098 |
1036 if pair is not None: |
1099 if pair is not None: |
1037 colorpair = pair |
1100 colorpair = pair |
1038 elif pairname is not None: |
1101 elif pairname is not None: |
1039 colorpair = self.colorpairnames[pairname] |
1102 colorpair = self.colorpairnames[pairname] |
1058 for textattr in (curses.A_UNDERLINE, curses.A_BOLD): |
1121 for textattr in (curses.A_UNDERLINE, curses.A_BOLD): |
1059 if textattr in attrlist: |
1122 if textattr in attrlist: |
1060 colorpair |= textattr |
1123 colorpair |= textattr |
1061 |
1124 |
1062 y, xstart = self.chunkpad.getyx() |
1125 y, xstart = self.chunkpad.getyx() |
1063 t = "" # variable for counting lines printed |
1126 t = "" # variable for counting lines printed |
1064 # if requested, show trailing whitespace |
1127 # if requested, show trailing whitespace |
1065 if showwhtspc: |
1128 if showwhtspc: |
1066 origlen = len(text) |
1129 origlen = len(text) |
1067 text = text.rstrip(' \n') # tabs have already been expanded |
1130 text = text.rstrip(' \n') # tabs have already been expanded |
1068 strippedlen = len(text) |
1131 strippedlen = len(text) |
1069 numtrailingspaces = origlen - strippedlen |
1132 numtrailingspaces = origlen - strippedlen |
1070 |
1133 |
1071 if towin: |
1134 if towin: |
1072 window.addstr(text, colorpair) |
1135 window.addstr(text, colorpair) |
1073 t += text |
1136 t += text |
1074 |
1137 |
1075 if showwhtspc: |
1138 if showwhtspc: |
1076 wscolorpair = colorpair | curses.A_REVERSE |
1139 wscolorpair = colorpair | curses.A_REVERSE |
1077 if towin: |
1140 if towin: |
1078 for i in range(numtrailingspaces): |
1141 for i in range(numtrailingspaces): |
1079 window.addch(curses.ACS_CKBOARD, wscolorpair) |
1142 window.addch(curses.ACS_CKBOARD, wscolorpair) |
1080 t += " " * numtrailingspaces |
1143 t += " " * numtrailingspaces |
1081 |
1144 |
1082 if align: |
1145 if align: |
1083 if towin: |
1146 if towin: |
1084 extrawhitespace = self.alignstring("", window) |
1147 extrawhitespace = self.alignstring("", window) |
1085 window.addstr(extrawhitespace, colorpair) |
1148 window.addstr(extrawhitespace, colorpair) |
1100 spaceselect = _('space/enter: select') |
1163 spaceselect = _('space/enter: select') |
1101 spacedeselect = _('space/enter: deselect') |
1164 spacedeselect = _('space/enter: deselect') |
1102 # Format the selected label into a place as long as the longer of the |
1165 # Format the selected label into a place as long as the longer of the |
1103 # two possible labels. This may vary by language. |
1166 # two possible labels. This may vary by language. |
1104 spacelen = max(len(spaceselect), len(spacedeselect)) |
1167 spacelen = max(len(spaceselect), len(spacedeselect)) |
1105 selectedlabel = '%-*s' % (spacelen, |
1168 selectedlabel = '%-*s' % ( |
1106 spacedeselect if selected else spaceselect) |
1169 spacelen, |
|
1170 spacedeselect if selected else spaceselect, |
|
1171 ) |
1107 segments = [ |
1172 segments = [ |
1108 _headermessages[self.operation], |
1173 _headermessages[self.operation], |
1109 '-', |
1174 '-', |
1110 _('[x]=selected **=collapsed'), |
1175 _('[x]=selected **=collapsed'), |
1111 _('c: confirm'), |
1176 _('c: confirm'), |
1211 text = header.prettystr() |
1281 text = header.prettystr() |
1212 chunkindex = self.chunklist.index(header) |
1282 chunkindex = self.chunklist.index(header) |
1213 |
1283 |
1214 if chunkindex != 0 and not header.folded: |
1284 if chunkindex != 0 and not header.folded: |
1215 # add separating line before headers |
1285 # add separating line before headers |
1216 outstr += self.printstring(self.chunkpad, '_' * self.xscreensize, |
1286 outstr += self.printstring( |
1217 towin=towin, align=False) |
1287 self.chunkpad, '_' * self.xscreensize, towin=towin, align=False |
|
1288 ) |
1218 # select color-pair based on if the header is selected |
1289 # select color-pair based on if the header is selected |
1219 colorpair = self.getcolorpair(name=selected and "selected" or "normal", |
1290 colorpair = self.getcolorpair( |
1220 attrlist=[curses.A_BOLD]) |
1291 name=selected and "selected" or "normal", attrlist=[curses.A_BOLD] |
|
1292 ) |
1221 |
1293 |
1222 # print out each line of the chunk, expanding it to screen width |
1294 # print out each line of the chunk, expanding it to screen width |
1223 |
1295 |
1224 # number of characters to indent lines on this level by |
1296 # number of characters to indent lines on this level by |
1225 indentnumchars = 0 |
1297 indentnumchars = 0 |
1227 if not header.folded or ignorefolding: |
1299 if not header.folded or ignorefolding: |
1228 textlist = text.split("\n") |
1300 textlist = text.split("\n") |
1229 linestr = checkbox + textlist[0] |
1301 linestr = checkbox + textlist[0] |
1230 else: |
1302 else: |
1231 linestr = checkbox + header.filename() |
1303 linestr = checkbox + header.filename() |
1232 outstr += self.printstring(self.chunkpad, linestr, pair=colorpair, |
1304 outstr += self.printstring( |
1233 towin=towin) |
1305 self.chunkpad, linestr, pair=colorpair, towin=towin |
|
1306 ) |
1234 if not header.folded or ignorefolding: |
1307 if not header.folded or ignorefolding: |
1235 if len(textlist) > 1: |
1308 if len(textlist) > 1: |
1236 for line in textlist[1:]: |
1309 for line in textlist[1:]: |
1237 linestr = " "*(indentnumchars + len(checkbox)) + line |
1310 linestr = " " * (indentnumchars + len(checkbox)) + line |
1238 outstr += self.printstring(self.chunkpad, linestr, |
1311 outstr += self.printstring( |
1239 pair=colorpair, towin=towin) |
1312 self.chunkpad, linestr, pair=colorpair, towin=towin |
|
1313 ) |
1240 |
1314 |
1241 return outstr |
1315 return outstr |
1242 |
1316 |
1243 def printhunklinesbefore(self, hunk, selected=False, towin=True, |
1317 def printhunklinesbefore( |
1244 ignorefolding=False): |
1318 self, hunk, selected=False, towin=True, ignorefolding=False |
|
1319 ): |
1245 "includes start/end line indicator" |
1320 "includes start/end line indicator" |
1246 outstr = "" |
1321 outstr = "" |
1247 # where hunk is in list of siblings |
1322 # where hunk is in list of siblings |
1248 hunkindex = hunk.header.hunks.index(hunk) |
1323 hunkindex = hunk.header.hunks.index(hunk) |
1249 |
1324 |
1250 if hunkindex != 0: |
1325 if hunkindex != 0: |
1251 # add separating line before headers |
1326 # add separating line before headers |
1252 outstr += self.printstring(self.chunkpad, ' '*self.xscreensize, |
1327 outstr += self.printstring( |
1253 towin=towin, align=False) |
1328 self.chunkpad, ' ' * self.xscreensize, towin=towin, align=False |
1254 |
1329 ) |
1255 colorpair = self.getcolorpair(name=selected and "selected" or "normal", |
1330 |
1256 attrlist=[curses.A_BOLD]) |
1331 colorpair = self.getcolorpair( |
|
1332 name=selected and "selected" or "normal", attrlist=[curses.A_BOLD] |
|
1333 ) |
1257 |
1334 |
1258 # print out from-to line with checkbox |
1335 # print out from-to line with checkbox |
1259 checkbox = self.getstatusprefixstring(hunk) |
1336 checkbox = self.getstatusprefixstring(hunk) |
1260 |
1337 |
1261 lineprefix = " "*self.hunkindentnumchars + checkbox |
1338 lineprefix = " " * self.hunkindentnumchars + checkbox |
1262 frtoline = " " + hunk.getfromtoline().strip("\n") |
1339 frtoline = " " + hunk.getfromtoline().strip("\n") |
1263 |
1340 |
1264 outstr += self.printstring(self.chunkpad, lineprefix, towin=towin, |
1341 outstr += self.printstring( |
1265 align=False) # add uncolored checkbox/indent |
1342 self.chunkpad, lineprefix, towin=towin, align=False |
1266 outstr += self.printstring(self.chunkpad, frtoline, pair=colorpair, |
1343 ) # add uncolored checkbox/indent |
1267 towin=towin) |
1344 outstr += self.printstring( |
|
1345 self.chunkpad, frtoline, pair=colorpair, towin=towin |
|
1346 ) |
1268 |
1347 |
1269 if hunk.folded and not ignorefolding: |
1348 if hunk.folded and not ignorefolding: |
1270 # skip remainder of output |
1349 # skip remainder of output |
1271 return outstr |
1350 return outstr |
1272 |
1351 |
1273 # print out lines of the chunk preceeding changed-lines |
1352 # print out lines of the chunk preceeding changed-lines |
1274 for line in hunk.before: |
1353 for line in hunk.before: |
1275 linestr = " "*(self.hunklineindentnumchars + len(checkbox)) + line |
1354 linestr = " " * (self.hunklineindentnumchars + len(checkbox)) + line |
1276 outstr += self.printstring(self.chunkpad, linestr, towin=towin) |
1355 outstr += self.printstring(self.chunkpad, linestr, towin=towin) |
1277 |
1356 |
1278 return outstr |
1357 return outstr |
1279 |
1358 |
1280 def printhunklinesafter(self, hunk, towin=True, ignorefolding=False): |
1359 def printhunklinesafter(self, hunk, towin=True, ignorefolding=False): |
1304 elif linestr.startswith("-"): |
1383 elif linestr.startswith("-"): |
1305 colorpair = self.getcolorpair(name="deletion") |
1384 colorpair = self.getcolorpair(name="deletion") |
1306 elif linestr.startswith("\\"): |
1385 elif linestr.startswith("\\"): |
1307 colorpair = self.getcolorpair(name="normal") |
1386 colorpair = self.getcolorpair(name="normal") |
1308 |
1387 |
1309 lineprefix = " "*self.hunklineindentnumchars + checkbox |
1388 lineprefix = " " * self.hunklineindentnumchars + checkbox |
1310 outstr += self.printstring(self.chunkpad, lineprefix, towin=towin, |
1389 outstr += self.printstring( |
1311 align=False) # add uncolored checkbox/indent |
1390 self.chunkpad, lineprefix, towin=towin, align=False |
1312 outstr += self.printstring(self.chunkpad, linestr, pair=colorpair, |
1391 ) # add uncolored checkbox/indent |
1313 towin=towin, showwhtspc=True) |
1392 outstr += self.printstring( |
|
1393 self.chunkpad, linestr, pair=colorpair, towin=towin, showwhtspc=True |
|
1394 ) |
1314 return outstr |
1395 return outstr |
1315 |
1396 |
1316 def printitem(self, item=None, ignorefolding=False, recursechildren=True, |
1397 def printitem( |
1317 towin=True): |
1398 self, item=None, ignorefolding=False, recursechildren=True, towin=True |
|
1399 ): |
1318 """ |
1400 """ |
1319 use __printitem() to print the the specified item.applied. |
1401 use __printitem() to print the the specified item.applied. |
1320 if item is not specified, then print the entire patch. |
1402 if item is not specified, then print the entire patch. |
1321 (hiding folded elements, etc. -- see __printitem() docstring) |
1403 (hiding folded elements, etc. -- see __printitem() docstring) |
1322 """ |
1404 """ |
1325 item = self.headerlist |
1407 item = self.headerlist |
1326 if recursechildren: |
1408 if recursechildren: |
1327 self.linesprintedtopadsofar = 0 |
1409 self.linesprintedtopadsofar = 0 |
1328 |
1410 |
1329 outstr = [] |
1411 outstr = [] |
1330 self.__printitem(item, ignorefolding, recursechildren, outstr, |
1412 self.__printitem( |
1331 towin=towin) |
1413 item, ignorefolding, recursechildren, outstr, towin=towin |
|
1414 ) |
1332 return ''.join(outstr) |
1415 return ''.join(outstr) |
1333 |
1416 |
1334 def outofdisplayedarea(self): |
1417 def outofdisplayedarea(self): |
1335 y, _ = self.chunkpad.getyx() # cursor location |
1418 y, _ = self.chunkpad.getyx() # cursor location |
1336 # * 2 here works but an optimization would be the max number of |
1419 # * 2 here works but an optimization would be the max number of |
1337 # consecutive non selectable lines |
1420 # consecutive non selectable lines |
1338 # i.e the max number of context line for any hunk in the patch |
1421 # i.e the max number of context line for any hunk in the patch |
1339 miny = min(0, self.firstlineofpadtoprint - self.yscreensize) |
1422 miny = min(0, self.firstlineofpadtoprint - self.yscreensize) |
1340 maxy = self.firstlineofpadtoprint + self.yscreensize * 2 |
1423 maxy = self.firstlineofpadtoprint + self.yscreensize * 2 |
1341 return y < miny or y > maxy |
1424 return y < miny or y > maxy |
1342 |
1425 |
1343 def handleselection(self, item, recursechildren): |
1426 def handleselection(self, item, recursechildren): |
1344 selected = (item is self.currentselecteditem) |
1427 selected = item is self.currentselecteditem |
1345 if selected and recursechildren: |
1428 if selected and recursechildren: |
1346 # assumes line numbering starting from line 0 |
1429 # assumes line numbering starting from line 0 |
1347 self.selecteditemstartline = self.linesprintedtopadsofar |
1430 self.selecteditemstartline = self.linesprintedtopadsofar |
1348 selecteditemlines = self.getnumlinesdisplayed(item, |
1431 selecteditemlines = self.getnumlinesdisplayed( |
1349 recursechildren=False) |
1432 item, recursechildren=False |
1350 self.selecteditemendline = (self.selecteditemstartline + |
1433 ) |
1351 selecteditemlines - 1) |
1434 self.selecteditemendline = ( |
|
1435 self.selecteditemstartline + selecteditemlines - 1 |
|
1436 ) |
1352 return selected |
1437 return selected |
1353 |
1438 |
1354 def __printitem(self, item, ignorefolding, recursechildren, outstr, |
1439 def __printitem( |
1355 towin=True): |
1440 self, item, ignorefolding, recursechildren, outstr, towin=True |
|
1441 ): |
1356 """ |
1442 """ |
1357 recursive method for printing out patch/header/hunk/hunk-line data to |
1443 recursive method for printing out patch/header/hunk/hunk-line data to |
1358 screen. also returns a string with all of the content of the displayed |
1444 screen. also returns a string with all of the content of the displayed |
1359 patch (not including coloring, etc.). |
1445 patch (not including coloring, etc.). |
1360 |
1446 |
1371 |
1457 |
1372 # patch object is a list of headers |
1458 # patch object is a list of headers |
1373 if isinstance(item, patch): |
1459 if isinstance(item, patch): |
1374 if recursechildren: |
1460 if recursechildren: |
1375 for hdr in item: |
1461 for hdr in item: |
1376 self.__printitem(hdr, ignorefolding, |
1462 self.__printitem( |
1377 recursechildren, outstr, towin) |
1463 hdr, ignorefolding, recursechildren, outstr, towin |
|
1464 ) |
1378 # todo: eliminate all isinstance() calls |
1465 # todo: eliminate all isinstance() calls |
1379 if isinstance(item, uiheader): |
1466 if isinstance(item, uiheader): |
1380 outstr.append(self.printheader(item, selected, towin=towin, |
1467 outstr.append( |
1381 ignorefolding=ignorefolding)) |
1468 self.printheader( |
|
1469 item, selected, towin=towin, ignorefolding=ignorefolding |
|
1470 ) |
|
1471 ) |
1382 if recursechildren: |
1472 if recursechildren: |
1383 for hnk in item.hunks: |
1473 for hnk in item.hunks: |
1384 self.__printitem(hnk, ignorefolding, |
1474 self.__printitem( |
1385 recursechildren, outstr, towin) |
1475 hnk, ignorefolding, recursechildren, outstr, towin |
1386 elif (isinstance(item, uihunk) and |
1476 ) |
1387 ((not item.header.folded) or ignorefolding)): |
1477 elif isinstance(item, uihunk) and ( |
|
1478 (not item.header.folded) or ignorefolding |
|
1479 ): |
1388 # print the hunk data which comes before the changed-lines |
1480 # print the hunk data which comes before the changed-lines |
1389 outstr.append(self.printhunklinesbefore(item, selected, towin=towin, |
1481 outstr.append( |
1390 ignorefolding=ignorefolding)) |
1482 self.printhunklinesbefore( |
|
1483 item, selected, towin=towin, ignorefolding=ignorefolding |
|
1484 ) |
|
1485 ) |
1391 if recursechildren: |
1486 if recursechildren: |
1392 for l in item.changedlines: |
1487 for l in item.changedlines: |
1393 self.__printitem(l, ignorefolding, |
1488 self.__printitem( |
1394 recursechildren, outstr, towin) |
1489 l, ignorefolding, recursechildren, outstr, towin |
1395 outstr.append(self.printhunklinesafter(item, towin=towin, |
1490 ) |
1396 ignorefolding=ignorefolding)) |
1491 outstr.append( |
1397 elif (isinstance(item, uihunkline) and |
1492 self.printhunklinesafter( |
1398 ((not item.hunk.folded) or ignorefolding)): |
1493 item, towin=towin, ignorefolding=ignorefolding |
1399 outstr.append(self.printhunkchangedline(item, selected, |
1494 ) |
1400 towin=towin)) |
1495 ) |
|
1496 elif isinstance(item, uihunkline) and ( |
|
1497 (not item.hunk.folded) or ignorefolding |
|
1498 ): |
|
1499 outstr.append( |
|
1500 self.printhunkchangedline(item, selected, towin=towin) |
|
1501 ) |
1401 |
1502 |
1402 return outstr |
1503 return outstr |
1403 |
1504 |
1404 def getnumlinesdisplayed(self, item=None, ignorefolding=False, |
1505 def getnumlinesdisplayed( |
1405 recursechildren=True): |
1506 self, item=None, ignorefolding=False, recursechildren=True |
|
1507 ): |
1406 """ |
1508 """ |
1407 return the number of lines which would be displayed if the item were |
1509 return the number of lines which would be displayed if the item were |
1408 to be printed to the display. the item will not be printed to the |
1510 to be printed to the display. the item will not be printed to the |
1409 display (pad). |
1511 display (pad). |
1410 if no item is given, assume the entire patch. |
1512 if no item is given, assume the entire patch. |
1411 if ignorefolding is True, folded items will be unfolded when counting |
1513 if ignorefolding is True, folded items will be unfolded when counting |
1412 the number of lines. |
1514 the number of lines. |
1413 """ |
1515 """ |
1414 |
1516 |
1415 # temporarily disable printing to windows by printstring |
1517 # temporarily disable printing to windows by printstring |
1416 patchdisplaystring = self.printitem(item, ignorefolding, |
1518 patchdisplaystring = self.printitem( |
1417 recursechildren, towin=False) |
1519 item, ignorefolding, recursechildren, towin=False |
|
1520 ) |
1418 numlines = len(patchdisplaystring) // self.xscreensize |
1521 numlines = len(patchdisplaystring) // self.xscreensize |
1419 return numlines |
1522 return numlines |
1420 |
1523 |
1421 def sigwinchhandler(self, n, frame): |
1524 def sigwinchhandler(self, n, frame): |
1422 "handle window resizing" |
1525 "handle window resizing" |
1427 self.numpadlines = self.getnumlinesdisplayed(ignorefolding=True) + 1 |
1530 self.numpadlines = self.getnumlinesdisplayed(ignorefolding=True) + 1 |
1428 self.chunkpad = curses.newpad(self.numpadlines, self.xscreensize) |
1531 self.chunkpad = curses.newpad(self.numpadlines, self.xscreensize) |
1429 except curses.error: |
1532 except curses.error: |
1430 pass |
1533 pass |
1431 |
1534 |
1432 def getcolorpair(self, fgcolor=None, bgcolor=None, name=None, |
1535 def getcolorpair( |
1433 attrlist=None): |
1536 self, fgcolor=None, bgcolor=None, name=None, attrlist=None |
|
1537 ): |
1434 """ |
1538 """ |
1435 get a curses color pair, adding it to self.colorpairs if it is not |
1539 get a curses color pair, adding it to self.colorpairs if it is not |
1436 already defined. an optional string, name, can be passed as a shortcut |
1540 already defined. an optional string, name, can be passed as a shortcut |
1437 for referring to the color-pair. by default, if no arguments are |
1541 for referring to the color-pair. by default, if no arguments are |
1438 specified, the white foreground / black background color-pair is |
1542 specified, the white foreground / black background color-pair is |
1519 e : edit the currently selected hunk |
1624 e : edit the currently selected hunk |
1520 a : toggle amend mode, only with commit -i |
1625 a : toggle amend mode, only with commit -i |
1521 c : confirm selected changes |
1626 c : confirm selected changes |
1522 r : review/edit and confirm selected changes |
1627 r : review/edit and confirm selected changes |
1523 q : quit without confirming (no changes will be made) |
1628 q : quit without confirming (no changes will be made) |
1524 ? : help (what you're currently reading)""") |
1629 ? : help (what you're currently reading)""" |
|
1630 ) |
1525 |
1631 |
1526 helpwin = curses.newwin(self.yscreensize, 0, 0, 0) |
1632 helpwin = curses.newwin(self.yscreensize, 0, 0, 0) |
1527 helplines = helptext.split("\n") |
1633 helplines = helptext.split("\n") |
1528 helplines = helplines + [" "]*( |
1634 helplines = helplines + [" "] * ( |
1529 self.yscreensize - self.numstatuslines - len(helplines) - 1) |
1635 self.yscreensize - self.numstatuslines - len(helplines) - 1 |
|
1636 ) |
1530 try: |
1637 try: |
1531 for line in helplines: |
1638 for line in helplines: |
1532 self.printstring(helpwin, line, pairname="legend") |
1639 self.printstring(helpwin, line, pairname="legend") |
1533 except curses.error: |
1640 except curses.error: |
1534 pass |
1641 pass |
1611 |
1718 |
1612 def reviewcommit(self): |
1719 def reviewcommit(self): |
1613 """ask for 'y' to be pressed to confirm selected. return True if |
1720 """ask for 'y' to be pressed to confirm selected. return True if |
1614 confirmed.""" |
1721 confirmed.""" |
1615 confirmtext = _( |
1722 confirmtext = _( |
1616 """If you answer yes to the following, your currently chosen patch chunks |
1723 """If you answer yes to the following, your currently chosen patch chunks |
1617 will be loaded into an editor. To modify the patch, make the changes in your |
1724 will be loaded into an editor. To modify the patch, make the changes in your |
1618 editor and save. To accept the current patch as-is, close the editor without |
1725 editor and save. To accept the current patch as-is, close the editor without |
1619 saving. |
1726 saving. |
1620 |
1727 |
1621 note: don't add/remove lines unless you also modify the range information. |
1728 note: don't add/remove lines unless you also modify the range information. |
1622 failing to follow this rule will result in the commit aborting. |
1729 failing to follow this rule will result in the commit aborting. |
1623 |
1730 |
1624 are you sure you want to review/edit and confirm the selected changes [yn]? |
1731 are you sure you want to review/edit and confirm the selected changes [yn]? |
1625 """) |
1732 """ |
|
1733 ) |
1626 with self.ui.timeblockedsection('crecord'): |
1734 with self.ui.timeblockedsection('crecord'): |
1627 response = self.confirmationwindow(confirmtext) |
1735 response = self.confirmationwindow(confirmtext) |
1628 if response is None: |
1736 if response is None: |
1629 response = "n" |
1737 response = "n" |
1630 if response.lower().startswith("y"): |
1738 if response.lower().startswith("y"): |
1640 new changeset will be created (the normal commit behavior). |
1748 new changeset will be created (the normal commit behavior). |
1641 """ |
1749 """ |
1642 |
1750 |
1643 if opts.get('amend') is None: |
1751 if opts.get('amend') is None: |
1644 opts['amend'] = True |
1752 opts['amend'] = True |
1645 msg = _("Amend option is turned on -- committing the currently " |
1753 msg = _( |
1646 "selected changes will not create a new changeset, but " |
1754 "Amend option is turned on -- committing the currently " |
1647 "instead update the most recently committed changeset.\n\n" |
1755 "selected changes will not create a new changeset, but " |
1648 "Press any key to continue.") |
1756 "instead update the most recently committed changeset.\n\n" |
|
1757 "Press any key to continue." |
|
1758 ) |
1649 elif opts.get('amend') is True: |
1759 elif opts.get('amend') is True: |
1650 opts['amend'] = None |
1760 opts['amend'] = None |
1651 msg = _("Amend option is turned off -- committing the currently " |
1761 msg = _( |
1652 "selected changes will create a new changeset.\n\n" |
1762 "Amend option is turned off -- committing the currently " |
1653 "Press any key to continue.") |
1763 "selected changes will create a new changeset.\n\n" |
|
1764 "Press any key to continue." |
|
1765 ) |
1654 if not test: |
1766 if not test: |
1655 self.confirmationwindow(msg) |
1767 self.confirmationwindow(msg) |
1656 |
1768 |
1657 def recenterdisplayedarea(self): |
1769 def recenterdisplayedarea(self): |
1658 """ |
1770 """ |
1865 pass |
1980 pass |
1866 |
1981 |
1867 # available colors: black, blue, cyan, green, magenta, white, yellow |
1982 # available colors: black, blue, cyan, green, magenta, white, yellow |
1868 # init_pair(color_id, foreground_color, background_color) |
1983 # init_pair(color_id, foreground_color, background_color) |
1869 self.initcolorpair(None, None, name="normal") |
1984 self.initcolorpair(None, None, name="normal") |
1870 self.initcolorpair(curses.COLOR_WHITE, curses.COLOR_MAGENTA, |
1985 self.initcolorpair( |
1871 name="selected") |
1986 curses.COLOR_WHITE, curses.COLOR_MAGENTA, name="selected" |
|
1987 ) |
1872 self.initcolorpair(curses.COLOR_RED, None, name="deletion") |
1988 self.initcolorpair(curses.COLOR_RED, None, name="deletion") |
1873 self.initcolorpair(curses.COLOR_GREEN, None, name="addition") |
1989 self.initcolorpair(curses.COLOR_GREEN, None, name="addition") |
1874 self.initcolorpair(curses.COLOR_WHITE, curses.COLOR_BLUE, name="legend") |
1990 self.initcolorpair(curses.COLOR_WHITE, curses.COLOR_BLUE, name="legend") |
1875 # newwin([height, width,] begin_y, begin_x) |
1991 # newwin([height, width,] begin_y, begin_x) |
1876 self.statuswin = curses.newwin(self.numstatuslines, 0, 0, 0) |
1992 self.statuswin = curses.newwin(self.numstatuslines, 0, 0, 0) |
1877 self.statuswin.keypad(1) # interpret arrow-key, etc. esc sequences |
1993 self.statuswin.keypad(1) # interpret arrow-key, etc. esc sequences |
1878 |
1994 |
1879 # figure out how much space to allocate for the chunk-pad which is |
1995 # figure out how much space to allocate for the chunk-pad which is |
1880 # used for displaying the patch |
1996 # used for displaying the patch |
1881 |
1997 |
1882 # stupid hack to prevent getnumlinesdisplayed from failing |
1998 # stupid hack to prevent getnumlinesdisplayed from failing |