~abentley/bzrtools/bzrtools.dev

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