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
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
//! Multiline terminal input with rich editing capabilities
//!
//! This crate provides a simple way to collect multiline text input from the terminal
//! with intuitive key bindings:
//! - **ENTER** to submit
//! - **CTRL+ENTER** or **SHIFT+ENTER** to insert newline
//! - **ESC** or **CTRL+C** to cancel
//!
//! # Quick Start
//!
//! ```no_run
//! use multiline_input::collect;
//!
//! match collect("Enter your message:") {
//! Ok(Some(text)) => println!("You entered: {}", text),
//! Ok(None) => println!("Cancelled"),
//! Err(e) => eprintln!("Error: {}", e),
//! }
//! ```
//!
//! # Advanced Usage with Builder
//!
//! ```no_run
//! use multiline_input::Builder;
//!
//! let editor = Builder::new()
//! .prompt("Enter commit message:")
//! .min_length(10)
//! .show_line_numbers(true)
//! .show_status(true)
//! .build();
//!
//! match editor.collect() {
//! Ok(Some(msg)) => println!("Commit: {}", msg),
//! Ok(None) => println!("Cancelled"),
//! Err(e) => eprintln!("Error: {}", e),
//! }
//! ```
//!
//! # Key Bindings
//!
//! | Key | Action |
//! |-----|--------|
//! | ENTER | Submit input |
//! | CTRL+ENTER | Insert newline |
//! | SHIFT+ENTER | Insert newline |
//! | ESC | Cancel |
//! | CTRL+C | Cancel |
//! | Backspace | Delete before cursor |
//! | Delete | Delete at cursor |
//! | Arrow keys | Move cursor |
//! | Home/End | Move to line start/end |
//! | CTRL+Home/End | Move to text start/end |
//!
//! # Testing
//!
//! This crate uses trait-based dependency injection for testability. The `TerminalOps` trait
//! abstracts all terminal operations, allowing tests to use `MockTerminal` instead of real
//! terminal I/O.
//!
//! ## Test Quality Guarantees
//!
//! - **Non-Fragile**: All tests use `MockTerminal` with explicit configuration
//! - **Deterministic**: Pre-programmed key sequences ensure consistent results
//! - **No Environment Dependencies**: Tests never interact with actual terminal
//! - **Fast**: Integration tests run instantly (no waiting for user input)
//!
//! ## Test Organization
//!
//! Tests are organized by functional domain in the `tests/` directory:
//! - `buffer_operations_test.rs` - Text buffer operations
//! - `key_handling_test.rs` - Key event parsing and action mapping
//! - `integration_workflows_test.rs` - End-to-end workflows
//! - `error_paths_test.rs` - Error handling (NoTty, TerminalTooSmall)
//! - `validation_test.rs` - Input validation logic
//! - `builder_config_test.rs` - Builder pattern and configuration
//!
//! Total: **44 tests** with 100% pass rate
//!
//! ## Example Test with MockTerminal
//!
//! ```ignore
//! use multiline_input::Builder;
//! // Note: MockTerminal is in tests/common/mock_terminal.rs
//!
//! #[test]
//! fn test_basic_input() {
//! let mut terminal = MockTerminal::new(true, (80, 24));
//! terminal.push_key(key(KeyCode::Char('h'), KeyModifiers::NONE));
//! terminal.push_key(key(KeyCode::Char('i'), KeyModifiers::NONE));
//! terminal.push_key(key(KeyCode::Enter, KeyModifiers::NONE));
//!
//! let editor = Builder::new()
//! .prompt("Input:")
//! .build_with(terminal);
//!
//! let result = editor.collect();
//! assert_eq!(result.unwrap(), Some("hi".to_string()));
//! }
//! ```
//!
//! See `tests/readme.md` for complete test documentation and examples.
// Re-export main types
pub use Builder;
pub use Editor;
pub use Error;
// Public API modules
// Internal modules (public for testing, not part of stable API)
/// Collect multiline input from terminal
///
/// Simple convenience function for basic usage. For advanced configuration,
/// use [`Builder`].
///
/// # Example
///
/// ```no_run
/// use multiline_input::collect;
///
/// match collect("Enter message:") {
/// Ok(Some(text)) => println!("Got: {}", text),
/// Ok(None) => println!("Cancelled"),
/// Err(e) => eprintln!("Error: {}", e),
/// }
/// ```
///
/// # Returns
///
/// - `Ok(Some(String))` - User submitted text
/// - `Ok(None)` - User cancelled (ESC or CTRL+C)
/// - `Err(Error)` - Terminal error or not running in TTY
/// Collect input with validation
///
/// # Example
///
/// ```no_run
/// use multiline_input::collect_validated;
///
/// let result = collect_validated("Enter message:", |text| {
/// if text.len() < 5 {
/// Err("Too short".to_string())
/// } else {
/// Ok(())
/// }
/// });
/// ```