basalt_tui/
note_editor.rs1mod editor;
2mod state;
3mod text_buffer;
4
5pub mod markdown_parser;
19
20pub use editor::Editor;
21use ratatui::{
22 crossterm::event::{KeyCode, KeyEvent, KeyModifiers},
23 layout::Size,
24};
25pub use state::{EditorState, View};
26pub use text_buffer::TextBuffer;
27
28use crate::{
29 app::{calc_scroll_amount, ActivePane, Message as AppMessage, ScrollAmount},
30 explorer,
31 note_editor::state::EditMode,
32 outline,
33};
34
35#[derive(Clone, Debug, PartialEq)]
36pub enum Message {
37 Save,
38 SwitchPaneNext,
39 SwitchPanePrevious,
40 ToggleExplorer,
41 ToggleOutline,
42 ToggleView,
43 EditView,
44 ReadView,
45 Exit,
46 KeyEvent(KeyEvent),
47 CursorUp,
48 CursorLeft,
49 CursorRight,
50 CursorWordForward,
51 CursorWordBackward,
52 CursorDown,
53 ScrollUp(ScrollAmount),
54 ScrollDown(ScrollAmount),
55 SetRow(usize),
56 Delete,
57}
58
59pub fn update<'a>(
60 message: &Message,
61 screen_size: Size,
62 state: &mut EditorState,
63) -> Option<AppMessage<'a>> {
64 match message {
65 Message::CursorLeft => state.cursor_left(),
66 Message::CursorRight => state.cursor_right(),
67 Message::CursorWordForward => state.cursor_word_forward(),
68 Message::CursorWordBackward => state.cursor_word_backward(),
69 Message::Delete => state.delete_char(),
70 Message::SetRow(row) => state.set_row(*row),
71
72 Message::CursorUp => {
73 state.cursor_up();
74 return Some(AppMessage::Outline(outline::Message::SelectAt(
75 state.current_row,
76 )));
77 }
78 Message::CursorDown => {
79 state.cursor_down();
80 return Some(AppMessage::Outline(outline::Message::SelectAt(
81 state.current_row,
82 )));
83 }
84 _ => {}
85 };
86
87 match state.view {
88 View::Edit(..) => match message {
89 Message::ToggleView => state.set_view(View::Read),
90 Message::ScrollUp(_) => state.cursor_up(),
91 Message::ScrollDown(_) => state.cursor_down(),
92 Message::KeyEvent(key) => {
93 state.edit((*key).into());
94
95 return Some(AppMessage::UpdateSelectedNoteContent((
96 state.content().to_string(),
97 None,
98 )));
99 }
100 Message::Exit => {
101 state.exit_insert();
102 state.set_view(View::Read);
103
104 return Some(AppMessage::UpdateSelectedNoteContent((
105 state.content().to_string(),
106 Some(state.nodes().to_vec()),
107 )));
108 }
109 _ => {}
110 },
111 View::Read => match message {
112 Message::ToggleView => state.set_view(View::Edit(EditMode::Source)),
113 Message::EditView => state.set_view(View::Edit(EditMode::Source)),
114 Message::ReadView => state.set_view(View::Read),
115 Message::Exit => state.set_view(View::Read),
116
117 Message::SetRow(row) => state.set_row(*row),
118 Message::ScrollUp(scroll_amount) => {
119 state.scroll_up(calc_scroll_amount(scroll_amount, screen_size.height.into()));
120 }
121 Message::ScrollDown(scroll_amount) => {
122 state.scroll_down(calc_scroll_amount(scroll_amount, screen_size.height.into()));
123 }
124 Message::ToggleExplorer => {
125 return Some(AppMessage::Explorer(explorer::Message::Toggle));
126 }
127 Message::ToggleOutline => {
128 return Some(AppMessage::Outline(outline::Message::Toggle));
129 }
130 Message::SwitchPaneNext => {
131 state.set_active(false);
132 return Some(AppMessage::SetActivePane(ActivePane::Outline));
133 }
134 Message::SwitchPanePrevious => {
135 state.set_active(false);
136 return Some(AppMessage::SetActivePane(ActivePane::Explorer));
137 }
138 Message::Save => {
139 state.save();
140 return Some(AppMessage::UpdateSelectedNoteContent((
141 state.content().to_string(),
142 None,
143 )));
144 }
145 _ => {}
146 },
147 }
148
149 None
150}
151
152pub fn handle_editing_event(key: &KeyEvent) -> Option<Message> {
153 match key.code {
154 KeyCode::Up => Some(Message::CursorUp),
155 KeyCode::Down => Some(Message::CursorDown),
156 KeyCode::Esc => Some(Message::Exit),
157 KeyCode::Backspace => Some(Message::Delete),
158 KeyCode::Char('e') if key.modifiers.contains(KeyModifiers::CONTROL) => {
159 Some(Message::ToggleView)
160 }
161 _ => Some(Message::KeyEvent(*key)),
162 }
163}