Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
aad3d01
Run POSIX pipes to interactive programs as the terminal's foreground job
tleonhardt Sep 26, 2026
0380c1c
Give the corrupt-history tests their own temp files
tleonhardt Sep 12, 2026
f4c1d67
Report terminal sizes when the job-control test's resize step times out
tleonhardt Sep 26, 2026
46a1c1a
Fix pager hangs and a startup race in terminal pipelines
tleonhardt Sep 27, 2026
f31659f
Harden terminal pipeline job control against failures found in review
tleonhardt Sep 27, 2026
e48ef27
Build the watcher test's stop status at run time, not collection
tleonhardt Sep 27, 2026
50fab1f
Restore the POSIX skip on the send_sigint pipeline-exit test
tleonhardt Sep 27, 2026
3fe7a97
Keep the job-control test's terminal setup out of bash's way
tleonhardt Sep 27, 2026
1345818
Cover the last untested job-control lines in cmd2.utils
tleonhardt Sep 27, 2026
e1cb8bc
Coordinate Ctrl-Z across a pipeline's job and fix review findings
tleonhardt Sep 27, 2026
330f149
Type-check as Linux on every OS, as CI does
tleonhardt Sep 27, 2026
ebe7a39
Pipe output in the console's code page on Windows
tleonhardt Sep 27, 2026
f4fdddb
Judge the relay race test only by answers given during the paused read
tleonhardt Sep 27, 2026
f5fe7cb
Correct the branch policy in CLAUDE.md
tleonhardt Sep 27, 2026
6b63ca9
Fix a writer race, the Android shell, code pages, and worker-thread s…
tleonhardt Sep 27, 2026
9fb1da2
Skip the no-codec code page test on Windows with Python 3.14+
tleonhardt Sep 27, 2026
ab7ce16
Harden pipeline signal handling and page in the console's code page
tleonhardt Sep 27, 2026
66a9713
Give joined shell producers the pipe, and detach the watcher at teardown
tleonhardt Sep 27, 2026
e6c31f2
Lend the relay's terminal only to a consumer that waits for it
tleonhardt Sep 27, 2026
e39777f
Keep the watcher's suspension count current across its wait
tleonhardt Sep 27, 2026
0509109
Merge branch 'main' into pipeline-job-control
tleonhardt Sep 28, 2026
0ae75cb
Merge branch 'main' into pipeline-job-control
tleonhardt Sep 30, 2026
6c098ec
Reflow this branch's comments to the 127-character line length
tleonhardt Sep 30, 2026
880c518
Fix a relay leak, a lost stdout restore, and a hang relaying Ctrl-Z
tleonhardt Sep 30, 2026
a645ace
Fix terminal handoffs and signaling found in review
tleonhardt Sep 30, 2026
b13f515
Use a shell producer in the joined-producer wait test
tleonhardt Sep 30, 2026
6a28fcf
Set the Windows console to UTF-8 while a pipe or the pager runs
tleonhardt Sep 30, 2026
d75c148
Cover a pipe write that Ctrl-C interrupts before its first chunk
tleonhardt Sep 30, 2026
e4840cb
Merge branch 'main' into pipeline-job-control
tleonhardt Oct 2, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 20 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,23 @@
## 4.3.0 (TBD)

- Bug Fixes
- On POSIX, piping a command's output to an interactive program such as `less`
(`help -v | less`) now runs that program as the terminal's foreground job, as a shell pipeline
does. It had run in a separate session that never received the terminal, so Ctrl-Z and `fg`
did not suspend and resume it together with cmd2. The program now owns the terminal as it
starts, so a pager can set its terminal modes, and Ctrl-C and Ctrl-Z reach the whole pipeline.
Pipes started from a worker thread, or whose output does not go to the terminal, such as one
nested in a command whose own output is piped, still run in their own session
- A `shell` command piped to an interactive program, such as `shell git log | less`, now joins
the pipeline's job, so both processes receive Ctrl-C and Ctrl-Z
- On Windows, fixed piped output appearing garbled in console programs such as `more`
(`help -v | more`), a regression in 4.2.4. Pipes are written as UTF-8, but console programs
decode their input with the console's code page. While a pipe or the pager runs, cmd2 now sets
the console to UTF-8 (code page 65001, as `chcp 65001` does) and restores its code pages
afterward, so console programs and UTF-8 tools such as `rg` both read the output correctly
- When copying a command's output to the clipboard (`help >`) fails, later commands' output is
no longer written to the temporary file that held it

