~abentley/bzrtools/bzrtools.dev

« back to all changes in this revision

Viewing changes to hunk_selector.py

  • Committer: Michael Ellerman
  • Date: 2005-11-28 08:45:46 UTC
  • mto: (0.3.1 shelf-dev) (325.1.2 bzrtools)
  • mto: This revision was merged to the branch mainline in revision 334.
  • Revision ID: michael@ellerman.id.au-20051128084546-372d14c519162bbd
Move UserInteractor into a seperate file.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
import sys
 
1
#!/usr/bin/python
2
2
 
3
3
from userinteractor import UserInteractor, UserOption
4
 
from errors import NoColor
5
 
import copy
6
4
 
7
5
class HunkSelector:
8
 
    strings = {}
9
 
 
10
 
    def __init__(self, patches, color=None):
11
 
        if color is True or color is None:
12
 
            try:
13
 
                from colordiff import DiffWriter
14
 
                from terminal import has_ansi_colors
15
 
                if has_ansi_colors():
16
 
                    self.diff_stream = DiffWriter(sys.stdout,
17
 
                                                  check_style=False)
18
 
                else:
19
 
                    if color is True:
20
 
                        raise NoColor()
21
 
                    self.diff_stream = sys.stdout
22
 
            except ImportError:
23
 
                if color is True:
24
 
                    raise NoBzrtoolsColor()
25
 
                self.diff_stream = sys.stdout
26
 
        else:
27
 
            self.diff_stream = sys.stdout
28
 
 
 
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.',
31
9
                default=True),
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')
39
16
        ]
40
17
 
41
18
        self.end_options = [
42
 
            UserOption('y', UserInteractor.FINISH, self.strings['finish_desc'],
43
 
                default=True),
 
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')
51
27
        ]
52
28
 
53
29
        self.patches = patches
54
30
        self.total_hunks = 0
55
31
 
 
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)
60
38
 
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)
69
47
 
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)
75
51
 
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):
79
 
        self._status()
80
 
        self.interactor.set_prompt(self.strings['end_prompt'])
 
54
    def end_callback(self):
 
55
        self.status()
 
56
        self.interactor.set_prompt("Shelve these changes, or restart?")
81
57
        self.interactor.set_options(self.end_options)
82
58
        return False
83
59
 
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
90
65
 
91
66
        if hunk.selected:
 
67
            self.interactor.get_option('n').default = True
 
68
            self.interactor.get_option('y').default = False
 
69
        else:
 
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
94
 
        else:
95
 
            self.interactor.get_option('y').default = False
96
 
            self.interactor.get_option('n').default = True
97
72
 
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
101
76
        return True
102
77
 
103
78
    # The user chooses to keep a hunk
104
 
    def _unselected(self, hunk):
 
79
    def keep(self, hunk):
105
80
        hunk.selected = False
106
81
        return True
107
82
 
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
114
89
                else:
115
90
                    hunk.selected = True
116
 
        self._status()
 
91
        self.status()
117
92
        return False
118
93
 
119
94
    # The user wants to see the status
120
 
    def _status(self, hunk=None):
 
95
    def status(self, hunk=None):
121
96
        print '\nStatus:'
122
97
        for patch in self.patches:
123
98
            print '  %s' % patch.oldname
124
 
            selected = 0
125
 
            unselected = 0
 
99
            shelve = 0
 
100
            keep = 0
126
101
            for hunk in patch.hunks:
127
102
                if hunk.selected:
128
 
                    selected += 1
 
103
                    shelve += 1
129
104
                else:
130
 
                    unselected += 1
 
105
                    keep += 1
131
106
 
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
134
109
            print
135
110
 
136
111
        # Tell the interactor we're not done with this item
137
112
        return False
138
113
 
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
142
 
            return ([], [])
143
 
 
144
 
        # Go through each patch and collect all selected/unselected hunks
 
115
        if self.total_hunks == 0:
 
116
            return []
 
117
 
 
118
        if not self.interactor.interact():
 
119
            # False from interact means they quit
 
120
            return []
 
121
 
145
122
        for patch in self.patches:
146
 
            patch.selected = []
147
 
            patch.unselected = []
 
123
            tmp = []
148
124
            for hunk in patch.hunks:
149
125
                if hunk.selected:
150
 
                    patch.selected.append(hunk)
151
 
                else:
152
 
                    patch.unselected.append(hunk)
153
 
 
154
 
        # Now build two lists, one of selected patches the other unselected
155
 
        selected_patches = []
156
 
        unselected_patches = []
157
 
 
 
126
                    tmp.append(hunk)
 
127
            patch.hunks = tmp
 
128
 
 
129
        tmp = []
158
130
        for patch in self.patches:
159
 
            if len(patch.selected):
160
 
                tmp = copy.copy(patch)
161
 
                tmp.hunks = tmp.selected
162
 
                del tmp.selected
163
 
                del tmp.unselected
164
 
                selected_patches.append(tmp)
165
 
 
166
 
            if len(patch.unselected):
167
 
                tmp = copy.copy(patch)
168
 
                tmp.hunks = tmp.unselected
169
 
                del tmp.selected
170
 
                del tmp.unselected
171
 
                unselected_patches.append(tmp)
172
 
 
173
 
        return (selected_patches, unselected_patches)
174
 
 
175
 
class ShelveHunkSelector(HunkSelector):
176
 
    def __init__(self, patches, color=None):
177
 
        self.strings = {}
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)
186
 
 
187
 
class UnshelveHunkSelector(HunkSelector):
188
 
    def __init__(self, patches, color=None):
189
 
        self.strings = {}
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)
 
131
            if len(patch.hunks):
 
132
                tmp.append(patch)
 
133
        self.patches = tmp
 
134
 
 
135
        return self.patches