diff --git a/local/recipes/tui/tlc/source/src/editor/handlers.rs b/local/recipes/tui/tlc/source/src/editor/handlers.rs index d373cf1065..7f17ba8d46 100644 --- a/local/recipes/tui/tlc/source/src/editor/handlers.rs +++ b/local/recipes/tui/tlc/source/src/editor/handlers.rs @@ -1343,3 +1343,145 @@ fn word_at_cursor(buf: &crate::editor::buffer::Buffer, pos: usize) -> String { } text[start..end].to_string() } + +#[cfg(test)] +mod tests { + use super::*; + use crate::editor::EditorResult; + + fn empty_editor() -> Editor { + Editor::new_empty() + } + + #[test] + fn default_mode_is_insert() { + let e = empty_editor(); + assert!(matches!(e.mode(), Mode::Insert)); + } + + #[test] + fn esc_with_modified_prompts_save() { + let mut e = empty_editor(); + e.insert_str("test"); + e.modified = true; + let result = e.handle_key(Key::ESCAPE); + assert!(matches!(result, EditorResult::Running)); + // Esc with dirty buffer opens save-before-close prompt + assert!(matches!(e.mode(), Mode::Prompt(PromptKind::SaveBeforeClose))); + } + + #[test] + fn f10_with_modified_prompts_save() { + let mut e = empty_editor(); + e.insert_str("test"); + e.modified = true; + let result = e.handle_key(Key::f(10)); + assert!(matches!(result, EditorResult::Running)); + assert!(matches!(e.mode(), Mode::Prompt(PromptKind::SaveBeforeClose))); + } + + #[test] + fn ctrl_s_in_insert_returns_running() { + let mut e = empty_editor(); + e.insert_str("test"); + let result = e.handle_key(Key::ctrl('s')); + assert!(matches!(result, EditorResult::Running)); + } + + #[test] + fn ctrl_q_toggles_literal_insert() { + let mut e = empty_editor(); + assert!(!e.insert_literal); + let _ = e.handle_key(Key::ctrl('q')); + assert!(e.insert_literal); + let _ = e.handle_key(Key::ctrl('q')); + assert!(!e.insert_literal); + } + + #[test] + fn f2_returns_save() { + let mut e = empty_editor(); + let result = e.handle_key(Key::f(2)); + assert!(matches!(result, EditorResult::Save)); + } + + #[test] + fn enter_in_insert_splits_line() { + let mut e = empty_editor(); + e.insert_str("hello"); + let len_before = e.buffer.len(); + let _ = e.handle_key(Key::ENTER); + // Enter inserts a newline, buffer grows + assert!(e.buffer.len() > len_before); + } + + #[test] + fn backspace_in_insert_deletes() { + let mut e = empty_editor(); + e.insert_str("hello"); + e.cursor.set_position(5, &e.buffer); + let len_before = e.buffer.len(); + let _ = e.handle_key(Key::BACKSPACE); + assert!(e.buffer.len() < len_before); + } + + #[test] + fn tab_in_insert_inserts_tab() { + let mut e = empty_editor(); + let len_before = e.buffer.len(); + let _ = e.handle_key(Key::TAB); + assert!(e.buffer.len() > len_before); + } + + #[test] + fn printable_char_in_insert_inserts() { + let mut e = empty_editor(); + let len_before = e.buffer.len(); + let _ = e.handle_key(Key { code: b'x' as u32, mods: Modifiers::empty() }); + assert_eq!(e.buffer.len(), len_before + 1); + } + + #[test] + fn insert_literal_mode_passes_char_through() { + let mut e = empty_editor(); + e.insert_literal = true; + // ESC in literal mode inserts the escape char, doesn't close + let _ = e.handle_key(Key::ESCAPE); + assert!(!e.insert_literal); // literal mode consumed + } + + #[test] + fn f9_toggles_menubar() { + let mut e = empty_editor(); + assert!(e.menubar.is_none()); + let _ = e.handle_key(Key::f(9)); + assert!(e.menubar.is_some()); + } + + #[test] + fn prompt_mode_esc_cancels() { + let mut e = empty_editor(); + e.mode = Mode::Prompt(PromptKind::Find); + let result = e.handle_key(Key::ESCAPE); + assert!(matches!(result, EditorResult::Running)); + assert!(!matches!(e.mode(), Mode::Prompt(_))); + } + + #[test] + fn bookmark_toggle_switches_to_prompt() { + let mut e = empty_editor(); + let _ = e.handle_key(Key::alt('m')); + assert!(matches!(e.mode(), Mode::Prompt(PromptKind::BookmarkSet))); + } + + #[test] + fn ctrl_h_in_insert_is_backspace() { + let mut e = empty_editor(); + e.insert_str("hello"); + e.cursor.set_position(5, &e.buffer); + let len_before = e.buffer.len(); + let _ = e.handle_key(Key::ctrl('h')); + // Ctrl-H is backspace alias (MC parity) — deletes character + assert_eq!(e.buffer.len(), len_before - 1); + } +}