Convert a raw char position to a visual (display) cursor position. Accounts for `}` and empty content positions.
(raw: &str, raw_pos: usize)
| 1976 | /// Convert a raw char position to a visual (display) cursor position. |
| 1977 | /// Accounts for `}` and empty content positions. |
| 1978 | pub fn raw_to_cursor(raw: &str, raw_pos: usize) -> usize { |
| 1979 | let chars: Vec<char> = raw.chars().collect(); |
| 1980 | let len = chars.len(); |
| 1981 | let mut visual = 0usize; |
| 1982 | let mut raw_idx = 0usize; |
| 1983 | let mut escaped = false; |
| 1984 | let mut in_style_def = false; |
| 1985 | |
| 1986 | while raw_idx < len && raw_idx < raw_pos { |
| 1987 | let c = chars[raw_idx]; |
| 1988 | |
| 1989 | if escaped { |
| 1990 | visual += 1; |
| 1991 | escaped = false; |
| 1992 | raw_idx += 1; |
| 1993 | continue; |
| 1994 | } |
| 1995 | |
| 1996 | match c { |
| 1997 | '\\' => { |
| 1998 | escaped = true; |
| 1999 | raw_idx += 1; |
| 2000 | } |
| 2001 | '{' if !in_style_def => { |
| 2002 | in_style_def = true; |
| 2003 | raw_idx += 1; |
| 2004 | } |
| 2005 | '|' if in_style_def => { |
| 2006 | in_style_def = false; |
| 2007 | // Check for empty content |
| 2008 | if raw_idx + 1 < len && chars[raw_idx + 1] == '}' { |
| 2009 | visual += 1; // empty content position |
| 2010 | raw_idx += 1; // now at `}` |
| 2011 | // Don't increment raw_idx again; `}` will be processed next |
| 2012 | } else { |
| 2013 | raw_idx += 1; |
| 2014 | } |
| 2015 | } |
| 2016 | '}' if !in_style_def => { |
| 2017 | visual += 1; // exit tag position |
| 2018 | raw_idx += 1; |
| 2019 | } |
| 2020 | _ if in_style_def => { |
| 2021 | raw_idx += 1; |
| 2022 | } |
| 2023 | _ => { |
| 2024 | visual += 1; |
| 2025 | raw_idx += 1; |
| 2026 | } |
| 2027 | } |
| 2028 | } |
| 2029 | |
| 2030 | visual |
| 2031 | } |
| 2032 | |
| 2033 | /// Count the total number of visual positions in a raw styled string. |
| 2034 | /// Includes visible chars, `}` exit positions, and empty content positions. |
no outgoing calls