1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
//! Live-input helpers for the `manage` CLI.
//!
//! Every prompt returns `Ok(None)` when stdin is **not** a TTY —
//! programmatic callers (the multitenant_demo bootstrap, tests,
//! scripts piping into the CLI) keep the existing
//! `Validation("--password required")` error path. Interactive
//! shells fall through to `Some(value)` after asking the user.
//!
//! Why this shape: the existing `manage::run` API takes
//! `args: impl IntoIterator<Item = String>` and returns a result —
//! tests + the demo lean on that contract. Adding a `Prompter` trait
//! parameter would ripple through every callsite. Wrapping live
//! input in TTY-gated helpers preserves the API and makes the
//! interactive UX opt-in via "did stdin come from a terminal?".
use ;
/// Read a non-empty trimmed line from stdin. Returns `Ok(None)` if
/// stdin isn't a TTY, the user typed nothing, or EOF was hit. The
/// caller decides whether `None` is fatal or merely "no answer".
///
/// Output is written to **stderr** so prompts don't interleave with
/// machine-readable stdout (e.g. when the operator pipes manage
/// output into another tool).
///
/// # Errors
/// Returns [`io::Error`] for terminal write/read failures.
/// Like [`ask`] but reads a password without echoing to the
/// terminal. Uses `rpassword` which calls `tcsetattr` on Unix and
/// the equivalent on Windows.
///
/// Returns `Ok(None)` for non-TTY stdin OR empty input — same shape
/// as [`ask`] so callers can use one match arm.
///
/// # Errors
/// Returns [`io::Error`] for terminal-mode toggle or read failures.