##// END OF EJS Templates
Add forgotten file.
Add forgotten file.

File last commit:

r1379:e11dd706
r1385:5dc754fb
Show More
linefrontendbase.py
179 lines | 5.9 KiB | text/x-python | PythonLexer
Gael Varoquaux
Split the frontend base class in different files and add a base class...
r1355 """
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
Gael Varoquaux
Proper tab completion that actually completes.
r1379
def common_prefix(strings):
ref = strings[0]
prefix = ''
for size in range(len(ref)):
test_prefix = ref[:size+1]
for string in strings[1:]:
if not string.startswith(test_prefix):
return prefix
prefix = test_prefix
return prefix
Gael Varoquaux
Split the frontend base class in different files and add a base class...
r1355 #-------------------------------------------------------------------------------
# Base class for the line-oriented front ends
#-------------------------------------------------------------------------------
class LineFrontEndBase(FrontEndBase):
Gael Varoquaux
Traceback capture now working.
r1360 # We need to keep the prompt number, to be able to increment
# it when there is an exception.
prompt_number = 1
Gael Varoquaux
Improve tab-completion.
r1373 # To bootstrap
last_result = dict(number=0)
Gael Varoquaux
Traceback capture now working.
r1360
Gael Varoquaux
Split the frontend base class in different files and add a base class...
r1355 #--------------------------------------------------------------------------
# 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__
Gael Varoquaux
Proper tab completion that actually completes.
r1379 def complete(self, line):
"""Complete line in engine's user_ns
Gael Varoquaux
Split the frontend base class in different files and add a base class...
r1355
Parameters
----------
Gael Varoquaux
Proper tab completion that actually completes.
r1379 line : string
Gael Varoquaux
Split the frontend base class in different files and add a base class...
r1355
Result
------
Gael Varoquaux
Proper tab completion that actually completes.
r1379 The replacement for the line and the list of possible completions.
Gael Varoquaux
Split the frontend base class in different files and add a base class...
r1355 """
Gael Varoquaux
Proper tab completion that actually completes.
r1379 completions = self.shell.complete(line)
complete_sep = re.compile('[\s\{\}\[\]\(\)\=]')
if completions:
prefix = common_prefix(completions)
residual = complete_sep.split(line)[:-1]
line = line[:-len(residual)] + prefix
return line, completions
Gael Varoquaux
Split the frontend base class in different files and add a base class...
r1355
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']
) )
Gael Varoquaux
Traceback capture now working.
r1360
Gael Varoquaux
Split the frontend base class in different files and add a base class...
r1355 def render_error(self, failure):
self.insert_text('\n\n'+str(failure)+'\n\n')
return failure
Gael Varoquaux
Traceback capture now working.
r1360
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):
Gael Varoquaux
Improve tab-completion.
r1373 if string in ('', '\n'):
return True
elif ( len(self.get_current_edit_buffer().split('\n'))>2
Gael Varoquaux
Correct small history bug. Add busy cursor.
r1371 and not re.findall(r"\n[\t ]*\n[\t ]*$", string)):
Gael Varoquaux
Traceback capture now working.
r1360 return False
else:
Gael Varoquaux
Improve tab-completion.
r1373 # Add line returns here, to make sure that the statement is
# complete.
return FrontEndBase.is_complete(self, string.rstrip() + '\n\n')
Gael Varoquaux
Split the frontend base class in different files and add a base class...
r1355
Gael Varoquaux
Traceback capture now working.
r1360 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:
Gael Varoquaux
Nice background color for already entered code....
r1374 raw_string = python_string
Gael Varoquaux
Traceback capture now working.
r1360 # Create a false result, in case there is an exception
Gael Varoquaux
Make code execution more robust.
r1362 self.last_result = dict(number=self.prompt_number)
Gael Varoquaux
Traceback capture now working.
r1360 try:
Gael Varoquaux
Correct small history bug. Add busy cursor.
r1371 self.history.input_cache[-1] = raw_string.rstrip()
Gael Varoquaux
Traceback capture now working.
r1360 result = self.shell.execute(python_string)
Gael Varoquaux
Make code execution more robust.
r1362 self.last_result = result
Gael Varoquaux
Traceback capture now working.
r1360 self.render_result(result)
Gael Varoquaux
Make code execution more robust.
r1362 except:
Gael Varoquaux
Traceback capture now working.
r1360 self.show_traceback()
finally:
Gael Varoquaux
Make code execution more robust.
r1362 self.after_execute()
def after_execute(self):
""" All the operations required after an execution to put the
terminal back in a shape where it is usable.
"""
self.prompt_number += 1
self.new_prompt(self.prompt % (self.last_result['number'] + 1))
# Start a new empty history entry
self._add_history(None, '')
Gael Varoquaux
Correct small history bug. Add busy cursor.
r1371 self.history_cursor = len(self.history.input_cache) - 1
Gael Varoquaux
Traceback capture now working.
r1360
Gael Varoquaux
History is now working. + misc keybindings.
r1358 def _on_enter(self):
Gael Varoquaux
Split the frontend base class in different files and add a base class...
r1355 """ Called when the return key is pressed in a line editing
buffer.
"""
current_buffer = self.get_current_edit_buffer()
Gael Varoquaux
Traceback capture now working.
r1360 cleaned_buffer = self.prefilter_input(current_buffer)
Gael Varoquaux
Correct small history bug. Add busy cursor.
r1371 if self.is_complete(cleaned_buffer):
Gael Varoquaux
Traceback capture now working.
r1360 self.execute(cleaned_buffer, raw_string=current_buffer)
Gael Varoquaux
Split the frontend base class in different files and add a base class...
r1355 else:
Gael Varoquaux
Correct small history bug. Add busy cursor.
r1371 if len(current_buffer.split('\n'))>2:
# We need to clean the trailing '\n'
self.write(self._get_indent_string(current_buffer[:-1]))
Gael Varoquaux
Traceback capture now working.
r1360 else:
Gael Varoquaux
Make code execution more robust.
r1362 self.write('\t')
Gael Varoquaux
Split the frontend base class in different files and add a base class...
r1355
#--------------------------------------------------------------------------
# Private API
#--------------------------------------------------------------------------
def _get_indent_string(self, string):
Gael Varoquaux
Make code execution more robust.
r1362 string = string.replace('\t', ' '*4)
Gael Varoquaux
Split the frontend base class in different files and add a base class...
r1355 string = string.split('\n')[-1]
indent_chars = len(string) - len(string.lstrip())
indent_string = '\t'*(indent_chars // 4) + \
' '*(indent_chars % 4)
return indent_string