##// END OF EJS Templates
Syncing with ipython-sync-frontend branch.
Gael Varoquaux -
r1352:0a349667 merge
parent child Browse files
Show More
@@ -0,0 +1,201 b''
1 # encoding: utf-8 -*- test-case-name:
2 # FIXME: Need to add tests.
3 # ipython1.frontend.cocoa.tests.test_cocoa_frontend -*-
4
5 """Classes to provide a Wx frontend to the
6 ipython1.kernel.engineservice.EngineService.
7
8 """
9
10 __docformat__ = "restructuredtext en"
11
12 #-------------------------------------------------------------------------------
13 # Copyright (C) 2008 The IPython Development Team
14 #
15 # Distributed under the terms of the BSD License. The full license is in
16 # the file COPYING, distributed as part of this software.
17 #-------------------------------------------------------------------------------
18
19 #-------------------------------------------------------------------------------
20 # Imports
21 #-------------------------------------------------------------------------------
22
23
24 import wx
25 from console_widget import ConsoleWidget
26 import re
27
28 import IPython
29 from IPython.kernel.core.interpreter import Interpreter
30 from IPython.frontend.frontendbase import FrontEndBase
31
32 #-------------------------------------------------------------------------------
33 # Classes to implement the Wx frontend
34 #-------------------------------------------------------------------------------
35
36
37
38
39 class IPythonWxController(FrontEndBase, ConsoleWidget):
40
41 output_prompt = \
42 '\n\x01\x1b[0;31m\x02Out[\x01\x1b[1;31m\x02%i\x01\x1b[0;31m\x02]: \x01\x1b[0m\x02'
43
44 # Are we entering multi line input?
45 multi_line_input = False
46
47 # The added tab stop to the string. It may, for instance, come from
48 # copy and pasting something with tabs.
49 tab_stop = 0
50 # FIXME: We still have to deal with this.
51
52 #--------------------------------------------------------------------------
53 # Public API
54 #--------------------------------------------------------------------------
55
56 def __init__(self, parent, id=wx.ID_ANY, pos=wx.DefaultPosition,
57 size=wx.DefaultSize, style=wx.CLIP_CHILDREN,
58 *args, **kwds):
59 """ Create Shell instance.
60 """
61 ConsoleWidget.__init__(self, parent, id, pos, size, style)
62 FrontEndBase.__init__(self, shell=Interpreter(),
63 )
64
65 # FIXME: Something is wrong with the history, I instanciate it
66 # with an empty cache, but this is not the way to do.
67 self.lines = {}
68
69 # Start the IPython engine
70 self.shell
71
72 # Capture Character keys
73 self.Bind(wx.EVT_KEY_DOWN, self._on_key_down)
74
75 #FIXME: print banner.
76 banner = """IPython1 %s -- An enhanced Interactive Python.""" \
77 % IPython.__version__
78
79
80 def complete(self, token):
81 """Complete token in engine's user_ns
82
83 Parameters
84 ----------
85 token : string
86
87 Result
88 ------
89 Deferred result of
90 IPython.kernel.engineservice.IEngineBase.complete
91 """
92
93 return self.shell.complete(token)
94
95
96 def render_result(self, result):
97 if 'stdout' in result and result['stdout']:
98 self.write('\n' + result['stdout'])
99 if 'display' in result and result['display']:
100 self.write("%s%s\n" % (
101 self.output_prompt % result['number'],
102 result['display']['pprint']
103 ) )
104
105
106 def render_error(self, failure):
107 self.insert_text('\n\n'+str(failure)+'\n\n')
108 return failure
109
110
111 #--------------------------------------------------------------------------
112 # Private API
113 #--------------------------------------------------------------------------
114
115
116 def _on_key_down(self, event, skip=True):
117 """ Capture the character events, let the parent
118 widget handle them, and put our logic afterward.
119 """
120 current_line_number = self.GetCurrentLine()
121 # Capture enter
122 if event.KeyCode in (13, wx.WXK_NUMPAD_ENTER) and \
123 event.Modifiers in (wx.MOD_NONE, wx.MOD_WIN):
124 self._on_enter()
125 # Up history
126 elif event.KeyCode == wx.WXK_UP and (
127 ( current_line_number == self.current_prompt_line and
128 event.Modifiers in (wx.MOD_NONE, wx.MOD_WIN) )
129 or event.ControlDown() ):
130 new_buffer = self.get_history_previous(
131 self.get_current_edit_buffer())
132 if new_buffer is not None:
133 self.replace_current_edit_buffer(new_buffer)
134 # Down history
135 elif event.KeyCode == wx.WXK_DOWN and (
136 ( current_line_number == self.LineCount -1 and
137 event.Modifiers in (wx.MOD_NONE, wx.MOD_WIN) )
138 or event.ControlDown() ):
139 new_buffer = self.get_history_next()
140 if new_buffer is not None:
141 self.replace_current_edit_buffer(new_buffer)
142 else:
143 ConsoleWidget._on_key_down(self, event, skip=True)
144
145
146 def _on_enter(self):
147 """ Called when the return key is pressed in a line editing
148 buffer.
149 """
150 current_buffer = self.get_current_edit_buffer()
151 current_buffer = current_buffer.replace('\r\n', '\n')
152 current_buffer = current_buffer.replace('\t', 4*' ')
153 cleaned_buffer = '\n'.join(l.rstrip()
154 for l in current_buffer.split('\n'))
155 if ( not self.multi_line_input
156 or re.findall(r"\n[\t ]*$", cleaned_buffer)):
157 if self.is_complete(cleaned_buffer):
158 self._add_history(None, cleaned_buffer.rstrip())
159 result = self.shell.execute(cleaned_buffer)
160 self.render_result(result)
161 self.new_prompt(self.prompt % (result['number'] + 1))
162 self.multi_line_input = False
163 else:
164 if self.multi_line_input:
165 self.write('\n' + self._get_indent_string(current_buffer))
166 else:
167 self.multi_line_input = True
168 self.write('\n\t')
169 else:
170 self.write('\n'+self._get_indent_string(current_buffer))
171
172
173 def _get_indent_string(self, string):
174 string = string.split('\n')[-1]
175 indent_chars = len(string) - len(string.lstrip())
176 indent_string = '\t'*(indent_chars // 4) + \
177 ' '*(indent_chars % 4)
178
179 return indent_string
180
181
182
183 if __name__ == '__main__':
184 class MainWindow(wx.Frame):
185 def __init__(self, parent, id, title):
186 wx.Frame.__init__(self, parent, id, title, size=(300,250))
187 self._sizer = wx.BoxSizer(wx.VERTICAL)
188 self.shell = IPythonWxController(self)
189 self._sizer.Add(self.shell, 1, wx.EXPAND)
190 self.SetSizer(self._sizer)
191 self.SetAutoLayout(1)
192 self.Show(True)
193
194 app = wx.PySimpleApp()
195 frame = MainWindow(None, wx.ID_ANY, 'Ipython')
196 frame.shell.SetFocus()
197 frame.SetSize((660, 460))
198 self = frame.shell
199
200 app.MainLoop()
201
@@ -26,7 +26,7 b' from console_widget import ConsoleWidget'
26 import re
26 import re
27
27
28 import IPython
28 import IPython
29 from IPython.kernel.core.interpreter import Interpreter
29 from IPython.kernel.engineservice import EngineService
30 from IPython.frontend.frontendbase import FrontEndBase
30 from IPython.frontend.frontendbase import FrontEndBase
31
31
32 #-------------------------------------------------------------------------------
32 #-------------------------------------------------------------------------------
@@ -59,7 +59,7 b' class IPythonWxController(FrontEndBase, ConsoleWidget):'
59 """ Create Shell instance.
59 """ Create Shell instance.
60 """
60 """
61 ConsoleWidget.__init__(self, parent, id, pos, size, style)
61 ConsoleWidget.__init__(self, parent, id, pos, size, style)
62 FrontEndBase.__init__(self, shell=Interpreter(),
62 FrontEndBase.__init__(self, engine=EngineService(),
63 )
63 )
64
64
65 # FIXME: Something is wrong with the history, I instanciate it
65 # FIXME: Something is wrong with the history, I instanciate it
@@ -67,7 +67,7 b' class IPythonWxController(FrontEndBase, ConsoleWidget):'
67 self.lines = {}
67 self.lines = {}
68
68
69 # Start the IPython engine
69 # Start the IPython engine
70 self.shell
70 self.engine.startService()
71
71
72 # Capture Character keys
72 # Capture Character keys
73 self.Bind(wx.EVT_KEY_DOWN, self._on_key_down)
73 self.Bind(wx.EVT_KEY_DOWN, self._on_key_down)
@@ -77,6 +77,12 b' class IPythonWxController(FrontEndBase, ConsoleWidget):'
77 % IPython.__version__
77 % IPython.__version__
78
78
79
79
80 def appWillTerminate_(self, notification):
81 """appWillTerminate"""
82
83 self.engine.stopService()
84
85
80 def complete(self, token):
86 def complete(self, token):
81 """Complete token in engine's user_ns
87 """Complete token in engine's user_ns
82
88
@@ -90,7 +96,7 b' class IPythonWxController(FrontEndBase, ConsoleWidget):'
90 IPython.kernel.engineservice.IEngineBase.complete
96 IPython.kernel.engineservice.IEngineBase.complete
91 """
97 """
92
98
93 return self.shell.complete(token)
99 return self.engine.complete(token)
94
100
95
101
96 def render_result(self, result):
102 def render_result(self, result):
@@ -156,7 +162,7 b' class IPythonWxController(FrontEndBase, ConsoleWidget):'
156 or re.findall(r"\n[\t ]*$", cleaned_buffer)):
162 or re.findall(r"\n[\t ]*$", cleaned_buffer)):
157 if self.is_complete(cleaned_buffer):
163 if self.is_complete(cleaned_buffer):
158 self._add_history(None, cleaned_buffer.rstrip())
164 self._add_history(None, cleaned_buffer.rstrip())
159 result = self.shell.execute(cleaned_buffer)
165 result = self.engine.shell.execute(cleaned_buffer)
160 self.render_result(result)
166 self.render_result(result)
161 self.new_prompt(self.prompt % (result['number'] + 1))
167 self.new_prompt(self.prompt % (result['number'] + 1))
162 self.multi_line_input = False
168 self.multi_line_input = False
General Comments 0
You need to be logged in to leave comments. Login now