Ask a person what they want instead of making them know - #60
Merged
Merged
Conversation
`drop`, `drop send` and `drop recv`, typed on their own in a terminal, open an interface: a chooser, a file browser, a code field, a destination picker, and a few checkboxes. Everything else is unchanged, which is the point — the flags are the program-facing surface and every harness that drives them keeps working untouched. The activation rule is deliberately conservative, and stricter than "no arguments on a terminal": - All three streams must be terminals, **stdout included**, though the interface never writes there. The transfer code goes to stdout so it survives a pipe, so a redirected stdout is somebody collecting that code and they should get it rather than a screen. - `DROP_STATUS` counts even with a bare command line. A harness exports it once and every `drop` it spawns inherits it. - **Any** flag means the command, not a curated list of flags that imply non-interactive use — that list would be wrong the first time somebody added a flag. Terminal lifecycle lands before any screen is drawn, because the worst failure here is not a bad screen but a shell that no longer echoes. `send` answers a signal with `std::process::exit(130)` and no unwinding, so the spool file can be deleted by hand; no destructor runs on that path, so `restore()` lives over an atomic and the handler calls it — before deleting the spool file, since that one cannot be recovered from by hand. `recv` had no termination handler at all and now has one. Ctrl-C also had to become an ordinary key: in raw mode the driver stops turning it into SIGINT. Three things the first person to use it found, each a design error rather than a discoverability one: - `enter` opened a folder while `s` selected one, so the gesture everybody makes first did the wrong thing. `enter` now picks whatever is highlighted, `→` opens, and choosing the folder you are standing in is the first row of the listing rather than a key to know about. - That was only safe once `esc` meant back. It meant "give up entirely", so one mistaken keystroke was unrecoverable. The flow is now a loop whose next screen is whichever answer is still missing. - The code field took any non-empty string and let `TransferCode::parse` reject it two screens later, from a program that had already exited. It is checked where it is typed, by the same parser. The sender's announcement says who the code is for and that `drop recv` on its own now works. ratatui and crossterm, both pure Rust, which is the bar `flate2` is already held to for four prebuilt targets. Release binary 26,988,848 → 27,482,824 bytes, +1.8%. Progress still prints below the closed interface; putting it on screen, and closing both sides on cancel, is phase 3 of the plan. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
|
You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard. |
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.
drop,drop sendanddrop recv, typed on their own in a terminal, open an interface: a chooser, a file browser, a code field, a destination picker, and a few checkboxes. Everything else is unchanged — the flags are the program-facing surface, and every harness that drives them keeps working untouched.The activation rule
Stricter than "no arguments on a terminal", deliberately:
DROP_STATUScounts even with a bare command line. A harness exports it once and everydropit spawns inherits it.Being wrong toward the command costs a person one extra word. Being wrong the other way hangs a CI job on a screen nobody can see.
Terminal lifecycle came first
The worst failure here is not a bad screen, it is a shell that no longer echoes.
sendanswers a signal withstd::process::exit(130)and no unwinding, so the spool file can be deleted by hand — but no destructor runs on that path.restore()therefore lives over an atomic and the signal handler calls it, before deleting the spool file, since the terminal is the one that cannot be recovered from by hand.recvhad no termination handler at all and now has one. And Ctrl-C had to become an ordinary key as well as a signal — in raw mode the driver stops turning it into SIGINT.Three things found by using it
Each a design error rather than a discoverability one:
enteropened a folder whilesselected one, so the gesture everybody makes first did the wrong thing.enternow picks whatever is highlighted,→opens, and choosing the folder you are standing in is the first row of the listing.escmeant back. It meant "give up entirely", so one mistaken keystroke was unrecoverable. The flow is now a loop whose next screen is whichever answer is still missing; stepping back clears the most recent one.TransferCode::parsereject it two screens later, from a program that had already exited. It is checked where it is typed, by the same parser.Cost
ratatuiandcrossterm, both pure Rust — the barflate2is already held to for four prebuilt targets. Release binary 26,988,848 → 27,482,824 bytes, +1.8%.Not in this PR
Progress still prints below the closed interface. Putting it on screen, closing both sides on cancel, and the receiver's missing
cancelmessage are phase 3 of the plan.Verification
Full workspace suite,
clippy --all-targets,fmt,check-secrets.sh— all pass. The interface itself is driven through a pty, since a shell cannot test it.🤖 Generated with Claude Code