standout_input/lib.rs
1//! Declarative input collection for CLI applications.
2//!
3//! `standout-input` provides a unified way to acquire user input from multiple
4//! sources—CLI arguments, stdin, environment variables, editors, and interactive
5//! prompts—with automatic fallback chains.
6//!
7//! # Quick Start
8//!
9//! ```ignore
10//! use standout_input::{InputChain, ArgSource, StdinSource, DefaultSource};
11//!
12//! // Try argument first, then piped stdin, then default
13//! let message = InputChain::<String>::new()
14//! .try_source(ArgSource::new("message"))
15//! .try_source(StdinSource::new())
16//! .default("default message".to_string())
17//! .resolve(&matches)?;
18//! ```
19//!
20//! # Features
21//!
22//! - **`editor`** (default) - Enable [`EditorCollector`] for editor-based input
23//! - **`simple-prompts`** (default) - Enable basic terminal prompts
24//! - **`inquire`** - Enable rich TUI prompts via the inquire crate
25//!
26//! # Architecture
27//!
28//! The crate is built around the [`InputCollector`] trait, which all input
29//! sources implement. Sources are composed into [`InputChain`]s that try each
30//! source in order until one provides input.
31//!
32//! ```text
33//! InputChain
34//! ├── ArgSource → None (not provided)
35//! ├── StdinSource → None (not piped)
36//! ├── EditorSource → Some("user input") ← returns this
37//! └── DefaultSource → (not reached)
38//! ```
39//!
40//! # Questionnaire answer sheets
41//!
42//! The [`questionnaire`] module renders an application-defined questionnaire
43//! — scalar fields plus nested and repeatable groups — as an editable prose
44//! answer sheet, collects answers interactively or from a named file or
45//! explicit stdin, and decodes every submission through one shared
46//! validation pipeline keyed by stable identity (with indexed occurrence
47//! paths for repeated items). See the module documentation for the format,
48//! the application/library ownership boundary, and the exact-match
49//! compatibility contract.
50//!
51//! # Testing
52//!
53//! All sources accept mock implementations for testing:
54//!
55//! ```
56//! use standout_input::{StdinSource, env::MockStdin};
57//!
58//! // Test with simulated piped input
59//! let source = StdinSource::with_reader(MockStdin::piped("test input"));
60//! ```
61
62mod chain;
63mod collector;
64pub mod env;
65mod error;
66mod inputs;
67pub mod questionnaire;
68mod responder;
69pub mod sources;
70
71// Re-export core types
72pub use chain::InputChain;
73pub use collector::{InputCollector, InputSourceKind, ResolvedInput};
74pub use error::InputError;
75pub use inputs::{Inputs, MissingInput};
76pub use responder::{
77 reset_default_prompt_responder, set_default_prompt_responder, PromptContext, PromptKind,
78 PromptResponder, PromptResponse, ScriptedResponder,
79};
80
81// Re-export sources at crate root for convenience
82pub use sources::{
83 read_if_piped, ArgSource, ClipboardSource, DefaultSource, EnvSource, FlagSource, StdinSource,
84};
85
86#[cfg(feature = "editor")]
87pub use sources::{EditorRunner, EditorSource, MockEditorResult, MockEditorRunner};
88
89#[cfg(feature = "simple-prompts")]
90pub use sources::{ConfirmPromptSource, MockTerminal, TerminalIO, TextPromptSource};
91
92#[cfg(feature = "inquire")]
93pub use sources::{
94 InquireConfirm, InquireEditor, InquireMultiSelect, InquirePassword, InquireSelect, InquireText,
95};
96
97// Re-export mock types for testing
98pub use env::{MockClipboard, MockEnv, MockStdin};
99
100// Re-export process-global default reader controls (used by test harnesses)
101pub use env::{
102 reset_default_clipboard_reader, reset_default_stdin_reader, set_default_clipboard_reader,
103 set_default_stdin_reader, DefaultClipboard, DefaultStdin,
104};