Source code for pypsi.plugins.block
#
# Copyright (c) 2015, Adam Meily <meily.adam@gmail.com>
# Pypsi - https://github.com/ameily/pypsi
#
# Permission to use, copy, modify, and/or distribute this software for any
# purpose with or without fee is hereby granted, provided that the above
# copyright notice and this permission notice appear in all copies.
#
# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
#
from pypsi.core import Command, Plugin
[docs]class BlockCommand(Command):
'''
Base class for any block commands that accept multiple statements from the
user. Block commands allow the user to input several individual statement
lines and postpone processing and execution until a later time. For
example, the :class:`pypsi.commands.macro.MacroCommand` is a block command
that allows the user to record several statements and then execute them
when the macro is called.
'''
def __init__(self, prompt='> ', **kwargs):
super(BlockCommand, self).__init__(**kwargs)
self.prompt = prompt
[docs] def begin_block(self, shell):
'''
Begin a block command and record subsequent statements to the block
buffer.
'''
plugin = shell.ctx.block
plugin.begin_block(shell, self)
self.old_prompt = shell.prompt
shell.prompt = self.prompt
[docs] def end_block(self, shell, lines):
'''
Called when a block has ended recording. Subclasses must implement this
method.
:param pypsi.shell.Shell shell: the active shell
:param list lines: the list of unprocessed statements (:class:`str`)
'''
raise NotImplementedError()
[docs]class BlockPlugin(Plugin):
'''
Provide the ability to record multiple statements for future processing and
execution. By itself, the :class:`BlockPlugin` doesn't do anything. Rather,
new :class:`BlockCommand` are developed that leverage this plugin's
preprocessor to record multiple statements from the user. Blocks are
terminated the user inputs the value of :data:`end_cmd`, at which point,
the active :class:`BlockCommand` is retrieved and
:meth:`BlockCommand.end_block` is called.
'''
def __init__(self, end_cmd='end', preprocess=20, **kwargs):
'''
:param str end_cmd: the statement that will terminate the active block
'''
super(BlockPlugin, self).__init__(preprocess=preprocess, **kwargs)
self.end_cmd = end_cmd
[docs] def setup(self, shell):
'''
Adds a reference to this instance in the shell's context. Allows
plugins and commands to get this plugin by accessing
``shell.ctx.block``.
'''
if 'block' not in shell.ctx:
shell.ctx.block = self
if 'recording_block' not in shell.ctx:
shell.ctx.recording_block = None
return 0
def on_input(self, shell, line):
if shell.ctx.recording_block is not None:
if line.strip() == self.end_cmd:
self.end_block(shell)
else:
shell.ctx.recording_block['lines'].append(line)
return None
return line
[docs] def begin_block(self, shell, cmd):
'''
Begin recording a new block.
:param pypsi.shell.Shell shell: the active shell
:param BlockCommand cmd: the active block command
'''
shell.ctx.recording_block = {
'cmd': cmd,
'lines': []
}
return 0
[docs] def end_block(self, shell):
'''
End the block. Calls the active block command's
:meth:`BlockCommand.end_block` method.
'''
shell.prompt = shell.ctx.recording_block['cmd'].old_prompt
shell.ctx.recording_block['cmd'].end_block(
shell, shell.ctx.recording_block['lines']
)
shell.ctx.recording_block = None
return 0
def on_input_canceled(self, shell):
if shell.ctx.recording_block is not None:
shell.ctx.recording_block['cmd'].cancel_block(shell)
shell.prompt = shell.ctx.recording_block['cmd'].old_prompt
shell.ctx.recording_block = None