Convert a visual (display) cursor position to a raw char position. Visual elements include: - Visible characters (escaped chars like `\{` count as one) - `}` closing a style tag (the "exit tag" position) - Empty content area of an empty `{name|}` tag `{name|` headers are transparent and occupy no visual positions. Position 0 always maps to raw 0. For visible char positions, the result is advanc
(raw: &str, visual_pos: usize)
| 1877 | /// For visible char positions, the result is advanced past any following |
| 1878 | /// `{name|` headers so the cursor lands inside the tag content. |
| 1879 | pub fn cursor_to_raw(raw: &str, visual_pos: usize) -> usize { |
| 1880 | if visual_pos == 0 { |
| 1881 | return 0; |
| 1882 | } |
| 1883 | |
| 1884 | let chars: Vec<char> = raw.chars().collect(); |
| 1885 | let len = chars.len(); |
| 1886 | let mut visual = 0usize; |
| 1887 | let mut raw_idx = 0usize; |
| 1888 | let mut escaped = false; |
| 1889 | let mut in_style_def = false; |
| 1890 | |
| 1891 | while raw_idx < len { |
| 1892 | let c = chars[raw_idx]; |
| 1893 | |
| 1894 | if escaped { |
| 1895 | // Escaped char is a visible element |
| 1896 | visual += 1; |
| 1897 | escaped = false; |
| 1898 | raw_idx += 1; |
| 1899 | if visual == visual_pos { |
| 1900 | return skip_tag_headers(&chars, raw_idx); |
| 1901 | } |
| 1902 | continue; |
| 1903 | } |
| 1904 | |
| 1905 | match c { |
| 1906 | '\\' => { |
| 1907 | escaped = true; |
| 1908 | raw_idx += 1; |
| 1909 | } |
| 1910 | '{' if !in_style_def => { |
| 1911 | in_style_def = true; |
| 1912 | raw_idx += 1; |
| 1913 | } |
| 1914 | '|' if in_style_def => { |
| 1915 | in_style_def = false; |
| 1916 | // Check for empty content: if next char is `}` |
| 1917 | if raw_idx + 1 < len && chars[raw_idx + 1] == '}' { |
| 1918 | // Empty content marker — counts as a visual element |
| 1919 | visual += 1; |
| 1920 | raw_idx += 1; // now at `}` |
| 1921 | if visual == visual_pos { |
| 1922 | return raw_idx; // position at `}`, i.e. between `|` and `}` |
| 1923 | } |
| 1924 | // The `}` itself will be processed in the next iteration |
| 1925 | } else { |
| 1926 | raw_idx += 1; |
| 1927 | } |
| 1928 | } |
| 1929 | '}' if !in_style_def => { |
| 1930 | // Closing brace counts as a visual element (exit tag position) |
| 1931 | visual += 1; |
| 1932 | raw_idx += 1; |
| 1933 | if visual == visual_pos { |
| 1934 | // After `}` — DON'T skip tag headers; cursor is outside the tag |
| 1935 | return raw_idx; |
| 1936 | } |