diff --git a/crates/lore-tui/src/action/sync.rs b/crates/lore-tui/src/action/sync.rs index 3403f85..777ff21 100644 --- a/crates/lore-tui/src/action/sync.rs +++ b/crates/lore-tui/src/action/sync.rs @@ -172,7 +172,15 @@ pub fn fetch_recent_runs(conn: &Connection, limit: usize) -> Result = row.get(8)?; Ok(( - id, status, command, started_at, finished_at, items, errors, error, run_id, + id, + status, + command, + started_at, + finished_at, + items, + errors, + error, + run_id, )) }) .context("querying sync runs")?; @@ -265,6 +273,7 @@ mod tests { .expect("insert project"); } + #[allow(clippy::too_many_arguments)] fn insert_sync_run( conn: &Connection, started_at: i64, @@ -314,8 +323,26 @@ mod tests { create_sync_schema(&conn); let now = 1_700_000_000_000_i64; - insert_sync_run(&conn, now - 60_000, Some(now - 30_000), "succeeded", "sync", 100, 0, None); - insert_sync_run(&conn, now - 120_000, Some(now - 90_000), "failed", "sync", 50, 2, Some("timeout")); + insert_sync_run( + &conn, + now - 60_000, + Some(now - 30_000), + "succeeded", + "sync", + 100, + 0, + None, + ); + insert_sync_run( + &conn, + now - 120_000, + Some(now - 90_000), + "failed", + "sync", + 50, + 2, + Some("timeout"), + ); let clock = FakeClock::from_ms(now); let result = detect_running_sync(&conn, &clock).unwrap(); @@ -386,8 +413,26 @@ mod tests { create_sync_schema(&conn); let now = 1_700_000_000_000_i64; - insert_sync_run(&conn, now - 120_000, Some(now - 90_000), "succeeded", "sync", 100, 0, None); - insert_sync_run(&conn, now - 60_000, Some(now - 30_000), "succeeded", "sync", 200, 0, None); + insert_sync_run( + &conn, + now - 120_000, + Some(now - 90_000), + "succeeded", + "sync", + 100, + 0, + None, + ); + insert_sync_run( + &conn, + now - 60_000, + Some(now - 30_000), + "succeeded", + "sync", + 200, + 0, + None, + ); let runs = fetch_recent_runs(&conn, 10).unwrap(); assert_eq!(runs.len(), 2); @@ -425,7 +470,16 @@ mod tests { create_sync_schema(&conn); let now = 1_700_000_000_000_i64; - insert_sync_run(&conn, now - 60_000, Some(now - 15_000), "succeeded", "sync", 0, 0, None); + insert_sync_run( + &conn, + now - 60_000, + Some(now - 15_000), + "succeeded", + "sync", + 0, + 0, + None, + ); let runs = fetch_recent_runs(&conn, 10).unwrap(); assert_eq!(runs[0].duration_ms, Some(45_000)); @@ -517,8 +571,26 @@ mod tests { let now = 1_700_000_000_000_i64; insert_project(&conn, 1, "group/repo"); - insert_sync_run(&conn, now - 120_000, Some(now - 90_000), "succeeded", "sync", 150, 0, None); - insert_sync_run(&conn, now - 60_000, Some(now - 30_000), "failed", "sync", 50, 2, Some("db locked")); + insert_sync_run( + &conn, + now - 120_000, + Some(now - 90_000), + "succeeded", + "sync", + 150, + 0, + None, + ); + insert_sync_run( + &conn, + now - 60_000, + Some(now - 30_000), + "failed", + "sync", + 50, + 2, + Some("db locked"), + ); let clock = FakeClock::from_ms(now); let overview = fetch_sync_overview(&conn, &clock).unwrap(); @@ -542,7 +614,16 @@ mod tests { insert_project(&conn, 1, "group/repo"); // A completed run. - insert_sync_run(&conn, now - 600_000, Some(now - 570_000), "succeeded", "sync", 200, 0, None); + insert_sync_run( + &conn, + now - 600_000, + Some(now - 570_000), + "succeeded", + "sync", + 200, + 0, + None, + ); // A currently running sync. conn.execute( diff --git a/crates/lore-tui/src/app/update.rs b/crates/lore-tui/src/app/update.rs index 4f84851..4924b6d 100644 --- a/crates/lore-tui/src/app/update.rs +++ b/crates/lore-tui/src/app/update.rs @@ -590,7 +590,10 @@ impl LoreApp { } // --- Search --- - Msg::SearchExecuted { generation, results } => { + Msg::SearchExecuted { + generation, + results, + } => { if self .supervisor .is_current(&TaskKey::LoadScreen(Screen::Search), generation) diff --git a/crates/lore-tui/src/entity_cache.rs b/crates/lore-tui/src/entity_cache.rs index 3cc7845..3265b7d 100644 --- a/crates/lore-tui/src/entity_cache.rs +++ b/crates/lore-tui/src/entity_cache.rs @@ -154,8 +154,16 @@ mod tests { // Insert a 4th item: should evict issue(2) (tick 2, lowest). cache.put(issue(4), "d"); // tick 5 - assert_eq!(cache.get(&issue(1)), Some(&"a"), "issue(1) should survive (recently accessed)"); - assert_eq!(cache.get(&issue(2)), None, "issue(2) should be evicted (LRU)"); + assert_eq!( + cache.get(&issue(1)), + Some(&"a"), + "issue(1) should survive (recently accessed)" + ); + assert_eq!( + cache.get(&issue(2)), + None, + "issue(2) should be evicted (LRU)" + ); assert_eq!(cache.get(&issue(3)), Some(&"c"), "issue(3) should survive"); assert_eq!(cache.get(&issue(4)), Some(&"d"), "issue(4) just inserted"); } diff --git a/crates/lore-tui/src/render_cache.rs b/crates/lore-tui/src/render_cache.rs index 68a9e96..c0cb20d 100644 --- a/crates/lore-tui/src/render_cache.rs +++ b/crates/lore-tui/src/render_cache.rs @@ -104,8 +104,7 @@ impl RenderCache { /// /// After a resize, only entries rendered at the new width are still valid. pub fn invalidate_width(&mut self, keep_width: u16) { - self.entries - .retain(|k, _| k.terminal_width == keep_width); + self.entries.retain(|k, _| k.terminal_width == keep_width); } /// Clear the entire cache (theme change — all colors invalidated). diff --git a/crates/lore-tui/src/session.rs b/crates/lore-tui/src/session.rs index 0d75183..9e400ff 100644 --- a/crates/lore-tui/src/session.rs +++ b/crates/lore-tui/src/session.rs @@ -95,8 +95,8 @@ pub fn save_session(state: &SessionState, path: &Path) -> Result<(), SessionErro fs::create_dir_all(parent).map_err(|e| SessionError::Io(e.to_string()))?; } - let json = serde_json::to_string_pretty(state) - .map_err(|e| SessionError::Serialize(e.to_string()))?; + let json = + serde_json::to_string_pretty(state).map_err(|e| SessionError::Serialize(e.to_string()))?; // Check size before writing. if json.len() as u64 > MAX_SESSION_SIZE { @@ -112,8 +112,7 @@ pub fn save_session(state: &SessionState, path: &Path) -> Result<(), SessionErro // Write to temp file, fsync, rename. let tmp_path = path.with_extension("tmp"); - let mut file = - fs::File::create(&tmp_path).map_err(|e| SessionError::Io(e.to_string()))?; + let mut file = fs::File::create(&tmp_path).map_err(|e| SessionError::Io(e.to_string()))?; file.write_all(payload.as_bytes()) .map_err(|e| SessionError::Io(e.to_string()))?; file.sync_all() @@ -179,10 +178,7 @@ pub fn load_session(path: &Path) -> Result { /// Move a corrupt session file to `.quarantine/` instead of deleting it. fn quarantine(path: &Path) -> Result<(), SessionError> { - let quarantine_dir = path - .parent() - .unwrap_or(Path::new(".")) - .join(".quarantine"); + let quarantine_dir = path.parent().unwrap_or(Path::new(".")).join(".quarantine"); fs::create_dir_all(&quarantine_dir).map_err(|e| SessionError::Io(e.to_string()))?; let filename = path diff --git a/crates/lore-tui/src/state/mod.rs b/crates/lore-tui/src/state/mod.rs index c88a753..1048d3d 100644 --- a/crates/lore-tui/src/state/mod.rs +++ b/crates/lore-tui/src/state/mod.rs @@ -22,13 +22,13 @@ pub mod issue_detail; pub mod issue_list; pub mod mr_detail; pub mod mr_list; +pub mod scope_picker; pub mod search; pub mod stats; pub mod sync; pub mod sync_delta_ledger; pub mod timeline; pub mod trace; -pub mod scope_picker; pub mod who; use std::collections::{HashMap, HashSet}; @@ -45,12 +45,12 @@ pub use issue_detail::IssueDetailState; pub use issue_list::IssueListState; pub use mr_detail::MrDetailState; pub use mr_list::MrListState; +pub use scope_picker::ScopePickerState; pub use search::SearchState; pub use stats::StatsState; pub use sync::SyncState; pub use timeline::TimelineState; pub use trace::TraceState; -pub use scope_picker::ScopePickerState; pub use who::WhoState; // --------------------------------------------------------------------------- diff --git a/crates/lore-tui/src/state/sync.rs b/crates/lore-tui/src/state/sync.rs index 1f5b531..6358d9d 100644 --- a/crates/lore-tui/src/state/sync.rs +++ b/crates/lore-tui/src/state/sync.rs @@ -356,12 +356,12 @@ impl SyncState { self.bytes_synced = bytes; self.items_synced = items; // Compute actual throughput from elapsed time since sync start. - if items > 0 { - if let Some(started) = self.started_at { - let elapsed_secs = started.elapsed().as_secs_f64(); - if elapsed_secs > 0.0 { - self.items_per_sec = items as f64 / elapsed_secs; - } + if items > 0 + && let Some(started) = self.started_at + { + let elapsed_secs = started.elapsed().as_secs_f64(); + if elapsed_secs > 0.0 { + self.items_per_sec = items as f64 / elapsed_secs; } } } @@ -375,8 +375,7 @@ impl SyncState { /// Overall progress fraction (average of all lanes). #[must_use] pub fn overall_progress(&self) -> f64 { - let active_lanes: Vec<&LaneProgress> = - self.lanes.iter().filter(|l| l.total > 0).collect(); + let active_lanes: Vec<&LaneProgress> = self.lanes.iter().filter(|l| l.total > 0).collect(); if active_lanes.is_empty() { return 0.0; } @@ -537,10 +536,7 @@ mod tests { } } // With ~0ms between calls, at most 0-1 additional emits expected. - assert!( - emitted <= 1, - "Expected at most 1 emit, got {emitted}" - ); + assert!(emitted <= 1, "Expected at most 1 emit, got {emitted}"); } #[test] diff --git a/crates/lore-tui/src/view/doctor.rs b/crates/lore-tui/src/view/doctor.rs index a40fdc3..f0cd5fb 100644 --- a/crates/lore-tui/src/view/doctor.rs +++ b/crates/lore-tui/src/view/doctor.rs @@ -127,7 +127,9 @@ pub fn render_doctor(frame: &mut Frame<'_>, state: &DoctorState, area: Rect) { let detail = if check.detail.len() > max_detail { format!( "{}...", - &check.detail[..check.detail.floor_char_boundary(max_detail.saturating_sub(3))] + &check.detail[..check + .detail + .floor_char_boundary(max_detail.saturating_sub(3))] ) } else { check.detail.clone() diff --git a/crates/lore-tui/src/view/mod.rs b/crates/lore-tui/src/view/mod.rs index 0a876ec..e77b090 100644 --- a/crates/lore-tui/src/view/mod.rs +++ b/crates/lore-tui/src/view/mod.rs @@ -16,12 +16,12 @@ pub mod issue_detail; pub mod issue_list; pub mod mr_detail; pub mod mr_list; -pub mod search; -pub mod timeline; -pub mod trace; pub mod scope_picker; +pub mod search; pub mod stats; pub mod sync; +pub mod timeline; +pub mod trace; pub mod who; use ftui::layout::{Constraint, Flex}; @@ -43,12 +43,12 @@ use issue_detail::render_issue_detail; use issue_list::render_issue_list; use mr_detail::render_mr_detail; use mr_list::render_mr_list; -use search::render_search; -use timeline::render_timeline; -use trace::render_trace; use scope_picker::render_scope_picker; +use search::render_search; use stats::render_stats; use sync::render_sync; +use timeline::render_timeline; +use trace::render_trace; use who::render_who; // --------------------------------------------------------------------------- @@ -261,10 +261,7 @@ mod tests { let has_content = (20..60u16).any(|x| { (8..16u16).any(|y| frame.buffer.get(x, y).is_some_and(|cell| !cell.is_empty())) }); - assert!( - has_content, - "Expected sync idle content in center area" - ); + assert!(has_content, "Expected sync idle content in center area"); }); } } diff --git a/crates/lore-tui/src/view/scope_picker.rs b/crates/lore-tui/src/view/scope_picker.rs index bd1a7eb..9bd1792 100644 --- a/crates/lore-tui/src/view/scope_picker.rs +++ b/crates/lore-tui/src/view/scope_picker.rs @@ -8,8 +8,8 @@ use ftui::render::cell::{Cell, PackedRgba}; use ftui::render::drawing::{BorderChars, Draw}; use ftui::render::frame::Frame; -use crate::state::scope_picker::ScopePickerState; use crate::state::ScopeContext; +use crate::state::scope_picker::ScopePickerState; use super::{ACCENT, BG_SURFACE, BORDER, TEXT, TEXT_MUTED}; @@ -131,7 +131,10 @@ pub fn render_scope_picker( // Truncate label to fit. let max_label_len = content_width.saturating_sub(2) as usize; // 2 for prefix let display = if label.len() > max_label_len { - format!("{prefix}{}...", &label[..label.floor_char_boundary(max_label_len.saturating_sub(3))]) + format!( + "{prefix}{}...", + &label[..label.floor_char_boundary(max_label_len.saturating_sub(3))] + ) } else { format!("{prefix}{label}") }; diff --git a/crates/lore-tui/src/view/stats.rs b/crates/lore-tui/src/view/stats.rs index a2c1d37..66c5642 100644 --- a/crates/lore-tui/src/view/stats.rs +++ b/crates/lore-tui/src/view/stats.rs @@ -93,7 +93,15 @@ pub fn render_stats(frame: &mut Frame<'_>, state: &StatsState, area: Rect) { if y >= area.bottom().saturating_sub(2) { break; } - render_stat_row(frame, area.x + 2, y, label, &format_count(*count), label_width, max_x); + render_stat_row( + frame, + area.x + 2, + y, + label, + &format_count(*count), + label_width, + max_x, + ); y += 1; } diff --git a/crates/lore-tui/src/view/sync.rs b/crates/lore-tui/src/view/sync.rs index db16f90..d6c7586 100644 --- a/crates/lore-tui/src/view/sync.rs +++ b/crates/lore-tui/src/view/sync.rs @@ -262,8 +262,16 @@ fn render_summary(frame: &mut Frame<'_>, state: &SyncState, area: Rect) { // Summary rows. let rows = [ ("Issues", summary.issues.new, summary.issues.updated), - ("MRs", summary.merge_requests.new, summary.merge_requests.updated), - ("Discussions", summary.discussions.new, summary.discussions.updated), + ( + "MRs", + summary.merge_requests.new, + summary.merge_requests.updated, + ), + ( + "Discussions", + summary.discussions.new, + summary.discussions.updated, + ), ("Notes", summary.notes.new, summary.notes.updated), ]; @@ -404,7 +412,10 @@ fn render_failed(frame: &mut Frame<'_>, area: Rect, error: &str) { // Truncate error to fit screen. let max_len = area.width.saturating_sub(4) as usize; let display_err = if error.len() > max_len { - format!("{}...", &error[..error.floor_char_boundary(max_len.saturating_sub(3))]) + format!( + "{}...", + &error[..error.floor_char_boundary(max_len.saturating_sub(3))] + ) } else { error.to_string() }; @@ -541,9 +552,7 @@ mod tests { state.complete(3000); state.summary = Some(SyncSummary { elapsed_ms: 3000, - project_errors: vec![ - ("grp/repo".into(), "timeout".into()), - ], + project_errors: vec![("grp/repo".into(), "timeout".into())], ..Default::default() }); let area = frame.bounds();