splitinput.py
137 lines
| 4.7 KiB
| text/x-python
|
PythonLexer
Brian Granger
|
r2244 | # encoding: utf-8 | ||
""" | ||||
Thomas Kluyver
|
r4746 | Simple utility for splitting user input. This is used by both inputsplitter and | ||
prefilter. | ||||
Brian Granger
|
r2244 | |||
Authors: | ||||
* Brian Granger | ||||
* Fernando Perez | ||||
""" | ||||
#----------------------------------------------------------------------------- | ||||
Matthias BUSSONNIER
|
r5390 | # Copyright (C) 2008-2011 The IPython Development Team | ||
Brian Granger
|
r2244 | # | ||
# 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 | ||||
Fernando Perez
|
r3038 | import sys | ||
Brian Granger
|
r2244 | |||
Thomas Kluyver
|
r4731 | from IPython.utils import py3compat | ||
Brandon Parsons
|
r6655 | from IPython.utils.encoding import get_stream_enc | ||
Thomas Kluyver
|
r4731 | |||
Brian Granger
|
r2244 | #----------------------------------------------------------------------------- | ||
# Main function | ||||
#----------------------------------------------------------------------------- | ||||
# RegExp for splitting line contents into pre-char//first word-method//rest. | ||||
# For clarity, each group in on one line. | ||||
Thomas Kluyver
|
r4746 | # WARNING: update the regexp if the escapes in interactiveshell are changed, as | ||
# they are hardwired in. | ||||
Brian Granger
|
r2244 | |||
# Although it's not solely driven by the regex, note that: | ||||
# ,;/% only trigger if they are the first character on the line | ||||
Bernardo B. Marques
|
r4872 | # ! and !! trigger if they are first char(s) *or* follow an indent | ||
Brian Granger
|
r2244 | # ? triggers as first or last char. | ||
Thomas Kluyver
|
r4746 | line_split = re.compile(""" | ||
^(\s*) # any leading space | ||||
([,;/%]|!!?|\?\??)? # escape character or characters | ||||
Fernando Perez
|
r6998 | \s*(%{0,2}[\w\.\*]*) # function/method, possibly with leading % | ||
Thomas Kluyver
|
r4746 | # to correctly treat things like '?%magic' | ||
(.*?$|$) # rest of line | ||||
""", re.VERBOSE) | ||||
Brian Granger
|
r2244 | |||
Fernando Perez
|
r6912 | |||
Brian Granger
|
r2244 | def split_user_input(line, pattern=None): | ||
Thomas Kluyver
|
r4746 | """Split user input into initial whitespace, escape character, function part | ||
and the rest. | ||||
Brian Granger
|
r2256 | """ | ||
Fernando Perez
|
r3038 | # We need to ensure that the rest of this routine deals only with unicode | ||
Brandon Parsons
|
r6655 | encoding = get_stream_enc(sys.stdin, 'utf-8') | ||
Brandon Parsons
|
r6651 | line = py3compat.cast_unicode(line, encoding) | ||
Bernardo B. Marques
|
r4872 | |||
Brian Granger
|
r2244 | if pattern is None: | ||
pattern = line_split | ||||
match = pattern.match(line) | ||||
if not match: | ||||
Brian Granger
|
r2256 | # print "match failed for line '%s'" % line | ||
Brian Granger
|
r2244 | try: | ||
ifun, the_rest = line.split(None,1) | ||||
except ValueError: | ||||
Brian Granger
|
r2256 | # print "split failed for line '%s'" % line | ||
Fernando Perez
|
r3038 | ifun, the_rest = line, u'' | ||
Brian Granger
|
r2244 | pre = re.match('^(\s*)(.*)',line).groups()[0] | ||
Thomas Kluyver
|
r4744 | esc = "" | ||
Brian Granger
|
r2244 | else: | ||
Thomas Kluyver
|
r4744 | pre, esc, ifun, the_rest = match.groups() | ||
Brian Granger
|
r2244 | |||
#print 'line:<%s>' % line # dbg | ||||
#print 'pre <%s> ifun <%s> rest <%s>' % (pre,ifun.strip(),the_rest) # dbg | ||||
Thomas Kluyver
|
r4746 | return pre, esc or '', ifun.strip(), the_rest.lstrip() | ||
Fernando Perez
|
r6912 | |||
Thomas Kluyver
|
r4746 | class LineInfo(object): | ||
"""A single line of input and associated info. | ||||
Bernardo B. Marques
|
r4872 | Includes the following as properties: | ||
Thomas Kluyver
|
r4746 | |||
line | ||||
The original, raw line | ||||
Bernardo B. Marques
|
r4872 | |||
Thomas Kluyver
|
r4746 | continue_prompt | ||
Is this line a continuation in a sequence of multiline input? | ||||
Bernardo B. Marques
|
r4872 | |||
Thomas Kluyver
|
r4746 | pre | ||
Any leading whitespace. | ||||
Bernardo B. Marques
|
r4872 | |||
Thomas Kluyver
|
r4746 | esc | ||
The escape character(s) in pre or the empty string if there isn't one. | ||||
Note that '!!' and '??' are possible values for esc. Otherwise it will | ||||
always be a single character. | ||||
Bernardo B. Marques
|
r4872 | |||
Thomas Kluyver
|
r4746 | ifun | ||
The 'function part', which is basically the maximal initial sequence | ||||
of valid python identifiers and the '.' character. This is what is | ||||
checked for alias and magic transformations, used for auto-calling, | ||||
etc. In contrast to Python identifiers, it may start with "%" and contain | ||||
"*". | ||||
Bernardo B. Marques
|
r4872 | |||
Thomas Kluyver
|
r4746 | the_rest | ||
Everything else on the line. | ||||
""" | ||||
def __init__(self, line, continue_prompt=False): | ||||
self.line = line | ||||
self.continue_prompt = continue_prompt | ||||
self.pre, self.esc, self.ifun, self.the_rest = split_user_input(line) | ||||
self.pre_char = self.pre.strip() | ||||
if self.pre_char: | ||||
self.pre_whitespace = '' # No whitespace allowd before esc chars | ||||
Bernardo B. Marques
|
r4872 | else: | ||
Thomas Kluyver
|
r4746 | self.pre_whitespace = self.pre | ||
def ofind(self, ip): | ||||
"""Do a full, attribute-walking lookup of the ifun in the various | ||||
namespaces for the given IPython InteractiveShell instance. | ||||
Fernando Perez
|
r6912 | Return a dict with keys: {found, obj, ospace, ismagic} | ||
Thomas Kluyver
|
r4746 | |||
Note: can cause state changes because of calling getattr, but should | ||||
only be run if autocall is on and if the line hasn't matched any | ||||
other, less dangerous handlers. | ||||
Does cache the results of the call, so can be called multiple times | ||||
without worrying about *further* damaging state. | ||||
""" | ||||
Fernando Perez
|
r6913 | return ip._ofind(self.ifun) | ||
Thomas Kluyver
|
r4746 | |||
Bernardo B. Marques
|
r4872 | def __str__(self): | ||
return "LineInfo [%s|%s|%s|%s]" %(self.pre, self.esc, self.ifun, self.the_rest) | ||||