feat: Add interactive prompts for missing required arguments - #97
feat: Add interactive prompts for missing required arguments#97rts1-godaddy wants to merge 3 commits into
Conversation
There was a problem hiding this comment.
Pull request overview
This PR adds a generalized “interactivity” mode to cli-engine so that missing required arguments can be recovered via interactive prompts in real terminals, while preserving existing clap error behavior for non-interactive contexts (CI/scripts/piped runs).
Changes:
- Introduces global interactivity detection +
--interactive/--non-interactiveflags, and threads the resulting mode through middleware andCommandContext. - Adds an interactive recovery path in
Cli::runforMissingRequiredArgumenterrors, backed by a newpromptmodule (usinginquire). - Adds unit/integration tests and updates public API coverage tests to account for the new
interactiveflag field.
Reviewed changes
Copilot reviewed 10 out of 11 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
| cli-engine/tests/interactivity.rs | New integration tests covering non-interactive error paths and flag conflict behavior. |
| cli-engine/tests/foundation.rs | Updates expected GlobalFlags defaults to include interactive. |
| cli-engine/tests/exhaustive_public_api.rs | Updates public API parsing expectations for new interactive field. |
| cli-engine/src/prompt.rs | New prompt helpers + missing-required-arg recovery logic and unit tests. |
| cli-engine/src/middleware.rs | Adds interactive to middleware snapshot state. |
| cli-engine/src/lib.rs | Exposes prompt module and re-exports interactivity-related APIs. |
| cli-engine/src/flags.rs | Adds interactivity detection, mode enum, and global flags; parses interactive into GlobalFlags. |
| cli-engine/src/command.rs | Adds CommandContext accessors for interactivity. |
| cli-engine/src/cli.rs | Hooks recovery into clap parse error handling and applies interactive to middleware. |
| cli-engine/Cargo.toml | Adds inquire dependency for interactive prompts. |
| Cargo.lock | Locks new transitive dependencies introduced by inquire. |
Suppressed comments (2)
cli-engine/src/prompt.rs:130
- The doc comment says user cancellation returns
None, but the function actually returnsSome(RecoveryResult::Cancelled { .. })on cancel. This mismatch makes it easy for callers to handle cancellation incorrectly.
/// Returns `None` if recovery is not possible (non-interactive, not a missing
/// arg error, or the user cancelled a prompt).
cli-engine/src/prompt.rs:426
- This test intends to validate the "non-interactive suppresses recovery" path, but the constructed clap
Commanddoes not define--non-interactive, so the error kind isUnknownArgumentrather thanMissingRequiredArgument. As written, it doesn't meaningfully cover the interactivity check.
let cmd =
clap::Command::new("test").arg(clap::Arg::new("name").long("name").required(true));
let err = cmd
.try_get_matches_from(["test", "--non-interactive"])
.expect_err("should fail");
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
|
This is working pretty great! I just ran across a bug trying it out in |
Looks like my last commit broke this :/ . let me fix that |
|
Another thing... I wonder if we should do some punctuation after the prompt text (a colon maybe?) so it's more visually clear where the prompt ends and where the input begins. |
| /// `"<domain>"` → `"domain"`). | ||
| fn strip_arg_decoration(raw: &str) -> &str { | ||
| raw.trim_start_matches('-') | ||
| .trim_matches(['<', '>', '[', ']']) |
There was a problem hiding this comment.
trim_matches only strips <>[] from the ends, so clap's --quote-token <TOKEN> becomes quote-token <TOKEN (trailing > gone, <TOKEN stays). That doesn't match get_long()/get_id(), arg_def is None, and the value is replayed as a positional — the gddy domain purchase unexpected-argument failure. We should also add a unit test for this.
There was a problem hiding this comment.
Ah, didn't realize Jacob already commented on this, same bug.
Summary
Test plan
cargo fmt --all --checkcargo clippy --all-targets -- -D warningscargo test --all-targetsManual verification
Setup:
Test WITHOUT the fix (baseline):
Test WITH the fix:
Cleanup: