Bliss shell: prompt_mac equivalent
Would it be possible to add hooks before/after command evaluation (something like spec's prompt_mac) which can be modified at runtime?
I want to send Bliss commands to our electronic logbook (ICAT+). Example with monkey patching to illustrate what I'm talking about:
import types
from bliss.common.session import get_current as getsession
from bliss.shell.cli import repl
def patchREPL():
"""Monkey-patch the current REPL to allow for custom pre/post execution hooks
"""
REPL = repl.REPL
if hasattr(REPL,'_pre_execute') or REPL is None:
return REPL
def _wrap_pre_execute(self, cli, line):
if callable(self._pre_execute):
self._pre_execute(line)
def _wrap_post_execute(self, exc_info, cli, line):
if callable(self._post_execute):
self._post_execute(line, exc_info)
REPL._pre_execute = None
REPL._post_execute = None
REPL._wrap_pre_execute = types.MethodType(_wrap_pre_execute, REPL)
REPL._wrap_post_execute = types.MethodType(_wrap_post_execute, REPL)
old = REPL._execute_task
def new(self, *args, **kwargs):
self._wrap_pre_execute(*args, **kwargs)
ret = old(*args, **kwargs)
self._wrap_post_execute(ret, *args, **kwargs)
return ret
REPL._execute_task = types.MethodType(new, REPL)
return REPL
class Elogbook(object):
...
def _newcommand(self, line, exc_info):
if exc_info is None:
self.command(line)
else:
self.error(line)
def addhook(self):
repl = patchREPL()
if repl:
repl._post_execute = self._newcommand
print('E-logbook hook added')
def removehook(self):
repl = patchREPL()
if repl:
repl._post_execute = None
print('E-logbook hook removed')
@classmethod
def factory(cls):
env_dict = getsession().env_dict
if env_dict.get('elog',None):
env_dict['elog'].removehook()
env_dict['elog'] = cls()
env_dict['elog'].addhook()
So one solution is to allow for adding hooks to BlissRepl
. On the other hand we are mostly interested in the commands that move motors and perform scans. So alternatively one could add a decorator for those types of functions, allowing for adding/removing hooks at runtime.