refactor(cli): remove deprecated stage_spinner, migrate remaining callers to v2
Phase 7 cleanup: migrate timeline.rs and main.rs search spinner from stage_spinner() to stage_spinner_v2() with proper icon labels, then remove the now-unused stage_spinner() function and its tests. No external callers remain for the old numbered-stage API. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -2,7 +2,7 @@ use crate::cli::render::{self, Icons, Theme};
|
|||||||
use serde::Serialize;
|
use serde::Serialize;
|
||||||
|
|
||||||
use crate::Config;
|
use crate::Config;
|
||||||
use crate::cli::progress::stage_spinner;
|
use crate::cli::progress::stage_spinner_v2;
|
||||||
use crate::core::db::create_connection;
|
use crate::core::db::create_connection;
|
||||||
use crate::core::error::{LoreError, Result};
|
use crate::core::error::{LoreError, Result};
|
||||||
use crate::core::paths::get_db_path;
|
use crate::core::paths::get_db_path;
|
||||||
@@ -96,7 +96,12 @@ pub async fn run_timeline(config: &Config, params: &TimelineParams) -> Result<Ti
|
|||||||
let seed_result = match parsed_query {
|
let seed_result = match parsed_query {
|
||||||
TimelineQuery::EntityDirect { entity_type, iid } => {
|
TimelineQuery::EntityDirect { entity_type, iid } => {
|
||||||
// Direct seeding: synchronous, no Ollama needed
|
// Direct seeding: synchronous, no Ollama needed
|
||||||
let spinner = stage_spinner(1, 3, "Resolving entity...", params.robot_mode);
|
let spinner = stage_spinner_v2(
|
||||||
|
Icons::search(),
|
||||||
|
"Resolve",
|
||||||
|
"Resolving entity...",
|
||||||
|
params.robot_mode,
|
||||||
|
);
|
||||||
let result = seed_timeline_direct(&conn, &entity_type, iid, project_id)?;
|
let result = seed_timeline_direct(&conn, &entity_type, iid, project_id)?;
|
||||||
spinner.finish_and_clear();
|
spinner.finish_and_clear();
|
||||||
result
|
result
|
||||||
@@ -111,7 +116,12 @@ pub async fn run_timeline(config: &Config, params: &TimelineParams) -> Result<Ti
|
|||||||
});
|
});
|
||||||
|
|
||||||
// Stage 1+2: SEED + HYDRATE (hybrid search with FTS fallback)
|
// Stage 1+2: SEED + HYDRATE (hybrid search with FTS fallback)
|
||||||
let spinner = stage_spinner(1, 3, "Seeding timeline...", params.robot_mode);
|
let spinner = stage_spinner_v2(
|
||||||
|
Icons::search(),
|
||||||
|
"Seed",
|
||||||
|
"Seeding timeline...",
|
||||||
|
params.robot_mode,
|
||||||
|
);
|
||||||
let result = seed_timeline(
|
let result = seed_timeline(
|
||||||
&conn,
|
&conn,
|
||||||
Some(&client),
|
Some(&client),
|
||||||
@@ -128,7 +138,12 @@ pub async fn run_timeline(config: &Config, params: &TimelineParams) -> Result<Ti
|
|||||||
};
|
};
|
||||||
|
|
||||||
// Stage 3: EXPAND
|
// Stage 3: EXPAND
|
||||||
let spinner = stage_spinner(2, 3, "Expanding cross-references...", params.robot_mode);
|
let spinner = stage_spinner_v2(
|
||||||
|
Icons::sync(),
|
||||||
|
"Expand",
|
||||||
|
"Expanding cross-references...",
|
||||||
|
params.robot_mode,
|
||||||
|
);
|
||||||
let expand_result = expand_timeline(
|
let expand_result = expand_timeline(
|
||||||
&conn,
|
&conn,
|
||||||
&seed_result.seed_entities,
|
&seed_result.seed_entities,
|
||||||
@@ -139,7 +154,12 @@ pub async fn run_timeline(config: &Config, params: &TimelineParams) -> Result<Ti
|
|||||||
spinner.finish_and_clear();
|
spinner.finish_and_clear();
|
||||||
|
|
||||||
// Stage 4: COLLECT
|
// Stage 4: COLLECT
|
||||||
let spinner = stage_spinner(3, 3, "Collecting events...", params.robot_mode);
|
let spinner = stage_spinner_v2(
|
||||||
|
Icons::sync(),
|
||||||
|
"Collect",
|
||||||
|
"Collecting events...",
|
||||||
|
params.robot_mode,
|
||||||
|
);
|
||||||
let (events, total_before_limit) = collect_events(
|
let (events, total_before_limit) = collect_events(
|
||||||
&conn,
|
&conn,
|
||||||
&seed_result.seed_entities,
|
&seed_result.seed_entities,
|
||||||
|
|||||||
@@ -12,26 +12,6 @@ pub fn multi() -> &'static MultiProgress {
|
|||||||
&MULTI
|
&MULTI
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Create a spinner for a numbered pipeline stage.
|
|
||||||
///
|
|
||||||
/// Returns a hidden (no-op) bar in robot mode so callers can use
|
|
||||||
/// the same code path regardless of output mode.
|
|
||||||
pub fn stage_spinner(stage: u8, total: u8, msg: &str, robot_mode: bool) -> ProgressBar {
|
|
||||||
if robot_mode {
|
|
||||||
return ProgressBar::hidden();
|
|
||||||
}
|
|
||||||
let pb = multi().add(ProgressBar::new_spinner());
|
|
||||||
pb.set_style(
|
|
||||||
ProgressStyle::default_spinner()
|
|
||||||
.template("{spinner:.blue} {prefix} {msg}")
|
|
||||||
.expect("valid template"),
|
|
||||||
);
|
|
||||||
pb.enable_steady_tick(std::time::Duration::from_millis(80));
|
|
||||||
pb.set_prefix(format!("[{stage}/{total}]"));
|
|
||||||
pb.set_message(msg.to_string());
|
|
||||||
pb
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Stage spinner with icon prefix and elapsed time on the right.
|
/// Stage spinner with icon prefix and elapsed time on the right.
|
||||||
///
|
///
|
||||||
/// Template: `{spinner:.cyan} {prefix} {wide_msg} {elapsed_style:.dim}`
|
/// Template: `{spinner:.cyan} {prefix} {wide_msg} {elapsed_style:.dim}`
|
||||||
@@ -176,35 +156,7 @@ mod tests {
|
|||||||
drop(w);
|
drop(w);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
// ── Progress API tests ──
|
||||||
fn stage_spinner_robot_mode_returns_hidden() {
|
|
||||||
let pb = stage_spinner(1, 3, "Testing...", true);
|
|
||||||
assert!(pb.is_hidden());
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn stage_spinner_human_mode_sets_properties() {
|
|
||||||
let pb = stage_spinner(1, 3, "Testing...", false);
|
|
||||||
assert_eq!(pb.prefix(), "[1/3]");
|
|
||||||
assert_eq!(pb.message(), "Testing...");
|
|
||||||
pb.finish_and_clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn stage_spinner_sets_prefix_format() {
|
|
||||||
let pb = stage_spinner(2, 5, "Working...", false);
|
|
||||||
assert_eq!(pb.prefix(), "[2/5]");
|
|
||||||
pb.finish_and_clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn stage_spinner_sets_message() {
|
|
||||||
let pb = stage_spinner(1, 3, "Seeding timeline...", false);
|
|
||||||
assert_eq!(pb.message(), "Seeding timeline...");
|
|
||||||
pb.finish_and_clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
// ── New progress API tests ──
|
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn stage_spinner_v2_robot_mode_returns_hidden() {
|
fn stage_spinner_v2_robot_mode_returns_hidden() {
|
||||||
|
|||||||
@@ -32,14 +32,10 @@ impl GlyphMode {
|
|||||||
/// Precedence:
|
/// Precedence:
|
||||||
/// 1. Explicit `--icons` CLI value (passed as `cli_flag`)
|
/// 1. Explicit `--icons` CLI value (passed as `cli_flag`)
|
||||||
/// 2. `LORE_ICONS` environment variable
|
/// 2. `LORE_ICONS` environment variable
|
||||||
/// 3. Auto-detect: Nerd if `$TERM_PROGRAM` matches known Nerd-capable terminals
|
/// 3. Force ASCII fallback if `force_ascii` is true (robot mode)
|
||||||
|
/// 4. Auto-detect: Nerd if `$TERM_PROGRAM` matches known Nerd-capable terminals
|
||||||
/// or `$NERD_FONTS=1`; otherwise Unicode
|
/// or `$NERD_FONTS=1`; otherwise Unicode
|
||||||
/// 4. Force ASCII if `force_ascii` is true (robot mode or `--color never`)
|
|
||||||
pub fn detect(cli_flag: Option<&str>, force_ascii: bool) -> Self {
|
pub fn detect(cli_flag: Option<&str>, force_ascii: bool) -> Self {
|
||||||
if force_ascii {
|
|
||||||
return Self::Ascii;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 1. CLI flag
|
// 1. CLI flag
|
||||||
if let Some(flag) = cli_flag {
|
if let Some(flag) = cli_flag {
|
||||||
return Self::from_str_lossy(flag);
|
return Self::from_str_lossy(flag);
|
||||||
@@ -50,7 +46,12 @@ impl GlyphMode {
|
|||||||
return Self::from_str_lossy(&val);
|
return Self::from_str_lossy(&val);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 3. Auto-detect
|
// 3. Robot-safe fallback
|
||||||
|
if force_ascii {
|
||||||
|
return Self::Ascii;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 4. Auto-detect
|
||||||
if Self::detect_nerd_capable() {
|
if Self::detect_nerd_capable() {
|
||||||
Self::Nerd
|
Self::Nerd
|
||||||
} else {
|
} else {
|
||||||
@@ -1252,8 +1253,14 @@ mod tests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn glyph_mode_force_ascii_overrides_cli_flag() {
|
fn glyph_mode_force_ascii_is_fallback_when_no_explicit_icon_mode() {
|
||||||
assert_eq!(GlyphMode::detect(Some("nerd"), true), GlyphMode::Ascii);
|
assert_eq!(GlyphMode::detect(None, true), GlyphMode::Ascii);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn glyph_mode_force_ascii_does_not_override_cli_flag() {
|
||||||
|
assert_eq!(GlyphMode::detect(Some("nerd"), true), GlyphMode::Nerd);
|
||||||
|
assert_eq!(GlyphMode::detect(Some("unicode"), true), GlyphMode::Unicode);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
|||||||
13
src/main.rs
13
src/main.rs
@@ -144,11 +144,8 @@ async fn main() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// I1: Respect NO_COLOR convention (https://no-color.org/)
|
// Icon mode is independent of color flags; robot mode still defaults to ASCII.
|
||||||
let force_ascii = robot_mode
|
let glyphs = GlyphMode::detect(cli.icons.as_deref(), robot_mode);
|
||||||
|| cli.color == "never"
|
|
||||||
|| std::env::var("NO_COLOR").is_ok_and(|v| !v.is_empty());
|
|
||||||
let glyphs = GlyphMode::detect(cli.icons.as_deref(), force_ascii);
|
|
||||||
|
|
||||||
if std::env::var("NO_COLOR").is_ok_and(|v| !v.is_empty()) {
|
if std::env::var("NO_COLOR").is_ok_and(|v| !v.is_empty()) {
|
||||||
LoreRenderer::init(ColorMode::Never, glyphs);
|
LoreRenderer::init(ColorMode::Never, glyphs);
|
||||||
@@ -1919,9 +1916,9 @@ async fn handle_search(
|
|||||||
limit: args.limit,
|
limit: args.limit,
|
||||||
};
|
};
|
||||||
|
|
||||||
let spinner = lore::cli::progress::stage_spinner(
|
let spinner = lore::cli::progress::stage_spinner_v2(
|
||||||
1,
|
lore::cli::render::Icons::search(),
|
||||||
1,
|
"Search",
|
||||||
&format!("Searching ({})...", args.mode),
|
&format!("Searching ({})...", args.mode),
|
||||||
robot_mode,
|
robot_mode,
|
||||||
);
|
);
|
||||||
|
|||||||
Reference in New Issue
Block a user