|
|
"""
|
|
|
Base front end class for all line-oriented frontends.
|
|
|
|
|
|
Currently this focuses on synchronous frontends.
|
|
|
"""
|
|
|
__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 re
|
|
|
|
|
|
import IPython
|
|
|
|
|
|
|
|
|
from frontendbase import FrontEndBase
|
|
|
from IPython.kernel.core.interpreter import Interpreter
|
|
|
|
|
|
#-------------------------------------------------------------------------------
|
|
|
# Base class for the line-oriented front ends
|
|
|
#-------------------------------------------------------------------------------
|
|
|
class LineFrontEndBase(FrontEndBase):
|
|
|
|
|
|
# We need to keep the prompt number, to be able to increment
|
|
|
# it when there is an exception.
|
|
|
prompt_number = 1
|
|
|
|
|
|
|
|
|
#--------------------------------------------------------------------------
|
|
|
# Public API
|
|
|
#--------------------------------------------------------------------------
|
|
|
|
|
|
def __init__(self, shell=None, history=None):
|
|
|
if shell is None:
|
|
|
shell = Interpreter()
|
|
|
FrontEndBase.__init__(self, shell=shell, history=history)
|
|
|
|
|
|
#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
|
|
|
|
|
|
|
|
|
def prefilter_input(self, string):
|
|
|
string = string.replace('\r\n', '\n')
|
|
|
string = string.replace('\t', 4*' ')
|
|
|
# Clean the trailing whitespace
|
|
|
string = '\n'.join(l.rstrip() for l in string.split('\n'))
|
|
|
return string
|
|
|
|
|
|
|
|
|
def is_complete(self, string):
|
|
|
if ( len(self.get_current_edit_buffer().split('\n'))>1
|
|
|
and not re.findall(r"\n[\t ]*$", string)):
|
|
|
return False
|
|
|
else:
|
|
|
return FrontEndBase.is_complete(self, string)
|
|
|
|
|
|
|
|
|
def execute(self, python_string, raw_string=None):
|
|
|
""" Send the python_string to the interpreter, stores the
|
|
|
raw_string in the history and starts a new prompt.
|
|
|
"""
|
|
|
if raw_string is None:
|
|
|
raw_string = string
|
|
|
# Create a false result, in case there is an exception
|
|
|
result = dict(number=self.prompt_number)
|
|
|
try:
|
|
|
self.history.input_cache[-1] = raw_string
|
|
|
result = self.shell.execute(python_string)
|
|
|
self.render_result(result)
|
|
|
except Exception, e:
|
|
|
self.show_traceback()
|
|
|
finally:
|
|
|
self.prompt_number += 1
|
|
|
self.new_prompt(self.prompt % (result['number'] + 1))
|
|
|
# Start a new empty history entry
|
|
|
self._add_history(None, '')
|
|
|
# The result contains useful information that can be used
|
|
|
# elsewhere.
|
|
|
self.last_result = result
|
|
|
|
|
|
|
|
|
def _on_enter(self):
|
|
|
""" Called when the return key is pressed in a line editing
|
|
|
buffer.
|
|
|
"""
|
|
|
current_buffer = self.get_current_edit_buffer()
|
|
|
cleaned_buffer = self.prefilter_input(current_buffer)
|
|
|
if self.is_complete(cleaned_buffer):
|
|
|
self.execute(cleaned_buffer, raw_string=current_buffer)
|
|
|
else:
|
|
|
if len(current_buffer.split('\n'))>1:
|
|
|
self.write('\n' + self._get_indent_string(current_buffer))
|
|
|
else:
|
|
|
self.write('\n\t')
|
|
|
|
|
|
|
|
|
#--------------------------------------------------------------------------
|
|
|
# Private API
|
|
|
#--------------------------------------------------------------------------
|
|
|
|
|
|
def _get_indent_string(self, string):
|
|
|
print >>sys.__stderr__, string.split('\n')
|
|
|
string = string.split('\n')[-1]
|
|
|
indent_chars = len(string) - len(string.lstrip())
|
|
|
indent_string = '\t'*(indent_chars // 4) + \
|
|
|
' '*(indent_chars % 4)
|
|
|
|
|
|
return indent_string
|
|
|
|
|
|
|
|
|
|