##// END OF EJS Templates
Usability tweaks. Better auto tab completion. Terminal size more...
Gael Varoquaux -
Show More
@@ -63,7 +63,7 b' _TRACE_STYLE = 17'
63
63
64
64
65 # system colors
65 # system colors
66 SYS_COLOUR_BACKGROUND = wx.SystemSettings.GetColour(wx.SYS_COLOUR_BACKGROUND)
66 #SYS_COLOUR_BACKGROUND = wx.SystemSettings.GetColour(wx.SYS_COLOUR_BACKGROUND)
67
67
68 #-------------------------------------------------------------------------------
68 #-------------------------------------------------------------------------------
69 # The console widget class
69 # The console widget class
@@ -100,12 +100,7 b' class ConsoleWidget(editwindow.EditWindow):'
100 #--------------------------------------------------------------------------
100 #--------------------------------------------------------------------------
101
101
102 def __init__(self, parent, id=wx.ID_ANY, pos=wx.DefaultPosition,
102 def __init__(self, parent, id=wx.ID_ANY, pos=wx.DefaultPosition,
103 size=wx.DefaultSize, style=0,
103 size=wx.DefaultSize, style=0, ):
104 autocomplete_mode='popup'):
105 """ Autocomplete_mode: Can be 'popup' or 'text'
106 'text' show autocompletion in the text buffer
107 'popup' show it with a dropdown popup
108 """
109 editwindow.EditWindow.__init__(self, parent, id, pos, size, style)
104 editwindow.EditWindow.__init__(self, parent, id, pos, size, style)
110 self.configure_scintilla()
105 self.configure_scintilla()
111
106
@@ -114,8 +109,6 b' class ConsoleWidget(editwindow.EditWindow):'
114 '\n\x01\x1b[0;34m\x02In [\x01\x1b[1;34m\x02%i\x01\x1b[0;34m\x02]: \x01\x1b[0m\x02'
109 '\n\x01\x1b[0;34m\x02In [\x01\x1b[1;34m\x02%i\x01\x1b[0;34m\x02]: \x01\x1b[0m\x02'
115 self.new_prompt(self.prompt % 1)
110 self.new_prompt(self.prompt % 1)
116
111
117 self.autocomplete_mode = autocomplete_mode
118
119 self.Bind(wx.EVT_KEY_DOWN, self._on_key_down)
112 self.Bind(wx.EVT_KEY_DOWN, self._on_key_down)
120 self.Bind(wx.EVT_KEY_UP, self._on_key_up)
113 self.Bind(wx.EVT_KEY_UP, self._on_key_up)
121
114
@@ -154,9 +147,10 b' class ConsoleWidget(editwindow.EditWindow):'
154 self.SetTabWidth(4)
147 self.SetTabWidth(4)
155
148
156 self.EnsureCaretVisible()
149 self.EnsureCaretVisible()
157 # Tell autocompletion to choose automaticaly out of a single
150 # we don't want scintilla's autocompletion to choose
158 # choice list
151 # automaticaly out of a single choice list, as we pop it up
159 self.AutoCompSetChooseSingle(True)
152 # automaticaly
153 self.AutoCompSetChooseSingle(False)
160 self.AutoCompSetMaxHeight(10)
154 self.AutoCompSetMaxHeight(10)
161
155
162 self.SetMargins(3, 3) #text is moved away from border with 3px
156 self.SetMargins(3, 3) #text is moved away from border with 3px
@@ -278,42 +272,41 b' class ConsoleWidget(editwindow.EditWindow):'
278 self.StyleSetSpec(style[0], "bold,fore:%s" % style[1])
272 self.StyleSetSpec(style[0], "bold,fore:%s" % style[1])
279
273
280
274
281 def write_completion(self, possibilities, mode=None):
275 def write_completion(self, possibilities):
282 if mode=='text' or self.autocomplete_mode == 'text':
276 # FIXME: This is non Wx specific and needs to be moved into
283 # FIXME: This is non Wx specific and needs to be moved into
277 # the base class.
284 # the base class.
278 current_buffer = self.get_current_edit_buffer()
285 current_buffer = self.get_current_edit_buffer()
279
286
280 self.write('\n')
287 self.write('\n')
281 max_len = len(max(possibilities, key=len)) + 1
288 max_len = len(max(possibilities, key=len))
282
289
283 #now we check how much symbol we can put on a line...
290 #now we check how much symbol we can put on a line...
284 chars_per_line = self.GetSize()[0]/self.GetCharWidth()
291 chars_per_line = self.GetSize()[0]/self.GetCharWidth()
285 symbols_per_line = max(1, chars_per_line/max_len)
292 symbols_per_line = max(1, chars_per_line/max_len)
286
293
287 pos = 1
294 pos = 1
288 buf = []
295 buf = []
289 for symbol in possibilities:
296 for symbol in possibilities:
290 if pos < symbols_per_line:
297 if pos < symbols_per_line:
291 buf.append(symbol.ljust(max_len))
298 buf.append(symbol.ljust(max_len))
292 pos += 1
299 pos += 1
293 else:
300 else:
294 buf.append(symbol.rstrip() +'\n')
301 buf.append(symbol.rstrip() +'\n')
295 pos = 1
302 pos = 1
296 self.write(''.join(buf))
303 self.write(''.join(buf))
297 self.new_prompt(self.prompt % (self.last_result['number'] + 1))
304 self.new_prompt(self.prompt % (self.last_result['number'] + 1))
298 self.replace_current_edit_buffer(current_buffer)
305 self.replace_current_edit_buffer(current_buffer)
299
306
300
307 else:
301 def pop_completion(self, possibilities, offset=0):
308 self.AutoCompSetIgnoreCase(False)
302 """ Pops up an autocompletion menu. Offset is the offset
309 self.AutoCompSetAutoHide(False)
303 in characters of the position at which the menu should
310 # compute the length ot the last word
304 appear, relativ to the cursor.
311 separators = [' ', '(', '[', '{', '\n', '\t', '.']
305 """
312 symbol = self.get_current_edit_buffer()
306 self.AutoCompSetIgnoreCase(False)
313 for separator in separators:
307 self.AutoCompSetAutoHide(False)
314 symbol = symbol.split(separator)[-1]
308 self.AutoCompSetMaxHeight(len(possibilities))
315 self.AutoCompSetMaxHeight(len(possibilities))
309 self.AutoCompShow(offset, " ".join(possibilities))
316 self.AutoCompShow(len(symbol), " ".join(possibilities))
317
310
318
311
319 def scroll_to_bottom(self):
312 def scroll_to_bottom(self):
@@ -344,6 +337,10 b' class ConsoleWidget(editwindow.EditWindow):'
344 self.ScrollPages(-1)
337 self.ScrollPages(-1)
345 elif event.KeyCode == wx.WXK_PAGEDOWN and event.ShiftDown():
338 elif event.KeyCode == wx.WXK_PAGEDOWN and event.ShiftDown():
346 self.ScrollPages(1)
339 self.ScrollPages(1)
340 elif event.KeyCode == wx.WXK_UP and event.ShiftDown():
341 self.ScrollLines(-1)
342 elif event.KeyCode == wx.WXK_DOWN and event.ShiftDown():
343 self.ScrollLinees(1)
347 else:
344 else:
348 catched = False
345 catched = False
349
346
@@ -41,7 +41,7 b' _RUNNING_BUFFER_MARKER = 31'
41 class IPythonWxController(PrefilterFrontEnd, ConsoleWidget):
41 class IPythonWxController(PrefilterFrontEnd, ConsoleWidget):
42
42
43 output_prompt = \
43 output_prompt = \
44 '\x01\x1b[0;31m\x02Out[\x01\x1b[1;31m\x02%i\x01\x1b[0;31m\x02]: \x01\x1b[0m\x02'
44 '\n\x01\x1b[0;31m\x02Out[\x01\x1b[1;31m\x02%i\x01\x1b[0;31m\x02]: \x01\x1b[0m\x02'
45
45
46 #--------------------------------------------------------------------------
46 #--------------------------------------------------------------------------
47 # Public API
47 # Public API
@@ -64,14 +64,13 b' class IPythonWxController(PrefilterFrontEnd, ConsoleWidget):'
64
64
65
65
66
66
67 def do_completion(self, mode=None):
67 def do_completion(self):
68 """ Do code completion.
68 """ Do code completion.
69 mode can be 'text', 'popup' or 'none' to use default.
70 """
69 """
71 line = self.get_current_edit_buffer()
70 line = self.get_current_edit_buffer()
72 new_line, completions = self.complete(line)
71 new_line, completions = self.complete(line)
73 if len(completions)>1:
72 if len(completions)>1:
74 self.write_completion(completions, mode=mode)
73 self.write_completion(completions)
75 self.replace_current_edit_buffer(new_line)
74 self.replace_current_edit_buffer(new_line)
76
75
77
76
@@ -91,21 +90,31 b' class IPythonWxController(PrefilterFrontEnd, ConsoleWidget):'
91 return False
90 return False
92 for name in base_symbol_string.split('.')[1:] + ['__doc__']:
91 for name in base_symbol_string.split('.')[1:] + ['__doc__']:
93 symbol = getattr(symbol, name)
92 symbol = getattr(symbol, name)
94 self.CallTipShow(self.GetCurrentPos(), symbol)
93 try:
94 self.CallTipShow(self.GetCurrentPos(), symbol)
95 except TypeError:
96 # The retrieve symbol couldn't be converted to a string
97 pass
95
98
96
99
97 def update_completion(self):
100 def popup_completion(self, create=False):
101 """ Updates the popup completion menu if it exists. If create is
102 true, open the menu.
103 """
98 line = self.get_current_edit_buffer()
104 line = self.get_current_edit_buffer()
99 if self.AutoCompActive() and not line[-1] == '.':
105 if (self.AutoCompActive() and not line[-1] == '.') \
100 line = line[:-1]
106 or create==True:
101 completions = self.complete(line)
107 suggestion, completions = self.complete(line)
102 choose_single = self.AutoCompGetChooseSingle()
108 offset=0
103 self.AutoCompSetChooseSingle(False)
109 if completions:
104 self.write_completion(completions, mode='popup')
110 complete_sep = re.compile('[\s\{\}\[\]\(\)\= ]')
105 self.AutoCompSetChooseSingle(choose_single)
111 residual = complete_sep.split(line)[-1]
112 offset = len(residual)
113 self.pop_completion(completions, offset=offset)
106
114
107
115
108 def execute(self, python_string, raw_string=None):
116 def execute(self, python_string, raw_string=None):
117 self.CallTipCancel()
109 self._cursor = wx.BusyCursor()
118 self._cursor = wx.BusyCursor()
110 if raw_string is None:
119 if raw_string is None:
111 raw_string = python_string
120 raw_string = python_string
@@ -113,6 +122,10 b' class IPythonWxController(PrefilterFrontEnd, ConsoleWidget):'
113 + max(1, len(raw_string.split('\n'))-1)
122 + max(1, len(raw_string.split('\n'))-1)
114 for i in range(self.current_prompt_line, end_line):
123 for i in range(self.current_prompt_line, end_line):
115 self.MarkerAdd(i, 31)
124 self.MarkerAdd(i, 31)
125 # Remove the trailing "\n" for cleaner display
126 self.SetSelection(self.GetLength()-1, self.GetLength())
127 self.ReplaceSelection('')
128 self.GotoPos(self.GetLength())
116 PrefilterFrontEnd.execute(self, python_string, raw_string=raw_string)
129 PrefilterFrontEnd.execute(self, python_string, raw_string=raw_string)
117
130
118
131
@@ -134,10 +147,10 b' class IPythonWxController(PrefilterFrontEnd, ConsoleWidget):'
134 if self.AutoCompActive():
147 if self.AutoCompActive():
135 event.Skip()
148 event.Skip()
136 if event.KeyCode in (wx.WXK_BACK, wx.WXK_DELETE):
149 if event.KeyCode in (wx.WXK_BACK, wx.WXK_DELETE):
137 wx.CallAfter(self.do_completion)
150 wx.CallAfter(self.popup_completion)
138 elif not event.KeyCode in (wx.WXK_UP, wx.WXK_DOWN, wx.WXK_LEFT,
151 elif not event.KeyCode in (wx.WXK_UP, wx.WXK_DOWN, wx.WXK_LEFT,
139 wx.WXK_RIGHT):
152 wx.WXK_RIGHT):
140 wx.CallAfter(self.update_completion)
153 wx.CallAfter(self.popup_completion)
141 else:
154 else:
142 # Up history
155 # Up history
143 if event.KeyCode == wx.WXK_UP and (
156 if event.KeyCode == wx.WXK_UP and (
@@ -162,7 +175,7 b' class IPythonWxController(PrefilterFrontEnd, ConsoleWidget):'
162 elif event.KeyCode == ord('\t'):
175 elif event.KeyCode == ord('\t'):
163 last_line = self.get_current_edit_buffer().split('\n')[-1]
176 last_line = self.get_current_edit_buffer().split('\n')[-1]
164 if not re.match(r'^\s*$', last_line):
177 if not re.match(r'^\s*$', last_line):
165 self.do_completion(mode='text')
178 self.do_completion()
166 else:
179 else:
167 event.Skip()
180 event.Skip()
168 elif event.KeyCode == ord('('):
181 elif event.KeyCode == ord('('):
@@ -176,7 +189,7 b' class IPythonWxController(PrefilterFrontEnd, ConsoleWidget):'
176 if event.KeyCode == 59:
189 if event.KeyCode == 59:
177 # Intercepting '.'
190 # Intercepting '.'
178 event.Skip()
191 event.Skip()
179 #self.do_completion(mode='popup')
192 self.popup_completion(create=True)
180 else:
193 else:
181 ConsoleWidget._on_key_up(self, event, skip=skip)
194 ConsoleWidget._on_key_up(self, event, skip=skip)
182
195
@@ -195,7 +208,7 b" if __name__ == '__main__':"
195 app = wx.PySimpleApp()
208 app = wx.PySimpleApp()
196 frame = MainWindow(None, wx.ID_ANY, 'Ipython')
209 frame = MainWindow(None, wx.ID_ANY, 'Ipython')
197 frame.shell.SetFocus()
210 frame.shell.SetFocus()
198 frame.SetSize((660, 460))
211 frame.SetSize((680, 460))
199 self = frame.shell
212 self = frame.shell
200
213
201 app.MainLoop()
214 app.MainLoop()
General Comments 0
You need to be logged in to leave comments. Login now