strop_engine/editor/
dispatch.rs1use super::{Editor, Key, Mode};
8
9#[derive(Debug, Clone, Copy, PartialEq, Eq)]
13pub enum InputOwner {
14 Pending,
16 HoverCard,
18 BlameCard,
20 Picker,
22 UndoBrowser,
24 Document,
26}
27
28impl InputOwner {
29 fn forwards_in_insert(self) -> bool {
34 matches!(self, Self::HoverCard | Self::BlameCard)
35 }
36}
37
38impl Editor {
39 pub fn input_owner(&self) -> InputOwner {
41 if self.pending.is_active() {
42 return InputOwner::Pending;
43 }
44 if self.picker_open() {
45 return InputOwner::Picker;
46 }
47 if self.hover_card.is_some() {
48 return InputOwner::HoverCard;
49 }
50 if self.blame_card.is_some() || self.card_request.is_some() {
51 return InputOwner::BlameCard;
52 }
53 if self.undo_browser.as_ref().is_some_and(|ub| {
56 self.docs
57 .get(ub.browser)
58 .is_some_and(|d| d.buf.name.as_deref() == Some("undo tree"))
59 }) {
60 return InputOwner::UndoBrowser;
61 }
62 InputOwner::Document
63 }
64
65 pub(super) fn dispatch_owned(&mut self, key: Key) {
69 let owner = self.input_owner();
70 if self.mode == Mode::Insert && owner.forwards_in_insert() {
71 self.dismiss_overlay(owner);
72 self.feed_document(key);
73 return;
74 }
75 match owner {
76 InputOwner::Pending => self.feed_pending(key),
77 InputOwner::HoverCard => {
78 if key == Key::Enter {
79 self.open_hover_document();
80 } else {
81 self.hover_card = None;
82 }
83 }
84 InputOwner::BlameCard => {
85 let had_card = self.blame_card.is_some();
86 if let Some(card) = self.dismiss_card_authority() {
87 if key == Key::Enter {
88 self.open_log_at(&card.sha);
89 }
90 }
91 if !had_card {
92 self.dispatch_owned(key);
95 }
96 }
97 InputOwner::Picker => self.feed_picker(key),
98 InputOwner::UndoBrowser => {
99 if !self.feed_undo_browser(key) {
100 self.feed_document(key);
101 }
102 }
103 InputOwner::Document => self.feed_document(key),
104 }
105 }
106
107 fn dismiss_overlay(&mut self, owner: InputOwner) {
110 match owner {
111 InputOwner::HoverCard => self.hover_card = None,
112 InputOwner::BlameCard => {
113 let _ = self.dismiss_card_authority();
114 }
115 _ => {}
116 }
117 }
118
119 fn feed_document(&mut self, key: Key) {
121 match self.mode {
122 Mode::Insert => self.feed_insert(key),
123 Mode::Visual | Mode::VisualLine | Mode::VisualBlock => self.feed_visual(key),
124 Mode::Normal => self.feed_normal(key),
125 }
126 }
127}
128
129#[cfg(test)]
130mod tests {
131 use super::*;
132 use strop_core::Buffer;
133
134 #[test]
135 fn late_cards_cannot_consume_modal_field_input() {
136 let mut editor = Editor::new(Buffer::from_text("x\n"));
137 editor.open_picker(strop_picker::Kind::RemoteAddress);
138 editor.hover_card = Some("late docs".into());
139 editor.feed_text("host");
140 assert_eq!(editor.picker.as_ref().unwrap().picker.input.text, "host");
141 }
142
143 #[test]
144 fn overlays_forward_in_insert_and_consume_in_normal() {
145 let mut e = Editor::new(Buffer::from_text("x\n"));
146 e.feed_text("i");
147 e.hover_card = Some("late docs".into());
148 e.feed(crate::editor::Key::Esc);
149 assert_eq!(e.mode, Mode::Normal, "esc landed through the overlay");
150 assert!(e.hover_card.is_none());
151 e.hover_card = Some("docs".into());
152 e.feed(crate::editor::Key::Char('j'));
153 assert!(e.hover_card.is_none(), "normal mode: the key dismisses");
154 }
155}