3
from userinteractor import UserInteractor, UserOption
7
def __init__(self, char, action, help, default=False):
10
self.default = default
14
Option('n', 'shelve', 'shelve this change for the moment.',
16
Option('y', 'keep', 'keep this change in your tree.'),
17
Option('d', 'done', 'done, skip to the end.'),
18
Option('i', 'invert', 'invert the current selection of all hunks.'),
19
Option('s', 'status', 'show status of hunks.'),
20
Option('q', 'quit', 'quit')
24
Option('y', 'continue', 'proceed to shelve selected changes.',
26
Option('r', 'restart', 'restart the hunk selection loop.'),
27
Option('s', 'status', 'show status of hunks.'),
28
Option('i', 'invert', 'invert the current selection of all hunks.'),
29
Option('q', 'quit', 'quit')
32
9
def __init__(self, patches):
10
self.standard_options = [
11
UserOption('y', self._selected, self.strings['select_desc'],
13
UserOption('n', self._unselected, self.strings['unselect_desc']),
14
UserOption('d', UserInteractor.FINISH, 'done, skip to the end.'),
15
UserOption('i', self._invert,
16
'invert the current selection status of all hunks.'),
17
UserOption('s', self._status,
18
'show selection status of all hunks.'),
19
UserOption('q', UserInteractor.QUIT, 'quit')
23
UserOption('y', UserInteractor.FINISH, self.strings['finish_desc'],
25
UserOption('r', UserInteractor.RESTART,
26
'restart the hunk selection loop.'),
27
UserOption('s', self._status,
28
'show selection status of all hunks.'),
29
UserOption('i', self._invert,
30
'invert the current selection status of all hunks.'),
31
UserOption('q', UserInteractor.QUIT, 'quit')
33
34
self.patches = patches
34
35
self.total_hunks = 0
37
self.interactor = UserInteractor()
38
self.interactor.set_item_callback(self._hunk_callback)
39
self.interactor.set_start_callback(self._start_callback)
40
self.interactor.set_end_callback(self._end_callback)
35
42
for patch in patches:
36
43
for hunk in patch.hunks:
37
# everything's shelved by default
44
# everything's selected by default
38
45
hunk.selected = True
39
46
self.total_hunks += 1
41
def __get_option(self, char):
42
for opt in self.standard_options:
45
raise Exception('Option "%s" not found!' % char)
47
def __select_loop(self):
49
for patch in self.patches:
52
while i < len(patch.hunks):
55
print patch.get_header(), hunk
59
prompt = 'Keep this change? (%d of %d)' \
60
% (j, self.total_hunks)
63
self.__get_option('n').default = True
64
self.__get_option('y').default = False
66
self.__get_option('n').default = False
67
self.__get_option('y').default = True
69
action = self.__ask_user(prompt, self.standard_options)
73
elif action == 'shelve':
75
elif action == 'done':
77
elif action == 'invert':
78
self.__invert_selection()
81
elif action == 'status':
84
elif action == 'quit':
91
if self.total_hunks == 0:
96
if not self.__select_loop():
101
prompt = "Shelve these changes, or restart?"
102
action = self.__ask_user(prompt, self.end_options)
104
if action == 'continue':
107
elif action == 'quit':
109
elif action == 'status':
111
elif action == 'invert':
112
self.__invert_selection()
113
elif action == 'restart':
117
for patch in self.patches:
119
for hunk in patch.hunks:
125
for patch in self.patches:
132
def __invert_selection(self):
47
# we need a back pointer in the callbacks
49
self.interactor.add_item(hunk)
51
# Called at the start of the main loop
52
def _start_callback(self):
53
self.last_printed = -1
54
self.interactor.set_prompt(self.strings['prompt'])
55
self.interactor.set_options(self.standard_options)
57
# Called at the end of the item loop, return False to indicate that the
58
# interaction isn't finished and the confirmation prompt should be displayed
59
def _end_callback(self):
61
self.interactor.set_prompt(self.strings['end_prompt'])
62
self.interactor.set_options(self.end_options)
65
# Called once for each hunk
66
def _hunk_callback(self, hunk, count):
67
if self.last_printed != count:
68
print hunk.patch.get_header(), hunk
69
self.last_printed = count
72
self.interactor.get_option('y').default = True
73
self.interactor.get_option('n').default = False
75
self.interactor.get_option('y').default = False
76
self.interactor.get_option('n').default = True
78
# The user chooses to (un)shelve a hunk
79
def _selected(self, hunk):
83
# The user chooses to keep a hunk
84
def _unselected(self, hunk):
88
# The user chooses to invert the selection
89
def _invert(self, hunk):
133
90
for patch in self.patches:
134
91
for hunk in patch.hunks:
135
92
if hunk.__dict__.has_key('selected'):
136
93
hunk.selected = not hunk.selected
138
95
hunk.selected = True
140
def __show_status(self):
99
# The user wants to see the status
100
def _status(self, hunk=None):
141
101
print '\nStatus:'
142
102
for patch in self.patches:
143
103
print ' %s' % patch.oldname
146
106
for hunk in patch.hunks:
147
107
if hunk.selected:
152
print ' %d hunks to be shelved' % shelve
153
print ' %d hunks to be kept' % keep
112
print ' ', self.strings['status_selected'] % selected
113
print ' ', self.strings['status_unselected'] % unselected
156
if sys.platform == "win32":
159
return msvcrt.getche()
164
fd = sys.stdin.fileno()
165
settings = termios.tcgetattr(fd)
168
ch = sys.stdin.read(1)
170
termios.tcsetattr(fd, termios.TCSADRAIN, settings)
173
def __ask_user(self, prompt, options):
175
sys.stdout.write(prompt)
176
sys.stdout.write(' [')
180
sys.stdout.write(opt.char)
181
sys.stdout.write('?] (%s): ' % default.char)
183
response = self.__getchar()
185
# default, which we see as newline, is 'n'
186
if response in ['\n', '\r', '\r\n']:
187
response = default.char
189
print response # because echo is off
192
if opt.char == response:
196
print ' %s - %s' % (opt.char, opt.help)
116
# Tell the interactor we're not done with this item
120
if self.total_hunks == 0 or not self.interactor.interact():
121
# False from interact means they chose to quit
124
# Go through each patch and collect all selected/unselected hunks
125
for patch in self.patches:
127
patch.unselected = []
128
for hunk in patch.hunks:
130
patch.selected.append(hunk)
132
patch.unselected.append(hunk)
134
# Now build two lists, one of selected patches the other unselected
135
selected_patches = []
136
unselected_patches = []
138
for patch in self.patches:
139
if len(patch.selected):
140
tmp = copy.copy(patch)
141
tmp.hunks = tmp.selected
144
selected_patches.append(tmp)
146
if len(patch.unselected):
147
tmp = copy.copy(patch)
148
tmp.hunks = tmp.unselected
151
unselected_patches.append(tmp)
153
return (selected_patches, unselected_patches)
155
class ShelveHunkSelector(HunkSelector):
156
def __init__(self, patches):
158
self.strings['status_selected'] = '%d hunks to be shelved'
159
self.strings['status_unselected'] = '%d hunks to be kept'
160
self.strings['select_desc'] = 'shelve this change.'
161
self.strings['unselect_desc'] = 'keep this change in your tree.'
162
self.strings['finish_desc'] = 'shelve selected changes.'
163
self.strings['prompt'] = 'Shelve this change? (%(count)d of %(total)d)'
164
self.strings['end_prompt'] = 'Shelve these changes?'
165
HunkSelector.__init__(self, patches)
167
class UnshelveHunkSelector(HunkSelector):
168
def __init__(self, patches):
170
self.strings['status_selected'] = '%d hunks to be unshelved'
171
self.strings['status_unselected'] = '%d hunks left on shelf'
172
self.strings['select_desc'] = 'unshelve this change.'
173
self.strings['unselect_desc'] = 'leave this change on the shelf.'
174
self.strings['finish_desc'] = 'unshelve selected changes.'
175
self.strings['prompt'] = 'Unshelve this change? ' \
176
'(%(count)d of %(total)d)'
177
self.strings['end_prompt'] = 'Unshelve these changes?'
178
HunkSelector.__init__(self, patches)