diff --git a/crates/fallback/src/lib.rs b/crates/fallback/src/lib.rs index 822c4ee4b..5c74cdbc7 100644 --- a/crates/fallback/src/lib.rs +++ b/crates/fallback/src/lib.rs @@ -63,15 +63,19 @@ pub fn fish_wcwidth(c: char) -> isize { } } -/// fish's internal versions of wcwidth and wcswidth pub fn fish_wcswidth(s: &wstr) -> isize { - // ascii fast path; empty iterator returns true for .all() - if s.chars().all(|c| c.is_ascii() && !c.is_ascii_control()) { + fish_wcswidth_canonicalizing(s, std::convert::identity) +} + +pub fn fish_wcswidth_canonicalizing(s: &wstr, canonicalize: fn(char) -> char) -> isize { + // ascii fast path + let chars = s.chars().map(canonicalize); + if chars.clone().all(|c| c.is_ascii() && !c.is_ascii_control()) { return s.len() as isize; } let mut result = 0; - for c in s.chars() { + for c in chars { let w = fish_wcwidth(c); if w < 0 { return -1; diff --git a/src/pager.rs b/src/pager.rs index 7dd742587..3535d96db 100644 --- a/src/pager.rs +++ b/src/pager.rs @@ -358,17 +358,14 @@ fn measure_completion_infos(&mut self) { comp.comp_width += 2; } - // This can return -1 if it can't calculate the width. So be cautious. - let comp_width = wcswidth_rendered(comp_string); if show_prefix { - comp.comp_width += usize::try_from(prefix_len).unwrap_or_default(); + comp.comp_width += prefix_len; } - comp.comp_width += usize::try_from(comp_width).unwrap_or_default(); + comp.comp_width += wcswidth_rendered(comp_string); } // This can return -1 if it can't calculate the width. So be cautious. - let desc_width = wcswidth_rendered(&comp.desc); - comp.desc_width = usize::try_from(desc_width).unwrap_or_default(); + comp.desc_width = wcswidth_rendered(&comp.desc); } } diff --git a/src/screen.rs b/src/screen.rs index 051c55fd1..8a38f188a 100644 --- a/src/screen.rs +++ b/src/screen.rs @@ -24,7 +24,7 @@ use crate::terminal::{BufferedOutputter, CardinalDirection, Outputter}; use crate::termsize::Termsize; use crate::wutil::fstat; -use fish_fallback::fish_wcwidth; +use fish_fallback::{fish_wcswidth_canonicalizing, fish_wcwidth}; use fish_wcstringutil::{fish_wcwidth_visible, string_prefixes_string, wcs2bytes}; use fish_widestring::ELLIPSIS_CHAR; use libc::{STDERR_FILENO, STDOUT_FILENO}; @@ -2065,8 +2065,11 @@ fn wcwidth_rendered_min_0(c: char) -> usize { pub fn wcwidth_rendered(c: char) -> isize { fish_wcwidth(rendered_character(c)) } -pub fn wcswidth_rendered(s: &wstr) -> isize { - s.chars().map(wcwidth_rendered).sum() +pub fn wcswidth_rendered(s: &wstr) -> usize { + fish_wcswidth_canonicalizing(s, rendered_character) + .max(0) + .try_into() + .unwrap() } #[cfg(test)]