Merge pull request #1728 from astronouth7303/events-precmd

Add on_precommand and on_postcommand
This commit is contained in:
Anthony Scopatz 2016-09-13 23:44:58 -04:00 committed by GitHub
commit 27b12fa860
4 changed files with 73 additions and 27 deletions

13
news/events-precmd.rst Normal file
View file

@ -0,0 +1,13 @@
**Added:**
* Added ``on_precommand`` and ``on_postcommand`` `events </events.html>`_
**Changed:** None
**Deprecated:** None
**Removed:** None
**Fixed:** None
**Security:** None

View file

@ -13,7 +13,7 @@ NEWSDIR = os.path.join(os.path.dirname(os.path.dirname(__file__)), 'news')
CATEGORIES = frozenset(['Added', 'Changed', 'Deprecated', 'Removed', CATEGORIES = frozenset(['Added', 'Changed', 'Deprecated', 'Removed',
'Fixed', 'Security']) 'Fixed', 'Security'])
single_grave_reg = re.compile(r'[^`]`[^`]+`[^`]') single_grave_reg = re.compile(r'[^`]`[^`]+`[^`_]')
def check_news_file(fname): def check_news_file(fname):
name = fname.name name = fname.name
@ -51,8 +51,7 @@ def check_news_file(fname):
pytest.fail('{}:{}: invalid rst'.format(name, i+1), pytest.fail('{}:{}: invalid rst'.format(name, i+1),
pytrace=False) pytrace=False)
if '`' in line: if '`' in line:
if line.count('`') % 4 != 0 \ if single_grave_reg.search(line):
or single_grave_reg.search(line):
pytest.fail("{}:{}: single grave accents" pytest.fail("{}:{}: single grave accents"
" are not valid rst".format(name, i+1), " are not valid rst".format(name, i+1),
pytrace=False) pytrace=False)

View file

@ -159,6 +159,9 @@ class BaseShell(object):
src, code = self.push(line) src, code = self.push(line)
if code is None: if code is None:
return return
events.on_precommand.fire(src)
hist = builtins.__xonsh_history__ # pylint: disable=no-member hist = builtins.__xonsh_history__ # pylint: disable=no-member
ts1 = None ts1 = None
store_stdout = builtins.__xonsh_env__.get('XONSH_STORE_STDOUT') # pylint: disable=no-member store_stdout = builtins.__xonsh_env__.get('XONSH_STORE_STDOUT') # pylint: disable=no-member
@ -181,6 +184,42 @@ class BaseShell(object):
ts1 = ts1 or time.time() ts1 = ts1 or time.time()
self._append_history(inp=src, ts=[ts0, ts1], tee_out=tee.getvalue()) self._append_history(inp=src, ts=[ts0, ts1], tee_out=tee.getvalue())
tee.close() tee.close()
self._fix_cwd()
if builtins.__xonsh_exit__: # pylint: disable=no-member
return True
def _append_history(self, tee_out=None, **info):
"""
Append information about the command to the history.
(Also handles on_postcommand because this is the place where all the information is available)
"""
hist = builtins.__xonsh_history__ # pylint: disable=no-member
info['rtn'] = hist.last_cmd_rtn
tee_out = tee_out or None
last_out = hist.last_cmd_out or None
if last_out is None and tee_out is None:
pass
elif last_out is None and tee_out is not None:
info['out'] = tee_out
elif last_out is not None and tee_out is None:
info['out'] = last_out
else:
info['out'] = tee_out + '\n' + last_out
events.on_postcommand.fire(
info['inp'],
info['rtn'],
info.get('out', None),
info['ts']
)
hist.append(info)
hist.last_cmd_rtn = hist.last_cmd_out = None
def _fix_cwd(self):
"""Check if the cwd changed out from under us"""
cwd = os.getcwd() cwd = os.getcwd()
if cwd != builtins.__xonsh_env__['PWD']: if cwd != builtins.__xonsh_env__['PWD']:
old = builtins.__xonsh_env__['PWD'] # working directory changed without updating $PWD old = builtins.__xonsh_env__['PWD'] # working directory changed without updating $PWD
@ -188,8 +227,6 @@ class BaseShell(object):
if old is not None: if old is not None:
builtins.__xonsh_env__['OLDPWD'] = old # and update $OLDPWD like dirstack. builtins.__xonsh_env__['OLDPWD'] = old # and update $OLDPWD like dirstack.
events.on_chdir.fire(old, cwd) # fire event after cwd actually changed. events.on_chdir.fire(old, cwd) # fire event after cwd actually changed.
if builtins.__xonsh_exit__: # pylint: disable=no-member
return True
def push(self, line): def push(self, line):
"""Pushes a line onto the buffer and compiles the code in a way that """Pushes a line onto the buffer and compiles the code in a way that
@ -280,23 +317,6 @@ class BaseShell(object):
self.settitle() self.settitle()
return p return p
def _append_history(self, tee_out=None, **info):
"""Append information about the command to the history."""
hist = builtins.__xonsh_history__ # pylint: disable=no-member
info['rtn'] = hist.last_cmd_rtn
tee_out = tee_out or None
last_out = hist.last_cmd_out or None
if last_out is None and tee_out is None:
pass
elif last_out is None and tee_out is not None:
info['out'] = tee_out
elif last_out is not None and tee_out is None:
info['out'] = last_out
else:
info['out'] = tee_out + '\n' + last_out
hist.append(info)
hist.last_cmd_rtn = hist.last_cmd_out = None
def format_color(self, string, **kwargs): def format_color(self, string, **kwargs):
"""Formats the colors in a string. This base implmentation does not """Formats the colors in a string. This base implmentation does not
actually do any coloring, but just returns the string directly. actually do any coloring, but just returns the string directly.

View file

@ -11,6 +11,20 @@ from xonsh.execer import Execer
from xonsh.platform import (best_shell_type, has_prompt_toolkit, from xonsh.platform import (best_shell_type, has_prompt_toolkit,
ptk_version_is_supported) ptk_version_is_supported)
from xonsh.tools import XonshError, to_bool_or_int from xonsh.tools import XonshError, to_bool_or_int
from xonsh.events import events
events.doc('on_precommand', """
on_precommand(cmd: str) -> None
Fires just before a command is executed.
""")
events.doc('on_postcommand', """
on_postcommand(cmd: str, rtn: int, out: str or None, ts: list) -> None
Fires just after a command is executed.
""")
class Shell(object): class Shell(object):