##// 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,14 +272,13 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':
283 # FIXME: This is non Wx specific and needs to be moved into
276 # FIXME: This is non Wx specific and needs to be moved into
284 # the base class.
277 # the base class.
285 current_buffer = self.get_current_edit_buffer()
278 current_buffer = self.get_current_edit_buffer()
286
279
287 self.write('\n')
280 self.write('\n')
288 max_len = len(max(possibilities, key=len))
281 max_len = len(max(possibilities, key=len)) + 1
289
282
290 #now we check how much symbol we can put on a line...
283 #now we check how much symbol we can put on a line...
291 chars_per_line = self.GetSize()[0]/self.GetCharWidth()
284 chars_per_line = self.GetSize()[0]/self.GetCharWidth()
@@ -304,16 +297,16 b' class ConsoleWidget(editwindow.EditWindow):'
304 self.new_prompt(self.prompt % (self.last_result['number'] + 1))
297 self.new_prompt(self.prompt % (self.last_result['number'] + 1))
305 self.replace_current_edit_buffer(current_buffer)
298 self.replace_current_edit_buffer(current_buffer)
306
299
307 else:
300
301 def pop_completion(self, possibilities, offset=0):
302 """ Pops up an autocompletion menu. Offset is the offset
303 in characters of the position at which the menu should
304 appear, relativ to the cursor.
305 """
308 self.AutoCompSetIgnoreCase(False)
306 self.AutoCompSetIgnoreCase(False)
309 self.AutoCompSetAutoHide(False)
307 self.AutoCompSetAutoHide(False)
310 # compute the length ot the last word
311 separators = [' ', '(', '[', '{', '\n', '\t', '.']
312 symbol = self.get_current_edit_buffer()
313 for separator in separators:
314 symbol = symbol.split(separator)[-1]
315 self.AutoCompSetMaxHeight(len(possibilities))
308 self.AutoCompSetMaxHeight(len(possibilities))
316 self.AutoCompShow(len(symbol), " ".join(possibilities))
309 self.AutoCompShow(offset, " ".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)
93 try:
94 self.CallTipShow(self.GetCurrentPos(), symbol)
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