Repository: python-cmd2/cmd2

Issue:
Please consider the ability to suppress diagnostics output of "set" command
Currently when a Settable's value is changed via "set" or via startup script, there is a small amount of diagnostics output that is always generated regardless of the "quiet" setting.  For example:

> set root '/.more-space'
root - was: '/.space'
now: '/.more-space'

This is somewhat jarring if we use a lot of "set" commands in startup script.  Would you please consider suppressing this output?

Discussion:

Patch:
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 1b40cfbe..19be0280 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -2,6 +2,9 @@
 * Bug Fixes
     * Fixed bug where setting `always_show_hint=True` did not show a hint when completing `Settables`
     * Fixed bug in editor detection logic on Linux systems that do not have `which`
+* Enhancements
+    * Added `silent_startup_script` option to `cmd2.Cmd.__init__()`. If `True`, then the startup script's
+      output will be suppressed. Anything written to stderr will still display.
 
 ## 1.4.0 (November 11, 2020)
 * Bug Fixes
diff --git a/cmd2/cmd2.py b/cmd2/cmd2.py
index 689f81a5..8ad3f7ba 100644
--- a/cmd2/cmd2.py
+++ b/cmd2/cmd2.py
@@ -199,7 +199,7 @@ class Cmd(cmd.Cmd):
 
     def __init__(self, completekey: str = 'tab', stdin=None, stdout=None, *,
                  persistent_history_file: str = '', persistent_history_length: int = 1000,
-                 startup_script: str = '', use_ipython: bool = False,
+                 startup_script: str = '', silent_startup_script: bool = False, use_ipython: bool = False,
                  allow_cli_args: bool = True, transcript_files: Optional[List[str]] = None,
                  allow_redirection: bool = True, multiline_commands: Optional[List[str]] = None,
                  terminators: Optional[List[str]] = None, shortcuts: Optional[Dict[str, str]] = None,
@@ -215,6 +215,8 @@ class Cmd(cmd.Cmd):
         :param persistent_history_length: max number of history items to write
                                           to the persistent history file
         :param startup_script: file path to a script to execute at startup
+        :param silent_startup_script: if ``True``, then the startup script's output will be
+                                      suppressed. Anything written to stderr will still display.
         :param use_ipython: should the "ipy" command be included for an embedded IPython shell
         :param allow_cli_args: if ``True``, then :meth:`cmd2.Cmd.__init__` will process command
                                line arguments as either commands to be run or, if ``-t`` or
@@ -363,7 +365,10 @@ class Cmd(cmd.Cmd):
         if startup_script:
             startup_script = os.path.abspath(os.path.expanduser(startup_script))
             if os.path.exists(startup_script):
-                self._startup_commands.append("run_script {}".format(utils.quote_string(startup_script)))
+                script_cmd = "run_script {}".format(utils.quote_string(startup_script))
+                if silent_startup_script:
+                    script_cmd += "> {}".format(os.devnull)
+                self._startup_commands.append(script_cmd)
 
         # Transcript files to run instead of interactive command loop
         self._transcript_files = None  # type: Optional[List[str]]


Test patch:
diff --git a/tests/test_cmd2.py b/tests/test_cmd2.py
index a2299abe..d523bb8f 100755
--- a/tests/test_cmd2.py
+++ b/tests/test_cmd2.py
@@ -2399,15 +2399,24 @@ def test_disabled_message_command_name(disable_commands_app):
     out, err = run_cmd(disable_commands_app, 'has_helper_funcs')
     assert err[0].startswith('has_helper_funcs is currently disabled')
 
-
-def test_startup_script(request):
+@pytest.mark.parametrize('silent_startup_script', [
+    True,
+    False
+])
+def test_startup_script(request, capsys, silent_startup_script):
     test_dir = os.path.dirname(request.module.__file__)
     startup_script = os.path.join(test_dir, '.cmd2rc')
-    app = cmd2.Cmd(allow_cli_args=False, startup_script=startup_script)
+    app = cmd2.Cmd(allow_cli_args=False, startup_script=startup_script, silent_startup_script=silent_startup_script)
     assert len(app._startup_commands) == 1
-    assert app._startup_commands[0] == "run_script {}".format(utils.quote_string(startup_script))
     app._startup_commands.append('quit')
     app.cmdloop()
+
+    out, err = capsys.readouterr()
+    if silent_startup_script:
+        assert not out
+    else:
+        assert out
+
     out, err = run_cmd(app, 'alias list')
     assert len(out) > 1
     assert 'alias create ls' in out[0]