Show More
@@ -652,13 +652,13 b' class ConsoleWidget(Configurable, QtGui.QWidget):' | |||
|
652 | 652 | """ |
|
653 | 653 | pass |
|
654 | 654 | |
|
655 | def _up_pressed(self): | |
|
655 | def _up_pressed(self, shift_modifier): | |
|
656 | 656 | """ Called when the up key is pressed. Returns whether to continue |
|
657 | 657 | processing the event. |
|
658 | 658 | """ |
|
659 | 659 | return True |
|
660 | 660 | |
|
661 | def _down_pressed(self): | |
|
661 | def _down_pressed(self, shift_modifier): | |
|
662 | 662 | """ Called when the down key is pressed. Returns whether to continue |
|
663 | 663 | processing the event. |
|
664 | 664 | """ |
@@ -1040,14 +1040,14 b' class ConsoleWidget(Configurable, QtGui.QWidget):' | |||
|
1040 | 1040 | intercepted = True |
|
1041 | 1041 | |
|
1042 | 1042 | elif key == QtCore.Qt.Key_Up: |
|
1043 | if self._reading or not self._up_pressed(): | |
|
1043 | if self._reading or not self._up_pressed(shift_down): | |
|
1044 | 1044 | intercepted = True |
|
1045 | 1045 | else: |
|
1046 | 1046 | prompt_line = self._get_prompt_cursor().blockNumber() |
|
1047 | 1047 | intercepted = cursor.blockNumber() <= prompt_line |
|
1048 | 1048 | |
|
1049 | 1049 | elif key == QtCore.Qt.Key_Down: |
|
1050 | if self._reading or not self._down_pressed(): | |
|
1050 | if self._reading or not self._down_pressed(shift_down): | |
|
1051 | 1051 | intercepted = True |
|
1052 | 1052 | else: |
|
1053 | 1053 | end_line = self._get_end_cursor().blockNumber() |
@@ -2,6 +2,7 b'' | |||
|
2 | 2 | from IPython.external.qt import QtGui |
|
3 | 3 | |
|
4 | 4 | # Local imports |
|
5 | from IPython.utils.traitlets import Bool | |
|
5 | 6 | from console_widget import ConsoleWidget |
|
6 | 7 | |
|
7 | 8 | |
@@ -9,6 +10,13 b' class HistoryConsoleWidget(ConsoleWidget):' | |||
|
9 | 10 | """ A ConsoleWidget that keeps a history of the commands that have been |
|
10 | 11 | executed and provides a readline-esque interface to this history. |
|
11 | 12 | """ |
|
13 | ||
|
14 | #------ Configuration ------------------------------------------------------ | |
|
15 | ||
|
16 | # If enabled, the input buffer will become "locked" to history movement when | |
|
17 | # an edit is made to a multi-line input buffer. To override the lock, use | |
|
18 | # Shift in conjunction with the standard history cycling keys. | |
|
19 | history_lock = Bool(False, config=True) | |
|
12 | 20 | |
|
13 | 21 | #--------------------------------------------------------------------------- |
|
14 | 22 | # 'object' interface |
@@ -55,12 +63,15 b' class HistoryConsoleWidget(ConsoleWidget):' | |||
|
55 | 63 | # 'ConsoleWidget' abstract interface |
|
56 | 64 | #--------------------------------------------------------------------------- |
|
57 | 65 | |
|
58 | def _up_pressed(self): | |
|
66 | def _up_pressed(self, shift_modifier): | |
|
59 | 67 | """ Called when the up key is pressed. Returns whether to continue |
|
60 | 68 | processing the event. |
|
61 | 69 | """ |
|
62 | 70 | prompt_cursor = self._get_prompt_cursor() |
|
63 | 71 | if self._get_cursor().blockNumber() == prompt_cursor.blockNumber(): |
|
72 | # Bail out if we're locked. | |
|
73 | if self._history_locked() and not shift_modifier: | |
|
74 | return False | |
|
64 | 75 | |
|
65 | 76 | # Set a search prefix based on the cursor position. |
|
66 | 77 | col = self._get_input_buffer_cursor_column() |
@@ -88,21 +99,24 b' class HistoryConsoleWidget(ConsoleWidget):' | |||
|
88 | 99 | |
|
89 | 100 | return True |
|
90 | 101 | |
|
91 | def _down_pressed(self): | |
|
102 | def _down_pressed(self, shift_modifier): | |
|
92 | 103 | """ Called when the down key is pressed. Returns whether to continue |
|
93 | 104 | processing the event. |
|
94 | 105 | """ |
|
95 | 106 | end_cursor = self._get_end_cursor() |
|
96 | 107 | if self._get_cursor().blockNumber() == end_cursor.blockNumber(): |
|
108 | # Bail out if we're locked. | |
|
109 | if self._history_locked() and not shift_modifier: | |
|
110 | return False | |
|
97 | 111 | |
|
98 | 112 | # Perform the search. |
|
99 | self.history_next(self._history_prefix) | |
|
113 | replaced = self.history_next(self._history_prefix) | |
|
100 | 114 | |
|
101 | 115 | # Emulate readline: keep the cursor position fixed for a prefix |
|
102 | 116 | # search. (We don't need to move the cursor to the end of the buffer |
|
103 | 117 | # in the other case because this happens automatically when the |
|
104 | 118 | # input buffer is set.) |
|
105 | if self._history_prefix: | |
|
119 | if self._history_prefix and replaced: | |
|
106 | 120 | cursor = self._get_prompt_cursor() |
|
107 | 121 | cursor.movePosition(QtGui.QTextCursor.Right, |
|
108 | 122 | n=len(self._history_prefix)) |
@@ -123,19 +137,26 b' class HistoryConsoleWidget(ConsoleWidget):' | |||
|
123 | 137 | ----------- |
|
124 | 138 | prefix : str, optional |
|
125 | 139 | If specified, search for an item with this prefix. |
|
140 | ||
|
141 | Returns: | |
|
142 | -------- | |
|
143 | Whether the input buffer was changed. | |
|
126 | 144 | """ |
|
127 | 145 | index = self._history_index |
|
146 | replace = False | |
|
128 | 147 | while index > 0: |
|
129 | 148 | index -= 1 |
|
130 | 149 | history = self._get_edited_history(index) |
|
131 | 150 | if history.startswith(prefix): |
|
151 | replace = True | |
|
132 | 152 | break |
|
133 | else: | |
|
134 | history = None | |
|
135 | 153 | |
|
136 | if history is not None: | |
|
137 |
self._s |
|
|
154 | if replace: | |
|
155 | self._store_edits() | |
|
138 | 156 | self._history_index = index |
|
157 | self.input_buffer = history | |
|
158 | ||
|
159 | return replace | |
|
139 | 160 | |
|
140 | 161 | def history_next(self, prefix=''): |
|
141 | 162 | """ If possible, set the input buffer to a subsequent history item. |
@@ -144,19 +165,26 b' class HistoryConsoleWidget(ConsoleWidget):' | |||
|
144 | 165 | ----------- |
|
145 | 166 | prefix : str, optional |
|
146 | 167 | If specified, search for an item with this prefix. |
|
168 | ||
|
169 | Returns: | |
|
170 | -------- | |
|
171 | Whether the input buffer was changed. | |
|
147 | 172 | """ |
|
148 | 173 | index = self._history_index |
|
174 | replace = False | |
|
149 | 175 | while self._history_index < len(self._history): |
|
150 | 176 | index += 1 |
|
151 | 177 | history = self._get_edited_history(index) |
|
152 | 178 | if history.startswith(prefix): |
|
179 | replace = True | |
|
153 | 180 | break |
|
154 |
|
|
|
155 | history = None | |
|
156 | ||
|
157 | if history is not None: | |
|
158 | self._set_edited_input_buffer(history) | |
|
181 | ||
|
182 | if replace: | |
|
183 | self._store_edits() | |
|
159 | 184 | self._history_index = index |
|
185 | self.input_buffer = history | |
|
186 | ||
|
187 | return replace | |
|
160 | 188 | |
|
161 | 189 | def history_tail(self, n=10): |
|
162 | 190 | """ Get the local history list. |
@@ -172,23 +200,35 b' class HistoryConsoleWidget(ConsoleWidget):' | |||
|
172 | 200 | # 'HistoryConsoleWidget' protected interface |
|
173 | 201 | #--------------------------------------------------------------------------- |
|
174 | 202 | |
|
203 | def _history_locked(self): | |
|
204 | """ Returns whether history movement is locked. | |
|
205 | """ | |
|
206 | return (self.history_lock and | |
|
207 | (self._get_edited_history(self._history_index) != | |
|
208 | self.input_buffer) and | |
|
209 | (self._get_prompt_cursor().blockNumber() != | |
|
210 | self._get_end_cursor().blockNumber())) | |
|
211 | ||
|
175 | 212 | def _get_edited_history(self, index): |
|
176 | 213 | """ Retrieves a history item, possibly with temporary edits. |
|
177 | 214 | """ |
|
178 | 215 | if index in self._history_edits: |
|
179 | 216 | return self._history_edits[index] |
|
217 | elif index == len(self._history): | |
|
218 | return unicode() | |
|
180 | 219 | return self._history[index] |
|
181 | 220 | |
|
182 | def _set_edited_input_buffer(self, source): | |
|
183 | """ Sets the input buffer to 'source', saving the current input buffer | |
|
184 | as a temporary history edit. | |
|
185 | """ | |
|
186 | self._history_edits[self._history_index] = self.input_buffer | |
|
187 | self.input_buffer = source | |
|
188 | ||
|
189 | 221 | def _set_history(self, history): |
|
190 | 222 | """ Replace the current history with a sequence of history items. |
|
191 | 223 | """ |
|
192 | 224 | self._history = list(history) |
|
193 | 225 | self._history_edits = {} |
|
194 | 226 | self._history_index = len(self._history) |
|
227 | ||
|
228 | def _store_edits(self): | |
|
229 | """ If there are edits to the current input buffer, store them. | |
|
230 | """ | |
|
231 | current = self.input_buffer | |
|
232 | if self._history_index == len(self._history) or \ | |
|
233 | self._history[self._history_index] != current: | |
|
234 | self._history_edits[self._history_index] = current |
General Comments 0
You need to be logged in to leave comments.
Login now