~abentley/bzrtools/bzrtools.dev

0.1.48 by Michael Ellerman
Move UserInteractor into a seperate file.
1
#!/usr/bin/python
2
3
import sys
4
5
class UserOption:
6
    def __init__(self, char, action, help, default=False):
7
        self.char = char
8
        self.action = action
9
        self.default = default
10
        self.help = help
11
12
class UserInteractor(object):
13
    # Special actions
14
    RESTART = 0
15
    QUIT = 1
16
    FINISH = 2
17
18
    def __init__(self):
19
        self.items = []
20
21
    def add_item(self, item):
22
        self.items.append(item)
23
        self.__total_items = len(self.items)
24
25
    def set_items(self, item_list):
26
        self.items = item_list
27
        self.__total_items = len(self.items)
28
29
    def set_item_callback(self, cb):
30
        self.item_callback = cb
31
32
    def set_start_callback(self, cb):
33
        self.start_callback = cb
34
35
    def set_end_callback(self, cb):
36
        self.end_callback = cb
37
38
    def set_prompt(self, prompt):
39
        self.prompt = prompt
40
41
    def set_options(self, opt_list):
0.1.50 by Michael Ellerman
The UserInteractor refactoring changed the order in which we print options,
42
        self._options = []
43
        self._option_dict = {}
0.1.48 by Michael Ellerman
Move UserInteractor into a seperate file.
44
        for option in opt_list:
45
            self.add_option(option)
46
47
    def add_option(self, option):
0.1.50 by Michael Ellerman
The UserInteractor refactoring changed the order in which we print options,
48
        self._options.append(option)
49
        self._option_dict[option.char] = option
0.1.48 by Michael Ellerman
Move UserInteractor into a seperate file.
50
51
    def get_option(self, char):
0.1.50 by Michael Ellerman
The UserInteractor refactoring changed the order in which we print options,
52
        return self._option_dict[char]
0.1.48 by Michael Ellerman
Move UserInteractor into a seperate file.
53
54
    def __do_action(self, action, item):
55
        if type(action) is int:
56
            if action == self.QUIT:
57
                self.__quit = True
58
                self.__finished = True
59
            elif action == self.RESTART:
60
                self.__restart = True
0.1.51 by Michael Ellerman
Restart after a done was broken, and we weren't resetting the print logic at
61
                self.__finished = False
0.1.48 by Michael Ellerman
Move UserInteractor into a seperate file.
62
            elif action == self.FINISH:
63
                self.__finished = True
64
            return True
65
        else:
66
            return action(item)
67
68
    def __select_loop(self):
69
        i = 0
70
        self.start_callback()
71
        while i < len(self.items):
72
                item = self.items[i]
73
74
                self.item_callback(item, i + 1)
75
76
                if self.__ask_once(item, i + 1):
77
                    i += 1
78
79
                if self.__quit or self.__finished:
80
                    break
81
82
    def interact(self):
83
        self.__quit = False
84
        self.__finished = False
85
86
        while not self.__quit and not self.__finished:
87
            self.__restart = False
88
89
            self.__select_loop()
90
            if self.__quit:
91
                break
92
93
            if self.end_callback():
94
                break
95
0.1.57 by Michael Ellerman
HunkSelector was broken if you did a "done" followed by "status/invert" etc.
96
            self.__finished = False
97
0.1.48 by Michael Ellerman
Move UserInteractor into a seperate file.
98
            self.__ask_once(None, self.__total_items)
99
            while not self.__finished and not self.__restart:
100
                self.__ask_once(None, -1)
101
102
        return not self.__quit
103
104
    def __ask_once(self, item, count):
105
        args = {'count': count, 'total' : self.__total_items}
106
107
        while True:
108
            sys.stdout.write(self.prompt % args)
109
            sys.stdout.write(' [')
0.1.50 by Michael Ellerman
The UserInteractor refactoring changed the order in which we print options,
110
            for opt in self._options:
0.1.48 by Michael Ellerman
Move UserInteractor into a seperate file.
111
                if opt.default:
112
                    default = opt
113
                sys.stdout.write(opt.char)
114
            sys.stdout.write('?] (%s): ' % default.char)
115
116
            response = self.__getchar()
117
118
            # default, which we see as newline, is 'n'
119
            if response in ['\n', '\r', '\r\n']:
120
                response = default.char
121
122
            print response # because echo is off
123
0.1.50 by Michael Ellerman
The UserInteractor refactoring changed the order in which we print options,
124
            for opt in self._options:
0.1.48 by Michael Ellerman
Move UserInteractor into a seperate file.
125
                if opt.char == response:
126
                    return self.__do_action(opt.action, item)
127
128
            self.__show_help()
129
0.1.57 by Michael Ellerman
HunkSelector was broken if you did a "done" followed by "status/invert" etc.
130
        return False # keep pychecker happy
131
0.1.48 by Michael Ellerman
Move UserInteractor into a seperate file.
132
    def __show_help(self):
0.1.50 by Michael Ellerman
The UserInteractor refactoring changed the order in which we print options,
133
        for opt in self._options:
134
            print '  %s - %s' % (opt.char, opt.help)
0.1.48 by Michael Ellerman
Move UserInteractor into a seperate file.
135
136
    if sys.platform == "win32":
137
        import msvcrt
138
        def __getchar(self):
139
            return msvcrt.getche()
140
    else:
141
        def __getchar(self):
142
            import tty
143
            import termios
144
            fd = sys.stdin.fileno()
145
            settings = termios.tcgetattr(fd)
146
            try:
147
                tty.setraw(fd)
148
                ch = sys.stdin.read(1)
149
            finally:
150
                termios.tcsetattr(fd, termios.TCSADRAIN, settings)
151
            return ch