##// END OF EJS Templates
More calltip fixing.
Gael Varoquaux -
Show More
@@ -1,219 +1,218 b''
1 1 # encoding: utf-8 -*- test-case-name:
2 2 # FIXME: Need to add tests.
3 3 # ipython1.frontend.cocoa.tests.test_cocoa_frontend -*-
4 4
5 5 """Classes to provide a Wx frontend to the
6 6 IPython.kernel.core.interpreter.
7 7
8 8 """
9 9
10 10 __docformat__ = "restructuredtext en"
11 11
12 12 #-------------------------------------------------------------------------------
13 13 # Copyright (C) 2008 The IPython Development Team
14 14 #
15 15 # Distributed under the terms of the BSD License. The full license is in
16 16 # the file COPYING, distributed as part of this software.
17 17 #-------------------------------------------------------------------------------
18 18
19 19 #-------------------------------------------------------------------------------
20 20 # Imports
21 21 #-------------------------------------------------------------------------------
22 22
23 23
24 24 import wx
25 25 import re
26 26 from wx import stc
27 27 from console_widget import ConsoleWidget
28 28 import __builtin__
29 29
30 30 from IPython.frontend.prefilterfrontend import PrefilterFrontEnd
31 31
32 32 #_COMMAND_BG = '#FAFAF1' # Nice green
33 33 _RUNNING_BUFFER_BG = '#FDFFD3' # Nice yellow
34 34
35 35 _RUNNING_BUFFER_MARKER = 31
36 36
37 37
38 38 #-------------------------------------------------------------------------------
39 39 # Classes to implement the Wx frontend
40 40 #-------------------------------------------------------------------------------
41 41 class IPythonWxController(PrefilterFrontEnd, ConsoleWidget):
42 42
43 43 output_prompt = \
44 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 47 # Public API
48 48 #--------------------------------------------------------------------------
49 49
50 50 def __init__(self, parent, id=wx.ID_ANY, pos=wx.DefaultPosition,
51 51 size=wx.DefaultSize, style=wx.CLIP_CHILDREN,
52 52 *args, **kwds):
53 53 """ Create Shell instance.
54 54 """
55 55 ConsoleWidget.__init__(self, parent, id, pos, size, style)
56 56 PrefilterFrontEnd.__init__(self)
57 57
58 58 # Capture Character keys
59 59 self.Bind(wx.EVT_KEY_DOWN, self._on_key_down)
60 60
61 61 # Marker for running buffer.
62 62 self.MarkerDefine(_RUNNING_BUFFER_MARKER, stc.STC_MARK_BACKGROUND,
63 63 background=_RUNNING_BUFFER_BG)
64 64
65 65
66 66
67 67 def do_completion(self):
68 68 """ Do code completion.
69 69 """
70 70 line = self.get_current_edit_buffer()
71 71 new_line, completions = self.complete(line)
72 72 if len(completions)>1:
73 73 self.write_completion(completions)
74 74 self.replace_current_edit_buffer(new_line)
75 75
76 76
77 77 def do_calltip(self):
78 separators = [' ', '(', '[', '{', '\n', '\t']
78 separators = re.compile('[\s\{\}\[\]\(\)\= ,:]')
79 79 symbol = self.get_current_edit_buffer()
80 for separator in separators:
81 symbol_string = symbol.split(separator)[-1]
80 symbol_string = separators.split(symbol)[-1]
82 81 base_symbol_string = symbol_string.split('.')[0]
83 82 if base_symbol_string in self.shell.user_ns:
84 83 symbol = self.shell.user_ns[base_symbol_string]
85 84 elif base_symbol_string in self.shell.user_global_ns:
86 85 symbol = self.shell.user_global_ns[base_symbol_string]
87 86 elif base_symbol_string in __builtin__.__dict__:
88 87 symbol = __builtin__.__dict__[base_symbol_string]
89 88 else:
90 89 return False
91 90 for name in symbol_string.split('.')[1:] + ['__doc__']:
92 91 symbol = getattr(symbol, name)
93 92 try:
94 93 self.AutoCompCancel()
95 94 wx.Yield()
96 95 self.CallTipShow(self.GetCurrentPos(), symbol)
97 except TypeError:
96 except:
98 97 # The retrieve symbol couldn't be converted to a string
99 98 pass
100 99
101 100
102 101 def popup_completion(self, create=False):
103 102 """ Updates the popup completion menu if it exists. If create is
104 103 true, open the menu.
105 104 """
106 105 line = self.get_current_edit_buffer()
107 106 if (self.AutoCompActive() and not line[-1] == '.') \
108 107 or create==True:
109 108 suggestion, completions = self.complete(line)
110 109 offset=0
111 110 if completions:
112 complete_sep = re.compile('[\s\{\}\[\]\(\)\= ]')
111 complete_sep = re.compile('[\s\{\}\[\]\(\)\= ,:]')
113 112 residual = complete_sep.split(line)[-1]
114 113 offset = len(residual)
115 114 self.pop_completion(completions, offset=offset)
116 115
117 116
118 117 def execute(self, python_string, raw_string=None):
119 118 self.CallTipCancel()
120 119 self._cursor = wx.BusyCursor()
121 120 if raw_string is None:
122 121 raw_string = python_string
123 122 end_line = self.current_prompt_line \
124 123 + max(1, len(raw_string.split('\n'))-1)
125 124 for i in range(self.current_prompt_line, end_line):
126 125 self.MarkerAdd(i, 31)
127 126 # Update the display:
128 127 wx.Yield()
129 128 # Remove the trailing "\n" for cleaner display
130 129 self.SetSelection(self.GetLength()-1, self.GetLength())
131 130 self.ReplaceSelection('')
132 131 self.GotoPos(self.GetLength())
133 132 PrefilterFrontEnd.execute(self, python_string, raw_string=raw_string)
134 133
135 134
136 135 def after_execute(self):
137 136 PrefilterFrontEnd.after_execute(self)
138 137 if hasattr(self, '_cursor'):
139 138 del self._cursor
140 139
141 140 #--------------------------------------------------------------------------
142 141 # Private API
143 142 #--------------------------------------------------------------------------
144 143
145 144
146 145 def _on_key_down(self, event, skip=True):
147 146 """ Capture the character events, let the parent
148 147 widget handle them, and put our logic afterward.
149 148 """
150 149 current_line_number = self.GetCurrentLine()
151 150 if event.KeyCode == ord('('):
152 151 event.Skip()
153 152 self.do_calltip()
154 153 elif self.AutoCompActive():
155 154 event.Skip()
156 155 if event.KeyCode in (wx.WXK_BACK, wx.WXK_DELETE):
157 156 wx.CallAfter(self.popup_completion, create=True)
158 157 elif not event.KeyCode in (wx.WXK_UP, wx.WXK_DOWN, wx.WXK_LEFT,
159 158 wx.WXK_RIGHT):
160 159 wx.CallAfter(self.popup_completion)
161 160 else:
162 161 # Up history
163 162 if event.KeyCode == wx.WXK_UP and (
164 163 ( current_line_number == self.current_prompt_line and
165 164 event.Modifiers in (wx.MOD_NONE, wx.MOD_WIN) )
166 165 or event.ControlDown() ):
167 166 new_buffer = self.get_history_previous(
168 167 self.get_current_edit_buffer())
169 168 if new_buffer is not None:
170 169 self.replace_current_edit_buffer(new_buffer)
171 170 if self.GetCurrentLine() > self.current_prompt_line:
172 171 # Go to first line, for seemless history up.
173 172 self.GotoPos(self.current_prompt_pos)
174 173 # Down history
175 174 elif event.KeyCode == wx.WXK_DOWN and (
176 175 ( current_line_number == self.LineCount -1 and
177 176 event.Modifiers in (wx.MOD_NONE, wx.MOD_WIN) )
178 177 or event.ControlDown() ):
179 178 new_buffer = self.get_history_next()
180 179 if new_buffer is not None:
181 180 self.replace_current_edit_buffer(new_buffer)
182 181 elif event.KeyCode == ord('\t'):
183 182 last_line = self.get_current_edit_buffer().split('\n')[-1]
184 183 if not re.match(r'^\s*$', last_line):
185 184 self.do_completion()
186 185 else:
187 186 event.Skip()
188 187 else:
189 188 ConsoleWidget._on_key_down(self, event, skip=skip)
190 189
191 190
192 191 def _on_key_up(self, event, skip=True):
193 192 if event.KeyCode == 59:
194 193 # Intercepting '.'
195 194 event.Skip()
196 195 self.popup_completion(create=True)
197 196 else:
198 197 ConsoleWidget._on_key_up(self, event, skip=skip)
199 198
200 199
201 200 if __name__ == '__main__':
202 201 class MainWindow(wx.Frame):
203 202 def __init__(self, parent, id, title):
204 203 wx.Frame.__init__(self, parent, id, title, size=(300,250))
205 204 self._sizer = wx.BoxSizer(wx.VERTICAL)
206 205 self.shell = IPythonWxController(self)
207 206 self._sizer.Add(self.shell, 1, wx.EXPAND)
208 207 self.SetSizer(self._sizer)
209 208 self.SetAutoLayout(1)
210 209 self.Show(True)
211 210
212 211 app = wx.PySimpleApp()
213 212 frame = MainWindow(None, wx.ID_ANY, 'Ipython')
214 213 frame.shell.SetFocus()
215 214 frame.SetSize((680, 460))
216 215 self = frame.shell
217 216
218 217 app.MainLoop()
219 218
General Comments 0
You need to be logged in to leave comments. Login now