From 631ac98acac352955d3ffc2cb9e31b83921c42eb Mon Sep 17 00:00:00 2001 From: nsfisis Date: Sun, 22 Feb 2026 21:36:27 +0900 Subject: fix(suggests): align output formatting and root package filtering with Composer Add blank lines between groups, use 78-dash separator in dual mode, sanitize reason strings by replacing newlines and stripping control characters, and include root package name in direct-deps filter so its suggestions are correctly shown by default. Co-Authored-By: Claude Opus 4.6 --- crates/mozart/src/commands/suggests.rs | 30 +++++++++++++++++++++++++----- 1 file changed, 25 insertions(+), 5 deletions(-) (limited to 'crates/mozart/src/commands/suggests.rs') diff --git a/crates/mozart/src/commands/suggests.rs b/crates/mozart/src/commands/suggests.rs index 0268fe8..9150dd5 100644 --- a/crates/mozart/src/commands/suggests.rs +++ b/crates/mozart/src/commands/suggests.rs @@ -143,7 +143,7 @@ pub async fn execute( render_by_suggestion(&filtered); } else if args.by_package && args.by_suggestion { render_by_package(&filtered); - println!("---"); + println!("{}", "-".repeat(78)); render_by_suggestion(&filtered); } else { // Default: by-package @@ -379,12 +379,28 @@ fn compute_direct_deps(working_dir: &Path) -> anyhow::Result> { } let root = mozart_core::package::read_from_file(&composer_json_path)?; let mut deps: HashSet = HashSet::new(); + // Include the root package itself so its suggestions are shown + if !root.name.is_empty() { + deps.insert(root.name.to_lowercase()); + } for name in root.require.keys().chain(root.require_dev.keys()) { deps.insert(name.to_lowercase()); } Ok(deps) } +// ─── Sanitization ──────────────────────────────────────────────────────────── + +/// Sanitize a suggestion reason string for safe terminal output. +/// Replaces newlines with spaces and strips control characters. +fn sanitize_reason(reason: &str) -> String { + reason + .replace(['\n', '\r'], " ") + .chars() + .filter(|c| !c.is_control() || *c == ' ') + .collect() +} + // ─── Rendering ─────────────────────────────────────────────────────────────── fn render_list(suggestions: &[&Suggestion]) { @@ -405,12 +421,14 @@ fn render_by_package(suggestions: &[&Suggestion]) { for (source, items) in &grouped { println!("{} suggests:", source); for s in items { - if s.reason.is_empty() { + let reason = sanitize_reason(&s.reason); + if reason.is_empty() { println!(" - {}", s.target); } else { - println!(" - {}: {}", s.target, s.reason); + println!(" - {}: {}", s.target, reason); } } + println!(); } } @@ -423,12 +441,14 @@ fn render_by_suggestion(suggestions: &[&Suggestion]) { for (target, items) in &grouped { println!("{} is suggested by:", target); for s in items { - if s.reason.is_empty() { + let reason = sanitize_reason(&s.reason); + if reason.is_empty() { println!(" - {}", s.source); } else { - println!(" - {}: {}", s.source, s.reason); + println!(" - {}: {}", s.source, reason); } } + println!(); } } -- cgit v1.3.1