From f75303f8e4b223698234aba3962c4f24dc80f647 Mon Sep 17 00:00:00 2001 From: Jamie Bliss Date: Tue, 13 Sep 2016 22:44:49 -0400 Subject: [PATCH 1/4] Add on_{pre,post}command events --- xonsh/base_shell.py | 68 +++++++++++++++++++++++++++++---------------- xonsh/shell.py | 14 ++++++++++ 2 files changed, 58 insertions(+), 24 deletions(-) diff --git a/xonsh/base_shell.py b/xonsh/base_shell.py index ea74e4759..f8c9838f8 100644 --- a/xonsh/base_shell.py +++ b/xonsh/base_shell.py @@ -159,6 +159,9 @@ class BaseShell(object): src, code = self.push(line) if code is None: return + + events.on_precommand.fire(src) + hist = builtins.__xonsh_history__ # pylint: disable=no-member ts1 = None store_stdout = builtins.__xonsh_env__.get('XONSH_STORE_STDOUT') # pylint: disable=no-member @@ -181,16 +184,50 @@ class BaseShell(object): ts1 = ts1 or time.time() self._append_history(inp=src, ts=[ts0, ts1], tee_out=tee.getvalue()) tee.close() - cwd = os.getcwd() - if cwd != builtins.__xonsh_env__['PWD']: - old = builtins.__xonsh_env__['PWD'] # working directory changed without updating $PWD - builtins.__xonsh_env__['PWD'] = cwd # track it now - if old is not None: - builtins.__xonsh_env__['OLDPWD'] = old # and update $OLDPWD like dirstack. - events.on_chdir.fire(old, cwd) # fire event after cwd actually changed. + + 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() + if cwd != builtins.__xonsh_env__['PWD']: + old = builtins.__xonsh_env__['PWD'] # working directory changed without updating $PWD + builtins.__xonsh_env__['PWD'] = cwd # track it now + if old is not None: + builtins.__xonsh_env__['OLDPWD'] = old # and update $OLDPWD like dirstack. + events.on_chdir.fire(old, cwd) # fire event after cwd actually changed. + def push(self, line): """Pushes a line onto the buffer and compiles the code in a way that enables multiline input. @@ -280,23 +317,6 @@ class BaseShell(object): self.settitle() 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): """Formats the colors in a string. This base implmentation does not actually do any coloring, but just returns the string directly. diff --git a/xonsh/shell.py b/xonsh/shell.py index 192ab9219..f364a6686 100644 --- a/xonsh/shell.py +++ b/xonsh/shell.py @@ -11,6 +11,20 @@ from xonsh.execer import Execer from xonsh.platform import (best_shell_type, has_prompt_toolkit, ptk_version_is_supported) 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): From 9da533eaa078711cee2b7cc05d80c90a9bdcef69 Mon Sep 17 00:00:00 2001 From: Jamie Bliss Date: Tue, 13 Sep 2016 22:52:53 -0400 Subject: [PATCH 2/4] Add news item. --- news/events-precmd.rst | 13 +++++++++++++ 1 file changed, 13 insertions(+) create mode 100644 news/events-precmd.rst diff --git a/news/events-precmd.rst b/news/events-precmd.rst new file mode 100644 index 000000000..997c8d9d2 --- /dev/null +++ b/news/events-precmd.rst @@ -0,0 +1,13 @@ +**Added:** + +* Added ``on_precommand`` and ``on_postcommand`` `events `_ + +**Changed:** None + +**Deprecated:** None + +**Removed:** None + +**Fixed:** None + +**Security:** None From 7b2e0421ca2bf6b5c9b0ff898e6dc3ade0c2cf9c Mon Sep 17 00:00:00 2001 From: Jamie Bliss Date: Tue, 13 Sep 2016 23:03:55 -0400 Subject: [PATCH 3/4] Allow links in news items --- tests/test_news.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/test_news.py b/tests/test_news.py index 88cc3a679..fc0c47a33 100644 --- a/tests/test_news.py +++ b/tests/test_news.py @@ -13,7 +13,7 @@ NEWSDIR = os.path.join(os.path.dirname(os.path.dirname(__file__)), 'news') CATEGORIES = frozenset(['Added', 'Changed', 'Deprecated', 'Removed', 'Fixed', 'Security']) -single_grave_reg = re.compile(r'[^`]`[^`]+`[^`]') +single_grave_reg = re.compile(r'[^`]`[^`]+`[^`_]') def check_news_file(fname): name = fname.name From 2f826d47ea7c2704d06afe9fb03842d985551361 Mon Sep 17 00:00:00 2001 From: Jamie Bliss Date: Tue, 13 Sep 2016 23:24:14 -0400 Subject: [PATCH 4/4] Fixing test and pep8 --- tests/test_news.py | 3 +-- xonsh/base_shell.py | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/tests/test_news.py b/tests/test_news.py index fc0c47a33..e3ed482c5 100644 --- a/tests/test_news.py +++ b/tests/test_news.py @@ -51,8 +51,7 @@ def check_news_file(fname): pytest.fail('{}:{}: invalid rst'.format(name, i+1), pytrace=False) if '`' in line: - if line.count('`') % 4 != 0 \ - or single_grave_reg.search(line): + if single_grave_reg.search(line): pytest.fail("{}:{}: single grave accents" " are not valid rst".format(name, i+1), pytrace=False) diff --git a/xonsh/base_shell.py b/xonsh/base_shell.py index f8c9838f8..928f6e3bc 100644 --- a/xonsh/base_shell.py +++ b/xonsh/base_shell.py @@ -192,7 +192,7 @@ class BaseShell(object): 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