Skip to content
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,9 @@ prompt is displayed.
- Added `Cmd2ArgumentParser.output_to()` context manager to temporarily set the output stream
during `argparse` operations. This is helpful for directing output for functions like
`parse_args()`, which default to `sys.stdout` and lack a `file` argument.
- Updated `set` command to consolidate its confirmation output into a single, colorized line.
The confirmation now uses `pfeedback()`, allowing it to be silenced when the `quiet` settable
is enabled.

## 3.5.1 (April 24, 2026)

Expand Down
13 changes: 12 additions & 1 deletion cmd2/cmd2.py
Original file line number Diff line number Diff line change
Expand Up @@ -4697,7 +4697,18 @@ def do_set(self, args: argparse.Namespace) -> None:
except ValueError as ex:
self.perror(f"Error setting {args.param}: {ex}")
else:
self.poutput(f"{args.param} - was: {orig_value!r}\nnow: {settable.value!r}")
# Create the feedback message using Rich Text for color
feedback_msg = Text.assemble(
args.param,
": ",
(f"{orig_value!r}", "red"),
"\n",
" " * max(0, len(args.param) - 1),
"-> ",
(f"{settable.value!r}", "green"),
)
self.pfeedback(feedback_msg)

Comment thread
tleonhardt marked this conversation as resolved.
self.last_result = True
return

Expand Down
64 changes: 28 additions & 36 deletions tests/test_cmd2.py
Original file line number Diff line number Diff line change
Expand Up @@ -160,16 +160,17 @@ def test_base_set(base_app) -> None:


def test_set(base_app) -> None:
out, _err = run_cmd(base_app, "set quiet True")
expected = normalize(
"""
quiet - was: False
now: True
"""
)
assert out == expected
out, err = run_cmd(base_app, "set quiet True")
assert not out
assert base_app.last_result is True

# Test quiet respect
out, err = run_cmd(base_app, "set timing False")
assert not out
assert not err
assert base_app.last_result is True

# Show one settable (this always goes to out)
line_found = False
out, _err = run_cmd(base_app, "set quiet")
for line in out:
Expand All @@ -180,6 +181,7 @@ def test_set(base_app) -> None:
assert line_found
assert len(base_app.last_result) == 1
assert base_app.last_result["quiet"] is True
base_app.quiet = False


def test_set_val_empty(base_app) -> None:
Expand Down Expand Up @@ -236,8 +238,8 @@ def test_set_allow_style(base_app, new_val, is_valid, expected) -> None:
# Verify the results
assert expected == ru.ALLOW_STYLE
if is_valid:
assert not err
assert out
assert err
assert not out


def test_set_traceback_show_locals(base_app: cmd2.Cmd) -> None:
Expand Down Expand Up @@ -275,9 +277,11 @@ def test_set_with_choices(base_app) -> None:
base_app.add_settable(fake_settable)

# Try a valid choice
_out, err = run_cmd(base_app, f"set fake {fake_choices[1]}")
out, err = run_cmd(base_app, f"set fake {fake_choices[1]}")
assert base_app.last_result is True
assert not err
assert not out
assert err[0].startswith(f"fake: {fake_choices[0]!r}")
assert err[1].endswith(f"-> {fake_choices[1]!r}")

# Try an invalid choice
_out, err = run_cmd(base_app, "set fake bad_value")
Expand All @@ -301,15 +305,10 @@ def onchange_app():


def test_set_onchange_hook(onchange_app) -> None:
out, _err = run_cmd(onchange_app, "set quiet True")
expected = normalize(
"""
You changed quiet
quiet - was: False
now: True
"""
)
assert out == expected
out, err = run_cmd(onchange_app, "set quiet True")
assert out == ["You changed quiet"]
# quiet: False -> True is not shown because quiet is now True
assert not err
assert onchange_app.last_result is True


Expand Down Expand Up @@ -875,17 +874,14 @@ def test_allow_clipboard(base_app) -> None:
def test_base_timing(base_app) -> None:
base_app.feedback_to_output = False
out, err = run_cmd(base_app, "set timing True")
expected = normalize(
"""timing - was: False
now: True
"""
)
assert out == expected
assert not out
assert err[0].startswith("timing: False")
assert err[1].endswith("-> True")

if sys.platform == "win32":
assert err[0].startswith("Elapsed: 0:00:00")
assert err[2].startswith("Elapsed: 0:00:00")
else:
assert err[0].startswith("Elapsed: 0:00:00.0")
assert err[2].startswith("Elapsed: 0:00:00.0")


def test_base_debug(base_app) -> None:
Expand All @@ -899,13 +895,9 @@ def test_base_debug(base_app) -> None:

# Set debug true
out, err = run_cmd(base_app, "set debug True")
expected = normalize(
"""
debug - was: False
now: True
"""
)
assert out == expected
assert not out
assert err[0].startswith("debug: False")
assert err[1].endswith("-> True")

# Verify that we now see the exception traceback
out, err = run_cmd(base_app, "edit")
Expand Down
8 changes: 3 additions & 5 deletions tests/test_commandset.py
Original file line number Diff line number Diff line change
Expand Up @@ -1103,11 +1103,9 @@ def __init__(self) -> None:

# change the value and verify the value changed
out, err = run_cmd(app, "set arbitrary_value 10")
expected = """
arbitrary_value - was: 5
now: 10
"""
assert out == normalize(expected)
assert not out
assert err[0].startswith("arbitrary_value: 5")
assert err[1].endswith("-> 10")
out, err = run_cmd(app, "set arbitrary_value")
any("arbitrary_value" in line and "10" in line for line in out)

Expand Down
Loading