From 0a34966789142561ef1d4a8cca9676258383491e 2008-07-12 17:41:29 From: Gael Varoquaux Date: 2008-07-12 17:41:29 Subject: [PATCH] Syncing with ipython-sync-frontend branch. --- diff --git a/IPython/frontend/wx/wx_frontend.py b/IPython/frontend/wx/wx_frontend.py index eb4e6b1..706e0fe 100644 --- a/IPython/frontend/wx/wx_frontend.py +++ b/IPython/frontend/wx/wx_frontend.py @@ -26,7 +26,7 @@ from console_widget import ConsoleWidget import re import IPython -from IPython.kernel.core.interpreter import Interpreter +from IPython.kernel.engineservice import EngineService from IPython.frontend.frontendbase import FrontEndBase #------------------------------------------------------------------------------- @@ -59,7 +59,7 @@ class IPythonWxController(FrontEndBase, ConsoleWidget): """ Create Shell instance. """ ConsoleWidget.__init__(self, parent, id, pos, size, style) - FrontEndBase.__init__(self, shell=Interpreter(), + FrontEndBase.__init__(self, engine=EngineService(), ) # FIXME: Something is wrong with the history, I instanciate it @@ -67,7 +67,7 @@ class IPythonWxController(FrontEndBase, ConsoleWidget): self.lines = {} # Start the IPython engine - self.shell + self.engine.startService() # Capture Character keys self.Bind(wx.EVT_KEY_DOWN, self._on_key_down) @@ -77,6 +77,12 @@ class IPythonWxController(FrontEndBase, ConsoleWidget): % IPython.__version__ + def appWillTerminate_(self, notification): + """appWillTerminate""" + + self.engine.stopService() + + def complete(self, token): """Complete token in engine's user_ns @@ -90,7 +96,7 @@ class IPythonWxController(FrontEndBase, ConsoleWidget): IPython.kernel.engineservice.IEngineBase.complete """ - return self.shell.complete(token) + return self.engine.complete(token) def render_result(self, result): @@ -156,7 +162,7 @@ class IPythonWxController(FrontEndBase, ConsoleWidget): or re.findall(r"\n[\t ]*$", cleaned_buffer)): if self.is_complete(cleaned_buffer): self._add_history(None, cleaned_buffer.rstrip()) - result = self.shell.execute(cleaned_buffer) + result = self.engine.shell.execute(cleaned_buffer) self.render_result(result) self.new_prompt(self.prompt % (result['number'] + 1)) self.multi_line_input = False diff --git a/IPython/frontend/wx/wx_frontend.py.moved b/IPython/frontend/wx/wx_frontend.py.moved new file mode 100644 index 0000000..eb4e6b1 --- /dev/null +++ b/IPython/frontend/wx/wx_frontend.py.moved @@ -0,0 +1,201 @@ +# encoding: utf-8 -*- test-case-name: +# FIXME: Need to add tests. +# ipython1.frontend.cocoa.tests.test_cocoa_frontend -*- + +"""Classes to provide a Wx frontend to the +ipython1.kernel.engineservice.EngineService. + +""" + +__docformat__ = "restructuredtext en" + +#------------------------------------------------------------------------------- +# Copyright (C) 2008 The IPython Development Team +# +# Distributed under the terms of the BSD License. The full license is in +# the file COPYING, distributed as part of this software. +#------------------------------------------------------------------------------- + +#------------------------------------------------------------------------------- +# Imports +#------------------------------------------------------------------------------- + + +import wx +from console_widget import ConsoleWidget +import re + +import IPython +from IPython.kernel.core.interpreter import Interpreter +from IPython.frontend.frontendbase import FrontEndBase + +#------------------------------------------------------------------------------- +# Classes to implement the Wx frontend +#------------------------------------------------------------------------------- + + + + +class IPythonWxController(FrontEndBase, ConsoleWidget): + + output_prompt = \ + '\n\x01\x1b[0;31m\x02Out[\x01\x1b[1;31m\x02%i\x01\x1b[0;31m\x02]: \x01\x1b[0m\x02' + + # Are we entering multi line input? + multi_line_input = False + + # The added tab stop to the string. It may, for instance, come from + # copy and pasting something with tabs. + tab_stop = 0 + # FIXME: We still have to deal with this. + + #-------------------------------------------------------------------------- + # Public API + #-------------------------------------------------------------------------- + + def __init__(self, parent, id=wx.ID_ANY, pos=wx.DefaultPosition, + size=wx.DefaultSize, style=wx.CLIP_CHILDREN, + *args, **kwds): + """ Create Shell instance. + """ + ConsoleWidget.__init__(self, parent, id, pos, size, style) + FrontEndBase.__init__(self, shell=Interpreter(), + ) + + # FIXME: Something is wrong with the history, I instanciate it + # with an empty cache, but this is not the way to do. + self.lines = {} + + # Start the IPython engine + self.shell + + # Capture Character keys + self.Bind(wx.EVT_KEY_DOWN, self._on_key_down) + + #FIXME: print banner. + banner = """IPython1 %s -- An enhanced Interactive Python.""" \ + % IPython.__version__ + + + def complete(self, token): + """Complete token in engine's user_ns + + Parameters + ---------- + token : string + + Result + ------ + Deferred result of + IPython.kernel.engineservice.IEngineBase.complete + """ + + return self.shell.complete(token) + + + def render_result(self, result): + if 'stdout' in result and result['stdout']: + self.write('\n' + result['stdout']) + if 'display' in result and result['display']: + self.write("%s%s\n" % ( + self.output_prompt % result['number'], + result['display']['pprint'] + ) ) + + + def render_error(self, failure): + self.insert_text('\n\n'+str(failure)+'\n\n') + return failure + + + #-------------------------------------------------------------------------- + # Private API + #-------------------------------------------------------------------------- + + + def _on_key_down(self, event, skip=True): + """ Capture the character events, let the parent + widget handle them, and put our logic afterward. + """ + current_line_number = self.GetCurrentLine() + # Capture enter + if event.KeyCode in (13, wx.WXK_NUMPAD_ENTER) and \ + event.Modifiers in (wx.MOD_NONE, wx.MOD_WIN): + self._on_enter() + # Up history + elif event.KeyCode == wx.WXK_UP and ( + ( current_line_number == self.current_prompt_line and + event.Modifiers in (wx.MOD_NONE, wx.MOD_WIN) ) + or event.ControlDown() ): + new_buffer = self.get_history_previous( + self.get_current_edit_buffer()) + if new_buffer is not None: + self.replace_current_edit_buffer(new_buffer) + # Down history + elif event.KeyCode == wx.WXK_DOWN and ( + ( current_line_number == self.LineCount -1 and + event.Modifiers in (wx.MOD_NONE, wx.MOD_WIN) ) + or event.ControlDown() ): + new_buffer = self.get_history_next() + if new_buffer is not None: + self.replace_current_edit_buffer(new_buffer) + else: + ConsoleWidget._on_key_down(self, event, skip=True) + + + def _on_enter(self): + """ Called when the return key is pressed in a line editing + buffer. + """ + current_buffer = self.get_current_edit_buffer() + current_buffer = current_buffer.replace('\r\n', '\n') + current_buffer = current_buffer.replace('\t', 4*' ') + cleaned_buffer = '\n'.join(l.rstrip() + for l in current_buffer.split('\n')) + if ( not self.multi_line_input + or re.findall(r"\n[\t ]*$", cleaned_buffer)): + if self.is_complete(cleaned_buffer): + self._add_history(None, cleaned_buffer.rstrip()) + result = self.shell.execute(cleaned_buffer) + self.render_result(result) + self.new_prompt(self.prompt % (result['number'] + 1)) + self.multi_line_input = False + else: + if self.multi_line_input: + self.write('\n' + self._get_indent_string(current_buffer)) + else: + self.multi_line_input = True + self.write('\n\t') + else: + self.write('\n'+self._get_indent_string(current_buffer)) + + + def _get_indent_string(self, string): + string = string.split('\n')[-1] + indent_chars = len(string) - len(string.lstrip()) + indent_string = '\t'*(indent_chars // 4) + \ + ' '*(indent_chars % 4) + + return indent_string + + + +if __name__ == '__main__': + class MainWindow(wx.Frame): + def __init__(self, parent, id, title): + wx.Frame.__init__(self, parent, id, title, size=(300,250)) + self._sizer = wx.BoxSizer(wx.VERTICAL) + self.shell = IPythonWxController(self) + self._sizer.Add(self.shell, 1, wx.EXPAND) + self.SetSizer(self._sizer) + self.SetAutoLayout(1) + self.Show(True) + + app = wx.PySimpleApp() + frame = MainWindow(None, wx.ID_ANY, 'Ipython') + frame.shell.SetFocus() + frame.SetSize((660, 460)) + self = frame.shell + + app.MainLoop() +