##// END OF EJS Templates
new completer for qtconsole...
Matthias BUSSONNIER -
Show More
@@ -1,7 +1,116 b''
1 """a navigable completer for the qtconsole"""
2 # coding : utf-8
3 #-----------------------------------------------------------------------------
4 # Copyright (c) 2012, IPython Development Team.$
5 #
6 # Distributed under the terms of the Modified BSD License.$
7 #
8 # The full license is in the file COPYING.txt, distributed with this software.
9 #-----------------------------------------------------------------------------
10
1 11 # System library imports
12 import IPython.utils.text as text
13
2 14 from IPython.external.qt import QtCore, QtGui
3 import IPython.utils.html_utils as html_utils
4 15
16 #--------------------------------------------------------------------------
17 # Return an HTML table with selected item in a special class
18 #--------------------------------------------------------------------------
19 def html_tableify(item_matrix, select=None, header=None , footer=None) :
20 """ returnr a string for an html table"""
21 if not item_matrix :
22 return ''
23 html_cols = []
24 tds = lambda text : u'<td>'+text+u' </td>'
25 trs = lambda text : u'<tr>'+text+u'</tr>'
26 tds_items = [map(tds, row) for row in item_matrix]
27 if select :
28 row, col = select
29 tds_items[row][col] = u'<td class="inverted">'\
30 +item_matrix[row][col]\
31 +u' </td>'
32 #select the right item
33 html_cols = map(trs, (u''.join(row) for row in tds_items))
34 head = ''
35 foot = ''
36 if header :
37 head = (u'<tr>'\
38 +''.join((u'<td>'+header+u'</td>')*len(item_matrix[0]))\
39 +'</tr>')
40
41 if footer :
42 foot = (u'<tr>'\
43 +''.join((u'<td>'+footer+u'</td>')*len(item_matrix[0]))\
44 +'</tr>')
45 html = (u'<table class="completion" style="white-space:pre">'+head+(u''.join(html_cols))+foot+u'</table>')
46 return html
47
48 class SlidingInterval(object):
49 """a bound interval that follows a cursor
50
51 internally used to scoll the completion view when the cursor
52 try to go beyond the edges, and show '...' when rows are hidden
53 """
54
55 _min = 0
56 _max = 1
57 _current = 0
58 def __init__(self, maximum=1, width=6, minimum=0, sticky_lenght=1):
59 """Create a new bounded interval
60
61 any value return by this will be bound between maximum and
62 minimum. usual width will be 'width', and sticky_length
63 set when the return interval should expand to max and min
64 """
65 self._min = minimum
66 self._max = maximum
67 self._start = 0
68 self._width = width
69 self._stop = self._start+self._width+1
70 self._sticky_lenght = sticky_lenght
71
72 @property
73 def current(self):
74 """current cursor position"""
75 return self._current
76
77 @current.setter
78 def current(self, value):
79 """set current cursor position"""
80 current = min(max(self._min, value), self._max)
81
82 self._current = current
83
84 if current > self._stop :
85 self._stop = current
86 self._start = current-self._width
87 elif current < self._start :
88 self._start = current
89 self._stop = current + self._width
90
91 if abs(self._start - self._min) <= self._sticky_lenght :
92 self._start = self._min
93
94 if abs(self._stop - self._max) <= self._sticky_lenght :
95 self._stop = self._max
96
97 @property
98 def start(self):
99 """begiiing of interval to show"""
100 return self._start
101
102 @property
103 def stop(self):
104 """end of interval to show"""
105 return self._stop
106
107 @property
108 def width(self):
109 return self._stop - self._start
110
111 @property
112 def nth(self):
113 return self.current - self.start
5 114
6 115 class CompletionHtml(QtGui.QWidget):
7 116 """ A widget for tab completion, navigable by arrow keys """
@@ -16,6 +125,8 b' class CompletionHtml(QtGui.QWidget):'
16 125 _size = (1, 1)
17 126 _old_cursor = None
18 127 _start_position = 0
128 _slice_start = 0
129 _slice_len = 4
19 130
20 131 def __init__(self, console_widget):
21 132 """ Create a completion widget that is attached to the specified Qt
@@ -27,6 +138,8 b' class CompletionHtml(QtGui.QWidget):'
27 138 self._text_edit = console_widget._control
28 139 self._console_widget = console_widget
29 140 self._text_edit.installEventFilter(self)
141 self._sliding_interval = None
142 self._justified_items = None
30 143
31 144 # Ensure that the text edit keeps focus when widget is displayed.
32 145 self.setFocusProxy(self._text_edit)
@@ -71,24 +184,36 b' class CompletionHtml(QtGui.QWidget):'
71 184 self.select_left()
72 185 self._update_list()
73 186 return True
187 elif key in ( QtCore.Qt.Key_Escape,):
188 self.cancel_completion()
189 return True
74 190 else :
75 self._cancel_completion()
191 self.cancel_completion()
76 192 else:
77 self._cancel_completion()
193 self.cancel_completion()
78 194
79 195 elif etype == QtCore.QEvent.FocusOut:
80 self._cancel_completion()
196 self.cancel_completion()
81 197
82 198 return super(CompletionHtml, self).eventFilter(obj, event)
83 199
84 200 #--------------------------------------------------------------------------
85 201 # 'CompletionHtml' interface
86 202 #--------------------------------------------------------------------------
87 def _cancel_completion(self):
88 """Cancel the completion, reseting internal variable, clearing buffer """
203 def cancel_completion(self):
204 """Cancel the completion
205
206 should be called when the completer have to be dismissed
207
208 This reset internal variable, clearing the temporary buffer
209 of the console where the completion are shown.
210 """
89 211 self._consecutive_tab = 0
212 self._slice_start = 0
90 213 self._console_widget._clear_temporary_buffer()
91 214 self._index = (0, 0)
215 if(self._sliding_interval):
216 self._sliding_interval = None
92 217
93 218 #
94 219 # ... 2 4 4 4 4 4 4 4 4 4 4 4 4
@@ -147,6 +272,12 b' class CompletionHtml(QtGui.QWidget):'
147 272 have gone before : %d:%d (%d:%d)"%(row, col, nr, nc) )
148 273
149 274
275 @property
276 def _slice_end(self):
277 end = self._slice_start+self._slice_len
278 if end > len(self._items) :
279 return None
280 return end
150 281
151 282 def select_up(self):
152 283 """move cursor up"""
@@ -176,27 +307,42 b' class CompletionHtml(QtGui.QWidget):'
176 307 return
177 308 self._start_position = cursor.position()
178 309 self._consecutive_tab = 1
179 ci = html_utils.columnize_info(items, empty=' ')
180 self._items = ci['item_matrix']
181 self._size = (ci['rows_number'], ci['columns_number'])
310 items_m, ci = text.compute_item_matrix(items, empty=' ')
311 self._sliding_interval = SlidingInterval(len(items_m)-1)
312
313 self._items = items_m
314 self._size = (ci['rows_numbers'], ci['columns_numbers'])
182 315 self._old_cursor = cursor
183 316 self._index = (0, 0)
317 sjoin = lambda x : [ y.ljust(w, ' ') for y, w in zip(x, ci['columns_width'])]
318 self._justified_items = map(sjoin, items_m)
184 319 self._update_list(hilight=False)
185 320
186 321
322
323
187 324 def _update_list(self, hilight=True):
188 325 """ update the list of completion and hilight the currently selected completion """
189 if len(self._items) > 100:
190 items = self._items[:100]
191 else :
192 items = self._items
193 items_m = items
326 self._sliding_interval.current = self._index[0]
327 head = None
328 foot = None
329 if self._sliding_interval.start > 0 :
330 head = '...'
331
332 if self._sliding_interval.stop < self._sliding_interval._max:
333 foot = '...'
334 items_m = self._justified_items[\
335 self._sliding_interval.start:\
336 self._sliding_interval.stop+1\
337 ]
194 338
195 339 self._console_widget._clear_temporary_buffer()
196 340 if(hilight):
197 strng = html_utils.html_tableify(items_m, select=self._index)
198 else:
199 strng = html_utils.html_tableify(items_m, select=None)
341 sel = (self._sliding_interval.nth, self._index[1])
342 else :
343 sel = None
344
345 strng = html_tableify(items_m, select=sel, header=head, footer=foot)
200 346 self._console_widget._fill_temporary_buffer(self._old_cursor, strng, html=True)
201 347
202 348 #--------------------------------------------------------------------------
@@ -211,7 +357,7 b' class CompletionHtml(QtGui.QWidget):'
211 357 item = item.strip()
212 358 if item :
213 359 self._current_text_cursor().insertText(item)
214 self._cancel_completion()
360 self.cancel_completion()
215 361
216 362 def _current_text_cursor(self):
217 363 """ Returns a cursor with text between the start position and the
@@ -223,4 +369,3 b' class CompletionHtml(QtGui.QWidget):'
223 369 QtGui.QTextCursor.KeepAnchor)
224 370 return cursor
225 371
226
@@ -1,6 +1,15 b''
1 """a simple completer for the qtconsole"""
2 #-----------------------------------------------------------------------------
3 # Copyright (c) 2012, IPython Development Team.$
4 #
5 # Distributed under the terms of the Modified BSD License.$
6 #
7 # The full license is in the file COPYING.txt, distributed with this software.
8 #-------------------------------------------------------------------
9
1 10 # System library imports
2 11 from IPython.external.qt import QtCore, QtGui
3 import IPython.utils.html_utils as html_utils
12 import IPython.utils.text as text
4 13
5 14
6 15 class CompletionPlain(QtGui.QWidget):
@@ -10,10 +19,6 b' class CompletionPlain(QtGui.QWidget):'
10 19 # 'QObject' interface
11 20 #--------------------------------------------------------------------------
12 21
13 _items = ()
14 _index = (0, 0)
15 _old_cursor = None
16
17 22 def __init__(self, console_widget):
18 23 """ Create a completion widget that is attached to the specified Qt
19 24 text edit widget.
@@ -33,18 +38,17 b' class CompletionPlain(QtGui.QWidget):'
33 38 if obj == self._text_edit:
34 39 etype = event.type()
35 40
36 if etype == QtCore.QEvent.KeyPress:
37 self._cancel_completion()
41 if etype in( QtCore.QEvent.KeyPress, QtCore.QEvent.FocusOut ):
42 self.cancel_completion()
38 43
39 44 return super(CompletionPlain, self).eventFilter(obj, event)
40 45
41 46 #--------------------------------------------------------------------------
42 47 # 'CompletionPlain' interface
43 48 #--------------------------------------------------------------------------
44 def _cancel_completion(self):
49 def cancel_completion(self):
45 50 """Cancel the completion, reseting internal variable, clearing buffer """
46 51 self._console_widget._clear_temporary_buffer()
47 self._index = (0, 0)
48 52
49 53
50 54 def show_items(self, cursor, items):
@@ -53,21 +57,6 b' class CompletionPlain(QtGui.QWidget):'
53 57 """
54 58 if not items :
55 59 return
56
57 ci = html_utils.columnize_info(items, empty=' ')
58 self._items = ci['item_matrix']
59 self._old_cursor = cursor
60 self._update_list()
61
62
63 def _update_list(self):
64 """ update the list of completion and hilight the currently selected completion """
65 if len(self._items) > 100:
66 items = self._items[:100]
67 else :
68 items = self._items
69 items_m = items
70
71 self._console_widget._clear_temporary_buffer()
72 strng = html_utils.html_tableify(items_m, select=None)
73 self._console_widget._fill_temporary_buffer(self._old_cursor, strng, html=True)
60 self.cancel_completion()
61 strng = text.columnize(items)
62 self._console_widget._fill_temporary_buffer(cursor, strng, html=False)
@@ -134,5 +134,5 b' class CompletionWidget(QtGui.QListWidget):'
134 134 else:
135 135 self.hide()
136 136
137 def _cancel_completion(self):
137 def cancel_completion(self):
138 138 self.hide()
@@ -843,7 +843,7 b' class ConsoleWidget(LoggingConfigurable, QtGui.QWidget):'
843 843 def _cancel_completion(self):
844 844 """ If text completion is progress, cancel it.
845 845 """
846 self._completion_widget._cancel_completion()
846 self._completion_widget.cancel_completion()
847 847
848 848 def _clear_temporary_buffer(self):
849 849 """ Clears the "temporary text" buffer, i.e. all the text following
@@ -105,13 +105,6 b' qt_flags = {'
105 105 "Disable rich text support."),
106 106 }
107 107
108 # not quite sure on how this works
109 #qt_flags.update(boolean_flag(
110 # 'gui-completion', 'ConsoleWidget.gui_completion',
111 # "use a GUI widget for tab completion",
112 # "use plaintext output for completion"
113 #))
114
115 108 # and app_flags from the Console Mixin
116 109 qt_flags.update(app_flags)
117 110 # add frontend flags to the full set
@@ -690,7 +690,7 b' def _get_or_default(mylist, i, default=None):'
690 690 return mylist[i]
691 691
692 692 @skip_doctest
693 def compute_item_matrix(items, *args, **kwargs) :
693 def compute_item_matrix(items, empty=None, *args, **kwargs) :
694 694 """Returns a nested list, and info to columnize items
695 695
696 696 Parameters :
@@ -698,6 +698,8 b' def compute_item_matrix(items, *args, **kwargs) :'
698 698
699 699 items :
700 700 list of strings to columize
701 empty : (default None)
702 default value to fill list if needed
701 703 separator_size : int (default=2)
702 704 How much caracters will be used as a separation between each columns.
703 705 displaywidth : int (default=80)
1 NO CONTENT: file was removed
General Comments 0
You need to be logged in to leave comments. Login now