##// END OF EJS Templates
Cleanup of config, renamed _xxxx_BG keus into stdout,stdin,stderr keys
Laurent Dufrechou -
Show More
@@ -1,552 +1,548 b''
1 # encoding: utf-8
1 # encoding: utf-8
2 """
2 """
3 A Wx widget to act as a console and input commands.
3 A Wx widget to act as a console and input commands.
4
4
5 This widget deals with prompts and provides an edit buffer
5 This widget deals with prompts and provides an edit buffer
6 restricted to after the last prompt.
6 restricted to after the last prompt.
7 """
7 """
8
8
9 __docformat__ = "restructuredtext en"
9 __docformat__ = "restructuredtext en"
10
10
11 #-------------------------------------------------------------------------------
11 #-------------------------------------------------------------------------------
12 # Copyright (C) 2008 The IPython Development Team
12 # Copyright (C) 2008 The IPython Development Team
13 #
13 #
14 # Distributed under the terms of the BSD License. The full license is
14 # Distributed under the terms of the BSD License. The full license is
15 # in the file COPYING, distributed as part of this software.
15 # in the file COPYING, distributed as part of this software.
16 #-------------------------------------------------------------------------------
16 #-------------------------------------------------------------------------------
17
17
18 #-------------------------------------------------------------------------------
18 #-------------------------------------------------------------------------------
19 # Imports
19 # Imports
20 #-------------------------------------------------------------------------------
20 #-------------------------------------------------------------------------------
21
21
22 import wx
22 import wx
23 import wx.stc as stc
23 import wx.stc as stc
24
24
25 from wx.py import editwindow
25 from wx.py import editwindow
26 import time
26 import time
27 import sys
27 import sys
28 import string
28 import string
29
29
30 LINESEP = '\n'
30 LINESEP = '\n'
31 if sys.platform == 'win32':
31 if sys.platform == 'win32':
32 LINESEP = '\n\r'
32 LINESEP = '\n\r'
33
33
34 import re
34 import re
35
35
36 # FIXME: Need to provide an API for non user-generated display on the
36 # FIXME: Need to provide an API for non user-generated display on the
37 # screen: this should not be editable by the user.
37 # screen: this should not be editable by the user.
38 #-------------------------------------------------------------------------------
38 #-------------------------------------------------------------------------------
39 # Constants
39 # Constants
40 #-------------------------------------------------------------------------------
40 #-------------------------------------------------------------------------------
41 _COMPLETE_BUFFER_MARKER = 31
41 _COMPLETE_BUFFER_MARKER = 31
42 _ERROR_MARKER = 30
42 _ERROR_MARKER = 30
43 _INPUT_MARKER = 29
43 _INPUT_MARKER = 29
44
44
45 _DEFAULT_SIZE = 10
45 _DEFAULT_SIZE = 10
46 if sys.platform == 'darwin':
46 if sys.platform == 'darwin':
47 _DEFAULT_SIZE = 12
47 _DEFAULT_SIZE = 12
48
48
49 _DEFAULT_STYLE = {
49 _DEFAULT_STYLE = {
50 #background definition
50 #background definition
51 'stdout' : 'fore:#0000FF',
52 'stderr' : 'fore:#007f00',
53 'trace' : 'fore:#FF0000',
54
55 'default' : 'size:%d' % _DEFAULT_SIZE,
51 'default' : 'size:%d' % _DEFAULT_SIZE,
56 'bracegood' : 'fore:#00AA00,back:#000000,bold',
52 'bracegood' : 'fore:#00AA00,back:#000000,bold',
57 'bracebad' : 'fore:#FF0000,back:#000000,bold',
53 'bracebad' : 'fore:#FF0000,back:#000000,bold',
58
54
59 # properties for the various Python lexer styles
55 # properties for the various Python lexer styles
60 'comment' : 'fore:#007F00',
56 'comment' : 'fore:#007F00',
61 'number' : 'fore:#007F7F',
57 'number' : 'fore:#007F7F',
62 'string' : 'fore:#7F007F,italic',
58 'string' : 'fore:#7F007F,italic',
63 'char' : 'fore:#7F007F,italic',
59 'char' : 'fore:#7F007F,italic',
64 'keyword' : 'fore:#00007F,bold',
60 'keyword' : 'fore:#00007F,bold',
65 'triple' : 'fore:#7F0000',
61 'triple' : 'fore:#7F0000',
66 'tripledouble' : 'fore:#7F0000',
62 'tripledouble' : 'fore:#7F0000',
67 'class' : 'fore:#0000FF,bold,underline',
63 'class' : 'fore:#0000FF,bold,underline',
68 'def' : 'fore:#007F7F,bold',
64 'def' : 'fore:#007F7F,bold',
69 'operator' : 'bold'
65 'operator' : 'bold'
70 }
66 }
71
67
72 # new style numbers
68 # new style numbers
73 _STDOUT_STYLE = 15
69 _STDOUT_STYLE = 15
74 _STDERR_STYLE = 16
70 _STDERR_STYLE = 16
75 _TRACE_STYLE = 17
71 _TRACE_STYLE = 17
76
72
77
73
78 # system colors
74 # system colors
79 #SYS_COLOUR_BACKGROUND = wx.SystemSettings.GetColour(wx.SYS_COLOUR_BACKGROUND)
75 #SYS_COLOUR_BACKGROUND = wx.SystemSettings.GetColour(wx.SYS_COLOUR_BACKGROUND)
80
76
81 #-------------------------------------------------------------------------------
77 #-------------------------------------------------------------------------------
82 # The console widget class
78 # The console widget class
83 #-------------------------------------------------------------------------------
79 #-------------------------------------------------------------------------------
84 class ConsoleWidget(editwindow.EditWindow):
80 class ConsoleWidget(editwindow.EditWindow):
85 """ Specialized styled text control view for console-like workflow.
81 """ Specialized styled text control view for console-like workflow.
86
82
87 This widget is mainly interested in dealing with the prompt and
83 This widget is mainly interested in dealing with the prompt and
88 keeping the cursor inside the editing line.
84 keeping the cursor inside the editing line.
89 """
85 """
90
86
91 # This is where the title captured from the ANSI escape sequences are
87 # This is where the title captured from the ANSI escape sequences are
92 # stored.
88 # stored.
93 title = 'Console'
89 title = 'Console'
94
90
95 # The buffer being edited.
91 # The buffer being edited.
96 def _set_input_buffer(self, string):
92 def _set_input_buffer(self, string):
97 self.SetSelection(self.current_prompt_pos, self.GetLength())
93 self.SetSelection(self.current_prompt_pos, self.GetLength())
98 self.ReplaceSelection(string)
94 self.ReplaceSelection(string)
99 self.GotoPos(self.GetLength())
95 self.GotoPos(self.GetLength())
100
96
101 def _get_input_buffer(self):
97 def _get_input_buffer(self):
102 """ Returns the text in current edit buffer.
98 """ Returns the text in current edit buffer.
103 """
99 """
104 input_buffer = self.GetTextRange(self.current_prompt_pos,
100 input_buffer = self.GetTextRange(self.current_prompt_pos,
105 self.GetLength())
101 self.GetLength())
106 input_buffer = input_buffer.replace(LINESEP, '\n')
102 input_buffer = input_buffer.replace(LINESEP, '\n')
107 return input_buffer
103 return input_buffer
108
104
109 input_buffer = property(_get_input_buffer, _set_input_buffer)
105 input_buffer = property(_get_input_buffer, _set_input_buffer)
110
106
111 style = _DEFAULT_STYLE.copy()
107 style = _DEFAULT_STYLE.copy()
112
108
113 # Translation table from ANSI escape sequences to color. Override
109 # Translation table from ANSI escape sequences to color. Override
114 # this to specify your colors.
110 # this to specify your colors.
115 ANSI_STYLES = {'0;30': [0, 'BLACK'], '0;31': [1, 'RED'],
111 ANSI_STYLES = {'0;30': [0, 'BLACK'], '0;31': [1, 'RED'],
116 '0;32': [2, 'GREEN'], '0;33': [3, 'BROWN'],
112 '0;32': [2, 'GREEN'], '0;33': [3, 'BROWN'],
117 '0;34': [4, 'BLUE'], '0;35': [5, 'PURPLE'],
113 '0;34': [4, 'BLUE'], '0;35': [5, 'PURPLE'],
118 '0;36': [6, 'CYAN'], '0;37': [7, 'LIGHT GREY'],
114 '0;36': [6, 'CYAN'], '0;37': [7, 'LIGHT GREY'],
119 '1;30': [8, 'DARK GREY'], '1;31': [9, 'RED'],
115 '1;30': [8, 'DARK GREY'], '1;31': [9, 'RED'],
120 '1;32': [10, 'SEA GREEN'], '1;33': [11, 'YELLOW'],
116 '1;32': [10, 'SEA GREEN'], '1;33': [11, 'YELLOW'],
121 '1;34': [12, 'LIGHT BLUE'], '1;35': [13, 'MEDIUM VIOLET RED'],
117 '1;34': [12, 'LIGHT BLUE'], '1;35': [13, 'MEDIUM VIOLET RED'],
122 '1;36': [14, 'LIGHT STEEL BLUE'], '1;37': [15, 'YELLOW']}
118 '1;36': [14, 'LIGHT STEEL BLUE'], '1;37': [15, 'YELLOW']}
123
119
124 #we define platform specific fonts
120 #we define platform specific fonts
125 if wx.Platform == '__WXMSW__':
121 if wx.Platform == '__WXMSW__':
126 faces = { 'times': 'Times New Roman',
122 faces = { 'times': 'Times New Roman',
127 'mono' : 'Courier New',
123 'mono' : 'Courier New',
128 'helv' : 'Arial',
124 'helv' : 'Arial',
129 'other': 'Comic Sans MS',
125 'other': 'Comic Sans MS',
130 'size' : 10,
126 'size' : 10,
131 'size2': 8,
127 'size2': 8,
132 }
128 }
133 elif wx.Platform == '__WXMAC__':
129 elif wx.Platform == '__WXMAC__':
134 faces = { 'times': 'Times New Roman',
130 faces = { 'times': 'Times New Roman',
135 'mono' : 'Monaco',
131 'mono' : 'Monaco',
136 'helv' : 'Arial',
132 'helv' : 'Arial',
137 'other': 'Comic Sans MS',
133 'other': 'Comic Sans MS',
138 'size' : 10,
134 'size' : 10,
139 'size2': 8,
135 'size2': 8,
140 }
136 }
141 else:
137 else:
142 faces = { 'times': 'Times',
138 faces = { 'times': 'Times',
143 'mono' : 'Courier',
139 'mono' : 'Courier',
144 'helv' : 'Helvetica',
140 'helv' : 'Helvetica',
145 'other': 'new century schoolbook',
141 'other': 'new century schoolbook',
146 'size' : 10,
142 'size' : 10,
147 'size2': 8,
143 'size2': 8,
148 }
144 }
149
145
150 # Store the last time a refresh was done
146 # Store the last time a refresh was done
151 _last_refresh_time = 0
147 _last_refresh_time = 0
152
148
153 #--------------------------------------------------------------------------
149 #--------------------------------------------------------------------------
154 # Public API
150 # Public API
155 #--------------------------------------------------------------------------
151 #--------------------------------------------------------------------------
156
152
157 def __init__(self, parent, id=wx.ID_ANY, pos=wx.DefaultPosition,
153 def __init__(self, parent, id=wx.ID_ANY, pos=wx.DefaultPosition,
158 size=wx.DefaultSize, style=wx.WANTS_CHARS, ):
154 size=wx.DefaultSize, style=wx.WANTS_CHARS, ):
159 editwindow.EditWindow.__init__(self, parent, id, pos, size, style)
155 editwindow.EditWindow.__init__(self, parent, id, pos, size, style)
160 self.configure_scintilla()
156 self.configure_scintilla()
161 self.enter_catched = False #this var track if 'enter' key as ever been processed
157 self.enter_catched = False #this var track if 'enter' key as ever been processed
162 #thus it will only be reallowed until key goes up
158 #thus it will only be reallowed until key goes up
163 self.current_prompt_pos = 0
159 self.current_prompt_pos = 0
164
160
165 self.Bind(wx.EVT_KEY_DOWN, self._on_key_down)
161 self.Bind(wx.EVT_KEY_DOWN, self._on_key_down)
166 self.Bind(wx.EVT_KEY_UP, self._on_key_up)
162 self.Bind(wx.EVT_KEY_UP, self._on_key_up)
167
163
168
164
169 def write(self, text, refresh=True):
165 def write(self, text, refresh=True):
170 """ Write given text to buffer, while translating the ansi escape
166 """ Write given text to buffer, while translating the ansi escape
171 sequences.
167 sequences.
172 """
168 """
173 # XXX: do not put print statements to sys.stdout/sys.stderr in
169 # XXX: do not put print statements to sys.stdout/sys.stderr in
174 # this method, the print statements will call this method, as
170 # this method, the print statements will call this method, as
175 # you will end up with an infinit loop
171 # you will end up with an infinit loop
176 title = self.title_pat.split(text)
172 title = self.title_pat.split(text)
177 if len(title)>1:
173 if len(title)>1:
178 self.title = title[-2]
174 self.title = title[-2]
179
175
180 text = self.title_pat.sub('', text)
176 text = self.title_pat.sub('', text)
181 segments = self.color_pat.split(text)
177 segments = self.color_pat.split(text)
182 segment = segments.pop(0)
178 segment = segments.pop(0)
183 self.GotoPos(self.GetLength())
179 self.GotoPos(self.GetLength())
184 self.StartStyling(self.GetLength(), 0xFF)
180 self.StartStyling(self.GetLength(), 0xFF)
185 try:
181 try:
186 self.AppendText(segment)
182 self.AppendText(segment)
187 except UnicodeDecodeError:
183 except UnicodeDecodeError:
188 # XXX: Do I really want to skip the exception?
184 # XXX: Do I really want to skip the exception?
189 pass
185 pass
190
186
191 if segments:
187 if segments:
192 for ansi_tag, text in zip(segments[::2], segments[1::2]):
188 for ansi_tag, text in zip(segments[::2], segments[1::2]):
193 self.StartStyling(self.GetLength(), 0xFF)
189 self.StartStyling(self.GetLength(), 0xFF)
194 try:
190 try:
195 self.AppendText(text)
191 self.AppendText(text)
196 except UnicodeDecodeError:
192 except UnicodeDecodeError:
197 # XXX: Do I really want to skip the exception?
193 # XXX: Do I really want to skip the exception?
198 pass
194 pass
199
195
200 if ansi_tag not in self.ANSI_STYLES:
196 if ansi_tag not in self.ANSI_STYLES:
201 style = 0
197 style = 0
202 else:
198 else:
203 style = self.ANSI_STYLES[ansi_tag][0]
199 style = self.ANSI_STYLES[ansi_tag][0]
204
200
205 self.SetStyling(len(text), style)
201 self.SetStyling(len(text), style)
206
202
207 self.GotoPos(self.GetLength())
203 self.GotoPos(self.GetLength())
208 if refresh:
204 if refresh:
209 current_time = time.time()
205 current_time = time.time()
210 if current_time - self._last_refresh_time > 0.03:
206 if current_time - self._last_refresh_time > 0.03:
211 if sys.platform == 'win32':
207 if sys.platform == 'win32':
212 wx.SafeYield()
208 wx.SafeYield()
213 else:
209 else:
214 wx.Yield()
210 wx.Yield()
215 # self.ProcessEvent(wx.PaintEvent())
211 # self.ProcessEvent(wx.PaintEvent())
216 self._last_refresh_time = current_time
212 self._last_refresh_time = current_time
217
213
218
214
219 def new_prompt(self, prompt):
215 def new_prompt(self, prompt):
220 """ Prints a prompt at start of line, and move the start of the
216 """ Prints a prompt at start of line, and move the start of the
221 current block there.
217 current block there.
222
218
223 The prompt can be given with ascii escape sequences.
219 The prompt can be given with ascii escape sequences.
224 """
220 """
225 self.write(prompt, refresh=False)
221 self.write(prompt, refresh=False)
226 # now we update our cursor giving end of prompt
222 # now we update our cursor giving end of prompt
227 self.current_prompt_pos = self.GetLength()
223 self.current_prompt_pos = self.GetLength()
228 self.current_prompt_line = self.GetCurrentLine()
224 self.current_prompt_line = self.GetCurrentLine()
229 self.EnsureCaretVisible()
225 self.EnsureCaretVisible()
230
226
231
227
232 def scroll_to_bottom(self):
228 def scroll_to_bottom(self):
233 maxrange = self.GetScrollRange(wx.VERTICAL)
229 maxrange = self.GetScrollRange(wx.VERTICAL)
234 self.ScrollLines(maxrange)
230 self.ScrollLines(maxrange)
235
231
236
232
237 def pop_completion(self, possibilities, offset=0):
233 def pop_completion(self, possibilities, offset=0):
238 """ Pops up an autocompletion menu. Offset is the offset
234 """ Pops up an autocompletion menu. Offset is the offset
239 in characters of the position at which the menu should
235 in characters of the position at which the menu should
240 appear, relativ to the cursor.
236 appear, relativ to the cursor.
241 """
237 """
242 self.AutoCompSetIgnoreCase(False)
238 self.AutoCompSetIgnoreCase(False)
243 self.AutoCompSetAutoHide(False)
239 self.AutoCompSetAutoHide(False)
244 self.AutoCompSetMaxHeight(len(possibilities))
240 self.AutoCompSetMaxHeight(len(possibilities))
245 self.AutoCompShow(offset, " ".join(possibilities))
241 self.AutoCompShow(offset, " ".join(possibilities))
246
242
247
243
248 def get_line_width(self):
244 def get_line_width(self):
249 """ Return the width of the line in characters.
245 """ Return the width of the line in characters.
250 """
246 """
251 return self.GetSize()[0]/self.GetCharWidth()
247 return self.GetSize()[0]/self.GetCharWidth()
252
248
253 #--------------------------------------------------------------------------
249 #--------------------------------------------------------------------------
254 # EditWindow API
250 # EditWindow API
255 #--------------------------------------------------------------------------
251 #--------------------------------------------------------------------------
256
252
257 def OnUpdateUI(self, event):
253 def OnUpdateUI(self, event):
258 """ Override the OnUpdateUI of the EditWindow class, to prevent
254 """ Override the OnUpdateUI of the EditWindow class, to prevent
259 syntax highlighting both for faster redraw, and for more
255 syntax highlighting both for faster redraw, and for more
260 consistent look and feel.
256 consistent look and feel.
261 """
257 """
262
258
263 #--------------------------------------------------------------------------
259 #--------------------------------------------------------------------------
264 # Styling API
260 # Styling API
265 #--------------------------------------------------------------------------
261 #--------------------------------------------------------------------------
266
262
267 def configure_scintilla(self):
263 def configure_scintilla(self):
268
264
269 p = self.style
265 p = self.style
270
266
271 #First we define the special background colors
267 #First we define the special background colors
272 if '_COMPLETE_BUFFER_BG' in p:
268 if 'trace' in p:
273 _COMPLETE_BUFFER_BG = p['_COMPLETE_BUFFER_BG']
269 _COMPLETE_BUFFER_BG = p['trace']
274 else:
270 else:
275 _COMPLETE_BUFFER_BG = '#FAFAF1' # Nice green
271 _COMPLETE_BUFFER_BG = '#FAFAF1' # Nice green
276
272
277 if '_INPUT_BUFFER_BG' in p:
273 if 'stdout' in p:
278 _INPUT_BUFFER_BG = p['_INPUT_BUFFER_BG']
274 _INPUT_BUFFER_BG = p['stdout']
279 else:
275 else:
280 _INPUT_BUFFER_BG = '#FDFFD3' # Nice yellow
276 _INPUT_BUFFER_BG = '#FDFFD3' # Nice yellow
281
277
282 if '_ERROR_BG' in p:
278 if 'stderr' in p:
283 _ERROR_BG = p['_ERROR_BG']
279 _ERROR_BG = p['stderr']
284 else:
280 else:
285 _ERROR_BG = '#FFF1F1' # Nice red
281 _ERROR_BG = '#FFF1F1' # Nice red
286
282
287 # Marker for complete buffer.
283 # Marker for complete buffer.
288 self.MarkerDefine(_COMPLETE_BUFFER_MARKER, stc.STC_MARK_BACKGROUND,
284 self.MarkerDefine(_COMPLETE_BUFFER_MARKER, stc.STC_MARK_BACKGROUND,
289 background = _COMPLETE_BUFFER_BG)
285 background = _COMPLETE_BUFFER_BG)
290
286
291 # Marker for current input buffer.
287 # Marker for current input buffer.
292 self.MarkerDefine(_INPUT_MARKER, stc.STC_MARK_BACKGROUND,
288 self.MarkerDefine(_INPUT_MARKER, stc.STC_MARK_BACKGROUND,
293 background = _INPUT_BUFFER_BG)
289 background = _INPUT_BUFFER_BG)
294 # Marker for tracebacks.
290 # Marker for tracebacks.
295 self.MarkerDefine(_ERROR_MARKER, stc.STC_MARK_BACKGROUND,
291 self.MarkerDefine(_ERROR_MARKER, stc.STC_MARK_BACKGROUND,
296 background = _ERROR_BG)
292 background = _ERROR_BG)
297
293
298 self.SetEOLMode(stc.STC_EOL_LF)
294 self.SetEOLMode(stc.STC_EOL_LF)
299
295
300 # Ctrl"+" or Ctrl "-" can be used to zoomin/zoomout the text inside
296 # Ctrl"+" or Ctrl "-" can be used to zoomin/zoomout the text inside
301 # the widget
297 # the widget
302 self.CmdKeyAssign(ord('+'), stc.STC_SCMOD_CTRL, stc.STC_CMD_ZOOMIN)
298 self.CmdKeyAssign(ord('+'), stc.STC_SCMOD_CTRL, stc.STC_CMD_ZOOMIN)
303 self.CmdKeyAssign(ord('-'), stc.STC_SCMOD_CTRL, stc.STC_CMD_ZOOMOUT)
299 self.CmdKeyAssign(ord('-'), stc.STC_SCMOD_CTRL, stc.STC_CMD_ZOOMOUT)
304 # Also allow Ctrl Shift "=" for poor non US keyboard users.
300 # Also allow Ctrl Shift "=" for poor non US keyboard users.
305 self.CmdKeyAssign(ord('='), stc.STC_SCMOD_CTRL|stc.STC_SCMOD_SHIFT,
301 self.CmdKeyAssign(ord('='), stc.STC_SCMOD_CTRL|stc.STC_SCMOD_SHIFT,
306 stc.STC_CMD_ZOOMIN)
302 stc.STC_CMD_ZOOMIN)
307
303
308 # Keys: we need to clear some of the keys the that don't play
304 # Keys: we need to clear some of the keys the that don't play
309 # well with a console.
305 # well with a console.
310 self.CmdKeyClear(ord('D'), stc.STC_SCMOD_CTRL)
306 self.CmdKeyClear(ord('D'), stc.STC_SCMOD_CTRL)
311 self.CmdKeyClear(ord('L'), stc.STC_SCMOD_CTRL)
307 self.CmdKeyClear(ord('L'), stc.STC_SCMOD_CTRL)
312 self.CmdKeyClear(ord('T'), stc.STC_SCMOD_CTRL)
308 self.CmdKeyClear(ord('T'), stc.STC_SCMOD_CTRL)
313 self.CmdKeyClear(ord('A'), stc.STC_SCMOD_CTRL)
309 self.CmdKeyClear(ord('A'), stc.STC_SCMOD_CTRL)
314
310
315 self.SetEOLMode(stc.STC_EOL_CRLF)
311 self.SetEOLMode(stc.STC_EOL_CRLF)
316 self.SetWrapMode(stc.STC_WRAP_CHAR)
312 self.SetWrapMode(stc.STC_WRAP_CHAR)
317 self.SetWrapMode(stc.STC_WRAP_WORD)
313 self.SetWrapMode(stc.STC_WRAP_WORD)
318 self.SetBufferedDraw(True)
314 self.SetBufferedDraw(True)
319
315
320 if 'antialiasing' in p:
316 if 'antialiasing' in p:
321 self.SetUseAntiAliasing(p['antialiasing'])
317 self.SetUseAntiAliasing(p['antialiasing'])
322 else:
318 else:
323 self.SetUseAntiAliasing(True)
319 self.SetUseAntiAliasing(True)
324
320
325 self.SetLayoutCache(stc.STC_CACHE_PAGE)
321 self.SetLayoutCache(stc.STC_CACHE_PAGE)
326 self.SetUndoCollection(False)
322 self.SetUndoCollection(False)
327 self.SetUseTabs(True)
323 self.SetUseTabs(True)
328 self.SetIndent(4)
324 self.SetIndent(4)
329 self.SetTabWidth(4)
325 self.SetTabWidth(4)
330
326
331 # we don't want scintilla's autocompletion to choose
327 # we don't want scintilla's autocompletion to choose
332 # automaticaly out of a single choice list, as we pop it up
328 # automaticaly out of a single choice list, as we pop it up
333 # automaticaly
329 # automaticaly
334 self.AutoCompSetChooseSingle(False)
330 self.AutoCompSetChooseSingle(False)
335 self.AutoCompSetMaxHeight(10)
331 self.AutoCompSetMaxHeight(10)
336 # XXX: this doesn't seem to have an effect.
332 # XXX: this doesn't seem to have an effect.
337 self.AutoCompSetFillUps('\n')
333 self.AutoCompSetFillUps('\n')
338
334
339 self.SetMargins(3, 3) #text is moved away from border with 3px
335 self.SetMargins(3, 3) #text is moved away from border with 3px
340 # Suppressing Scintilla margins
336 # Suppressing Scintilla margins
341 self.SetMarginWidth(0, 0)
337 self.SetMarginWidth(0, 0)
342 self.SetMarginWidth(1, 0)
338 self.SetMarginWidth(1, 0)
343 self.SetMarginWidth(2, 0)
339 self.SetMarginWidth(2, 0)
344
340
345 # Xterm escape sequences
341 # Xterm escape sequences
346 self.color_pat = re.compile('\x01?\x1b\[(.*?)m\x02?')
342 self.color_pat = re.compile('\x01?\x1b\[(.*?)m\x02?')
347 self.title_pat = re.compile('\x1b]0;(.*?)\x07')
343 self.title_pat = re.compile('\x1b]0;(.*?)\x07')
348
344
349 # styles
345 # styles
350
346
351 if 'carret_color' in p:
347 if 'carret_color' in p:
352 self.SetCaretForeground(p['carret_color'])
348 self.SetCaretForeground(p['carret_color'])
353 else:
349 else:
354 self.SetCaretForeground('BLACK')
350 self.SetCaretForeground('BLACK')
355
351
356 if 'background_color' in p:
352 if 'background_color' in p:
357 background_color = p['background_color']
353 background_color = p['background_color']
358 else:
354 else:
359 background_color = 'WHITE'
355 background_color = 'WHITE'
360
356
361 if 'default' in p:
357 if 'default' in p:
362 if 'back' not in p['default']:
358 if 'back' not in p['default']:
363 p['default']+=',back:%s' % background_color
359 p['default']+=',back:%s' % background_color
364 if 'size' not in p['default']:
360 if 'size' not in p['default']:
365 p['default']+=',size:%s' % self.faces['size']
361 p['default']+=',size:%s' % self.faces['size']
366 if 'face' not in p['default']:
362 if 'face' not in p['default']:
367 p['default']+=',face:%s' % self.faces['mono']
363 p['default']+=',face:%s' % self.faces['mono']
368
364
369 self.StyleSetSpec(stc.STC_STYLE_DEFAULT, p['default'])
365 self.StyleSetSpec(stc.STC_STYLE_DEFAULT, p['default'])
370 else:
366 else:
371 self.StyleSetSpec(stc.STC_STYLE_DEFAULT, "fore:%s,back:%s,size:%d,face:%s"
367 self.StyleSetSpec(stc.STC_STYLE_DEFAULT, "fore:%s,back:%s,size:%d,face:%s"
372 % (self.ANSI_STYLES['0;30'][1], background_color,
368 % (self.ANSI_STYLES['0;30'][1], background_color,
373 self.faces['size'], self.faces['mono']))
369 self.faces['size'], self.faces['mono']))
374
370
375 #all styles = default one
371 #all styles = default one
376 self.StyleClearAll()
372 self.StyleClearAll()
377
373
378 # XXX: two lines below are usefull if not using the lexer
374 # XXX: two lines below are usefull if not using the lexer
379 #for style in self.ANSI_STYLES.values():
375 #for style in self.ANSI_STYLES.values():
380 # self.StyleSetSpec(style[0], "bold,fore:%s" % style[1])
376 # self.StyleSetSpec(style[0], "bold,fore:%s" % style[1])
381
377
382 #prompt definition
378 #prompt definition
383 if 'prompt_in1' in p:
379 if 'prompt_in1' in p:
384 self.prompt_in1 = p['prompt_in1']
380 self.prompt_in1 = p['prompt_in1']
385 else:
381 else:
386 self.prompt_in1 = \
382 self.prompt_in1 = \
387 '\n\x01\x1b[0;34m\x02In [\x01\x1b[1;34m\x02$number\x01\x1b[0;34m\x02]: \x01\x1b[0m\x02'
383 '\n\x01\x1b[0;34m\x02In [\x01\x1b[1;34m\x02$number\x01\x1b[0;34m\x02]: \x01\x1b[0m\x02'
388
384
389 if 'prompt_out' in p:
385 if 'prompt_out' in p:
390 self.prompt_out = p['prompt_out']
386 self.prompt_out = p['prompt_out']
391 else:
387 else:
392 self.prompt_out = \
388 self.prompt_out = \
393 '\x01\x1b[0;31m\x02Out[\x01\x1b[1;31m\x02$number\x01\x1b[0;31m\x02]: \x01\x1b[0m\x02'
389 '\x01\x1b[0;31m\x02Out[\x01\x1b[1;31m\x02$number\x01\x1b[0;31m\x02]: \x01\x1b[0m\x02'
394
390
395 self.output_prompt_template = string.Template(self.prompt_out)
391 self.output_prompt_template = string.Template(self.prompt_out)
396 self.input_prompt_template = string.Template(self.prompt_in1)
392 self.input_prompt_template = string.Template(self.prompt_in1)
397
393
398 if 'stdout' in p:
394 if 'stdout' in p:
399 self.StyleSetSpec(_STDOUT_STYLE, p['stdout'])
395 self.StyleSetSpec(_STDOUT_STYLE, p['stdout'])
400 if 'stderr' in p:
396 if 'stderr' in p:
401 self.StyleSetSpec(_STDERR_STYLE, p['stderr'])
397 self.StyleSetSpec(_STDERR_STYLE, p['stderr'])
402 if 'trace' in p:
398 if 'trace' in p:
403 self.StyleSetSpec(_TRACE_STYLE, p['trace'])
399 self.StyleSetSpec(_TRACE_STYLE, p['trace'])
404 if 'bracegood' in p:
400 if 'bracegood' in p:
405 self.StyleSetSpec(stc.STC_STYLE_BRACELIGHT, p['bracegood'])
401 self.StyleSetSpec(stc.STC_STYLE_BRACELIGHT, p['bracegood'])
406 if 'bracebad' in p:
402 if 'bracebad' in p:
407 self.StyleSetSpec(stc.STC_STYLE_BRACEBAD, p['bracebad'])
403 self.StyleSetSpec(stc.STC_STYLE_BRACEBAD, p['bracebad'])
408 if 'comment' in p:
404 if 'comment' in p:
409 self.StyleSetSpec(stc.STC_P_COMMENTLINE, p['comment'])
405 self.StyleSetSpec(stc.STC_P_COMMENTLINE, p['comment'])
410 if 'number' in p:
406 if 'number' in p:
411 self.StyleSetSpec(stc.STC_P_NUMBER, p['number'])
407 self.StyleSetSpec(stc.STC_P_NUMBER, p['number'])
412 if 'string' in p:
408 if 'string' in p:
413 self.StyleSetSpec(stc.STC_P_STRING, p['string'])
409 self.StyleSetSpec(stc.STC_P_STRING, p['string'])
414 if 'char' in p:
410 if 'char' in p:
415 self.StyleSetSpec(stc.STC_P_CHARACTER, p['char'])
411 self.StyleSetSpec(stc.STC_P_CHARACTER, p['char'])
416 if 'keyword' in p:
412 if 'keyword' in p:
417 self.StyleSetSpec(stc.STC_P_WORD, p['keyword'])
413 self.StyleSetSpec(stc.STC_P_WORD, p['keyword'])
418 if 'keyword' in p:
414 if 'keyword' in p:
419 self.StyleSetSpec(stc.STC_P_WORD2, p['keyword'])
415 self.StyleSetSpec(stc.STC_P_WORD2, p['keyword'])
420 if 'triple' in p:
416 if 'triple' in p:
421 self.StyleSetSpec(stc.STC_P_TRIPLE, p['triple'])
417 self.StyleSetSpec(stc.STC_P_TRIPLE, p['triple'])
422 if 'tripledouble' in p:
418 if 'tripledouble' in p:
423 self.StyleSetSpec(stc.STC_P_TRIPLEDOUBLE, p['tripledouble'])
419 self.StyleSetSpec(stc.STC_P_TRIPLEDOUBLE, p['tripledouble'])
424 if 'class' in p:
420 if 'class' in p:
425 self.StyleSetSpec(stc.STC_P_CLASSNAME, p['class'])
421 self.StyleSetSpec(stc.STC_P_CLASSNAME, p['class'])
426 if 'def' in p:
422 if 'def' in p:
427 self.StyleSetSpec(stc.STC_P_DEFNAME, p['def'])
423 self.StyleSetSpec(stc.STC_P_DEFNAME, p['def'])
428 if 'operator' in p:
424 if 'operator' in p:
429 self.StyleSetSpec(stc.STC_P_OPERATOR, p['operator'])
425 self.StyleSetSpec(stc.STC_P_OPERATOR, p['operator'])
430 if 'comment' in p:
426 if 'comment' in p:
431 self.StyleSetSpec(stc.STC_P_COMMENTBLOCK, p['comment'])
427 self.StyleSetSpec(stc.STC_P_COMMENTBLOCK, p['comment'])
432
428
433 #--------------------------------------------------------------------------
429 #--------------------------------------------------------------------------
434 # Private API
430 # Private API
435 #--------------------------------------------------------------------------
431 #--------------------------------------------------------------------------
436
432
437 def _on_key_down(self, event, skip=True):
433 def _on_key_down(self, event, skip=True):
438 """ Key press callback used for correcting behavior for
434 """ Key press callback used for correcting behavior for
439 console-like interfaces: the cursor is constraint to be after
435 console-like interfaces: the cursor is constraint to be after
440 the last prompt.
436 the last prompt.
441
437
442 Return True if event as been catched.
438 Return True if event as been catched.
443 """
439 """
444 catched = True
440 catched = True
445 # Intercept some specific keys.
441 # Intercept some specific keys.
446 if event.KeyCode == ord('L') and event.ControlDown() :
442 if event.KeyCode == ord('L') and event.ControlDown() :
447 self.scroll_to_bottom()
443 self.scroll_to_bottom()
448 elif event.KeyCode == ord('K') and event.ControlDown() :
444 elif event.KeyCode == ord('K') and event.ControlDown() :
449 self.input_buffer = ''
445 self.input_buffer = ''
450 elif event.KeyCode == ord('A') and event.ControlDown() :
446 elif event.KeyCode == ord('A') and event.ControlDown() :
451 self.GotoPos(self.GetLength())
447 self.GotoPos(self.GetLength())
452 self.SetSelectionStart(self.current_prompt_pos)
448 self.SetSelectionStart(self.current_prompt_pos)
453 self.SetSelectionEnd(self.GetCurrentPos())
449 self.SetSelectionEnd(self.GetCurrentPos())
454 catched = True
450 catched = True
455 elif event.KeyCode == ord('E') and event.ControlDown() :
451 elif event.KeyCode == ord('E') and event.ControlDown() :
456 self.GotoPos(self.GetLength())
452 self.GotoPos(self.GetLength())
457 catched = True
453 catched = True
458 elif event.KeyCode == wx.WXK_PAGEUP:
454 elif event.KeyCode == wx.WXK_PAGEUP:
459 self.ScrollPages(-1)
455 self.ScrollPages(-1)
460 elif event.KeyCode == wx.WXK_PAGEDOWN:
456 elif event.KeyCode == wx.WXK_PAGEDOWN:
461 self.ScrollPages(1)
457 self.ScrollPages(1)
462 elif event.KeyCode == wx.WXK_UP and event.ShiftDown():
458 elif event.KeyCode == wx.WXK_UP and event.ShiftDown():
463 self.ScrollLines(-1)
459 self.ScrollLines(-1)
464 elif event.KeyCode == wx.WXK_DOWN and event.ShiftDown():
460 elif event.KeyCode == wx.WXK_DOWN and event.ShiftDown():
465 self.ScrollLines(1)
461 self.ScrollLines(1)
466 else:
462 else:
467 catched = False
463 catched = False
468
464
469 if self.AutoCompActive():
465 if self.AutoCompActive():
470 event.Skip()
466 event.Skip()
471 else:
467 else:
472 if event.KeyCode in (13, wx.WXK_NUMPAD_ENTER) and \
468 if event.KeyCode in (13, wx.WXK_NUMPAD_ENTER) and \
473 event.Modifiers in (wx.MOD_NONE, wx.MOD_WIN):
469 event.Modifiers in (wx.MOD_NONE, wx.MOD_WIN):
474 catched = True
470 catched = True
475 if not self.enter_catched:
471 if not self.enter_catched:
476 self.CallTipCancel()
472 self.CallTipCancel()
477 self.write('\n', refresh=False)
473 self.write('\n', refresh=False)
478 # Under windows scintilla seems to be doing funny stuff to the
474 # Under windows scintilla seems to be doing funny stuff to the
479 # line returns here, but the getter for input_buffer filters
475 # line returns here, but the getter for input_buffer filters
480 # this out.
476 # this out.
481 if sys.platform == 'win32':
477 if sys.platform == 'win32':
482 self.input_buffer = self.input_buffer
478 self.input_buffer = self.input_buffer
483 self._on_enter()
479 self._on_enter()
484 self.enter_catched = True
480 self.enter_catched = True
485
481
486 elif event.KeyCode == wx.WXK_HOME:
482 elif event.KeyCode == wx.WXK_HOME:
487 if event.Modifiers in (wx.MOD_NONE, wx.MOD_WIN):
483 if event.Modifiers in (wx.MOD_NONE, wx.MOD_WIN):
488 self.GotoPos(self.current_prompt_pos)
484 self.GotoPos(self.current_prompt_pos)
489 catched = True
485 catched = True
490
486
491 elif event.Modifiers == wx.MOD_SHIFT:
487 elif event.Modifiers == wx.MOD_SHIFT:
492 # FIXME: This behavior is not ideal: if the selection
488 # FIXME: This behavior is not ideal: if the selection
493 # is already started, it will jump.
489 # is already started, it will jump.
494 self.SetSelectionStart(self.current_prompt_pos)
490 self.SetSelectionStart(self.current_prompt_pos)
495 self.SetSelectionEnd(self.GetCurrentPos())
491 self.SetSelectionEnd(self.GetCurrentPos())
496 catched = True
492 catched = True
497
493
498 elif event.KeyCode == wx.WXK_UP:
494 elif event.KeyCode == wx.WXK_UP:
499 if self.GetCurrentLine() > self.current_prompt_line:
495 if self.GetCurrentLine() > self.current_prompt_line:
500 if self.GetCurrentLine() == self.current_prompt_line + 1 \
496 if self.GetCurrentLine() == self.current_prompt_line + 1 \
501 and self.GetColumn(self.GetCurrentPos()) < \
497 and self.GetColumn(self.GetCurrentPos()) < \
502 self.GetColumn(self.current_prompt_pos):
498 self.GetColumn(self.current_prompt_pos):
503 self.GotoPos(self.current_prompt_pos)
499 self.GotoPos(self.current_prompt_pos)
504 else:
500 else:
505 event.Skip()
501 event.Skip()
506 catched = True
502 catched = True
507
503
508 elif event.KeyCode in (wx.WXK_LEFT, wx.WXK_BACK):
504 elif event.KeyCode in (wx.WXK_LEFT, wx.WXK_BACK):
509 if self.GetCurrentPos() > self.current_prompt_pos:
505 if self.GetCurrentPos() > self.current_prompt_pos:
510 event.Skip()
506 event.Skip()
511 catched = True
507 catched = True
512
508
513 if skip and not catched:
509 if skip and not catched:
514 # Put the cursor back in the edit region
510 # Put the cursor back in the edit region
515 if self.GetCurrentPos() < self.current_prompt_pos:
511 if self.GetCurrentPos() < self.current_prompt_pos:
516 self.GotoPos(self.current_prompt_pos)
512 self.GotoPos(self.current_prompt_pos)
517 else:
513 else:
518 event.Skip()
514 event.Skip()
519
515
520 return catched
516 return catched
521
517
522
518
523 def _on_key_up(self, event, skip=True):
519 def _on_key_up(self, event, skip=True):
524 """ If cursor is outside the editing region, put it back.
520 """ If cursor is outside the editing region, put it back.
525 """
521 """
526 event.Skip()
522 event.Skip()
527 if self.GetCurrentPos() < self.current_prompt_pos:
523 if self.GetCurrentPos() < self.current_prompt_pos:
528 self.GotoPos(self.current_prompt_pos)
524 self.GotoPos(self.current_prompt_pos)
529
525
530 self.enter_catched = False #we re-allow enter event processing
526 self.enter_catched = False #we re-allow enter event processing
531
527
532
528
533 if __name__ == '__main__':
529 if __name__ == '__main__':
534 # Some simple code to test the console widget.
530 # Some simple code to test the console widget.
535 class MainWindow(wx.Frame):
531 class MainWindow(wx.Frame):
536 def __init__(self, parent, id, title):
532 def __init__(self, parent, id, title):
537 wx.Frame.__init__(self, parent, id, title, size=(300,250))
533 wx.Frame.__init__(self, parent, id, title, size=(300,250))
538 self._sizer = wx.BoxSizer(wx.VERTICAL)
534 self._sizer = wx.BoxSizer(wx.VERTICAL)
539 self.console_widget = ConsoleWidget(self)
535 self.console_widget = ConsoleWidget(self)
540 self._sizer.Add(self.console_widget, 1, wx.EXPAND)
536 self._sizer.Add(self.console_widget, 1, wx.EXPAND)
541 self.SetSizer(self._sizer)
537 self.SetSizer(self._sizer)
542 self.SetAutoLayout(1)
538 self.SetAutoLayout(1)
543 self.Show(True)
539 self.Show(True)
544
540
545 app = wx.PySimpleApp()
541 app = wx.PySimpleApp()
546 w = MainWindow(None, wx.ID_ANY, 'ConsoleWidget')
542 w = MainWindow(None, wx.ID_ANY, 'ConsoleWidget')
547 w.SetSize((780, 460))
543 w.SetSize((780, 460))
548 w.Show()
544 w.Show()
549
545
550 app.MainLoop()
546 app.MainLoop()
551
547
552
548
@@ -1,183 +1,179 b''
1 """
1 """
2 Entry point for a simple application giving a graphical frontend to
2 Entry point for a simple application giving a graphical frontend to
3 ipython.
3 ipython.
4 """
4 """
5
5
6 try:
6 try:
7 import wx
7 import wx
8 except ImportError, e:
8 except ImportError, e:
9 e.message = """%s
9 e.message = """%s
10 ________________________________________________________________________________
10 ________________________________________________________________________________
11 You need wxPython to run this application.
11 You need wxPython to run this application.
12 """ % e.message
12 """ % e.message
13 e.args = (e.message, ) + e.args[1:]
13 e.args = (e.message, ) + e.args[1:]
14 raise e
14 raise e
15
15
16 import wx.stc as stc
16 import wx.stc as stc
17
17
18 from wx_frontend import WxController
18 from wx_frontend import WxController
19 import __builtin__
19 import __builtin__
20
20
21
21
22 class IPythonXController(WxController):
22 class IPythonXController(WxController):
23 """ Sub class of WxController that adds some application-specific
23 """ Sub class of WxController that adds some application-specific
24 bindings.
24 bindings.
25 """
25 """
26
26
27 debug = False
27 debug = False
28
28
29 def __init__(self, *args, **kwargs):
29 def __init__(self, *args, **kwargs):
30
30
31 WxController.__init__(self, *args, **kwargs)
31 WxController.__init__(self, *args, **kwargs)
32 self.ipython0.ask_exit = self.do_exit
32 self.ipython0.ask_exit = self.do_exit
33
33
34 if kwargs['styledef'] is not None:
34 if kwargs['styledef'] is not None:
35 self.style = kwargs['styledef']
35 self.style = kwargs['styledef']
36
36
37 #we add a vertical line to console widget
37 #we add a vertical line to console widget
38 self.SetEdgeMode(stc.STC_EDGE_LINE)
38 self.SetEdgeMode(stc.STC_EDGE_LINE)
39 self.SetEdgeColumn(88)
39 self.SetEdgeColumn(88)
40
40
41 self.configure_scintilla()
41 self.configure_scintilla()
42
42
43 # Scroll to top
43 # Scroll to top
44 maxrange = self.GetScrollRange(wx.VERTICAL)
44 maxrange = self.GetScrollRange(wx.VERTICAL)
45 self.ScrollLines(-maxrange)
45 self.ScrollLines(-maxrange)
46
46
47
47
48 def _on_key_down(self, event, skip=True):
48 def _on_key_down(self, event, skip=True):
49 # Intercept Ctrl-D to quit
49 # Intercept Ctrl-D to quit
50 if event.KeyCode == ord('D') and event.ControlDown() and \
50 if event.KeyCode == ord('D') and event.ControlDown() and \
51 self.input_buffer == '' and \
51 self.input_buffer == '' and \
52 self._input_state == 'readline':
52 self._input_state == 'readline':
53 wx.CallAfter(self.ask_exit)
53 wx.CallAfter(self.ask_exit)
54 else:
54 else:
55 WxController._on_key_down(self, event, skip=skip)
55 WxController._on_key_down(self, event, skip=skip)
56
56
57
57
58 def ask_exit(self):
58 def ask_exit(self):
59 """ Ask the user whether to exit.
59 """ Ask the user whether to exit.
60 """
60 """
61 self._input_state = 'subprocess'
61 self._input_state = 'subprocess'
62 self.write('\n', refresh=False)
62 self.write('\n', refresh=False)
63 self.capture_output()
63 self.capture_output()
64 self.ipython0.shell.exit()
64 self.ipython0.shell.exit()
65 self.release_output()
65 self.release_output()
66 if not self.ipython0.exit_now:
66 if not self.ipython0.exit_now:
67 wx.CallAfter(self.new_prompt,
67 wx.CallAfter(self.new_prompt,
68 self.input_prompt_template.substitute(
68 self.input_prompt_template.substitute(
69 number=self.last_result['number'] + 1))
69 number=self.last_result['number'] + 1))
70 else:
70 else:
71 wx.CallAfter(wx.GetApp().Exit)
71 wx.CallAfter(wx.GetApp().Exit)
72 self.write('Exiting ...', refresh=False)
72 self.write('Exiting ...', refresh=False)
73
73
74
74
75 def do_exit(self):
75 def do_exit(self):
76 """ Exits the interpreter, kills the windows.
76 """ Exits the interpreter, kills the windows.
77 """
77 """
78 WxController.do_exit(self)
78 WxController.do_exit(self)
79 self.release_output()
79 self.release_output()
80 wx.CallAfter(wx.Exit)
80 wx.CallAfter(wx.Exit)
81
81
82
82
83
83
84 class IPythonX(wx.Frame):
84 class IPythonX(wx.Frame):
85 """ Main frame of the IPythonX app.
85 """ Main frame of the IPythonX app.
86 """
86 """
87
87
88 def __init__(self, parent, id, title, debug=False, style=None):
88 def __init__(self, parent, id, title, debug=False, style=None):
89 wx.Frame.__init__(self, parent, id, title, size=(300,250))
89 wx.Frame.__init__(self, parent, id, title, size=(300,250))
90 self._sizer = wx.BoxSizer(wx.VERTICAL)
90 self._sizer = wx.BoxSizer(wx.VERTICAL)
91 self.shell = IPythonXController(self, debug=debug, styledef=style)
91 self.shell = IPythonXController(self, debug=debug, styledef=style)
92 self._sizer.Add(self.shell, 1, wx.EXPAND)
92 self._sizer.Add(self.shell, 1, wx.EXPAND)
93 self.SetSizer(self._sizer)
93 self.SetSizer(self._sizer)
94 self.SetAutoLayout(1)
94 self.SetAutoLayout(1)
95 self.Show(True)
95 self.Show(True)
96 wx.EVT_CLOSE(self, self.on_close)
96 wx.EVT_CLOSE(self, self.on_close)
97
97
98
98
99 def on_close(self, event):
99 def on_close(self, event):
100 """ Called on closing the windows.
100 """ Called on closing the windows.
101
101
102 Stops the event loop, to close all the child windows.
102 Stops the event loop, to close all the child windows.
103 """
103 """
104 wx.CallAfter(wx.Exit)
104 wx.CallAfter(wx.Exit)
105
105
106
106
107 def main():
107 def main():
108 from optparse import OptionParser
108 from optparse import OptionParser
109 usage = """usage: %prog [options]
109 usage = """usage: %prog [options]
110
110
111 Simple graphical frontend to IPython, using WxWidgets."""
111 Simple graphical frontend to IPython, using WxWidgets."""
112 parser = OptionParser(usage=usage)
112 parser = OptionParser(usage=usage)
113 parser.add_option("-d", "--debug",
113 parser.add_option("-d", "--debug",
114 action="store_true", dest="debug", default=False,
114 action="store_true", dest="debug", default=False,
115 help="Enable debug message for the wx frontend.")
115 help="Enable debug message for the wx frontend.")
116
116
117 parser.add_option("-s", "--style",
117 parser.add_option("-s", "--style",
118 dest="colorset", default="white",
118 dest="colorset", default="white",
119 help="style: white, black")
119 help="style: white, black")
120
120
121 options, args = parser.parse_args()
121 options, args = parser.parse_args()
122
122
123 # Clear the options, to avoid having the ipython0 instance complain
123 # Clear the options, to avoid having the ipython0 instance complain
124 import sys
124 import sys
125 sys.argv = sys.argv[:1]
125 sys.argv = sys.argv[:1]
126
126
127 style = None
127 style = None
128
128
129 if options.colorset == 'black':
129 if options.colorset == 'black':
130 style = {
130 style = {
131 #advanced options
131 #advanced options
132 'antialiasing' : True,
132 'antialiasing' : True,
133
133
134 #background + carret color
134 #background + carret color
135 'carret_color' : 'WHITE',
135 'carret_color' : 'WHITE',
136 'background_color' : 'BLACK',
136 'background_color' : 'BLACK',
137
137
138 #prompt
138 #prompt
139 'prompt_in1' : \
139 'prompt_in1' : \
140 '\n\x01\x1b[0;30m\x02In [\x01\x1b[1;34m\x02$number\x01\x1b[0;30m\x02]: \x01\x1b[0m\x02',
140 '\n\x01\x1b[0;30m\x02In [\x01\x1b[1;34m\x02$number\x01\x1b[0;30m\x02]: \x01\x1b[0m\x02',
141
141
142 'prompt_out' : \
142 'prompt_out' : \
143 '\x01\x1b[0;31m\x02Out[\x01\x1b[1;31m\x02$number\x01\x1b[0;31m\x02]: \x01\x1b[0m\x02',
143 '\x01\x1b[0;31m\x02Out[\x01\x1b[1;31m\x02$number\x01\x1b[0;31m\x02]: \x01\x1b[0m\x02',
144
144
145 #we define the background of old inputs
145 #we define the background of old inputs
146 '_COMPLETE_BUFFER_BG' : '#000000', # RRGGBB: Black
146 'trace' : '#000000', # RRGGBB: Black
147 #we define the background of current input
147 #we define the background of current input
148 '_INPUT_BUFFER_BG' : '#444444', # RRGGBB: Light black
148 'stdout' : '#444444', # RRGGBB: Light black
149 #we define the background when an error is reported
149 #we define the background when an error is reported
150 '_ERROR_BG' : '#800000', # RRGGBB: Light Red
150 'stderr' : '#800000', # RRGGBB: Light Red
151
151
152 #'stdout' : '',#fore:#0000FF',
153 #'stderr' : '',#fore:#007f00',
154 #'trace' : '',#fore:#FF0000',
155
156 #'bracegood' : 'fore:#0000FF,back:#0000FF,bold',
152 #'bracegood' : 'fore:#0000FF,back:#0000FF,bold',
157 #'bracebad' : 'fore:#FF0000,back:#0000FF,bold',
153 #'bracebad' : 'fore:#FF0000,back:#0000FF,bold',
158 'default' : "fore:%s,bold" % ("#EEEEEE"),
154 'default' : "fore:%s,bold" % ("#EEEEEE"),
159
155
160 # properties for the various Python lexer styles
156 # properties for the various Python lexer styles
161 'comment' : 'fore:#BBBBBB,italic',
157 'comment' : 'fore:#BBBBBB,italic',
162 'number' : 'fore:#FF9692',
158 'number' : 'fore:#FF9692',
163 'string' : 'fore:#ed9d13,italic',
159 'string' : 'fore:#ed9d13,italic',
164 'char' : 'fore:#FFFFFF,italic',
160 'char' : 'fore:#FFFFFF,italic',
165 'keyword' : 'fore:#6AB825,bold',
161 'keyword' : 'fore:#6AB825,bold',
166 'triple' : 'fore:#FF7BDD',
162 'triple' : 'fore:#FF7BDD',
167 'tripledouble' : 'fore:#FF7BDD',
163 'tripledouble' : 'fore:#FF7BDD',
168 'class' : 'fore:#FF00FF,bold,underline',
164 'class' : 'fore:#FF00FF,bold,underline',
169 'def' : 'fore:#FFFF00,bold',
165 'def' : 'fore:#FFFF00,bold',
170 'operator' : 'bold'
166 'operator' : 'bold'
171 }
167 }
172
168
173
169
174 app = wx.PySimpleApp()
170 app = wx.PySimpleApp()
175 frame = IPythonX(None, wx.ID_ANY, 'IPythonX', debug=options.debug, style=style)
171 frame = IPythonX(None, wx.ID_ANY, 'IPythonX', debug=options.debug, style=style)
176 frame.shell.SetFocus()
172 frame.shell.SetFocus()
177 frame.shell.app = app
173 frame.shell.app = app
178 frame.SetSize((680, 460))
174 frame.SetSize((680, 460))
179
175
180 app.MainLoop()
176 app.MainLoop()
181
177
182 if __name__ == '__main__':
178 if __name__ == '__main__':
183 main()
179 main()
General Comments 0
You need to be logged in to leave comments. Login now