##// END OF EJS Templates
Tweak magics.
Gael Varoquaux -
Show More
@@ -1,149 +1,159 b''
1 """
1 """
2 Frontend class that uses IPython0 to prefilter the inputs.
2 Frontend class that uses IPython0 to prefilter the inputs.
3
3
4 Using the IPython0 mechanism gives us access to the magics.
4 Using the IPython0 mechanism gives us access to the magics.
5 """
5 """
6 __docformat__ = "restructuredtext en"
6 __docformat__ = "restructuredtext en"
7
7
8 #-------------------------------------------------------------------------------
8 #-------------------------------------------------------------------------------
9 # Copyright (C) 2008 The IPython Development Team
9 # Copyright (C) 2008 The IPython Development Team
10 #
10 #
11 # Distributed under the terms of the BSD License. The full license is in
11 # Distributed under the terms of the BSD License. The full license is in
12 # the file COPYING, distributed as part of this software.
12 # the file COPYING, distributed as part of this software.
13 #-------------------------------------------------------------------------------
13 #-------------------------------------------------------------------------------
14
14
15 #-------------------------------------------------------------------------------
15 #-------------------------------------------------------------------------------
16 # Imports
16 # Imports
17 #-------------------------------------------------------------------------------
17 #-------------------------------------------------------------------------------
18 import sys
18 import sys
19
19
20 from linefrontendbase import LineFrontEndBase, common_prefix
20 from linefrontendbase import LineFrontEndBase, common_prefix
21
21
22 from IPython.ipmaker import make_IPython
22 from IPython.ipmaker import make_IPython
23 from IPython.ipapi import IPApi
23 from IPython.ipapi import IPApi
24 from IPython.kernel.core.redirector_output_trap import RedirectorOutputTrap
24 from IPython.kernel.core.redirector_output_trap import RedirectorOutputTrap
25
25
26 from IPython.genutils import Term
26 from IPython.genutils import Term
27 import pydoc
27 import pydoc
28
28
29 #-------------------------------------------------------------------------------
29 #-------------------------------------------------------------------------------
30 # Utility functions (temporary, should be moved out of here)
30 # Utility functions (temporary, should be moved out of here)
31 #-------------------------------------------------------------------------------
31 #-------------------------------------------------------------------------------
32 import os
32 import os
33 def xterm_system(command):
33 def xterm_system(command):
34 """ Run a command in a separate console window.
34 """ Run a command in a separate console window.
35 """
35 """
36 os.system(("""xterm -title "%s" -e \'/bin/sh -c "%s ; """
36 os.system(("""xterm -title "%s" -e \'/bin/sh -c "%s ; """
37 """echo; echo press enter to close ; """
37 """echo; echo press enter to close ; """
38 # """echo \\"\x1b]0;%s (finished -- press enter to close)\x07\\" ;
38 # """echo \\"\x1b]0;%s (finished -- press enter to close)\x07\\" ;
39 """read foo;"\' """) % (command, command) )
39 """read foo;"\' """) % (command, command) )
40
40
41 def system_call(command):
42 """ Temporary hack for aliases
43 """
44 def my_system_call(args):
45 os.system("%s %s" % (command, args))
46 return my_system_call
47
41 #-------------------------------------------------------------------------------
48 #-------------------------------------------------------------------------------
42 # Frontend class using ipython0 to do the prefiltering.
49 # Frontend class using ipython0 to do the prefiltering.
43 #-------------------------------------------------------------------------------
50 #-------------------------------------------------------------------------------
44 class PrefilterFrontEnd(LineFrontEndBase):
51 class PrefilterFrontEnd(LineFrontEndBase):
45
52
46 def __init__(self, *args, **kwargs):
53 def __init__(self, *args, **kwargs):
47 LineFrontEndBase.__init__(self, *args, **kwargs)
54 LineFrontEndBase.__init__(self, *args, **kwargs)
48 # Instanciate an IPython0 interpreter to be able to use the
55 # Instanciate an IPython0 interpreter to be able to use the
49 # prefiltering.
56 # prefiltering.
50 self.ipython0 = make_IPython()
57 self.ipython0 = make_IPython()
51 # Set the pager:
58 # Set the pager:
52 self.ipython0.set_hook('show_in_pager',
59 self.ipython0.set_hook('show_in_pager',
53 lambda s, string: self.write("\n"+string))
60 lambda s, string: self.write("\n"+string))
54 self.ipython0.write = self.write
61 self.ipython0.write = self.write
55 self._ip = _ip = IPApi(self.ipython0)
62 self._ip = _ip = IPApi(self.ipython0)
56 # XXX: Hack: mix the two namespaces
63 # XXX: Hack: mix the two namespaces
57 self.shell.user_ns = self.ipython0.user_ns
64 self.shell.user_ns = self.ipython0.user_ns
58 self.shell.user_global_ns = self.ipython0.user_global_ns
65 self.shell.user_global_ns = self.ipython0.user_global_ns
59 # Make sure the raw system call doesn't get called, as we don't
66 # Make sure the raw system call doesn't get called, as we don't
60 # have a stdin accessible.
67 # have a stdin accessible.
61 self._ip.system = xterm_system
68 self._ip.system = xterm_system
69 # XXX: Muck around with magics so that they work better
70 # in our environment
71 self.ipython0.magic_ls = system_call('ls -CF')
62 self.shell.output_trap = RedirectorOutputTrap(
72 self.shell.output_trap = RedirectorOutputTrap(
63 out_callback=self.write,
73 out_callback=self.write,
64 err_callback=self.write,
74 err_callback=self.write,
65 )
75 )
66 # Capture and release the outputs, to make sure all the
76 # Capture and release the outputs, to make sure all the
67 # shadow variables are set
77 # shadow variables are set
68 self.capture_output()
78 self.capture_output()
69 self.release_output()
79 self.release_output()
70
80
71
81
72 def prefilter_input(self, input_string):
82 def prefilter_input(self, input_string):
73 """ Using IPython0 to prefilter the commands.
83 """ Using IPython0 to prefilter the commands.
74 """
84 """
75 input_string = LineFrontEndBase.prefilter_input(self, input_string)
85 input_string = LineFrontEndBase.prefilter_input(self, input_string)
76 filtered_lines = []
86 filtered_lines = []
77 # The IPython0 prefilters sometime produce output. We need to
87 # The IPython0 prefilters sometime produce output. We need to
78 # capture it.
88 # capture it.
79 self.capture_output()
89 self.capture_output()
80 self.last_result = dict(number=self.prompt_number)
90 self.last_result = dict(number=self.prompt_number)
81 try:
91 try:
82 for line in input_string.split('\n'):
92 for line in input_string.split('\n'):
83 filtered_lines.append(self.ipython0.prefilter(line, False))
93 filtered_lines.append(self.ipython0.prefilter(line, False))
84 except:
94 except:
85 # XXX: probably not the right thing to do.
95 # XXX: probably not the right thing to do.
86 self.ipython0.showsyntaxerror()
96 self.ipython0.showsyntaxerror()
87 self.after_execute()
97 self.after_execute()
88 finally:
98 finally:
89 self.release_output()
99 self.release_output()
90
100
91 filtered_string = '\n'.join(filtered_lines)
101 filtered_string = '\n'.join(filtered_lines)
92 return filtered_string
102 return filtered_string
93
103
94
104
95 def show_traceback(self):
105 def show_traceback(self):
96 self.capture_output()
106 self.capture_output()
97 self.ipython0.showtraceback()
107 self.ipython0.showtraceback()
98 self.release_output()
108 self.release_output()
99
109
100
110
101 def execute(self, python_string, raw_string=None):
111 def execute(self, python_string, raw_string=None):
102 self.capture_output()
112 self.capture_output()
103 LineFrontEndBase.execute(self, python_string,
113 LineFrontEndBase.execute(self, python_string,
104 raw_string=raw_string)
114 raw_string=raw_string)
105 self.release_output()
115 self.release_output()
106
116
107
117
108 def capture_output(self):
118 def capture_output(self):
109 """ Capture all the output mechanisms we can think of.
119 """ Capture all the output mechanisms we can think of.
110 """
120 """
111 self.__old_cout_write = Term.cout.write
121 self.__old_cout_write = Term.cout.write
112 self.__old_err_write = Term.cerr.write
122 self.__old_err_write = Term.cerr.write
113 Term.cout.write = self.write
123 Term.cout.write = self.write
114 Term.cerr.write = self.write
124 Term.cerr.write = self.write
115 self.__old_stdout = sys.stdout
125 self.__old_stdout = sys.stdout
116 self.__old_stderr= sys.stderr
126 self.__old_stderr= sys.stderr
117 sys.stdout = Term.cout
127 sys.stdout = Term.cout
118 sys.stderr = Term.cerr
128 sys.stderr = Term.cerr
119 self.__old_help_output = pydoc.help.output
129 self.__old_help_output = pydoc.help.output
120 pydoc.help.output = self.shell.output_trap.out
130 pydoc.help.output = self.shell.output_trap.out
121
131
122
132
123 def release_output(self):
133 def release_output(self):
124 """ Release all the different captures we have made.
134 """ Release all the different captures we have made.
125 """
135 """
126 Term.cout.write = self.__old_cout_write
136 Term.cout.write = self.__old_cout_write
127 Term.cerr.write = self.__old_err_write
137 Term.cerr.write = self.__old_err_write
128 sys.stdout = self.__old_stdout
138 sys.stdout = self.__old_stdout
129 sys.stderr = self.__old_stderr
139 sys.stderr = self.__old_stderr
130 pydoc.help.output = self.__old_help_output
140 pydoc.help.output = self.__old_help_output
131
141
132
142
133 def complete(self, line):
143 def complete(self, line):
134 word = line.split('\n')[-1].split(' ')[-1]
144 word = line.split('\n')[-1].split(' ')[-1]
135 completions = self.ipython0.complete(word)
145 completions = self.ipython0.complete(word)
136 # FIXME: The proper sort should be done in the complete method.
146 # FIXME: The proper sort should be done in the complete method.
137 key = lambda x: x.replace('_', '')
147 key = lambda x: x.replace('_', '')
138 completions.sort(key=key)
148 completions.sort(key=key)
139 if completions:
149 if completions:
140 prefix = common_prefix(completions)
150 prefix = common_prefix(completions)
141 line = line[:-len(word)] + prefix
151 line = line[:-len(word)] + prefix
142 return line, completions
152 return line, completions
143
153
144
154
145 def do_exit(self):
155 def do_exit(self):
146 """ Exit the shell, cleanup and save the history.
156 """ Exit the shell, cleanup and save the history.
147 """
157 """
148 self.ipython0.atexit_operations()
158 self.ipython0.atexit_operations()
149
159
@@ -1,423 +1,421 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
26
27 import re
27 import re
28
28
29 # FIXME: Need to provide an API for non user-generated display on the
29 # FIXME: Need to provide an API for non user-generated display on the
30 # screen: this should not be editable by the user.
30 # screen: this should not be editable by the user.
31
31
32 if wx.Platform == '__WXMSW__':
32 if wx.Platform == '__WXMSW__':
33 _DEFAULT_SIZE = 80
33 _DEFAULT_SIZE = 80
34 else:
34 else:
35 _DEFAULT_SIZE = 10
35 _DEFAULT_SIZE = 10
36
36
37 _DEFAULT_STYLE = {
37 _DEFAULT_STYLE = {
38 'stdout' : 'fore:#0000FF',
38 'stdout' : 'fore:#0000FF',
39 'stderr' : 'fore:#007f00',
39 'stderr' : 'fore:#007f00',
40 'trace' : 'fore:#FF0000',
40 'trace' : 'fore:#FF0000',
41
41
42 'default' : 'size:%d' % _DEFAULT_SIZE,
42 'default' : 'size:%d' % _DEFAULT_SIZE,
43 'bracegood' : 'fore:#FFFFFF,back:#0000FF,bold',
43 'bracegood' : 'fore:#FFFFFF,back:#0000FF,bold',
44 'bracebad' : 'fore:#000000,back:#FF0000,bold',
44 'bracebad' : 'fore:#000000,back:#FF0000,bold',
45
45
46 # properties for the various Python lexer styles
46 # properties for the various Python lexer styles
47 'comment' : 'fore:#007F00',
47 'comment' : 'fore:#007F00',
48 'number' : 'fore:#007F7F',
48 'number' : 'fore:#007F7F',
49 'string' : 'fore:#7F007F,italic',
49 'string' : 'fore:#7F007F,italic',
50 'char' : 'fore:#7F007F,italic',
50 'char' : 'fore:#7F007F,italic',
51 'keyword' : 'fore:#00007F,bold',
51 'keyword' : 'fore:#00007F,bold',
52 'triple' : 'fore:#7F0000',
52 'triple' : 'fore:#7F0000',
53 'tripledouble' : 'fore:#7F0000',
53 'tripledouble' : 'fore:#7F0000',
54 'class' : 'fore:#0000FF,bold,underline',
54 'class' : 'fore:#0000FF,bold,underline',
55 'def' : 'fore:#007F7F,bold',
55 'def' : 'fore:#007F7F,bold',
56 'operator' : 'bold'
56 'operator' : 'bold'
57 }
57 }
58
58
59 # new style numbers
59 # new style numbers
60 _STDOUT_STYLE = 15
60 _STDOUT_STYLE = 15
61 _STDERR_STYLE = 16
61 _STDERR_STYLE = 16
62 _TRACE_STYLE = 17
62 _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
70 #-------------------------------------------------------------------------------
70 #-------------------------------------------------------------------------------
71 class ConsoleWidget(editwindow.EditWindow):
71 class ConsoleWidget(editwindow.EditWindow):
72 """ Specialized styled text control view for console-like workflow.
72 """ Specialized styled text control view for console-like workflow.
73
73
74 This widget is mainly interested in dealing with the prompt and
74 This widget is mainly interested in dealing with the prompt and
75 keeping the cursor inside the editing line.
75 keeping the cursor inside the editing line.
76 """
76 """
77
77
78 title = 'Console'
78 title = 'Console'
79
79
80 style = _DEFAULT_STYLE.copy()
80 style = _DEFAULT_STYLE.copy()
81
81
82 # Translation table from ANSI escape sequences to color. Override
82 # Translation table from ANSI escape sequences to color. Override
83 # this to specify your colors.
83 # this to specify your colors.
84 ANSI_STYLES = {'0;30': [0, 'BLACK'], '0;31': [1, 'RED'],
84 ANSI_STYLES = {'0;30': [0, 'BLACK'], '0;31': [1, 'RED'],
85 '0;32': [2, 'GREEN'], '0;33': [3, 'BROWN'],
85 '0;32': [2, 'GREEN'], '0;33': [3, 'BROWN'],
86 '0;34': [4, 'BLUE'], '0;35': [5, 'PURPLE'],
86 '0;34': [4, 'BLUE'], '0;35': [5, 'PURPLE'],
87 '0;36': [6, 'CYAN'], '0;37': [7, 'LIGHT GREY'],
87 '0;36': [6, 'CYAN'], '0;37': [7, 'LIGHT GREY'],
88 '1;30': [8, 'DARK GREY'], '1;31': [9, 'RED'],
88 '1;30': [8, 'DARK GREY'], '1;31': [9, 'RED'],
89 '1;32': [10, 'SEA GREEN'], '1;33': [11, 'YELLOW'],
89 '1;32': [10, 'SEA GREEN'], '1;33': [11, 'YELLOW'],
90 '1;34': [12, 'LIGHT BLUE'], '1;35':
90 '1;34': [12, 'LIGHT BLUE'], '1;35':
91 [13, 'MEDIUM VIOLET RED'],
91 [13, 'MEDIUM VIOLET RED'],
92 '1;36': [14, 'LIGHT STEEL BLUE'], '1;37': [15, 'YELLOW']}
92 '1;36': [14, 'LIGHT STEEL BLUE'], '1;37': [15, 'YELLOW']}
93
93
94 # The color of the carret (call _apply_style() after setting)
94 # The color of the carret (call _apply_style() after setting)
95 carret_color = 'BLACK'
95 carret_color = 'BLACK'
96
96
97
97
98 #--------------------------------------------------------------------------
98 #--------------------------------------------------------------------------
99 # Public API
99 # Public API
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 editwindow.EditWindow.__init__(self, parent, id, pos, size, style)
104 editwindow.EditWindow.__init__(self, parent, id, pos, size, style)
105 self.configure_scintilla()
105 self.configure_scintilla()
106
106
107 # FIXME: we need to retrieve this from the interpreter.
107 # FIXME: we need to retrieve this from the interpreter.
108 self.prompt = \
108 self.prompt = \
109 '\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'
110 self.new_prompt(self.prompt % 1)
110 self.new_prompt(self.prompt % 1)
111
111
112 self.Bind(wx.EVT_KEY_DOWN, self._on_key_down)
112 self.Bind(wx.EVT_KEY_DOWN, self._on_key_down)
113 self.Bind(wx.EVT_KEY_UP, self._on_key_up)
113 self.Bind(wx.EVT_KEY_UP, self._on_key_up)
114
114
115
115
116 def configure_scintilla(self):
116 def configure_scintilla(self):
117 # Ctrl"+" or Ctrl "-" can be used to zoomin/zoomout the text inside
117 # Ctrl"+" or Ctrl "-" can be used to zoomin/zoomout the text inside
118 # the widget
118 # the widget
119 self.CmdKeyAssign(ord('+'), stc.STC_SCMOD_CTRL, stc.STC_CMD_ZOOMIN)
119 self.CmdKeyAssign(ord('+'), stc.STC_SCMOD_CTRL, stc.STC_CMD_ZOOMIN)
120 self.CmdKeyAssign(ord('-'), stc.STC_SCMOD_CTRL, stc.STC_CMD_ZOOMOUT)
120 self.CmdKeyAssign(ord('-'), stc.STC_SCMOD_CTRL, stc.STC_CMD_ZOOMOUT)
121 # Also allow Ctrl Shift "=" for poor non US keyboard users.
121 # Also allow Ctrl Shift "=" for poor non US keyboard users.
122 self.CmdKeyAssign(ord('='), stc.STC_SCMOD_CTRL|stc.STC_SCMOD_SHIFT,
122 self.CmdKeyAssign(ord('='), stc.STC_SCMOD_CTRL|stc.STC_SCMOD_SHIFT,
123 stc.STC_CMD_ZOOMIN)
123 stc.STC_CMD_ZOOMIN)
124
124
125 #self.CmdKeyAssign(stc.STC_KEY_PRIOR, stc.STC_SCMOD_SHIFT,
125 #self.CmdKeyAssign(stc.STC_KEY_PRIOR, stc.STC_SCMOD_SHIFT,
126 # stc.STC_CMD_PAGEUP)
126 # stc.STC_CMD_PAGEUP)
127
127
128 #self.CmdKeyAssign(stc.STC_KEY_NEXT, stc.STC_SCMOD_SHIFT,
128 #self.CmdKeyAssign(stc.STC_KEY_NEXT, stc.STC_SCMOD_SHIFT,
129 # stc.STC_CMD_PAGEDOWN)
129 # stc.STC_CMD_PAGEDOWN)
130
130
131 # Keys: we need to clear some of the keys the that don't play
131 # Keys: we need to clear some of the keys the that don't play
132 # well with a console.
132 # well with a console.
133 self.CmdKeyClear(ord('D'), stc.STC_SCMOD_CTRL)
133 self.CmdKeyClear(ord('D'), stc.STC_SCMOD_CTRL)
134 self.CmdKeyClear(ord('L'), stc.STC_SCMOD_CTRL)
134 self.CmdKeyClear(ord('L'), stc.STC_SCMOD_CTRL)
135 self.CmdKeyClear(ord('T'), stc.STC_SCMOD_CTRL)
135 self.CmdKeyClear(ord('T'), stc.STC_SCMOD_CTRL)
136
136
137
137
138 self.SetEOLMode(stc.STC_EOL_CRLF)
138 self.SetEOLMode(stc.STC_EOL_CRLF)
139 self.SetWrapMode(stc.STC_WRAP_CHAR)
139 self.SetWrapMode(stc.STC_WRAP_CHAR)
140 self.SetWrapMode(stc.STC_WRAP_WORD)
140 self.SetWrapMode(stc.STC_WRAP_WORD)
141 self.SetBufferedDraw(True)
141 self.SetBufferedDraw(True)
142 self.SetUseAntiAliasing(True)
142 self.SetUseAntiAliasing(True)
143 self.SetLayoutCache(stc.STC_CACHE_PAGE)
143 self.SetLayoutCache(stc.STC_CACHE_PAGE)
144 self.SetUndoCollection(False)
144 self.SetUndoCollection(False)
145 self.SetUseTabs(True)
145 self.SetUseTabs(True)
146 self.SetIndent(4)
146 self.SetIndent(4)
147 self.SetTabWidth(4)
147 self.SetTabWidth(4)
148
148
149 self.EnsureCaretVisible()
149 self.EnsureCaretVisible()
150 # we don't want scintilla's autocompletion to choose
150 # we don't want scintilla's autocompletion to choose
151 # automaticaly out of a single choice list, as we pop it up
151 # automaticaly out of a single choice list, as we pop it up
152 # automaticaly
152 # automaticaly
153 self.AutoCompSetChooseSingle(False)
153 self.AutoCompSetChooseSingle(False)
154 self.AutoCompSetMaxHeight(10)
154 self.AutoCompSetMaxHeight(10)
155
155
156 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
157 # Suppressing Scintilla margins
157 # Suppressing Scintilla margins
158 self.SetMarginWidth(0, 0)
158 self.SetMarginWidth(0, 0)
159 self.SetMarginWidth(1, 0)
159 self.SetMarginWidth(1, 0)
160 self.SetMarginWidth(2, 0)
160 self.SetMarginWidth(2, 0)
161
161
162 self._apply_style()
162 self._apply_style()
163
163
164 # Xterm escape sequences
164 # Xterm escape sequences
165 self.color_pat = re.compile('\x01?\x1b\[(.*?)m\x02?')
165 self.color_pat = re.compile('\x01?\x1b\[(.*?)m\x02?')
166 self.title_pat = re.compile('\x1b]0;(.*?)\x07')
166 self.title_pat = re.compile('\x1b]0;(.*?)\x07')
167
167
168 #self.SetEdgeMode(stc.STC_EDGE_LINE)
168 #self.SetEdgeMode(stc.STC_EDGE_LINE)
169 #self.SetEdgeColumn(80)
169 #self.SetEdgeColumn(80)
170
170
171 # styles
171 # styles
172 p = self.style
172 p = self.style
173 self.StyleSetSpec(stc.STC_STYLE_DEFAULT, p['default'])
173 self.StyleSetSpec(stc.STC_STYLE_DEFAULT, p['default'])
174 self.StyleClearAll()
174 self.StyleClearAll()
175 self.StyleSetSpec(_STDOUT_STYLE, p['stdout'])
175 self.StyleSetSpec(_STDOUT_STYLE, p['stdout'])
176 self.StyleSetSpec(_STDERR_STYLE, p['stderr'])
176 self.StyleSetSpec(_STDERR_STYLE, p['stderr'])
177 self.StyleSetSpec(_TRACE_STYLE, p['trace'])
177 self.StyleSetSpec(_TRACE_STYLE, p['trace'])
178
178
179 self.StyleSetSpec(stc.STC_STYLE_BRACELIGHT, p['bracegood'])
179 self.StyleSetSpec(stc.STC_STYLE_BRACELIGHT, p['bracegood'])
180 self.StyleSetSpec(stc.STC_STYLE_BRACEBAD, p['bracebad'])
180 self.StyleSetSpec(stc.STC_STYLE_BRACEBAD, p['bracebad'])
181 self.StyleSetSpec(stc.STC_P_COMMENTLINE, p['comment'])
181 self.StyleSetSpec(stc.STC_P_COMMENTLINE, p['comment'])
182 self.StyleSetSpec(stc.STC_P_NUMBER, p['number'])
182 self.StyleSetSpec(stc.STC_P_NUMBER, p['number'])
183 self.StyleSetSpec(stc.STC_P_STRING, p['string'])
183 self.StyleSetSpec(stc.STC_P_STRING, p['string'])
184 self.StyleSetSpec(stc.STC_P_CHARACTER, p['char'])
184 self.StyleSetSpec(stc.STC_P_CHARACTER, p['char'])
185 self.StyleSetSpec(stc.STC_P_WORD, p['keyword'])
185 self.StyleSetSpec(stc.STC_P_WORD, p['keyword'])
186 self.StyleSetSpec(stc.STC_P_WORD2, p['keyword'])
186 self.StyleSetSpec(stc.STC_P_WORD2, p['keyword'])
187 self.StyleSetSpec(stc.STC_P_TRIPLE, p['triple'])
187 self.StyleSetSpec(stc.STC_P_TRIPLE, p['triple'])
188 self.StyleSetSpec(stc.STC_P_TRIPLEDOUBLE, p['tripledouble'])
188 self.StyleSetSpec(stc.STC_P_TRIPLEDOUBLE, p['tripledouble'])
189 self.StyleSetSpec(stc.STC_P_CLASSNAME, p['class'])
189 self.StyleSetSpec(stc.STC_P_CLASSNAME, p['class'])
190 self.StyleSetSpec(stc.STC_P_DEFNAME, p['def'])
190 self.StyleSetSpec(stc.STC_P_DEFNAME, p['def'])
191 self.StyleSetSpec(stc.STC_P_OPERATOR, p['operator'])
191 self.StyleSetSpec(stc.STC_P_OPERATOR, p['operator'])
192 self.StyleSetSpec(stc.STC_P_COMMENTBLOCK, p['comment'])
192 self.StyleSetSpec(stc.STC_P_COMMENTBLOCK, p['comment'])
193
193
194
194
195 def write(self, text):
195 def write(self, text):
196 """ Write given text to buffer, while translating the ansi escape
196 """ Write given text to buffer, while translating the ansi escape
197 sequences.
197 sequences.
198 """
198 """
199 # XXX: do not put print statements in this method, the print
199 # XXX: do not put print statements in this method, the print
200 # statements will call this method, and you will end up with
200 # statements will call this method, and you will end up with
201 # an infinit loop
201 # an infinit loop
202 title = self.title_pat.split(text)
202 title = self.title_pat.split(text)
203 if len(title)>1:
203 if len(title)>1:
204 import sys
205 print >>sys.__stderr__, "title :", title
206 self.title = title[-2]
204 self.title = title[-2]
207
205
208 text = self.title_pat.sub('', text)
206 text = self.title_pat.sub('', text)
209 segments = self.color_pat.split(text)
207 segments = self.color_pat.split(text)
210 segment = segments.pop(0)
208 segment = segments.pop(0)
211 self.StartStyling(self.GetLength(), 0xFF)
209 self.StartStyling(self.GetLength(), 0xFF)
212 self.AppendText(segment)
210 self.AppendText(segment)
213
211
214 if segments:
212 if segments:
215 for ansi_tag, text in zip(segments[::2], segments[1::2]):
213 for ansi_tag, text in zip(segments[::2], segments[1::2]):
216 self.StartStyling(self.GetLength(), 0xFF)
214 self.StartStyling(self.GetLength(), 0xFF)
217 self.AppendText(text)
215 self.AppendText(text)
218
216
219 if ansi_tag == '0':
217 if ansi_tag not in self.ANSI_STYLES:
220 style = 0
218 style = 0
221 else:
219 else:
222 style = self.ANSI_STYLES[ansi_tag][0]
220 style = self.ANSI_STYLES[ansi_tag][0]
223
221
224 self.SetStyling(len(text), style)
222 self.SetStyling(len(text), style)
225
223
226 self.GotoPos(self.GetLength())
224 self.GotoPos(self.GetLength())
227 wx.Yield()
225 wx.Yield()
228
226
229
227
230 def new_prompt(self, prompt):
228 def new_prompt(self, prompt):
231 """ Prints a prompt at start of line, and move the start of the
229 """ Prints a prompt at start of line, and move the start of the
232 current block there.
230 current block there.
233
231
234 The prompt can be give with ascii escape sequences.
232 The prompt can be give with ascii escape sequences.
235 """
233 """
236 self.write(prompt)
234 self.write(prompt)
237 # now we update our cursor giving end of prompt
235 # now we update our cursor giving end of prompt
238 self.current_prompt_pos = self.GetLength()
236 self.current_prompt_pos = self.GetLength()
239 self.current_prompt_line = self.GetCurrentLine()
237 self.current_prompt_line = self.GetCurrentLine()
240 wx.Yield()
238 wx.Yield()
241 self.EnsureCaretVisible()
239 self.EnsureCaretVisible()
242
240
243
241
244 def replace_current_edit_buffer(self, text):
242 def replace_current_edit_buffer(self, text):
245 """ Replace currently entered command line with given text.
243 """ Replace currently entered command line with given text.
246 """
244 """
247 self.SetSelection(self.current_prompt_pos, self.GetLength())
245 self.SetSelection(self.current_prompt_pos, self.GetLength())
248 self.ReplaceSelection(text)
246 self.ReplaceSelection(text)
249 self.GotoPos(self.GetLength())
247 self.GotoPos(self.GetLength())
250
248
251
249
252 def get_current_edit_buffer(self):
250 def get_current_edit_buffer(self):
253 """ Returns the text in current edit buffer.
251 """ Returns the text in current edit buffer.
254 """
252 """
255 return self.GetTextRange(self.current_prompt_pos,
253 return self.GetTextRange(self.current_prompt_pos,
256 self.GetLength())
254 self.GetLength())
257
255
258
256
259 #--------------------------------------------------------------------------
257 #--------------------------------------------------------------------------
260 # Private API
258 # Private API
261 #--------------------------------------------------------------------------
259 #--------------------------------------------------------------------------
262
260
263 def _apply_style(self):
261 def _apply_style(self):
264 """ Applies the colors for the different text elements and the
262 """ Applies the colors for the different text elements and the
265 carret.
263 carret.
266 """
264 """
267 self.SetCaretForeground(self.carret_color)
265 self.SetCaretForeground(self.carret_color)
268
266
269 #self.StyleClearAll()
267 #self.StyleClearAll()
270 self.StyleSetSpec(stc.STC_STYLE_BRACELIGHT,
268 self.StyleSetSpec(stc.STC_STYLE_BRACELIGHT,
271 "fore:#FF0000,back:#0000FF,bold")
269 "fore:#FF0000,back:#0000FF,bold")
272 self.StyleSetSpec(stc.STC_STYLE_BRACEBAD,
270 self.StyleSetSpec(stc.STC_STYLE_BRACEBAD,
273 "fore:#000000,back:#FF0000,bold")
271 "fore:#000000,back:#FF0000,bold")
274
272
275 for style in self.ANSI_STYLES.values():
273 for style in self.ANSI_STYLES.values():
276 self.StyleSetSpec(style[0], "bold,fore:%s" % style[1])
274 self.StyleSetSpec(style[0], "bold,fore:%s" % style[1])
277
275
278
276
279 def write_completion(self, possibilities):
277 def write_completion(self, possibilities):
280 # FIXME: This is non Wx specific and needs to be moved into
278 # FIXME: This is non Wx specific and needs to be moved into
281 # the base class.
279 # the base class.
282 current_buffer = self.get_current_edit_buffer()
280 current_buffer = self.get_current_edit_buffer()
283
281
284 self.write('\n')
282 self.write('\n')
285 max_len = len(max(possibilities, key=len)) + 1
283 max_len = len(max(possibilities, key=len)) + 1
286
284
287 #now we check how much symbol we can put on a line...
285 #now we check how much symbol we can put on a line...
288 chars_per_line = self.GetSize()[0]/self.GetCharWidth()
286 chars_per_line = self.GetSize()[0]/self.GetCharWidth()
289 symbols_per_line = max(1, chars_per_line/max_len)
287 symbols_per_line = max(1, chars_per_line/max_len)
290
288
291 pos = 1
289 pos = 1
292 buf = []
290 buf = []
293 for symbol in possibilities:
291 for symbol in possibilities:
294 if pos < symbols_per_line:
292 if pos < symbols_per_line:
295 buf.append(symbol.ljust(max_len))
293 buf.append(symbol.ljust(max_len))
296 pos += 1
294 pos += 1
297 else:
295 else:
298 buf.append(symbol.rstrip() +'\n')
296 buf.append(symbol.rstrip() +'\n')
299 pos = 1
297 pos = 1
300 self.write(''.join(buf))
298 self.write(''.join(buf))
301 self.new_prompt(self.prompt % (self.last_result['number'] + 1))
299 self.new_prompt(self.prompt % (self.last_result['number'] + 1))
302 self.replace_current_edit_buffer(current_buffer)
300 self.replace_current_edit_buffer(current_buffer)
303
301
304
302
305 def pop_completion(self, possibilities, offset=0):
303 def pop_completion(self, possibilities, offset=0):
306 """ Pops up an autocompletion menu. Offset is the offset
304 """ Pops up an autocompletion menu. Offset is the offset
307 in characters of the position at which the menu should
305 in characters of the position at which the menu should
308 appear, relativ to the cursor.
306 appear, relativ to the cursor.
309 """
307 """
310 self.AutoCompSetIgnoreCase(False)
308 self.AutoCompSetIgnoreCase(False)
311 self.AutoCompSetAutoHide(False)
309 self.AutoCompSetAutoHide(False)
312 self.AutoCompSetMaxHeight(len(possibilities))
310 self.AutoCompSetMaxHeight(len(possibilities))
313 self.AutoCompShow(offset, " ".join(possibilities))
311 self.AutoCompShow(offset, " ".join(possibilities))
314
312
315
313
316 def scroll_to_bottom(self):
314 def scroll_to_bottom(self):
317 maxrange = self.GetScrollRange(wx.VERTICAL)
315 maxrange = self.GetScrollRange(wx.VERTICAL)
318 self.ScrollLines(maxrange)
316 self.ScrollLines(maxrange)
319
317
320
318
321 def _on_enter(self):
319 def _on_enter(self):
322 """ Called when the return key is hit.
320 """ Called when the return key is hit.
323 """
321 """
324 pass
322 pass
325
323
326
324
327 def _on_key_down(self, event, skip=True):
325 def _on_key_down(self, event, skip=True):
328 """ Key press callback used for correcting behavior for
326 """ Key press callback used for correcting behavior for
329 console-like interfaces: the cursor is constraint to be after
327 console-like interfaces: the cursor is constraint to be after
330 the last prompt.
328 the last prompt.
331
329
332 Return True if event as been catched.
330 Return True if event as been catched.
333 """
331 """
334 catched = True
332 catched = True
335 # Intercept some specific keys.
333 # Intercept some specific keys.
336 if event.KeyCode == ord('L') and event.ControlDown() :
334 if event.KeyCode == ord('L') and event.ControlDown() :
337 self.scroll_to_bottom()
335 self.scroll_to_bottom()
338 elif event.KeyCode == ord('K') and event.ControlDown() :
336 elif event.KeyCode == ord('K') and event.ControlDown() :
339 self.replace_current_edit_buffer('')
337 self.replace_current_edit_buffer('')
340 elif event.KeyCode == wx.WXK_PAGEUP and event.ShiftDown():
338 elif event.KeyCode == wx.WXK_PAGEUP and event.ShiftDown():
341 self.ScrollPages(-1)
339 self.ScrollPages(-1)
342 elif event.KeyCode == wx.WXK_PAGEDOWN and event.ShiftDown():
340 elif event.KeyCode == wx.WXK_PAGEDOWN and event.ShiftDown():
343 self.ScrollPages(1)
341 self.ScrollPages(1)
344 elif event.KeyCode == wx.WXK_UP and event.ShiftDown():
342 elif event.KeyCode == wx.WXK_UP and event.ShiftDown():
345 self.ScrollLines(-1)
343 self.ScrollLines(-1)
346 elif event.KeyCode == wx.WXK_DOWN and event.ShiftDown():
344 elif event.KeyCode == wx.WXK_DOWN and event.ShiftDown():
347 self.ScrollLines(1)
345 self.ScrollLines(1)
348 else:
346 else:
349 catched = False
347 catched = False
350
348
351 if self.AutoCompActive():
349 if self.AutoCompActive():
352 event.Skip()
350 event.Skip()
353 else:
351 else:
354 if event.KeyCode in (13, wx.WXK_NUMPAD_ENTER) and \
352 if event.KeyCode in (13, wx.WXK_NUMPAD_ENTER) and \
355 event.Modifiers in (wx.MOD_NONE, wx.MOD_WIN):
353 event.Modifiers in (wx.MOD_NONE, wx.MOD_WIN):
356 catched = True
354 catched = True
357 self.CallTipCancel()
355 self.CallTipCancel()
358 self.write('\n')
356 self.write('\n')
359 self._on_enter()
357 self._on_enter()
360
358
361 elif event.KeyCode == wx.WXK_HOME:
359 elif event.KeyCode == wx.WXK_HOME:
362 if event.Modifiers in (wx.MOD_NONE, wx.MOD_WIN):
360 if event.Modifiers in (wx.MOD_NONE, wx.MOD_WIN):
363 self.GotoPos(self.current_prompt_pos)
361 self.GotoPos(self.current_prompt_pos)
364 catched = True
362 catched = True
365
363
366 elif event.Modifiers in (wx.MOD_SHIFT, wx.MOD_WIN) :
364 elif event.Modifiers in (wx.MOD_SHIFT, wx.MOD_WIN) :
367 # FIXME: This behavior is not ideal: if the selection
365 # FIXME: This behavior is not ideal: if the selection
368 # is already started, it will jump.
366 # is already started, it will jump.
369 self.SetSelectionStart(self.current_prompt_pos)
367 self.SetSelectionStart(self.current_prompt_pos)
370 self.SetSelectionEnd(self.GetCurrentPos())
368 self.SetSelectionEnd(self.GetCurrentPos())
371 catched = True
369 catched = True
372
370
373 elif event.KeyCode == wx.WXK_UP:
371 elif event.KeyCode == wx.WXK_UP:
374 if self.GetCurrentLine() > self.current_prompt_line:
372 if self.GetCurrentLine() > self.current_prompt_line:
375 if self.GetCurrentLine() == self.current_prompt_line + 1 \
373 if self.GetCurrentLine() == self.current_prompt_line + 1 \
376 and self.GetColumn(self.GetCurrentPos()) < \
374 and self.GetColumn(self.GetCurrentPos()) < \
377 self.GetColumn(self.current_prompt_pos):
375 self.GetColumn(self.current_prompt_pos):
378 self.GotoPos(self.current_prompt_pos)
376 self.GotoPos(self.current_prompt_pos)
379 else:
377 else:
380 event.Skip()
378 event.Skip()
381 catched = True
379 catched = True
382
380
383 elif event.KeyCode in (wx.WXK_LEFT, wx.WXK_BACK):
381 elif event.KeyCode in (wx.WXK_LEFT, wx.WXK_BACK):
384 if self.GetCurrentPos() > self.current_prompt_pos:
382 if self.GetCurrentPos() > self.current_prompt_pos:
385 event.Skip()
383 event.Skip()
386 catched = True
384 catched = True
387
385
388 if skip and not catched:
386 if skip and not catched:
389 event.Skip()
387 event.Skip()
390
388
391 return catched
389 return catched
392
390
393
391
394 def _on_key_up(self, event, skip=True):
392 def _on_key_up(self, event, skip=True):
395 """ If cursor is outside the editing region, put it back.
393 """ If cursor is outside the editing region, put it back.
396 """
394 """
397 event.Skip()
395 event.Skip()
398 if self.GetCurrentPos() < self.current_prompt_pos:
396 if self.GetCurrentPos() < self.current_prompt_pos:
399 self.GotoPos(self.current_prompt_pos)
397 self.GotoPos(self.current_prompt_pos)
400
398
401
399
402
400
403
401
404 if __name__ == '__main__':
402 if __name__ == '__main__':
405 # Some simple code to test the console widget.
403 # Some simple code to test the console widget.
406 class MainWindow(wx.Frame):
404 class MainWindow(wx.Frame):
407 def __init__(self, parent, id, title):
405 def __init__(self, parent, id, title):
408 wx.Frame.__init__(self, parent, id, title, size=(300,250))
406 wx.Frame.__init__(self, parent, id, title, size=(300,250))
409 self._sizer = wx.BoxSizer(wx.VERTICAL)
407 self._sizer = wx.BoxSizer(wx.VERTICAL)
410 self.console_widget = ConsoleWidget(self)
408 self.console_widget = ConsoleWidget(self)
411 self._sizer.Add(self.console_widget, 1, wx.EXPAND)
409 self._sizer.Add(self.console_widget, 1, wx.EXPAND)
412 self.SetSizer(self._sizer)
410 self.SetSizer(self._sizer)
413 self.SetAutoLayout(1)
411 self.SetAutoLayout(1)
414 self.Show(True)
412 self.Show(True)
415
413
416 app = wx.PySimpleApp()
414 app = wx.PySimpleApp()
417 w = MainWindow(None, wx.ID_ANY, 'ConsoleWidget')
415 w = MainWindow(None, wx.ID_ANY, 'ConsoleWidget')
418 w.SetSize((780, 460))
416 w.SetSize((780, 460))
419 w.Show()
417 w.Show()
420
418
421 app.MainLoop()
419 app.MainLoop()
422
420
423
421
General Comments 0
You need to be logged in to leave comments. Login now