Skip to main content

fresh/view/popup/input/
base.rs

1//! Shared input handling logic for popups.
2//!
3//! Contains common functionality used by multiple popup types:
4//! - Escape to dismiss
5//! - PageUp/PageDown for scrolling
6//! - Home/End for jumping to start/end
7//! - Ctrl+C for copying selected text
8
9use crate::input::handler::{DeferredAction, InputContext, InputResult};
10use crate::view::popup::Popup;
11use crossterm::event::{KeyCode, KeyEvent, KeyModifiers};
12
13/// Result of attempting to handle a key event with shared logic
14pub enum SharedHandleResult {
15    /// The key was handled by shared logic
16    Handled(InputResult),
17    /// The key should be handled by popup-specific logic
18    NotHandled,
19}
20
21/// Try to handle common popup keys (Esc, PageUp/Down, Home/End, Ctrl+C)
22pub fn try_handle_shared(
23    event: &KeyEvent,
24    popup: Option<&mut Popup>,
25    ctx: &mut InputContext,
26) -> SharedHandleResult {
27    match event.code {
28        // Escape always dismisses
29        KeyCode::Esc => {
30            ctx.defer(DeferredAction::ClosePopup);
31            SharedHandleResult::Handled(InputResult::Consumed)
32        }
33
34        // Page navigation
35        KeyCode::PageUp => {
36            if let Some(p) = popup {
37                p.page_up();
38            }
39            SharedHandleResult::Handled(InputResult::Consumed)
40        }
41        KeyCode::PageDown => {
42            if let Some(p) = popup {
43                p.page_down();
44            }
45            SharedHandleResult::Handled(InputResult::Consumed)
46        }
47        KeyCode::Home => {
48            if let Some(p) = popup {
49                p.select_first();
50            }
51            SharedHandleResult::Handled(InputResult::Consumed)
52        }
53        KeyCode::End => {
54            if let Some(p) = popup {
55                p.select_last();
56            }
57            SharedHandleResult::Handled(InputResult::Consumed)
58        }
59
60        // Ctrl+C to copy selected text
61        KeyCode::Char('c') if event.modifiers == KeyModifiers::CONTROL => {
62            if let Some(p) = popup {
63                if p.has_selection() {
64                    if let Some(text) = p.get_selected_text() {
65                        ctx.defer(DeferredAction::CopyToClipboard(text));
66                    }
67                }
68            }
69            SharedHandleResult::Handled(InputResult::Consumed)
70        }
71
72        _ => SharedHandleResult::NotHandled,
73    }
74}
75
76/// Handle arrow key navigation for list-based popups
77pub fn handle_list_navigation(event: &KeyEvent, popup: Option<&mut Popup>) -> Option<InputResult> {
78    match event.code {
79        KeyCode::Up if event.modifiers.is_empty() => {
80            if let Some(p) = popup {
81                p.select_prev();
82            }
83            Some(InputResult::Consumed)
84        }
85        KeyCode::Down if event.modifiers.is_empty() => {
86            if let Some(p) = popup {
87                p.select_next();
88            }
89            Some(InputResult::Consumed)
90        }
91        _ => None,
92    }
93}