From fc23e4e398176272650a5eae75abf6df6ebd9d55 Mon Sep 17 00:00:00 2001 From: Amolith Date: Mon, 2 Mar 2026 10:21:39 -0700 Subject: [PATCH] Use short IDs in next and rm human output next extracted task IDs as raw ULID strings for the scoring engine then displayed those same strings. rm did the same with unblocked_ids in its warning message. Both now go through TaskId::Display or display_id() at render time. Add display_id() to TaskId for contexts where a raw &str needs shortening without constructing a TaskId. --- src/cmd/next.rs | 6 ++++-- src/cmd/rm.rs | 15 ++++++++------- tests/cli_next.rs | 3 ++- tests/cli_rm.rs | 2 +- 4 files changed, 15 insertions(+), 11 deletions(-) diff --git a/src/cmd/next.rs b/src/cmd/next.rs index d879194dbb067268aa137502cb3eca434c7ba71e..1da1d3711b567fe0a29909f9dbff43e5f8a27a2d 100644 --- a/src/cmd/next.rs +++ b/src/cmd/next.rs @@ -96,9 +96,10 @@ pub fn run(root: &Path, mode_str: &str, verbose: bool, limit: usize, json: bool) table.set_header(vec!["#", "ID", "SCORE", "TITLE"]); for (i, s) in scored.iter().enumerate() { + let short = db::TaskId::display_id(&s.id); table.add_row(vec![ Cell::new(i + 1), - cell_bold(&s.id, use_color), + cell_bold(&short, use_color), Cell::new(format!("{:.2}", s.score)), Cell::new(&s.title), ]); @@ -108,7 +109,8 @@ pub fn run(root: &Path, mode_str: &str, verbose: bool, limit: usize, json: bool) if verbose { println!(); for (i, s) in scored.iter().enumerate() { - println!("{}. {} — score: {:.2}", i + 1, s.id, s.score); + let short = db::TaskId::display_id(&s.id); + println!("{}. {} — score: {:.2}", i + 1, short, s.score); } } } diff --git a/src/cmd/rm.rs b/src/cmd/rm.rs index 38b6722544c71d9a47e0f4f088e08c2055bac0c1..be0bfc329f61f2face8bf4e6a5db1d74295e1309 100644 --- a/src/cmd/rm.rs +++ b/src/cmd/rm.rs @@ -38,11 +38,11 @@ pub fn run(root: &Path, ids: &[String], recursive: bool, force: bool, json: bool .map(|id| id.as_str().to_string()) .collect(); - let unblocked_ids: Vec = all + let unblocked_ids: Vec = all .iter() .filter(|t| !deleted_set.contains(t.id.as_str())) .filter(|t| t.blockers.iter().any(|b| deleted_set.contains(b.as_str()))) - .map(|t| t.id.as_str().to_string()) + .map(|t| t.id.clone()) .collect(); let ts = db::now_utc(); @@ -73,10 +73,8 @@ pub fn run(root: &Path, ids: &[String], recursive: bool, force: bool, json: bool })?; if !force && !unblocked_ids.is_empty() { - eprintln!( - "warning: removed blockers from {}", - unblocked_ids.join(", ") - ); + let short: Vec = unblocked_ids.iter().map(ToString::to_string).collect(); + eprintln!("warning: removed blockers from {}", short.join(", ")); } if json { @@ -86,7 +84,10 @@ pub fn run(root: &Path, ids: &[String], recursive: bool, force: bool, json: bool .iter() .map(|id| id.as_str().to_string()) .collect(), - unblocked_ids, + unblocked_ids: unblocked_ids + .iter() + .map(|id| id.as_str().to_string()) + .collect(), }; println!("{}", serde_json::to_string(&out)?); } else { diff --git a/tests/cli_next.rs b/tests/cli_next.rs index 07ca5c9477d4dbd5b6ae565efafc1851c4251fd3..02693ba29f87736e94f68c0e59023fef38e32d3f 100644 --- a/tests/cli_next.rs +++ b/tests/cli_next.rs @@ -45,12 +45,13 @@ fn next_single_task() { let tmp = init_tmp(); let id = create_task(&tmp, "Only task", "high", "low"); + let short = &id[id.len() - 7..]; td(&tmp) .arg("next") .current_dir(&tmp) .assert() .success() - .stdout(predicate::str::contains(&id)) + .stdout(predicate::str::contains(short)) .stdout(predicate::str::contains("Only task")) .stdout(predicate::str::contains("SCORE")); } diff --git a/tests/cli_rm.rs b/tests/cli_rm.rs index 37809c677042c2e1a14e437d6e2dea933dcb191f..3d3587bf538781805611fdecc6dddd65e8e02f19 100644 --- a/tests/cli_rm.rs +++ b/tests/cli_rm.rs @@ -137,7 +137,7 @@ fn rm_detaches_dependents_and_warns() { .assert() .success() .stderr(predicate::str::contains("warning")) - .stderr(predicate::str::contains(&dependent)); + .stderr(predicate::str::contains(&dependent[dependent.len() - 7..])); let dependent_task = get_task_json(&tmp, &dependent); let blockers = dependent_task["blockers"].as_array().unwrap();