Show More
@@ -1,108 +1,159 | |||
|
1 | 1 | # System library imports |
|
2 | 2 | from PyQt4 import QtGui |
|
3 | 3 | |
|
4 | 4 | # Local imports |
|
5 | 5 | from console_widget import ConsoleWidget |
|
6 | 6 | |
|
7 | 7 | |
|
8 | 8 | class HistoryConsoleWidget(ConsoleWidget): |
|
9 | 9 | """ A ConsoleWidget that keeps a history of the commands that have been |
|
10 | executed. | |
|
10 | executed and provides a readline-esque interface to this history. | |
|
11 | 11 | """ |
|
12 | 12 | |
|
13 | 13 | #--------------------------------------------------------------------------- |
|
14 | 14 | # 'object' interface |
|
15 | 15 | #--------------------------------------------------------------------------- |
|
16 | 16 | |
|
17 | 17 | def __init__(self, *args, **kw): |
|
18 | 18 | super(HistoryConsoleWidget, self).__init__(*args, **kw) |
|
19 | ||
|
20 | # HistoryConsoleWidget protected variables. | |
|
19 | 21 | self._history = [] |
|
20 | 22 | self._history_index = 0 |
|
23 | self._history_prefix = '' | |
|
21 | 24 | |
|
22 | 25 | #--------------------------------------------------------------------------- |
|
23 | 26 | # 'ConsoleWidget' public interface |
|
24 | 27 | #--------------------------------------------------------------------------- |
|
25 | 28 | |
|
26 | 29 | def execute(self, source=None, hidden=False, interactive=False): |
|
27 | 30 | """ Reimplemented to the store history. |
|
28 | 31 | """ |
|
29 | 32 | if not hidden: |
|
30 | 33 | history = self.input_buffer if source is None else source |
|
31 | 34 | |
|
32 | 35 | executed = super(HistoryConsoleWidget, self).execute( |
|
33 | 36 | source, hidden, interactive) |
|
34 | 37 | |
|
35 | 38 | if executed and not hidden: |
|
36 | 39 | # Save the command unless it was an empty string or was identical |
|
37 | 40 | # to the previous command. |
|
38 | 41 | history = history.rstrip() |
|
39 | 42 | if history and (not self._history or self._history[-1] != history): |
|
40 | 43 | self._history.append(history) |
|
41 | 44 | |
|
42 | 45 | # Move the history index to the most recent item. |
|
43 | 46 | self._history_index = len(self._history) |
|
44 | 47 | |
|
45 | 48 | return executed |
|
46 | 49 | |
|
47 | 50 | #--------------------------------------------------------------------------- |
|
48 | 51 | # 'ConsoleWidget' abstract interface |
|
49 | 52 | #--------------------------------------------------------------------------- |
|
50 | 53 | |
|
51 | 54 | def _up_pressed(self): |
|
52 | 55 | """ Called when the up key is pressed. Returns whether to continue |
|
53 | 56 | processing the event. |
|
54 | 57 | """ |
|
55 | 58 | prompt_cursor = self._get_prompt_cursor() |
|
56 | 59 | if self._get_cursor().blockNumber() == prompt_cursor.blockNumber(): |
|
57 | self.history_previous() | |
|
58 | 60 | |
|
59 | # Go to the first line of prompt for seemless history scrolling. | |
|
61 | # Set a search prefix based on the cursor position. | |
|
62 | col = self._get_input_buffer_cursor_column() | |
|
63 | input_buffer = self.input_buffer | |
|
64 | if self._history_index == len(self._history) or \ | |
|
65 | (self._history_prefix and col != len(self._history_prefix)): | |
|
66 | self._history_index = len(self._history) | |
|
67 | self._history_prefix = input_buffer[:col] | |
|
68 | ||
|
69 | # Perform the search. | |
|
70 | self.history_previous(self._history_prefix) | |
|
71 | ||
|
72 | # Go to the first line of the prompt for seemless history scrolling. | |
|
73 | # Emulate readline: keep the cursor position fixed for a prefix | |
|
74 | # search. | |
|
60 | 75 | cursor = self._get_prompt_cursor() |
|
61 | cursor.movePosition(QtGui.QTextCursor.EndOfLine) | |
|
76 | if self._history_prefix: | |
|
77 | cursor.movePosition(QtGui.QTextCursor.Right, | |
|
78 | n=len(self._history_prefix)) | |
|
79 | else: | |
|
80 | cursor.movePosition(QtGui.QTextCursor.EndOfLine) | |
|
62 | 81 | self._set_cursor(cursor) |
|
63 | 82 | |
|
64 | 83 | return False |
|
84 | ||
|
65 | 85 | return True |
|
66 | 86 | |
|
67 | 87 | def _down_pressed(self): |
|
68 | 88 | """ Called when the down key is pressed. Returns whether to continue |
|
69 | 89 | processing the event. |
|
70 | 90 | """ |
|
71 | 91 | end_cursor = self._get_end_cursor() |
|
72 | 92 | if self._get_cursor().blockNumber() == end_cursor.blockNumber(): |
|
73 | self.history_next() | |
|
93 | ||
|
94 | # Perform the search. | |
|
95 | self.history_next(self._history_prefix) | |
|
96 | ||
|
97 | # Emulate readline: keep the cursor position fixed for a prefix | |
|
98 | # search. (We don't need to move the cursor to the end of the buffer | |
|
99 | # in the other case because this happens automatically when the | |
|
100 | # input buffer is set.) | |
|
101 | if self._history_prefix: | |
|
102 | cursor = self._get_prompt_cursor() | |
|
103 | cursor.movePosition(QtGui.QTextCursor.Right, | |
|
104 | n=len(self._history_prefix)) | |
|
105 | self._set_cursor(cursor) | |
|
106 | ||
|
74 | 107 | return False |
|
108 | ||
|
75 | 109 | return True |
|
76 | 110 | |
|
77 | 111 | #--------------------------------------------------------------------------- |
|
78 | 112 | # 'HistoryConsoleWidget' public interface |
|
79 | 113 | #--------------------------------------------------------------------------- |
|
80 | 114 | |
|
81 | def history_previous(self): | |
|
82 |
""" If possible, set the input buffer to |
|
|
83 | history. | |
|
84 | """ | |
|
85 | if self._history_index > 0: | |
|
86 | self._history_index -= 1 | |
|
87 | self.input_buffer = self._history[self._history_index] | |
|
115 | def history_previous(self, prefix=''): | |
|
116 | """ If possible, set the input buffer to a previous item in the history. | |
|
88 | 117 |
|
|
89 | def history_next(self): | |
|
90 | """ Set the input buffer to the next item in the history, or a blank | |
|
91 | line if there is no subsequent item. | |
|
118 | Parameters: | |
|
119 | ----------- | |
|
120 | prefix : str, optional | |
|
121 | If specified, search for an item with this prefix. | |
|
92 | 122 | """ |
|
93 |
i |
|
|
123 | index = self._history_index | |
|
124 | while index > 0: | |
|
125 | index -= 1 | |
|
126 | history = self._history[index] | |
|
127 | if history.startswith(prefix): | |
|
128 | break | |
|
129 | else: | |
|
130 | history = None | |
|
131 | ||
|
132 | if history is not None: | |
|
133 | self._history_index = index | |
|
134 | self.input_buffer = history | |
|
135 | ||
|
136 | def history_next(self, prefix=''): | |
|
137 | """ Set the input buffer to a subsequent item in the history, or to the | |
|
138 | original search prefix if there is no such item. | |
|
139 | ||
|
140 | Parameters: | |
|
141 | ----------- | |
|
142 | prefix : str, optional | |
|
143 | If specified, search for an item with this prefix. | |
|
144 | """ | |
|
145 | while self._history_index < len(self._history) - 1: | |
|
94 | 146 | self._history_index += 1 |
|
95 | if self._history_index < len(self._history): | |
|
96 | self.input_buffer = self._history[self._history_index] | |
|
97 |
|
|
|
98 | self.input_buffer = '' | |
|
99 | ||
|
100 | #--------------------------------------------------------------------------- | |
|
101 | # 'HistoryConsoleWidget' protected interface | |
|
102 | #--------------------------------------------------------------------------- | |
|
147 | history = self._history[self._history_index] | |
|
148 | if history.startswith(prefix): | |
|
149 | break | |
|
150 | else: | |
|
151 | self._history_index = len(self._history) | |
|
152 | history = prefix | |
|
153 | self.input_buffer = history | |
|
103 | 154 | |
|
104 |
def |
|
|
155 | def set_history(self, history): | |
|
105 | 156 | """ Replace the current history with a sequence of history items. |
|
106 | 157 | """ |
|
107 | 158 | self._history = list(history) |
|
108 | 159 | self._history_index = len(self._history) |
General Comments 0
You need to be logged in to leave comments.
Login now