Repository navigation
fix: a relative current_dir runs a relative program, and inspect's help says what it does - #561
Merged
Merged
Conversation
…lp says what it does A relative `TerminalBuilder::current_dir`, and so `termlens inspect --cwd ./examples ./myapp`, never worked with a relative program path. The PTY layer joined the directory onto the program, `./examples/./myapp`, and the child then entered the directory before exec, so the path was looked up a second time from inside it and did not exist. The exec failure could not even be reported: the PTY layer's pre-exec hook closes every inherited descriptor, std's error pipe included, so the child died of a runtime abort, `fatal runtime error: assertion failed: output.write(&bytes) .is_ok()`, which inspect showed as `exited: killed by signal: Aborted`. 0.11.4 behaves the same. `spawn` now makes a relative directory absolute against the test process's own first, as `std::process::Command` treats one, and a relative program then resolves inside it as documented. Tests, each checked to fail without the fix: - process.rs spawns `./emit` from a relative `current_dir`. The scratch directory sits deeper than the test's own working directory, because a directory as deep as it, like target/debug beside crates/termlens, maps onto itself when the path is applied twice and hid the bug in a first version of this test. It now asserts that before trusting a pass. - inspect.rs runs the example and `termlens inspect` with `--cwd inspect-relative ./echo` from the directory above. The help of `termlens inspect` and examples/inspect.rs, which mirror each other, now says what three behaviours are, all checked by running them: - the silence window starts only once the program has drawn something, so a program that only clears the screen runs to the deadline; - the child also gets TERM=xterm-256color and SHELL=/bin/sh, and --inherit-env keeps the caller's environment but for TERM; - --cwd's argument is DIR, not PATH beside the PATH variable, in the help and in its diagnostic (pinned in both test suites), and a relative program path is found inside it. The CLI README's `--cwd ./examples ./myapp` example is the broken case; it and its paragraph now say where the program is found, as does the skill's line. Found by a documentation review. Signed-off-by: Vyncint Ng <115854244+vyncint@users.noreply.github.com>
vyncint
added a commit
that referenced
this pull request
Oct 7, 2026
Each was checked against the code or by running it before it changed;
one more item is a style tidy, marked as such.
README:
- `Screen::parse` reads the snapshot format, not an insta `.snap`: it
rejects the `---` header on line 1. The body below it parses, and the
`termlens` command reads a whole `.snap` because it strips the header.
- The skill has five recipes, not four.
SKILL.md:
- §7's mask row said `mask_matching` "spans a wrap the way `find_all`
does". A value split by a soft wrap is two rows and stays unmasked
(measured: 10 columns, `SECRET-VALUE-42`); a needle with `\n` is what
spans rows. Rule 12 already says so for `contains`.
- Rule 10 said `format!("{:?}")` is the same as `Display`. It wraps the
text in `Screen(…)`, which `Screen::parse`, `diff` and `render` refuse.
- §6 said every error's `Display` ends with the screen. Only the wait
errors (timeout, EOF, emulator) and a failed write carry one.
SECURITY.md: "bot-authored commits are rejected by CI" is true except for
Dependabot, which CONTRIBUTING's AI tooling policy exempts from the
identity rule only; the provenance line now says so.
DESIGN.md:
- The writer queue is unbounded (`mpsc::channel`), capped on reply bytes;
one paragraph said bounded, the next unbounded.
- The user-facing Windows list is in docs/LIMITATIONS.md, not the README.
- `CSI 18 t` is answered, and `14 t`/`16 t` once a cell size is declared,
so "the non-pixel `CSI t` reports" were never all unanswered; the same
correction in LIMITATIONS.md names `11 t` and `19 t` instead.
- The compatibility corpus starts at 0.10.1, not "each published release".
emit's steps: an argument beginning with `--` must be a step, so `emit
--foo` exits 2 rather than printing `--foo`; TEXT and `--text` say so.
Rustdoc:
- `Unsupported`'s summary was `Clipboard`'s first sentence, so docs.rs
described the type as clipboard data; the sentence is back on
`Clipboard`, which had no summary.
- `assert_screen_snapshot!` repeated the Display-versus-Debug reason that
#559 corrected in the skill.
- `wait_frame` pointed at a README Windows note that is not in the README.
- `Screen`'s Debug impl said "exactly like Display"; it adds `Screen(…)`.
- Style, not a contradiction: `mask_matching` carried the crate's only
`# Examples` heading; the rest of the crate's doctests have none.
Found by a documentation sweep; the same sweep found the relative
`current_dir` bug and the inspect help errors fixed in #561.
Signed-off-by: Vyncint Ng <115854244+vyncint@users.noreply.github.com>
vyncint
added a commit
that referenced
this pull request
Oct 7, 2026
Each was checked against the code or by running it before it changed;
one more item is a style tidy, marked as such.
README:
- `Screen::parse` reads the snapshot format, not an insta `.snap`: it
rejects the `---` header on line 1. The body below it parses, and the
`termlens` command reads a whole `.snap` because it strips the header.
- The skill has five recipes, not four.
SKILL.md:
- §7's mask row said `mask_matching` "spans a wrap the way `find_all`
does". A value split by a soft wrap is two rows and stays unmasked
(measured: 10 columns, `SECRET-VALUE-42`); a needle with `\n` is what
spans rows. Rule 12 already says so for `contains`.
- Rule 10 said `format!("{:?}")` is the same as `Display`. It wraps the
text in `Screen(…)`, which `Screen::parse`, `diff` and `render` refuse.
- §6 said every error's `Display` ends with the screen. Only the wait
errors (timeout, EOF, emulator) and a failed write carry one.
SECURITY.md: "bot-authored commits are rejected by CI" is true except for
Dependabot, which CONTRIBUTING's AI tooling policy exempts from the
identity rule only; the provenance line now says so.
DESIGN.md:
- The writer queue is unbounded (`mpsc::channel`), capped on reply bytes;
one paragraph said bounded, the next unbounded.
- The user-facing Windows list is in docs/LIMITATIONS.md, not the README.
- `CSI 18 t` is answered, and `14 t`/`16 t` once a cell size is declared,
so "the non-pixel `CSI t` reports" were never all unanswered; the same
correction in LIMITATIONS.md names `11 t` and `19 t` instead.
- The compatibility corpus starts at 0.10.1, not "each published release".
emit's steps: an argument beginning with `--` must be a step, so `emit
--foo` exits 2 rather than printing `--foo`; TEXT and `--text` say so.
Rustdoc:
- `Unsupported`'s summary was `Clipboard`'s first sentence, so docs.rs
described the type as clipboard data; the sentence is back on
`Clipboard`, which had no summary.
- `assert_screen_snapshot!` repeated the Display-versus-Debug reason that
#559 corrected in the skill.
- `wait_frame` pointed at a README Windows note that is not in the README.
- `Screen`'s Debug impl said "exactly like Display"; it adds `Screen(…)`.
- Style, not a contradiction: `mask_matching` carried the crate's only
`# Examples` heading; the rest of the crate's doctests have none.
Found by a documentation sweep; the same sweep found the relative
`current_dir` bug and the inspect help errors fixed in #561.
Signed-off-by: Vyncint Ng <115854244+vyncint@users.noreply.github.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
A relative
TerminalBuilder::current_dir, and sotermlens inspect --cwd ./examples ./myapp, never worked with a relative program path. The PTYlayer joined the directory onto the program,
./examples/./myapp, and thechild then entered the directory before exec, so the path was looked up a
second time from inside it and did not exist. The exec failure could not
even be reported: the PTY layer's pre-exec hook closes every inherited
descriptor, std's error pipe included, so the child died of a runtime
abort,
fatal runtime error: assertion failed: output.write(&bytes) .is_ok(), which inspect showed asexited: killed by signal: Aborted.0.11.4 behaves the same.
spawnnow makes a relative directory absoluteagainst the test process's own first, as
std::process::Commandtreatsone, and a relative program then resolves inside it as documented.
Tests, each checked to fail without the fix:
./emitfrom a relativecurrent_dir. The scratchdirectory sits deeper than the test's own working directory, because a
directory as deep as it, like target/debug beside crates/termlens, maps
onto itself when the path is applied twice and hid the bug in a first
version of this test. It now asserts that before trusting a pass.
termlens inspectwith--cwd inspect-relative ./echofrom the directory above.The help of
termlens inspectand examples/inspect.rs, which mirror eachother, now says what three behaviours are, all checked by running them:
so a program that only clears the screen runs to the deadline;
--inherit-env keeps the caller's environment but for TERM;
and in its diagnostic (pinned in both test suites), and a relative
program path is found inside it.
The CLI README's
--cwd ./examples ./myappexample is the broken case;it and its paragraph now say where the program is found, as does the
skill's line. Found by a documentation review.