excel_cli/app/
edit.rs

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        // Initialize TextArea with content and settings
16        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                    // Confirm edit and exit Vim mode
37                    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            // Get content from TextArea
48            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}