pub const APPROVAL_NAVIGATE_DENY: &str = "Use ↑↓ or Tab to navigate • Enter to select • Esc to deny";
pub const APPROVAL_NAVIGATE_CANCEL: &str = "Use ↑↓ or Tab to navigate • Enter to select • Esc to cancel";
pub const APPROVAL_NAVIGATE_STOP: &str = "Use ↑↓ or Tab to navigate • Enter to select • Esc to stop";
pub fn choose_handling_line(object: &str) -> String {
format!("Choose how to handle {object}:")
}
pub fn truncate_modal_text(text: &str, max_chars: usize) -> String {
if text.chars().count() <= max_chars {
return text.to_string();
}
let mut truncated = text.chars().take(max_chars.saturating_sub(1)).collect::<String>();
truncated.push('…');
truncated
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn approval_hints_share_navigation_prefix_but_differ_by_exit_verb() {
for hint in [APPROVAL_NAVIGATE_DENY, APPROVAL_NAVIGATE_CANCEL, APPROVAL_NAVIGATE_STOP] {
assert!(hint.starts_with("Use ↑↓ or Tab to navigate • Enter to select • Esc to "));
}
assert!(APPROVAL_NAVIGATE_DENY.ends_with("deny"));
assert!(APPROVAL_NAVIGATE_CANCEL.ends_with("cancel"));
assert!(APPROVAL_NAVIGATE_STOP.ends_with("stop"));
}
#[test]
fn choose_handling_line_interpolates_object_as_sentence() {
assert_eq!(choose_handling_line("this tool"), "Choose how to handle this tool:");
assert_eq!(
choose_handling_line("workspace lifecycle hooks"),
"Choose how to handle workspace lifecycle hooks:"
);
}
#[test]
fn truncate_modal_text_marks_truncation_with_ellipsis_only_when_shortened() {
assert_eq!(truncate_modal_text("short", 10), "short");
assert_eq!(truncate_modal_text("exactly-ten", 11), "exactly-ten");
assert_eq!(truncate_modal_text("over the limit text", 10), "over the …");
}
}