1use crate::actions::{ActionCommand, ActionType, CellAction};
2use crate::app::AppState;
3use crate::app::InputMode;
4use crate::app::{Transition, VimMode, VimState};
5use anyhow::Result;
6use ratatui::style::{Modifier, Style};
7use tui_textarea::Input;
8
9impl AppState<'_> {
10 pub fn start_editing(&mut self) {
11 self.input_mode = InputMode::Editing;
12 let content = self.get_cell_content(self.selected_cell.0, self.selected_cell.1);
13 self.input_buffer.clone_from(&content);
14
15 let mut text_area = tui_textarea::TextArea::default();
17 text_area.insert_str(&content);
18 text_area.set_tab_length(4);
19 text_area.set_cursor_line_style(Style::default());
20 text_area.set_cursor_style(Style::default().add_modifier(Modifier::REVERSED));
21
22 self.text_area = text_area;
23 self.vim_state = Some(VimState::new(VimMode::Normal));
24 }
25
26 pub fn handle_vim_input(&mut self, input: Input) -> Result<()> {
27 if let Some(vim_state) = &mut self.vim_state {
28 match vim_state.transition(input, &mut self.text_area) {
29 Transition::Mode(mode) => {
30 self.vim_state = Some(VimState::new(mode));
31 }
32 Transition::Pending(pending) => {
33 self.vim_state = Some(vim_state.clone().with_pending(pending));
34 }
35 Transition::Exit => {
36 self.confirm_edit()?;
38 }
39 Transition::Nop => {}
40 }
41 }
42 Ok(())
43 }
44
45 pub fn confirm_edit(&mut self) -> Result<()> {
46 if let InputMode::Editing = self.input_mode {
47 let content = self.text_area.lines().join("\n");
49 let (row, col) = self.selected_cell;
50
51 self.workbook.ensure_cell_exists(row, col);
52 self.ensure_column_widths();
53
54 let sheet_index = self.workbook.get_current_sheet_index();
55 let sheet_name = self.workbook.get_current_sheet_name();
56
57 let old_cell = self.workbook.get_current_sheet().data[row][col].clone();
58
59 let mut new_cell = old_cell.clone();
60 new_cell.value.clone_from(&content);
61
62 let cell_action = CellAction::new(
63 sheet_index,
64 sheet_name,
65 row,
66 col,
67 old_cell,
68 new_cell,
69 ActionType::Edit,
70 );
71
72 self.undo_history.push(ActionCommand::Cell(cell_action));
73
74 self.workbook.set_cell_value(row, col, content)?;
75 self.input_mode = InputMode::Normal;
76 self.input_buffer = String::new();
77 self.text_area = tui_textarea::TextArea::default();
78 self.vim_state = None;
79 }
80 Ok(())
81 }
82
83 pub fn copy_cell(&mut self) {
84 let content = self.get_cell_content_mut(self.selected_cell.0, self.selected_cell.1);
85 self.clipboard = Some(content);
86 self.add_notification("Cell content copied".to_string());
87 }
88
89 pub fn cut_cell(&mut self) -> Result<()> {
90 let (row, col) = self.selected_cell;
91
92 self.workbook.ensure_cell_exists(row, col);
93
94 self.ensure_column_widths();
95
96 let content = self.get_cell_content(row, col);
97 self.clipboard = Some(content);
98
99 let sheet_index = self.workbook.get_current_sheet_index();
100 let sheet_name = self.workbook.get_current_sheet_name();
101
102 let old_cell = self.workbook.get_current_sheet().data[row][col].clone();
103
104 let mut new_cell = old_cell.clone();
105 new_cell.value = String::new();
106
107 let cell_action = CellAction::new(
108 sheet_index,
109 sheet_name,
110 row,
111 col,
112 old_cell,
113 new_cell,
114 ActionType::Cut,
115 );
116
117 self.undo_history.push(ActionCommand::Cell(cell_action));
118 self.workbook.set_cell_value(row, col, String::new())?;
119
120 self.add_notification("Cell content cut".to_string());
121 Ok(())
122 }
123
124 pub fn paste_cell(&mut self) -> Result<()> {
125 if let Some(content) = self.clipboard.clone() {
126 let (row, col) = self.selected_cell;
127
128 self.workbook.ensure_cell_exists(row, col);
129 self.ensure_column_widths();
130
131 let sheet_index = self.workbook.get_current_sheet_index();
132 let sheet_name = self.workbook.get_current_sheet_name();
133
134 let old_cell = self.workbook.get_current_sheet().data[row][col].clone();
135
136 let mut new_cell = old_cell.clone();
137 new_cell.value.clone_from(&content);
138
139 let cell_action = CellAction::new(
140 sheet_index,
141 sheet_name,
142 row,
143 col,
144 old_cell,
145 new_cell,
146 ActionType::Paste,
147 );
148
149 self.undo_history.push(ActionCommand::Cell(cell_action));
150 self.workbook.set_cell_value(row, col, content)?;
151 self.add_notification("Content pasted".to_string());
152 } else {
153 self.add_notification("Clipboard is empty".to_string());
154 }
155 Ok(())
156 }
157}