Skip to content

Commit fb1afc0

Browse files
limeytexanclaude
andcommitted
Add tee-compatible append, ignore-interrupts, and output-error options
Adopt the parts of tee(1)'s option vocabulary that map onto t3's command-runner model, so t3 is more familiar as a tee replacement (issue #1). - -a, --append: open the log file with "a" so output is appended rather than overwriting, e.g. to accumulate a log across multiple build steps. - -i, --ignore-interrupts: t3 and its timestamp workers ignore SIGINT (set before the workers are forked, so they inherit it) while the command child restores the default disposition. A Ctrl-C therefore interrupts the command but lets t3 drain the workers' remaining output and exit with the command's status, instead of being torn down mid-flush and dropping the buffered tail. - --output-error[=MODE]: choose what t3 does when a write to one of its outputs fails - warn, warn-nopipe, exit, exit-nopipe, and tee's default (exit on a broken pipe, diagnose other errors). SIGPIPE is ignored so a closed consumer yields EPIPE for this logic rather than killing t3, and a failed output is dropped while the others keep going - so --output-error=warn-nopipe preserves the complete log file even when a downstream reader of t3's own stdout/stderr (e.g. `t3 log -- cmd | head`) goes away. The logfile's deferred write errors are reported at close. t3's existing -p (--plain) deliberately does not take on tee's pipe-mode meaning; pipe behavior is reached through --output-error=...-nopipe instead. This divergence is noted in the README and man page. Add golden tests for -a and --output-error, and document all three options in the usage text, README, and man page. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
1 parent 8e99e73 commit fb1afc0

5 files changed

Lines changed: 423 additions & 19 deletions

File tree

Makefile

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ $(MAN1DIR)/%: %
3434
cp $< $@
3535
chmod 444 $@
3636

37-
.PHONY: all install lint clean stress bench
37+
.PHONY: all install lint format clean stress options-test test bench
3838
all: $(BIN) $(MAN1)
3939

4040
install: $(INSTBIN) $(INSTMAN1)
@@ -159,8 +159,13 @@ stress: $(BIN) tests/stress tests/run-stress tests/check-stream.awk
159159
@T3=./$(BIN) STRESS_THREADS=$(STRESS_THREADS) STRESS_LINES=$(STRESS_LINES) \
160160
tests/run-stress
161161

162-
# Run the stress test as part of the standard `make test` suite.
163-
test: stress
162+
# Behavioral tests for the tee-compatible options (--append, --output-error)
163+
# that the golden-file harness cannot express.
164+
options-test: $(BIN) tests/run-options
165+
@T3=./$(BIN) tests/run-options
166+
167+
# Run the stress and option tests as part of the standard `make test` suite.
168+
test: stress options-test
164169

165170
# Benchmark: estimate t3's marginal per-line overhead. Manual only - not part
166171
# of `make test`. Tunable, e.g. `make bench COUNT=2000000 WIDTHS="32 128"`.

README.md

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -125,11 +125,36 @@ Invoke provided command and write its colorized, precise time-stamped output bot
125125
-e, --errcolor C set the ANSI escape sequence used to color stderr
126126
-t, --ts enable timestamps in all outputs
127127
-r, --relative display timestamps as relative offsets from start time (implies --ts)
128+
-a, --append append to the log file instead of overwriting it
129+
-i, --ignore-interrupts ignore interrupt signals (finish flushing output on Ctrl-C)
130+
--output-error[=MODE] set behavior on a write error; MODE is one of
131+
warn, warn-nopipe, exit, exit-nopipe (a bare --output-error
132+
means warn; with no --output-error, t3 exits on a broken
133+
pipe and warns on other write errors)
128134
-h, --help print this help message
129135
-v, --version print version string
130136
--debug enable debugging
131137
```
132138

139+
The `-a`/`--append`, `-i`/`--ignore-interrupts`, and `--output-error` options
140+
take their names and broad meaning from [`tee(1)`](https://www.gnu.org/software/coreutils/tee),
141+
with a few deliberate differences noted below.
142+
143+
- **`-i`/`--ignore-interrupts`** does more than `tee`'s: it makes `t3` *and* its
144+
timestamp worker processes ignore `SIGINT`, while the wrapped command keeps
145+
the default disposition (so a `Ctrl-C` still interrupts the command). `t3`
146+
then drains and flushes the command's final output before exiting, rather
147+
than being torn down mid-flush.
148+
- **`--output-error`** — by default, matching `tee`, `t3` **exits** when a write
149+
to its own stdout or stderr fails with a broken pipe, so the log file can be
150+
left truncated if a downstream consumer (e.g. `t3 log -- cmd | head`) closes
151+
early. On such a fatal write error `t3` exits with a failure status, which
152+
**replaces the wrapped command's own exit status**. Pass
153+
**`--output-error=warn-nopipe`** to instead ignore broken-pipe errors and keep
154+
the log file (and the surviving stream) complete.
155+
- **`-p`** remains `t3`'s `--plain`, *not* `tee`'s pipe-mode flag; reach the
156+
pipe-aware behavior through `--output-error=…-nopipe`.
157+
133158
## Installing
134159

135160
The easiest way to get `t3` is using Flox:

0 commit comments

Comments
 (0)