## 4.2.4 (September 8, 2026)

- Bug Fixes
Expand Down
4 changes: 2 additions & 2 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -111,8 +111,8 @@ embedded Python/IPython shells and `run_pyscript` while keeping isolation.
- Anything not documented under `docs/api/` is not public API (`cmd2/constants.py` says so
explicitly).
- Add user-visible changes to `CHANGELOG.md` under the current in-progress version heading.
- `main` is the branch for the next PATCH release; MAJOR/MINOR work happens on a branch named for
the target version. Releases are tagged and published from `main`.
- `main` is the branch for the next release, whether PATCH, MINOR, or MAJOR. Feature branches merge
into `main`, and all releases are tagged and published from it.
- Do not commit spec, plan, or markdown documents without asking first. Save plans to
`~/.superpowers/plans/` rather than the project directory.
- This project uses a 127 character maximum line length for all Python code, including for comments.
Expand Down
282 changes: 207 additions & 75 deletions cmd2/cmd2.py

Large diffs are not rendered by default.

798 changes: 788 additions & 10 deletions cmd2/utils.py

Large diffs are not rendered by default.

4 changes: 4 additions & 0 deletions docs/features/redirection.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,10 @@ Piping the output of a `cmd2` command to a shell command works just like in POSI

- pipe as input to a shell command with `|`, as in `mycommand args | wc`

On POSIX systems, a pipe to an interactive program such as `less` runs as the terminal's foreground
job, as it would in a shell: the program can read the keyboard, and Ctrl-C and Ctrl-Z reach it. A
`shell` command whose output is piped this way, as in `shell git log | less`, joins the same job.

## Multiple Pipes and Redirection

Multiple pipes, optionally followed by a redirect, are supported. Thus, it is possible to do
Expand Down
9 changes: 9 additions & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ dev = [
"mkdocstrings[python]>=1",
"mypy>=2.3.1",
"prek>=0.3.5",
"pyte>=0.8.2",
"pytest>=8.1.1",
"pytest-cov>=5",
"pytest-mock>=3.14.1",
Expand All @@ -62,6 +63,7 @@ quality = ["prek>=0.3.5"]
test = [
"codecov>=2.1",
"coverage>=7.11.3",
"pyte>=0.8.2",
"pytest>=8.1.1",
"pytest-cov>=5",
"pytest-mock>=3.14.1",
Expand Down Expand Up @@ -91,6 +93,9 @@ exclude = [
"^tests/", # tests directory
]
files = ['.']
# Check as CI does, on Linux, so results don't depend on the developer's OS. Windows-only
# branches are skipped, and POSIX-only job control would otherwise fail to check on Windows.
platform = "linux"
show_column_numbers = true
show_error_codes = true
show_error_context = true
Expand All @@ -104,6 +109,8 @@ warn_unused_ignores = true
testpaths = ["tests"]
addopts = [
"-n=auto",
# Spread slow terminal cases across workers instead of queuing them in one batch.
"--maxschedchunk=1",
"--cov=cmd2",
"--cov-config=pyproject.toml",
"--cov-report=xml",
Expand All @@ -112,6 +119,8 @@ addopts = [
]

[tool.coverage.run]
# Include the cmd2 applications launched by the terminal integration tests.
patch = ["subprocess"]
# Use sys.monitoring on Python 3.12+; coverage falls back with a warning on 3.11.
core = "sysmon"
source = ["cmd2"]
Expand Down
Loading
Loading