diff --git a/IPython/frontend/prefilterfrontend.py b/IPython/frontend/prefilterfrontend.py new file mode 100644 index 0000000..62a21f8 --- /dev/null +++ b/IPython/frontend/prefilterfrontend.py @@ -0,0 +1,143 @@ +""" +Frontend class that uses IPython0 to prefilter the inputs. + +Using the IPython0 mechanism gives us access to the magics. +""" +__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 sys + +from linefrontendbase import LineFrontEndBase, common_prefix + +from IPython.ipmaker import make_IPython +from IPython.ipapi import IPApi +from IPython.kernel.core.sync_output_trap import SyncOutputTrap + +from IPython.genutils import Term + +#------------------------------------------------------------------------------- +# Utility functions (temporary, should be moved out of here) +#------------------------------------------------------------------------------- +import os +def xterm_system(command): + """ Run a command in a separate console window. + """ + os.system(""" + xterm -title "%s" -e \'/bin/sh -c "%s ; + printf \\"\\\\n\\"; + printf \\"press a key to close\\" ; + printf \\"\x1b]0;%s (finished -- press a key to close)\x07\\" ; + read foo;"\' + """ % (command, command, command) ) + +#------------------------------------------------------------------------------- +# Frontend class using ipython0 to do the prefiltering. +#------------------------------------------------------------------------------- +class PrefilterFrontEnd(LineFrontEndBase): + + def __init__(self, *args, **kwargs): + LineFrontEndBase.__init__(self, *args, **kwargs) + # Instanciate an IPython0 interpreter to be able to use the + # prefiltering. + self.ipython0 = make_IPython() + # Set the pager: + self.ipython0.set_hook('show_in_pager', + lambda s, string: self.write("\n"+string)) + self.ipython0.write = self.write + self._ip = _ip = IPApi(self.ipython0) + # XXX: Hack: mix the two namespaces + self.shell.user_ns = self.ipython0.user_ns + self.shell.user_global_ns = self.ipython0.user_global_ns + # Make sure the raw system call doesn't get called, as we don't + # have a stdin accessible. + self._ip.system = xterm_system + # Redefine a serie of magics to avoid os.system: + # FIXME: I am redefining way too much magics. + for alias_name, (_, alias_value) in \ + _ip.IP.shell.alias_table.iteritems(): + magic = lambda s : _ip.magic('sx %s %s' % (alias_value, s)) + setattr(_ip.IP, 'magic_%s' % alias_name, magic) + # FIXME: I should create a real file-like object dedicated to this + # terminal + Term.cout.flush = lambda : None + Term.cout.getvalue = lambda : '' + Term.cerr.flush = lambda : None + Term.cerr.getvalue = lambda : '' + self.shell.output_trap = SyncOutputTrap(write_out=self.write, + write_err=self.write) + + + + def prefilter_input(self, input_string): + """ Using IPython0 to prefilter the commands. + """ + input_string = LineFrontEndBase.prefilter_input(self, input_string) + filtered_lines = [] + # The IPython0 prefilters sometime produce output. We need to + # capture it. + self.capture_output() + self.last_result = dict(number=self.prompt_number) + try: + for line in input_string.split('\n'): + filtered_lines.append(self.ipython0.prefilter(line, False)) + except: + # XXX: probably not the right thing to do. + self.ipython0.showsyntaxerror() + self.after_execute() + finally: + self.release_output() + + filtered_string = '\n'.join(filtered_lines) + return filtered_string + + + def show_traceback(self): + self.capture_output() + self.ipython0.showtraceback() + self.release_output() + + + def capture_output(self): + """ Capture all the output mechanism we can think of. + """ + self.__old_cout_write = Term.cout.write + self.__old_err_write = Term.cerr.write + Term.cout.write = self.write + Term.cerr.write = self.write + self.__old_stdout = sys.stdout + self.__old_stderr= sys.stderr + sys.stdout = Term.cout + sys.stderr = Term.cerr + # FIXME: I still need to provide the writelines method + + def release_output(self): + """ Release all the different captures we have made, + and flush the buffers. + """ + Term.cout.write = self.__old_cout_write + Term.cerr.write = self.__old_err_write + sys.stdout = self.__old_stdout + sys.stderr = self.__old_stderr + + + def complete(self, line): + word = line.split('\n')[-1].split(' ')[-1] + completions = self.ipython0.complete(word) + key = lambda x: x.replace('_', '') + completions.sort(key=key) + if completions: + prefix = common_prefix(completions) + line = line[:-len(word)] + prefix + return line, completions + +