diff options
-rw-r--r-- | CHANGELOG.md | 11 | ||||
-rw-r--r-- | cmd2/cmd2.py | 23 | ||||
-rw-r--r-- | tests/test_cmd2.py | 13 |
3 files changed, 37 insertions, 10 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md index 8bde2d33..6d21b33c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,17 @@ * Enhancements * Added ability to include command name placeholders in the message printed when trying to run a disabled command. * See docstring for ``disable_command()`` or ``disable_category()`` for more details. + * Added instance attributes to customize error messages without having to override methods. Theses messages can + also be colored. + * `help_error` - the error that prints when no help information can be found + * `default_error` - the error that prints when a non-existent command is run +* Potentially breaking changes + * The following commands now write to stderr instead of stdout when printing an error. This will make catching + errors easier in pyscript. + * ``do_help()`` - when no help information can be found + * ``default()`` - in all cases since this is called when an invalid command name is run + * ``_report_disabled_command_usage()`` - in all cases since this is called when a disabled command is run + * Removed *** from beginning of error messages printed by `do_help()` and `default()`. ## 0.9.11 (March 13, 2019) * Bug Fixes diff --git a/cmd2/cmd2.py b/cmd2/cmd2.py index 6b085a98..e41d947d 100644 --- a/cmd2/cmd2.py +++ b/cmd2/cmd2.py @@ -428,6 +428,12 @@ class Cmd(cmd.Cmd): # Used to keep track of whether a continuation prompt is being displayed self.at_continuation_prompt = False + # The error that prints when no help information can be found + self.help_error = "No help on {}" + + # The error that prints when a non-existent command is run + self.default_error = "{} is not a recognized command, alias, or macro" + # If this string is non-empty, then this warning message will print if a broken pipe error occurs while printing self.broken_pipe_warning = '' @@ -2057,8 +2063,8 @@ class Cmd(cmd.Cmd): return self.do_shell(statement.command_and_args) else: - self.perror('*** {} is not a recognized command, alias, or macro'.format(statement.command), - err_color=Fore.RESET, traceback_war=False) + err_msg = self.default_error.format(statement.command) + self.decolorized_write(sys.stderr, "{}\n".format(err_msg)) def pseudo_raw_input(self, prompt: str) -> str: """Began life as a copy of cmd's cmdloop; like raw_input but @@ -2586,12 +2592,21 @@ class Cmd(cmd.Cmd): else: # Getting help for a specific command func = self.cmd_func(args.command) + help_func = getattr(self, HELP_FUNC_PREFIX + args.command, None) + + # If the command function uses argparse, then use argparse's help if func and hasattr(func, 'argparser'): completer = AutoCompleter(getattr(func, 'argparser'), self) tokens = [args.command] + args.subcommand self.poutput(completer.format_help(tokens)) + + # If there is no help information then print an error + elif help_func is None and (func is None or not func.__doc__): + err_msg = self.help_error.format(args.command) + self.decolorized_write(sys.stderr, "{}\n".format(err_msg)) + + # Otherwise delegate to cmd base class do_help() else: - # No special behavior needed, delegate to cmd base class do_help() super().do_help(args.command) def _help_menu(self, verbose: bool = False) -> None: @@ -3719,7 +3734,7 @@ class Cmd(cmd.Cmd): :param message_to_print: the message reporting that the command is disabled :param kwargs: not used """ - self.perror(message_to_print, err_color=Fore.RESET, traceback_war=False) + self.decolorized_write(sys.stderr, "{}\n".format(message_to_print)) def cmdloop(self, intro: Optional[str] = None) -> None: """This is an outer wrapper around _cmdloop() which deals with extra features provided by cmd2. diff --git a/tests/test_cmd2.py b/tests/test_cmd2.py index 44ca89e0..6733be19 100644 --- a/tests/test_cmd2.py +++ b/tests/test_cmd2.py @@ -952,10 +952,10 @@ undoc """) assert out == expected -def test_help_undocumented(help_app): - out = run_cmd(help_app, 'help undoc') - expected = normalize('*** No help on undoc') - assert out == expected +def test_help_undocumented(help_app, capsys): + run_cmd(help_app, 'help undoc') + out, err = capsys.readouterr() + assert err.startswith("No help on undoc") def test_help_overridden_method(help_app): out = run_cmd(help_app, 'help edit') @@ -1787,8 +1787,9 @@ def test_macro_create_with_escaped_args(base_app, capsys): assert out == normalize("Macro 'fake' created") # Run the macro - out = run_cmd(base_app, 'fake') - assert 'No help on {1}' in out[0] + run_cmd(base_app, 'fake') + out, err = capsys.readouterr() + assert err.startswith('No help on {1}') def test_macro_usage_with_missing_args(base_app, capsys): # Create the macro |