3
3
from userinteractor import UserInteractor, UserOption
4
from errors import NoColor
10
def __init__(self, patches, color=None):
11
if color is True or color is None:
13
from colordiff import DiffWriter
14
from terminal import has_ansi_colors
16
self.diff_stream = DiffWriter(sys.stdout,
21
self.diff_stream = sys.stdout
24
raise NoBzrtoolsColor()
25
self.diff_stream = sys.stdout
27
self.diff_stream = sys.stdout
6
def __init__(self, patches):
29
7
self.standard_options = [
30
UserOption('y', self._selected, self.strings['select_desc'],
8
UserOption('n', self.shelve, 'shelve this change for the moment.',
32
UserOption('n', self._unselected, self.strings['unselect_desc']),
10
UserOption('y', self.keep, 'keep this change in your tree.'),
33
11
UserOption('d', UserInteractor.FINISH, 'done, skip to the end.'),
34
UserOption('i', self._invert,
35
'invert the current selection status of all hunks.'),
36
UserOption('s', self._status,
37
'show selection status of all hunks.'),
12
UserOption('i', self.invert,
13
'invert the current selection of all hunks.'),
14
UserOption('s', self.status, 'show status of hunks.'),
38
15
UserOption('q', UserInteractor.QUIT, 'quit')
41
18
self.end_options = [
42
UserOption('y', UserInteractor.FINISH, self.strings['finish_desc'],
19
UserOption('y', UserInteractor.FINISH,
20
'proceed to shelve selected changes.', default=True),
44
21
UserOption('r', UserInteractor.RESTART,
45
22
'restart the hunk selection loop.'),
46
UserOption('s', self._status,
47
'show selection status of all hunks.'),
48
UserOption('i', self._invert,
49
'invert the current selection status of all hunks.'),
23
UserOption('s', self.status, 'show status of hunks.'),
24
UserOption('i', self.invert,
25
'invert the current selection of all hunks.'),
50
26
UserOption('q', UserInteractor.QUIT, 'quit')
53
29
self.patches = patches
54
30
self.total_hunks = 0
32
self.last_printed = -1
56
33
self.interactor = UserInteractor()
57
self.interactor.set_item_callback(self._hunk_callback)
58
self.interactor.set_start_callback(self._start_callback)
59
self.interactor.set_end_callback(self._end_callback)
34
self.interactor.set_prompt('Keep this change? (%(count)d of %(total)d)')
35
self.interactor.set_item_callback(self.hunk_callback)
36
self.interactor.set_start_callback(self.start_callback)
37
self.interactor.set_end_callback(self.end_callback)
61
39
for patch in patches:
62
40
for hunk in patch.hunks:
63
# everything's selected by default
41
# everything's shelved by default
64
42
hunk.selected = True
65
43
self.total_hunks += 1
66
44
# we need a back pointer in the callbacks
68
46
self.interactor.add_item(hunk)
70
48
# Called at the start of the main loop
71
def _start_callback(self):
72
self.last_printed = -1
73
self.interactor.set_prompt(self.strings['prompt'])
49
def start_callback(self):
74
50
self.interactor.set_options(self.standard_options)
76
52
# Called at the end of the item loop, return False to indicate that the
77
53
# interaction isn't finished and the confirmation prompt should be displayed
78
def _end_callback(self):
80
self.interactor.set_prompt(self.strings['end_prompt'])
54
def end_callback(self):
56
self.interactor.set_prompt("Shelve these changes, or restart?")
81
57
self.interactor.set_options(self.end_options)
84
60
# Called once for each hunk
85
def _hunk_callback(self, hunk, count):
61
def hunk_callback(self, hunk, count):
86
62
if self.last_printed != count:
87
self.diff_stream.write(str(hunk.patch.get_header()))
88
self.diff_stream.write(str(hunk))
63
print hunk.patch.get_header(), hunk
89
64
self.last_printed = count
67
self.interactor.get_option('n').default = True
68
self.interactor.get_option('y').default = False
70
self.interactor.get_option('n').default = False
92
71
self.interactor.get_option('y').default = True
93
self.interactor.get_option('n').default = False
95
self.interactor.get_option('y').default = False
96
self.interactor.get_option('n').default = True
98
# The user chooses to (un)shelve a hunk
99
def _selected(self, hunk):
73
# The user chooses to shelve a hunk
74
def shelve(self, hunk):
100
75
hunk.selected = True
103
78
# The user chooses to keep a hunk
104
def _unselected(self, hunk):
105
80
hunk.selected = False
108
83
# The user chooses to invert the selection
109
def _invert(self, hunk):
84
def invert(self, hunk):
110
85
for patch in self.patches:
111
86
for hunk in patch.hunks:
112
87
if hunk.__dict__.has_key('selected'):
113
88
hunk.selected = not hunk.selected
115
90
hunk.selected = True
119
94
# The user wants to see the status
120
def _status(self, hunk=None):
95
def status(self, hunk=None):
122
97
for patch in self.patches:
123
98
print ' %s' % patch.oldname
126
101
for hunk in patch.hunks:
127
102
if hunk.selected:
132
print ' ', self.strings['status_selected'] % selected
133
print ' ', self.strings['status_unselected'] % unselected
107
print ' %d hunks to be shelved' % shelve
108
print ' %d hunks to be kept' % keep
136
111
# Tell the interactor we're not done with this item
139
114
def select(self):
140
if self.total_hunks == 0 or not self.interactor.interact():
141
# False from interact means they chose to quit
144
# Go through each patch and collect all selected/unselected hunks
115
if self.total_hunks == 0:
118
if not self.interactor.interact():
119
# False from interact means they quit
145
122
for patch in self.patches:
147
patch.unselected = []
148
124
for hunk in patch.hunks:
149
125
if hunk.selected:
150
patch.selected.append(hunk)
152
patch.unselected.append(hunk)
154
# Now build two lists, one of selected patches the other unselected
155
selected_patches = []
156
unselected_patches = []
158
130
for patch in self.patches:
159
if len(patch.selected):
160
tmp = copy.copy(patch)
161
tmp.hunks = tmp.selected
164
selected_patches.append(tmp)
166
if len(patch.unselected):
167
tmp = copy.copy(patch)
168
tmp.hunks = tmp.unselected
171
unselected_patches.append(tmp)
173
return (selected_patches, unselected_patches)
175
class ShelveHunkSelector(HunkSelector):
176
def __init__(self, patches, color=None):
178
self.strings['status_selected'] = '%d hunks to be shelved'
179
self.strings['status_unselected'] = '%d hunks to be kept'
180
self.strings['select_desc'] = 'shelve this change.'
181
self.strings['unselect_desc'] = 'keep this change in your tree.'
182
self.strings['finish_desc'] = 'shelve selected changes.'
183
self.strings['prompt'] = 'Shelve this change? (%(count)d of %(total)d)'
184
self.strings['end_prompt'] = 'Shelve these changes?'
185
HunkSelector.__init__(self, patches, color)
187
class UnshelveHunkSelector(HunkSelector):
188
def __init__(self, patches, color=None):
190
self.strings['status_selected'] = '%d hunks to be unshelved'
191
self.strings['status_unselected'] = '%d hunks left on shelf'
192
self.strings['select_desc'] = 'unshelve this change.'
193
self.strings['unselect_desc'] = 'leave this change on the shelf.'
194
self.strings['finish_desc'] = 'unshelve selected changes.'
195
self.strings['prompt'] = 'Unshelve this change? ' \
196
'(%(count)d of %(total)d)'
197
self.strings['end_prompt'] = 'Unshelve these changes?'
198
HunkSelector.__init__(self, patches, color)