From be8537c0cf11e7e478cb73ea2927e08ffc94ac49 Mon Sep 17 00:00:00 2001 From: Yigong Wang Date: Sat, 31 Mar 2018 17:26:46 -0400 Subject: [PATCH] Add recent REPL results globals *i and most recent error *e This comment add *1, *2, *3 as globals for recent REPL results. *e global is also added for the most recent error object. --- NEWS.rst | 2 ++ hy/cmdline.py | 35 +++++++++++++++++++++++------------ tests/test_bin.py | 11 +++++++++-- 3 files changed, 34 insertions(+), 14 deletions(-) diff --git a/NEWS.rst b/NEWS.rst index eb0aaf8..709bd50 100644 --- a/NEWS.rst +++ b/NEWS.rst @@ -20,6 +20,8 @@ New Features ------------------------------ * Python 3.7 is now supported * Added `mangle` and `unmangle` as core functions +* More REPL history result variables: `*2`, `*3`. Added last REPL error + variable: `*e` * `defclass` in Python 3 now supports specifying metaclasses and other keyword arguments * Added a command-line option `-E` per CPython diff --git a/hy/cmdline.py b/hy/cmdline.py index 779ec40..d99a7aa 100644 --- a/hy/cmdline.py +++ b/hy/cmdline.py @@ -73,8 +73,20 @@ class HyREPL(code.InteractiveConsole): code.InteractiveConsole.__init__(self, locals=locals, filename=filename) + # Pre-mangle symbols for repl recent results: *1, *2, *3 + self._repl_results_symbols = [mangle("*{}".format(i + 1)) for i in range(3)] + self.locals.update({sym: None for sym in self._repl_results_symbols}) + def runsource(self, source, filename='', symbol='single'): global SIMPLE_TRACEBACKS + + def error_handler(e, use_simple_traceback=False): + self.locals[mangle("*e")] = e + if use_simple_traceback: + print(e, file=sys.stderr) + else: + self.showtraceback() + try: try: do = import_buffer_to_hst(source) @@ -84,7 +96,7 @@ class HyREPL(code.InteractiveConsole): if e.source is None: e.source = source e.filename = filename - print(e, file=sys.stderr) + error_handler(e, use_simple_traceback=True) return False try: @@ -101,24 +113,23 @@ class HyREPL(code.InteractiveConsole): if e.source is None: e.source = source e.filename = filename - if SIMPLE_TRACEBACKS: - print(e, file=sys.stderr) - else: - self.showtraceback() + error_handler(e, use_simple_traceback=SIMPLE_TRACEBACKS) return False - except Exception: - self.showtraceback() + except Exception as e: + error_handler(e) return False if value is not None: - # Make the last non-None value available to - # the user as `*1`. - self.locals[mangle("*1")] = value + # Shift exisitng REPL results + next_result = value + for sym in self._repl_results_symbols: + self.locals[sym], next_result = next_result, self.locals[sym] + # Print the value. try: output = self.output_fn(value) - except Exception: - self.showtraceback() + except Exception as e: + error_handler(e) return False print(output) return False diff --git a/tests/test_bin.py b/tests/test_bin.py index ad74781..9bfb27f 100644 --- a/tests/test_bin.py +++ b/tests/test_bin.py @@ -75,8 +75,15 @@ def test_bin_hy_stdin_multiline(): def test_bin_hy_history(): - output, _ = run_cmd("hy", '(+ "a" "b")\n(+ *1 "y" "z")') - assert "'abyz'" in output + output, _ = run_cmd("hy", '''(+ "a" "b") + (+ "c" "d") + (+ "e" "f") + (.format "*1: {}, *2: {}, *3: {}," *1 *2 *3)''') + assert "'*1: ef, *2: cd, *3: ab,'" in output + + output, _ = run_cmd("hy", '''(raise (Exception "TEST ERROR")) + (+ "err: " (str *e))''') + assert "'err: TEST ERROR'" in output def test_bin_hy_stdin_comments():