From f8070bbbd07d23a62b388042494a24d31b76eb8d Mon Sep 17 00:00:00 2001 From: vangel76 Date: Mon, 9 Nov 2026 23:21:03 +0100 Subject: [PATCH] fix(selection): keep the Tab run's column when Enter skips hidden rows after a merged cell Co-Authored-By: Claude Opus 5.5 --- crates/engine/src/cmd/edit/selection.rs | 7 ++++++- crates/ui-egui/src/app/editing.rs | 18 ++++++++++++++++++ 2 files changed, 24 insertions(+), 1 deletion(-) diff --git a/crates/engine/src/cmd/edit/selection.rs b/crates/engine/src/cmd/edit/selection.rs index e59f59394..e85d537ec 100644 --- a/crates/engine/src/cmd/edit/selection.rs +++ b/crates/engine/src/cmd/edit/selection.rs @@ -92,7 +92,12 @@ pub(super) fn selection_move(s: &mut Session, p: &Json) -> Result { } let mut guard = 0; while (sheet.is_row_hidden(t.row) || sheet.is_col_hidden(t.col)) && guard < 100_000 { - let n = t.offset_clamped(dr.signum(), dc.signum()); + // Step each hidden axis along its own direction, so a diagonal exit from a merge + // (Tab-run return column) keeps its column while skipping hidden rows. + let n = CellRef::new( + if sheet.is_row_hidden(t.row) { t.offset_clamped(dr.signum(), 0).row } else { t.row }, + if sheet.is_col_hidden(t.col) { t.offset_clamped(0, dc.signum()).col } else { t.col }, + ); if n == t { break; } diff --git a/crates/ui-egui/src/app/editing.rs b/crates/ui-egui/src/app/editing.rs index c2333caee..b9680f30a 100644 --- a/crates/ui-egui/src/app/editing.rs +++ b/crates/ui-egui/src/app/editing.rs @@ -546,4 +546,22 @@ mod merged_cell_enter_tests { app.move_after_enter(1, 0); assert_eq!(sel(&app), "A4"); } + + #[test] + fn enter_from_a_merged_cell_in_a_tab_run_skips_a_hidden_row_and_keeps_the_column() { + let mut session = Session::new(); + session.new_workbook(); + let mut app = SheetApp::new(session, Default::default()); + app.run("selection.set", json!({"range": "D2:E3"})).unwrap(); + app.run("home.mergeCells", json!({})).unwrap(); + app.run("selection.set", json!({"range": "A4"})).unwrap(); + app.run("home.hideRows", json!({})).unwrap(); + let sel = |app: &SheetApp| app.session.active().map(|d| d.selection.a1()).unwrap_or_default(); + app.run("selection.set", json!({"cell": "C2"})).unwrap(); + app.move_after_enter(0, 1); + assert_eq!(sel(&app), "D2:E3"); + // Row 4 is hidden: Enter lands on C5, the run's column, not B5. + app.move_after_enter(1, 0); + assert_eq!(sel(&app), "C5"); + } }