use crate::cli::render::{self, StyledCell, Theme}; pub(crate) fn format_assignees(assignees: &[String]) -> String { if assignees.is_empty() { return "-".to_string(); } let max_shown = 2; let shown: Vec = assignees .iter() .take(max_shown) .map(|s| format!("@{}", render::truncate(s, 10))) .collect(); let overflow = assignees.len().saturating_sub(max_shown); if overflow > 0 { format!("{} +{}", shown.join(", "), overflow) } else { shown.join(", ") } } pub(crate) fn format_discussions(total: i64, unresolved: i64) -> StyledCell { if total == 0 { return StyledCell::plain(String::new()); } if unresolved > 0 { let text = format!("{total}/"); let warn = Theme::warning().render(&format!("{unresolved}!")); StyledCell::plain(format!("{text}{warn}")) } else { StyledCell::plain(format!("{total}")) } } pub(crate) fn format_branches(target: &str, source: &str, max_width: usize) -> String { let full = format!("{} <- {}", target, source); render::truncate(&full, max_width) } pub(crate) fn truncate_body(body: &str, max_len: usize) -> String { if body.chars().count() <= max_len { body.to_string() } else { let truncated: String = body.chars().take(max_len).collect(); format!("{truncated}...") } } pub(crate) fn format_note_type(note_type: Option<&str>) -> &'static str { match note_type { Some("DiffNote") => "Diff", Some("DiscussionNote") => "Disc", _ => "-", } } pub(crate) fn format_note_path(path: Option<&str>, line: Option) -> String { match (path, line) { (Some(p), Some(l)) => format!("{p}:{l}"), (Some(p), None) => p.to_string(), _ => "-".to_string(), } } pub(crate) fn format_note_parent(noteable_type: Option<&str>, parent_iid: Option) -> String { match (noteable_type, parent_iid) { (Some("Issue"), Some(iid)) => format!("Issue #{iid}"), (Some("MergeRequest"), Some(iid)) => format!("MR !{iid}"), _ => "-".to_string(), } }