From e60a74e9cfc277e33451b8547c2d92d5e9259d16 Mon Sep 17 00:00:00 2001 From: Cyan Date: Sun, 18 Oct 2026 17:05:55 +0800 Subject: [PATCH] Clicking a row/column while in a formula now highlights that row/column --- crates/ui-egui/src/editor.rs | 44 ++++++++++++++----- crates/ui-egui/tests/formula_point_headers.rs | 4 ++ 2 files changed, 36 insertions(+), 12 deletions(-) diff --git a/crates/ui-egui/src/editor.rs b/crates/ui-egui/src/editor.rs index 4aada2953..f79169fce 100644 --- a/crates/ui-egui/src/editor.rs +++ b/crates/ui-egui/src/editor.rs @@ -208,20 +208,29 @@ pub fn formula_refs(text: &str) -> Vec<(usize, usize, RangeRef, Option, Tok::Sheet(a, _) => (Some(a.clone()), toks[i].start, i + 1), _ => (None, toks[i].start, i), }; - if let Some(Tok::Word(w)) = toks.get(j).map(|t| &t.tok) - && let Some(c) = CellRef::parse(w) - { - let mut end = toks[j].end; - let mut range = RangeRef::cell(c); - if let (Some(Tok::Colon | Tok::Trim(_)), Some(Tok::Word(w2))) = (toks.get(j + 1).map(|t| &t.tok), toks.get(j + 2).map(|t| &t.tok)) - && let Some(c2) = CellRef::parse(w2) - { - range = RangeRef::new(c, c2); - end = toks[j + 2].end; - i = j + 3; + if let Some(Tok::Word(w)) = toks.get(j).map(|t| &t.tok) { + let range_end = if matches!(toks.get(j + 1).map(|t| &t.tok), Some(Tok::Colon | Tok::Trim(_))) { + toks.get(j + 2).and_then(|token| { + let end = match &token.tok { + Tok::Word(w) => Some(w.clone()), + Tok::Number(n) if n.fract() == 0.0 && *n >= 1.0 => Some(format!("{n}")), + _ => None, + }?; + RangeRef::parse(&format!("{w}:{end}")).map(|range| (range, token.end)) + }) } else { + None + }; + let (range, end) = if let Some(range_end) = range_end { + i = j + 3; + range_end + } else if let Some(c) = CellRef::parse(w) { i = j + 1; - } + (RangeRef::cell(c), toks[j].end) + } else { + i += 1; + continue; + }; let key = body.get(start..end).unwrap_or("").replace('$', "").to_ascii_uppercase(); let idx = match seen.iter().position(|k| *k == key) { Some(k) => k, @@ -329,4 +338,15 @@ mod tests { assert_eq!(r[1].2.a1(), "B2:C3"); assert_eq!(r[3].3.as_deref(), Some("Sheet2")); } + + #[test] + fn whole_row_and_column_ref_spans() { + let refs = formula_refs("=SUM(C:C,4:6,$D:$E,Sheet2!7:8)"); + assert_eq!(refs.len(), 4); + assert_eq!(refs[0].2.a1(), "C:C"); + assert_eq!(refs[1].2.a1(), "4:6"); + assert_eq!(refs[2].2.a1(), "D:E"); + assert_eq!(refs[3].2.a1(), "7:8"); + assert_eq!(refs[3].3.as_deref(), Some("Sheet2")); + } } diff --git a/crates/ui-egui/tests/formula_point_headers.rs b/crates/ui-egui/tests/formula_point_headers.rs index 4313fb9f6..846fcb350 100644 --- a/crates/ui-egui/tests/formula_point_headers.rs +++ b/crates/ui-egui/tests/formula_point_headers.rs @@ -52,6 +52,8 @@ fn column_header_click_inserts_a_column_reference() { let app = h.state(); assert_eq!(app.editor.as_ref().map(|e| e.text.as_str()), Some("=SUM(C:C")); assert_eq!(app.session.active().unwrap().selection.current().a1(), "F8"); + let text = app.editor.as_ref().map_or("", |ed| ed.text.as_str()); + assert_eq!(gridcraft_ui_egui::editor::formula_refs(text).first().map(|r| r.2.a1()).as_deref(), Some("C:C")); } #[test] @@ -62,6 +64,8 @@ fn row_header_click_inserts_a_row_reference() { let app = h.state(); assert_eq!(app.editor.as_ref().map(|e| e.text.as_str()), Some("=SUM(4:4")); assert_eq!(app.session.active().unwrap().selection.current().a1(), "F8"); + let text = app.editor.as_ref().map_or("", |ed| ed.text.as_str()); + assert_eq!(gridcraft_ui_egui::editor::formula_refs(text).first().map(|r| r.2.a1()).as_deref(), Some("4:4")); } #[test]