Convert a "structural visual" position (includes } and empty content markers) to a "content position" (just visible chars, matching strip_styling output). Content position is clamped to stripped text length.
(raw: &str, cursor_pos: usize)
| 2354 | /// to a "content position" (just visible chars, matching strip_styling output). |
| 2355 | /// Content position is clamped to stripped text length. |
| 2356 | pub fn cursor_to_content(raw: &str, cursor_pos: usize) -> usize { |
| 2357 | let chars: Vec<char> = raw.chars().collect(); |
| 2358 | let len = chars.len(); |
| 2359 | let mut visual = 0usize; |
| 2360 | let mut content = 0usize; |
| 2361 | let mut escaped = false; |
| 2362 | let mut in_style_def = false; |
| 2363 | |
| 2364 | for i in 0..len { |
| 2365 | if visual >= cursor_pos { |
| 2366 | break; |
| 2367 | } |
| 2368 | let c = chars[i]; |
| 2369 | |
| 2370 | if escaped { |
| 2371 | visual += 1; |
| 2372 | content += 1; |
| 2373 | escaped = false; |
| 2374 | continue; |
| 2375 | } |
| 2376 | |
| 2377 | match c { |
| 2378 | '\\' => { escaped = true; } |
| 2379 | '{' if !in_style_def => { in_style_def = true; } |
| 2380 | '|' if in_style_def => { |
| 2381 | in_style_def = false; |
| 2382 | if i + 1 < len && chars[i + 1] == '}' { |
| 2383 | visual += 1; // empty content position (not a real content char) |
| 2384 | } |
| 2385 | } |
| 2386 | '}' if !in_style_def => { |
| 2387 | visual += 1; // } position (not a real content char) |
| 2388 | } |
| 2389 | _ if in_style_def => {} |
| 2390 | _ => { |
| 2391 | visual += 1; |
| 2392 | content += 1; |
| 2393 | } |
| 2394 | } |
| 2395 | } |
| 2396 | |
| 2397 | content |
| 2398 | } |
| 2399 | |
| 2400 | /// Convert a "content position" (from strip_styling output) back to a |
| 2401 | /// "structural visual" position (includes } and empty content markers). |
no outgoing calls