Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Close popups automatically #1285

Merged
Merged
11 changes: 9 additions & 2 deletions helix-term/src/compositor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ pub type Callback = Box<dyn FnOnce(&mut Compositor, &mut Context)>;
pub enum EventResult {
Ignored,
Consumed(Option<Callback>),
Used(Callback),
bram209 marked this conversation as resolved.
Show resolved Hide resolved
}

use helix_view::Editor;
Expand Down Expand Up @@ -138,16 +139,22 @@ impl Compositor {

// propagate events through the layers until we either find a layer that consumes it or we
// run out of layers (event bubbling)
for layer in self.layers.iter_mut().rev() {
bram209 marked this conversation as resolved.
Show resolved Hide resolved
for i in (0..self.layers.len()).rev() {
let layer = self.layers[i].as_mut();

match layer.handle_event(event, cx) {
EventResult::Consumed(Some(callback)) => {
callback(self, cx);
return true;
}
EventResult::Consumed(None) => return true,
EventResult::Ignored => false,
EventResult::Used(callback) => {
callback(self, cx);
}
EventResult::Ignored => {}
};
}

false
}

Expand Down
18 changes: 13 additions & 5 deletions helix-term/src/ui/popup.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use crate::{
compositor::{Component, Compositor, Context, EventResult},
compositor::{Callback, Component, Compositor, Context, EventResult},
ctrl, key,
};
use crossterm::event::Event;
Expand Down Expand Up @@ -100,14 +100,14 @@ impl<T: Component> Component for Popup<T> {
_ => return EventResult::Ignored,
};

let close_fn = EventResult::Consumed(Some(Box::new(|compositor: &mut Compositor, _| {
let close_fn: Callback = Box::new(|compositor, _| {
// remove the layer
compositor.pop();
})));
});

match key.into() {
// esc or ctrl-c aborts the completion and closes the menu
key!(Esc) | ctrl!('c') => close_fn,
key!(Esc) | ctrl!('c') => EventResult::Consumed(Some(close_fn)),
ctrl!('d') => {
self.scroll(self.size.1 as usize / 2, true);
EventResult::Consumed(None)
Expand All @@ -116,7 +116,15 @@ impl<T: Component> Component for Popup<T> {
self.scroll(self.size.1 as usize / 2, false);
EventResult::Consumed(None)
}
_ => self.contents.handle_event(event, cx),
_ => {
let contents_event_result = self.contents.handle_event(event, cx);

if let EventResult::Ignored = contents_event_result {
EventResult::Used(close_fn)
} else {
contents_event_result
}
}
}
// for some events, we want to process them but send ignore, specifically all input except
// tab/enter/ctrl-k or whatever will confirm the selection/ ctrl-n/ctrl-p for scroll.
Expand Down