NOTE: `display_width()` is ported from https://docs.rs/ansi-width/0.1.0/src/ansi_width/lib.rs.html#9-55 Return the display width of a unicode string. This functions takes ANSI-escaped color codes into account.
(text: &str)
| 14 | /// Return the display width of a unicode string. |
| 15 | /// This functions takes ANSI-escaped color codes into account. |
| 16 | pub(crate) fn display_width(text: &str) -> usize { |
| 17 | let mut width = 0; |
| 18 | let mut chars = text.chars(); |
| 19 | |
| 20 | // This lint is a false positive, because we use the iterator later, leading to |
| 21 | // ownership issues if we follow the lint. |
| 22 | #[allow(clippy::while_let_on_iterator)] |
| 23 | while let Some(c) = chars.next() { |
| 24 | // ESC starts escape sequences, so we need to take characters until the |
| 25 | // end of the escape sequence. |
| 26 | if c == ESC { |
| 27 | let Some(c) = chars.next() else { |
| 28 | break; |
| 29 | }; |
| 30 | match c { |
| 31 | // String terminator character: ends other sequences |
| 32 | // We probably won't encounter this but it's here for completeness. |
| 33 | // Or for if we get passed invalid codes. |
| 34 | '\\' => { |
| 35 | // ignore |
| 36 | } |
| 37 | // Control Sequence Introducer: continue until `\x40-\x7C` |
| 38 | '[' => while !matches!(chars.next(), Some('\x40'..='\x7C') | None) {}, |
| 39 | // Operating System Command: continue until ST |
| 40 | ']' => { |
| 41 | let mut last = c; |
| 42 | while let Some(new) = chars.next() { |
| 43 | if new == '\x07' || (new == '\\' && last == ESC) { |
| 44 | break; |
| 45 | } |
| 46 | last = new; |
| 47 | } |
| 48 | } |
| 49 | // We don't know what character it is, best bet is to fall back to unicode width |
| 50 | // The ESC is assumed to have 0 width in this case. |
| 51 | _ => { |
| 52 | width += unicode_width::UnicodeWidthChar::width(c).unwrap_or(0); |
| 53 | } |
| 54 | } |
| 55 | } else { |
| 56 | // If it's a normal character outside an escape sequence, use the |
| 57 | // unicode width. |
| 58 | width += unicode_width::UnicodeWidthChar::width(c).unwrap_or(0); |
| 59 | } |
| 60 | } |
| 61 | width |
| 62 | } |
| 63 | |
| 64 | pub fn transpose<T>(v: Vec<Vec<T>>) -> Vec<Vec<T>> { |
| 65 | if v.is_empty() || v[0].is_empty() { |
no outgoing calls
no test coverage detected