##// END OF EJS Templates
First go at new input transformation system
First go at new input transformation system

File last commit:

r10090:c0a48480
r10090:c0a48480
Show More
inputtransformer.py
112 lines | 3.2 KiB | text/x-python | PythonLexer
import abc
import re
from IPython.core.splitinput import split_user_input, LineInfo
from IPython.core.inputsplitter import (ESC_SHELL, ESC_SH_CAP, ESC_HELP,
ESC_HELP2, ESC_MAGIC, ESC_MAGIC2,
ESC_QUOTE, ESC_QUOTE2, ESC_PAREN)
from IPython.core.inputsplitter import EscapedTransformer, _make_help_call, has_comment
class InputTransformer(object):
__metaclass__ = abc.ABCMeta
@abc.abstractmethod
def push(self, line):
pass
@abc.abstractmethod
def reset(self):
pass
class StatelessInputTransformer(InputTransformer):
"""Decorator for a stateless input transformer implemented as a function."""
def __init__(self, func):
self.func = func
def push(self, line):
return self.func(line)
def reset(self):
pass
class CoroutineInputTransformer(InputTransformer):
"""Decorator for an input transformer implemented as a coroutine."""
def __init__(self, coro):
# Prime it
self.coro = coro()
next(self.coro)
def push(self, line):
return self.coro.send(line)
def reset(self):
self.coro.send(None)
@CoroutineInputTransformer
def escaped_transformer():
et = EscapedTransformer()
line = ''
while True:
line = (yield line)
if not line or line.isspace():
continue
lineinf = LineInfo(line)
if lineinf.esc not in et.tr:
continue
parts = []
while line is not None:
parts.append(line.rstrip('\\'))
if not line.endswith('\\'):
break
line = (yield None)
# Output
lineinf = LineInfo(' '.join(parts))
line = et.tr[lineinf.esc](lineinf)
_initial_space_re = re.compile(r'\s*')
_help_end_re = re.compile(r"""(%{0,2}
[a-zA-Z_*][\w*]* # Variable name
(\.[a-zA-Z_*][\w*]*)* # .etc.etc
)
(\?\??)$ # ? or ??""",
re.VERBOSE)
@StatelessInputTransformer
def transform_help_end(line):
"""Translate lines with ?/?? at the end"""
m = _help_end_re.search(line)
if m is None or has_comment(line):
return line
target = m.group(1)
esc = m.group(3)
lspace = _initial_space_re.match(line).group(0)
# If we're mid-command, put it back on the next prompt for the user.
next_input = line.rstrip('?') if line.strip() != m.group(0) else None
return _make_help_call(target, esc, lspace, next_input)
@CoroutineInputTransformer
def cellmagic():
tpl = 'get_ipython().run_cell_magic(%r, %r, %r)'
line = ''
while True:
line = (yield line)
if not line.startswith(ESC_MAGIC2):
continue
first = line
body = []
line = (yield None)
while (line is not None) and (line.strip() != ''):
body.append(line)
line = (yield None)
# Output
magic_name, _, first = first.partition(' ')
magic_name = magic_name.lstrip(ESC_MAGIC2)
line = tpl % (magic_name, first, '\n'.join(body))