refactor(cli): migrate all command modules from console::style to Theme
Replace all console::style() calls in command modules with the centralized Theme API and render:: utility functions. This ensures consistent color behavior across the entire CLI, proper NO_COLOR/--color never support via the LoreRenderer singleton, and eliminates duplicated formatting code. Changes per module: - count.rs: Theme for table headers, render::format_number replacing local duplicate. Removed local format_number implementation. - doctor.rs: Theme::success/warning/error for check status symbols and messages. Unicode escapes for check/warning/cross symbols. - drift.rs: Theme::bold/error/success for drift detection headers and status messages. - embed.rs: Compact output format — headline with count, zero-suppressed detail lines, 'nothing to embed' short-circuit for no-op runs. - generate_docs.rs: Same compact pattern — headline + detail + hint for next step. No-op short-circuit when regenerated==0. - ingest.rs: Theme for project summaries, sync status, dry-run preview. All console::style -> Theme replacements. - list.rs: Replace comfy-table with render::LoreTable for issue/MR listing. Remove local colored_cell, colored_cell_hex, format_relative_time, truncate_with_ellipsis, and format_labels (all moved to render.rs). - list_tests.rs: Update test assertions to use render:: functions. - search.rs: Add render_snippet() for FTS5 <mark> tag highlighting via Theme::bold().underline(). Compact result layout with type badges. - show.rs: Theme for entity detail views, delegate format_date and wrap_text to render module. - stats.rs: Section-based layout using render::section_divider. Compact middle-dot format for document counts. Color-coded embedding coverage percentage (green >=95%, yellow >=50%, red <50%). - sync.rs: Compact sync summary — headline with counts and elapsed time, zero-suppressed detail lines, visually prominent error-only section. - sync_status.rs: Theme for run history headers, removed local format_number duplicate. - timeline.rs: Theme for headers/footers, render:: for date/truncate, standard format! padding replacing console::pad_str. - who.rs: Theme for all expert/workload/active/overlap/review output modes, render:: for relative time and truncation. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
use std::sync::Arc;
|
||||
use std::sync::atomic::{AtomicUsize, Ordering};
|
||||
|
||||
use console::style;
|
||||
use crate::cli::render::Theme;
|
||||
use indicatif::{ProgressBar, ProgressStyle};
|
||||
use rusqlite::Connection;
|
||||
use serde::Serialize;
|
||||
@@ -293,7 +293,7 @@ async fn run_ingest_inner(
|
||||
if display.show_text {
|
||||
println!(
|
||||
"{}",
|
||||
style("Full sync: resetting cursors to fetch all data...").yellow()
|
||||
Theme::warning().render("Full sync: resetting cursors to fetch all data...")
|
||||
);
|
||||
}
|
||||
for (local_project_id, _, path) in &projects {
|
||||
@@ -341,7 +341,10 @@ async fn run_ingest_inner(
|
||||
"merge requests"
|
||||
};
|
||||
if display.show_text {
|
||||
println!("{}", style(format!("Ingesting {type_label}...")).blue());
|
||||
println!(
|
||||
"{}",
|
||||
Theme::info().render(&format!("Ingesting {type_label}..."))
|
||||
);
|
||||
println!();
|
||||
}
|
||||
|
||||
@@ -746,7 +749,7 @@ fn print_issue_project_summary(path: &str, result: &IngestProjectResult) {
|
||||
|
||||
println!(
|
||||
" {}: {} issues fetched{}",
|
||||
style(path).cyan(),
|
||||
Theme::info().render(path),
|
||||
result.issues_upserted,
|
||||
labels_str
|
||||
);
|
||||
@@ -761,7 +764,7 @@ fn print_issue_project_summary(path: &str, result: &IngestProjectResult) {
|
||||
if result.issues_skipped_discussion_sync > 0 {
|
||||
println!(
|
||||
" {} unchanged issues (discussion sync skipped)",
|
||||
style(result.issues_skipped_discussion_sync).dim()
|
||||
Theme::dim().render(&result.issues_skipped_discussion_sync.to_string())
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -784,7 +787,7 @@ fn print_mr_project_summary(path: &str, result: &IngestMrProjectResult) {
|
||||
|
||||
println!(
|
||||
" {}: {} MRs fetched{}{}",
|
||||
style(path).cyan(),
|
||||
Theme::info().render(path),
|
||||
result.mrs_upserted,
|
||||
labels_str,
|
||||
assignees_str
|
||||
@@ -808,7 +811,7 @@ fn print_mr_project_summary(path: &str, result: &IngestMrProjectResult) {
|
||||
if result.mrs_skipped_discussion_sync > 0 {
|
||||
println!(
|
||||
" {} unchanged MRs (discussion sync skipped)",
|
||||
style(result.mrs_skipped_discussion_sync).dim()
|
||||
Theme::dim().render(&result.mrs_skipped_discussion_sync.to_string())
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -942,21 +945,19 @@ pub fn print_ingest_summary(result: &IngestResult) {
|
||||
if result.resource_type == "issues" {
|
||||
println!(
|
||||
"{}",
|
||||
style(format!(
|
||||
Theme::success().render(&format!(
|
||||
"Total: {} issues, {} discussions, {} notes",
|
||||
result.issues_upserted, result.discussions_fetched, result.notes_upserted
|
||||
))
|
||||
.green()
|
||||
);
|
||||
|
||||
if result.issues_skipped_discussion_sync > 0 {
|
||||
println!(
|
||||
"{}",
|
||||
style(format!(
|
||||
Theme::dim().render(&format!(
|
||||
"Skipped discussion sync for {} unchanged issues.",
|
||||
result.issues_skipped_discussion_sync
|
||||
))
|
||||
.dim()
|
||||
);
|
||||
}
|
||||
} else {
|
||||
@@ -968,24 +969,22 @@ pub fn print_ingest_summary(result: &IngestResult) {
|
||||
|
||||
println!(
|
||||
"{}",
|
||||
style(format!(
|
||||
Theme::success().render(&format!(
|
||||
"Total: {} MRs, {} discussions, {} notes{}",
|
||||
result.mrs_upserted,
|
||||
result.discussions_fetched,
|
||||
result.notes_upserted,
|
||||
diffnotes_str
|
||||
))
|
||||
.green()
|
||||
);
|
||||
|
||||
if result.mrs_skipped_discussion_sync > 0 {
|
||||
println!(
|
||||
"{}",
|
||||
style(format!(
|
||||
Theme::dim().render(&format!(
|
||||
"Skipped discussion sync for {} unchanged MRs.",
|
||||
result.mrs_skipped_discussion_sync
|
||||
))
|
||||
.dim()
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -1006,8 +1005,8 @@ pub fn print_ingest_summary(result: &IngestResult) {
|
||||
pub fn print_dry_run_preview(preview: &DryRunPreview) {
|
||||
println!(
|
||||
"{} {}",
|
||||
style("Dry Run Preview").cyan().bold(),
|
||||
style("(no changes will be made)").yellow()
|
||||
Theme::info().bold().render("Dry Run Preview"),
|
||||
Theme::warning().render("(no changes will be made)")
|
||||
);
|
||||
println!();
|
||||
|
||||
@@ -1017,27 +1016,31 @@ pub fn print_dry_run_preview(preview: &DryRunPreview) {
|
||||
"merge requests"
|
||||
};
|
||||
|
||||
println!(" Resource type: {}", style(type_label).white().bold());
|
||||
println!(" Resource type: {}", Theme::bold().render(type_label));
|
||||
println!(
|
||||
" Sync mode: {}",
|
||||
if preview.sync_mode == "full" {
|
||||
style("full (all data will be re-fetched)").yellow()
|
||||
Theme::warning().render("full (all data will be re-fetched)")
|
||||
} else {
|
||||
style("incremental (only changes since last sync)").green()
|
||||
Theme::success().render("incremental (only changes since last sync)")
|
||||
}
|
||||
);
|
||||
println!(" Projects: {}", preview.projects.len());
|
||||
println!();
|
||||
|
||||
println!("{}", style("Projects to sync:").cyan().bold());
|
||||
println!("{}", Theme::info().bold().render("Projects to sync:"));
|
||||
for project in &preview.projects {
|
||||
let sync_status = if !project.has_cursor {
|
||||
style("initial sync").yellow()
|
||||
Theme::warning().render("initial sync")
|
||||
} else {
|
||||
style("incremental").green()
|
||||
Theme::success().render("incremental")
|
||||
};
|
||||
|
||||
println!(" {} ({})", style(&project.path).white(), sync_status);
|
||||
println!(
|
||||
" {} ({})",
|
||||
Theme::bold().render(&project.path),
|
||||
sync_status
|
||||
);
|
||||
println!(" Existing {}: {}", type_label, project.existing_count);
|
||||
|
||||
if let Some(ref last_synced) = project.last_synced {
|
||||
|
||||
Reference in New Issue
Block a user