pub struct TuiState {Show 14 fields
pub pending_hat: Option<(HatId, String)>,
pub iteration: u32,
pub prev_iteration: u32,
pub loop_started: Option<Instant>,
pub iteration_started: Option<Instant>,
pub last_event: Option<String>,
pub last_event_at: Option<Instant>,
pub show_help: bool,
pub loop_mode: LoopMode,
pub in_scroll_mode: bool,
pub search_query: String,
pub search_forward: bool,
pub max_iterations: Option<u32>,
pub idle_timeout_remaining: Option<Duration>,
/* private fields */
}Expand description
Observable state derived from loop events.
Fields§
§pending_hat: Option<(HatId, String)>Which hat will process next event (ID + display name).
iteration: u32Current iteration number (0-indexed, display as +1).
prev_iteration: u32Previous iteration number (for detecting changes).
loop_started: Option<Instant>When loop began.
iteration_started: Option<Instant>When current iteration began.
last_event: Option<String>Most recent event topic.
last_event_at: Option<Instant>Timestamp of last event.
show_help: boolWhether to show help overlay.
loop_mode: LoopModeLoop execution mode.
in_scroll_mode: boolWhether in scroll mode.
search_query: StringCurrent search query (if in search input mode).
search_forward: boolSearch direction (true = forward, false = backward).
max_iterations: Option<u32>Maximum iterations from config.
idle_timeout_remaining: Option<Duration>Idle timeout countdown.
Implementations§
Source§impl TuiState
impl TuiState
Sourcepub fn new() -> Self
pub fn new() -> Self
Creates empty state.
Examples found in repository?
27fn main() {
28 let output_dir = std::env::current_dir().unwrap().join("tui-validation");
29 fs::create_dir_all(&output_dir).unwrap();
30
31 // Create a fully populated state for validation
32 let mut state = TuiState::new();
33 let event = Event::new("task.start", "");
34 state.update(&event);
35
36 state.iteration = 2;
37 state.max_iterations = Some(10);
38 state.loop_started = Some(std::time::Instant::now().checked_sub(Duration::from_secs(272)).unwrap());
39 state.pending_hat = Some((HatId::new("builder"), "🔨Builder".to_string()));
40 state.loop_mode = ralph_tui::LoopMode::Auto;
41 state.last_event = Some("build.task".to_string());
42 state.last_event_at = Some(std::time::Instant::now()); // Active
43
44 // Render header
45 let backend = TestBackend::new(80, 3);
46 let mut terminal = Terminal::new(backend).unwrap();
47 terminal
48 .draw(|f| {
49 let widget = ralph_tui::header::render(&state);
50 f.render_widget(widget, f.area());
51 })
52 .unwrap();
53 let header_output = render_to_string(&terminal);
54 fs::write(output_dir.join("header.txt"), &header_output).unwrap();
55 println!("Header output written to tui-validation/header.txt");
56 println!("{}", header_output);
57 println!();
58
59 // Render header with scroll mode
60 state.in_scroll_mode = true;
61 let backend = TestBackend::new(80, 3);
62 let mut terminal = Terminal::new(backend).unwrap();
63 terminal
64 .draw(|f| {
65 let widget = ralph_tui::header::render(&state);
66 f.render_widget(widget, f.area());
67 })
68 .unwrap();
69 let header_scroll_output = render_to_string(&terminal);
70 fs::write(output_dir.join("header_scroll.txt"), &header_scroll_output).unwrap();
71 println!("Header (scroll mode) output written to tui-validation/header_scroll.txt");
72 println!("{}", header_scroll_output);
73 println!();
74 state.in_scroll_mode = false;
75
76 // Render header with paused mode
77 state.loop_mode = ralph_tui::LoopMode::Paused;
78 let backend = TestBackend::new(80, 3);
79 let mut terminal = Terminal::new(backend).unwrap();
80 terminal
81 .draw(|f| {
82 let widget = ralph_tui::header::render(&state);
83 f.render_widget(widget, f.area());
84 })
85 .unwrap();
86 let header_paused_output = render_to_string(&terminal);
87 fs::write(output_dir.join("header_paused.txt"), &header_paused_output).unwrap();
88 println!("Header (paused mode) output written to tui-validation/header_paused.txt");
89 println!("{}", header_paused_output);
90 println!();
91 state.loop_mode = ralph_tui::LoopMode::Auto;
92
93 // Render header with idle countdown
94 state.idle_timeout_remaining = Some(Duration::from_secs(25));
95 let backend = TestBackend::new(80, 3);
96 let mut terminal = Terminal::new(backend).unwrap();
97 terminal
98 .draw(|f| {
99 let widget = ralph_tui::header::render(&state);
100 f.render_widget(widget, f.area());
101 })
102 .unwrap();
103 let header_idle_output = render_to_string(&terminal);
104 fs::write(output_dir.join("header_idle.txt"), &header_idle_output).unwrap();
105 println!("Header (idle countdown) output written to tui-validation/header_idle.txt");
106 println!("{}", header_idle_output);
107 println!();
108 state.idle_timeout_remaining = None;
109
110 // Render footer (default)
111 let scroll_manager = ralph_tui::scroll::ScrollManager::new();
112 let backend = TestBackend::new(80, 3);
113 let mut terminal = Terminal::new(backend).unwrap();
114 terminal
115 .draw(|f| {
116 let widget = ralph_tui::footer::render(&state, &scroll_manager);
117 f.render_widget(widget, f.area());
118 })
119 .unwrap();
120 let footer_output = render_to_string(&terminal);
121 fs::write(output_dir.join("footer_active.txt"), &footer_output).unwrap();
122 println!("Footer (active) output written to tui-validation/footer_active.txt");
123 println!("{}", footer_output);
124 println!();
125
126 // Render footer (idle state)
127 state.last_event_at = Some(std::time::Instant::now().checked_sub(Duration::from_secs(10)).unwrap());
128 let backend = TestBackend::new(80, 3);
129 let mut terminal = Terminal::new(backend).unwrap();
130 terminal
131 .draw(|f| {
132 let widget = ralph_tui::footer::render(&state, &scroll_manager);
133 f.render_widget(widget, f.area());
134 })
135 .unwrap();
136 let footer_idle_output = render_to_string(&terminal);
137 fs::write(output_dir.join("footer_idle.txt"), &footer_idle_output).unwrap();
138 println!("Footer (idle) output written to tui-validation/footer_idle.txt");
139 println!("{}", footer_idle_output);
140 println!();
141
142 // Render footer (done state)
143 state.pending_hat = None;
144 let backend = TestBackend::new(80, 3);
145 let mut terminal = Terminal::new(backend).unwrap();
146 terminal
147 .draw(|f| {
148 let widget = ralph_tui::footer::render(&state, &scroll_manager);
149 f.render_widget(widget, f.area());
150 })
151 .unwrap();
152 let footer_done_output = render_to_string(&terminal);
153 fs::write(output_dir.join("footer_done.txt"), &footer_done_output).unwrap();
154 println!("Footer (done) output written to tui-validation/footer_done.txt");
155 println!("{}", footer_done_output);
156 println!();
157
158 // Render full layout simulation
159 state.pending_hat = Some((HatId::new("builder"), "🔨Builder".to_string()));
160 state.last_event_at = Some(std::time::Instant::now());
161 let backend = TestBackend::new(100, 24);
162 let mut terminal = Terminal::new(backend).unwrap();
163 terminal
164 .draw(|f| {
165 let chunks = Layout::default()
166 .direction(Direction::Vertical)
167 .constraints([
168 Constraint::Length(3),
169 Constraint::Min(0),
170 Constraint::Length(3),
171 ])
172 .split(f.area());
173
174 f.render_widget(ralph_tui::header::render(&state), chunks[0]);
175 // Middle content area (just empty for this test)
176 f.render_widget(
177 ratatui::widgets::Block::default()
178 .borders(ratatui::widgets::Borders::ALL)
179 .title(" Terminal Output "),
180 chunks[1],
181 );
182 f.render_widget(ralph_tui::footer::render(&state, &scroll_manager), chunks[2]);
183 })
184 .unwrap();
185 let full_output = render_to_string(&terminal);
186 fs::write(output_dir.join("full_layout.txt"), &full_output).unwrap();
187 println!("Full layout output written to tui-validation/full_layout.txt");
188 println!("{}", full_output);
189
190 println!("\n=== All validation outputs written to tui-validation/ ===");
191}Sourcepub fn with_hat_map(hat_map: HashMap<String, (HatId, String)>) -> Self
pub fn with_hat_map(hat_map: HashMap<String, (HatId, String)>) -> Self
Creates state with a custom hat map for dynamic topic-to-hat resolution.
Sourcepub fn update(&mut self, event: &Event)
pub fn update(&mut self, event: &Event)
Updates state based on event topic.
Examples found in repository?
27fn main() {
28 let output_dir = std::env::current_dir().unwrap().join("tui-validation");
29 fs::create_dir_all(&output_dir).unwrap();
30
31 // Create a fully populated state for validation
32 let mut state = TuiState::new();
33 let event = Event::new("task.start", "");
34 state.update(&event);
35
36 state.iteration = 2;
37 state.max_iterations = Some(10);
38 state.loop_started = Some(std::time::Instant::now().checked_sub(Duration::from_secs(272)).unwrap());
39 state.pending_hat = Some((HatId::new("builder"), "🔨Builder".to_string()));
40 state.loop_mode = ralph_tui::LoopMode::Auto;
41 state.last_event = Some("build.task".to_string());
42 state.last_event_at = Some(std::time::Instant::now()); // Active
43
44 // Render header
45 let backend = TestBackend::new(80, 3);
46 let mut terminal = Terminal::new(backend).unwrap();
47 terminal
48 .draw(|f| {
49 let widget = ralph_tui::header::render(&state);
50 f.render_widget(widget, f.area());
51 })
52 .unwrap();
53 let header_output = render_to_string(&terminal);
54 fs::write(output_dir.join("header.txt"), &header_output).unwrap();
55 println!("Header output written to tui-validation/header.txt");
56 println!("{}", header_output);
57 println!();
58
59 // Render header with scroll mode
60 state.in_scroll_mode = true;
61 let backend = TestBackend::new(80, 3);
62 let mut terminal = Terminal::new(backend).unwrap();
63 terminal
64 .draw(|f| {
65 let widget = ralph_tui::header::render(&state);
66 f.render_widget(widget, f.area());
67 })
68 .unwrap();
69 let header_scroll_output = render_to_string(&terminal);
70 fs::write(output_dir.join("header_scroll.txt"), &header_scroll_output).unwrap();
71 println!("Header (scroll mode) output written to tui-validation/header_scroll.txt");
72 println!("{}", header_scroll_output);
73 println!();
74 state.in_scroll_mode = false;
75
76 // Render header with paused mode
77 state.loop_mode = ralph_tui::LoopMode::Paused;
78 let backend = TestBackend::new(80, 3);
79 let mut terminal = Terminal::new(backend).unwrap();
80 terminal
81 .draw(|f| {
82 let widget = ralph_tui::header::render(&state);
83 f.render_widget(widget, f.area());
84 })
85 .unwrap();
86 let header_paused_output = render_to_string(&terminal);
87 fs::write(output_dir.join("header_paused.txt"), &header_paused_output).unwrap();
88 println!("Header (paused mode) output written to tui-validation/header_paused.txt");
89 println!("{}", header_paused_output);
90 println!();
91 state.loop_mode = ralph_tui::LoopMode::Auto;
92
93 // Render header with idle countdown
94 state.idle_timeout_remaining = Some(Duration::from_secs(25));
95 let backend = TestBackend::new(80, 3);
96 let mut terminal = Terminal::new(backend).unwrap();
97 terminal
98 .draw(|f| {
99 let widget = ralph_tui::header::render(&state);
100 f.render_widget(widget, f.area());
101 })
102 .unwrap();
103 let header_idle_output = render_to_string(&terminal);
104 fs::write(output_dir.join("header_idle.txt"), &header_idle_output).unwrap();
105 println!("Header (idle countdown) output written to tui-validation/header_idle.txt");
106 println!("{}", header_idle_output);
107 println!();
108 state.idle_timeout_remaining = None;
109
110 // Render footer (default)
111 let scroll_manager = ralph_tui::scroll::ScrollManager::new();
112 let backend = TestBackend::new(80, 3);
113 let mut terminal = Terminal::new(backend).unwrap();
114 terminal
115 .draw(|f| {
116 let widget = ralph_tui::footer::render(&state, &scroll_manager);
117 f.render_widget(widget, f.area());
118 })
119 .unwrap();
120 let footer_output = render_to_string(&terminal);
121 fs::write(output_dir.join("footer_active.txt"), &footer_output).unwrap();
122 println!("Footer (active) output written to tui-validation/footer_active.txt");
123 println!("{}", footer_output);
124 println!();
125
126 // Render footer (idle state)
127 state.last_event_at = Some(std::time::Instant::now().checked_sub(Duration::from_secs(10)).unwrap());
128 let backend = TestBackend::new(80, 3);
129 let mut terminal = Terminal::new(backend).unwrap();
130 terminal
131 .draw(|f| {
132 let widget = ralph_tui::footer::render(&state, &scroll_manager);
133 f.render_widget(widget, f.area());
134 })
135 .unwrap();
136 let footer_idle_output = render_to_string(&terminal);
137 fs::write(output_dir.join("footer_idle.txt"), &footer_idle_output).unwrap();
138 println!("Footer (idle) output written to tui-validation/footer_idle.txt");
139 println!("{}", footer_idle_output);
140 println!();
141
142 // Render footer (done state)
143 state.pending_hat = None;
144 let backend = TestBackend::new(80, 3);
145 let mut terminal = Terminal::new(backend).unwrap();
146 terminal
147 .draw(|f| {
148 let widget = ralph_tui::footer::render(&state, &scroll_manager);
149 f.render_widget(widget, f.area());
150 })
151 .unwrap();
152 let footer_done_output = render_to_string(&terminal);
153 fs::write(output_dir.join("footer_done.txt"), &footer_done_output).unwrap();
154 println!("Footer (done) output written to tui-validation/footer_done.txt");
155 println!("{}", footer_done_output);
156 println!();
157
158 // Render full layout simulation
159 state.pending_hat = Some((HatId::new("builder"), "🔨Builder".to_string()));
160 state.last_event_at = Some(std::time::Instant::now());
161 let backend = TestBackend::new(100, 24);
162 let mut terminal = Terminal::new(backend).unwrap();
163 terminal
164 .draw(|f| {
165 let chunks = Layout::default()
166 .direction(Direction::Vertical)
167 .constraints([
168 Constraint::Length(3),
169 Constraint::Min(0),
170 Constraint::Length(3),
171 ])
172 .split(f.area());
173
174 f.render_widget(ralph_tui::header::render(&state), chunks[0]);
175 // Middle content area (just empty for this test)
176 f.render_widget(
177 ratatui::widgets::Block::default()
178 .borders(ratatui::widgets::Borders::ALL)
179 .title(" Terminal Output "),
180 chunks[1],
181 );
182 f.render_widget(ralph_tui::footer::render(&state, &scroll_manager), chunks[2]);
183 })
184 .unwrap();
185 let full_output = render_to_string(&terminal);
186 fs::write(output_dir.join("full_layout.txt"), &full_output).unwrap();
187 println!("Full layout output written to tui-validation/full_layout.txt");
188 println!("{}", full_output);
189
190 println!("\n=== All validation outputs written to tui-validation/ ===");
191}Sourcepub fn get_pending_hat_display(&self) -> String
pub fn get_pending_hat_display(&self) -> String
Returns formatted hat display (emoji + name).
Sourcepub fn get_loop_elapsed(&self) -> Option<Duration>
pub fn get_loop_elapsed(&self) -> Option<Duration>
Time since loop started.
Sourcepub fn get_iteration_elapsed(&self) -> Option<Duration>
pub fn get_iteration_elapsed(&self) -> Option<Duration>
Time since iteration started.
Sourcepub fn iteration_changed(&self) -> bool
pub fn iteration_changed(&self) -> bool
True if iteration changed since last check.
Trait Implementations§
Auto Trait Implementations§
impl Freeze for TuiState
impl RefUnwindSafe for TuiState
impl Send for TuiState
impl Sync for TuiState
impl Unpin for TuiState
impl UnwindSafe for TuiState
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Source§impl<T> Downcast for Twhere
T: Any,
impl<T> Downcast for Twhere
T: Any,
Source§fn into_any(self: Box<T>) -> Box<dyn Any>
fn into_any(self: Box<T>) -> Box<dyn Any>
Box<dyn Trait> (where Trait: Downcast) to Box<dyn Any>. Box<dyn Any> can
then be further downcast into Box<ConcreteType> where ConcreteType implements Trait.Source§fn into_any_rc(self: Rc<T>) -> Rc<dyn Any>
fn into_any_rc(self: Rc<T>) -> Rc<dyn Any>
Rc<Trait> (where Trait: Downcast) to Rc<Any>. Rc<Any> can then be
further downcast into Rc<ConcreteType> where ConcreteType implements Trait.Source§fn as_any(&self) -> &(dyn Any + 'static)
fn as_any(&self) -> &(dyn Any + 'static)
&Trait (where Trait: Downcast) to &Any. This is needed since Rust cannot
generate &Any’s vtable from &Trait’s.Source§fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)
fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)
&mut Trait (where Trait: Downcast) to &Any. This is needed since Rust cannot
generate &mut Any’s vtable from &mut Trait’s.Source§impl<T> DowncastSync for T
impl<T> DowncastSync for T
Source§impl<T> Instrument for T
impl<T> Instrument for T
Source§fn instrument(self, span: Span) -> Instrumented<Self>
fn instrument(self, span: Span) -> Instrumented<Self>
Source§fn in_current_span(self) -> Instrumented<Self>
fn in_current_span(self) -> Instrumented<Self>
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self>
fn into_either(self, into_left: bool) -> Either<Self, Self>
self into a Left variant of Either<Self, Self>
if into_left is true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
self into a Left variant of Either<Self, Self>
if into_left(&self) returns true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read more