excel_cli/utils/
cell_navigation.rs1use crate::excel::Sheet;
2
3#[derive(Debug, Clone, Copy)]
5pub enum Direction {
6 Left,
7 Right,
8 Up,
9 Down,
10}
11
12#[must_use]
16pub fn find_non_empty_cell(
17 sheet: &Sheet,
18 current_pos: (usize, usize),
19 direction: Direction,
20 max_bounds: (usize, usize),
21) -> Option<(usize, usize)> {
22 let (row, col) = current_pos;
23 let (max_row, max_col) = max_bounds;
24
25 match direction {
27 Direction::Left if col <= 1 => return None,
28 Direction::Right if col >= max_col => return None,
29 Direction::Up if row <= 1 => return None,
30 Direction::Down if row >= max_row => return None,
31 _ => {}
32 }
33
34 let current_cell_is_empty = row >= sheet.data.len()
36 || col >= sheet.data[row].len()
37 || sheet.data[row][col].value.is_empty();
38
39 if current_cell_is_empty {
40 match direction {
42 Direction::Left => {
43 for c in (1..col).rev() {
44 if row < sheet.data.len()
45 && c < sheet.data[row].len()
46 && !sheet.data[row][c].value.is_empty()
47 {
48 return Some((row, c));
49 }
50 }
51 Some((row, 1))
53 }
54 Direction::Right => {
55 for c in (col + 1)..=max_col {
56 if row < sheet.data.len()
57 && c < sheet.data[row].len()
58 && !sheet.data[row][c].value.is_empty()
59 {
60 return Some((row, c));
61 }
62 }
63 Some((row, max_col))
65 }
66 Direction::Up => {
67 for r in (1..row).rev() {
68 if r < sheet.data.len()
69 && col < sheet.data[r].len()
70 && !sheet.data[r][col].value.is_empty()
71 {
72 return Some((r, col));
73 }
74 }
75 Some((1, col))
77 }
78 Direction::Down => {
79 for r in (row + 1)..=max_row {
80 if r < sheet.data.len()
81 && col < sheet.data[r].len()
82 && !sheet.data[r][col].value.is_empty()
83 {
84 return Some((r, col));
85 }
86 }
87 Some((max_row, col))
89 }
90 }
91 } else {
92 match direction {
94 Direction::Left => {
95 let mut last_non_empty = col;
96
97 for c in (1..col).rev() {
98 if row < sheet.data.len() && c < sheet.data[row].len() {
99 if sheet.data[row][c].value.is_empty() {
100 return Some((row, c + 1));
101 }
102 last_non_empty = c;
103 } else {
104 return Some((row, c + 1));
105 }
106 }
107
108 Some((row, last_non_empty))
109 }
110 Direction::Right => {
111 let mut last_non_empty = col;
112
113 for c in (col + 1)..=max_col {
114 if row < sheet.data.len() && c < sheet.data[row].len() {
115 if sheet.data[row][c].value.is_empty() {
116 return Some((row, c - 1));
117 }
118 last_non_empty = c;
119 } else {
120 return Some((row, c - 1));
121 }
122 }
123
124 Some((row, last_non_empty))
125 }
126 Direction::Up => {
127 let mut last_non_empty = row;
128
129 for r in (1..row).rev() {
130 if r < sheet.data.len() && col < sheet.data[r].len() {
131 if sheet.data[r][col].value.is_empty() {
132 return Some((r + 1, col));
133 }
134 last_non_empty = r;
135 } else {
136 return Some((r + 1, col));
137 }
138 }
139
140 Some((last_non_empty, col))
141 }
142 Direction::Down => {
143 let mut last_non_empty = row;
144
145 for r in (row + 1)..=max_row {
146 if r < sheet.data.len() && col < sheet.data[r].len() {
147 if sheet.data[r][col].value.is_empty() {
148 return Some((r - 1, col));
149 }
150 last_non_empty = r;
151 } else {
152 return Some((r - 1, col));
153 }
154 }
155
156 Some((last_non_empty, col))
157 }
158 }
159 }
160}