aboutsummaryrefslogtreecommitdiff
path: root/helix-term
diff options
context:
space:
mode:
authorBram2022-02-23 03:46:12 +0000
committerGitHub2022-02-23 03:46:12 +0000
commit40eb1268c72b60f1249389c58892e7c45d268cff (patch)
tree84f741c7067547b4af3e6b0a867c10639d00ede8 /helix-term
parente1a92fd3998aca2a313d4cbf0aca3157eca0b53f (diff)
Close some popups automatically (#1285)
* Add Event::Used to use event callback without consuming * Close popup if contents ignored event * collect event results before executing callbacks * don't add new result variant, use Ignored(..) instead * break in match cases * Make auto_close configurable * fix merge * auto close hover popups * fix formatting
Diffstat (limited to 'helix-term')
-rw-r--r--helix-term/src/commands.rs2
-rw-r--r--helix-term/src/commands/lsp.rs2
-rw-r--r--helix-term/src/compositor.rs29
-rw-r--r--helix-term/src/ui/completion.rs2
-rw-r--r--helix-term/src/ui/editor.rs24
-rw-r--r--helix-term/src/ui/menu.rs4
-rw-r--r--helix-term/src/ui/picker.rs2
-rw-r--r--helix-term/src/ui/popup.rs31
-rw-r--r--helix-term/src/ui/prompt.rs2
9 files changed, 64 insertions, 34 deletions
diff --git a/helix-term/src/commands.rs b/helix-term/src/commands.rs
index 4cded7ef..1272cc8a 100644
--- a/helix-term/src/commands.rs
+++ b/helix-term/src/commands.rs
@@ -2921,7 +2921,7 @@ pub mod cmd {
let call: job::Callback =
Box::new(move |editor: &mut Editor, compositor: &mut Compositor| {
let contents = ui::Markdown::new(contents, editor.syn_loader.clone());
- let popup = Popup::new("hover", contents);
+ let popup = Popup::new("hover", contents).auto_close(true);
compositor.replace_or_push("hover", Box::new(popup));
});
Ok(call)
diff --git a/helix-term/src/commands/lsp.rs b/helix-term/src/commands/lsp.rs
index af11cd4e..798dedc6 100644
--- a/helix-term/src/commands/lsp.rs
+++ b/helix-term/src/commands/lsp.rs
@@ -633,7 +633,7 @@ pub fn hover(cx: &mut Context) {
// skip if contents empty
let contents = ui::Markdown::new(contents, editor.syn_loader.clone());
- let popup = Popup::new("hover", contents);
+ let popup = Popup::new("hover", contents).auto_close(true);
compositor.replace_or_push("hover", Box::new(popup));
}
},
diff --git a/helix-term/src/compositor.rs b/helix-term/src/compositor.rs
index dd7ebe1d..2f80de00 100644
--- a/helix-term/src/compositor.rs
+++ b/helix-term/src/compositor.rs
@@ -19,7 +19,7 @@ pub type Callback = Box<dyn FnOnce(&mut Compositor, &mut Context)>;
// Cursive-inspired
pub enum EventResult {
- Ignored,
+ Ignored(Option<Callback>),
Consumed(Option<Callback>),
}
@@ -36,7 +36,7 @@ pub struct Context<'a> {
pub trait Component: Any + AnyComponent {
/// Process input events, return true if handled.
fn handle_event(&mut self, _event: Event, _ctx: &mut Context) -> EventResult {
- EventResult::Ignored
+ EventResult::Ignored(None)
}
// , args: ()
@@ -146,19 +146,34 @@ impl Compositor {
keys.push(key.into());
}
+ let mut callbacks = Vec::new();
+ let mut consumed = false;
+
// 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() {
match layer.handle_event(event, cx) {
EventResult::Consumed(Some(callback)) => {
- callback(self, cx);
- return true;
+ callbacks.push(callback);
+ consumed = true;
+ break;
+ }
+ EventResult::Consumed(None) => {
+ consumed = true;
+ break;
+ }
+ EventResult::Ignored(Some(callback)) => {
+ callbacks.push(callback);
}
- EventResult::Consumed(None) => return true,
- EventResult::Ignored => false,
+ EventResult::Ignored(None) => {}
};
}
- false
+
+ for callback in callbacks {
+ callback(self, cx)
+ }
+
+ consumed
}
pub fn render(&mut self, cx: &mut Context) {
diff --git a/helix-term/src/ui/completion.rs b/helix-term/src/ui/completion.rs
index d3b618a9..adaac1a7 100644
--- a/helix-term/src/ui/completion.rs
+++ b/helix-term/src/ui/completion.rs
@@ -276,7 +276,7 @@ impl Component for Completion {
code: KeyCode::Esc, ..
}) = event
{
- return EventResult::Ignored;
+ return EventResult::Ignored(None);
}
self.popup.handle_event(event, cx)
}
diff --git a/helix-term/src/ui/editor.rs b/helix-term/src/ui/editor.rs
index fc749ebb..29552b67 100644
--- a/helix-term/src/ui/editor.rs
+++ b/helix-term/src/ui/editor.rs
@@ -872,9 +872,7 @@ impl EditorView {
let path = match doc.path() {
Some(path) => path.clone(),
- None => {
- return EventResult::Ignored;
- }
+ None => return EventResult::Ignored(None),
};
let line = coords.row + view.offset.row;
@@ -884,7 +882,7 @@ impl EditorView {
}
}
- EventResult::Ignored
+ EventResult::Ignored(None)
}
MouseEvent {
@@ -897,7 +895,7 @@ impl EditorView {
let pos = match view.pos_at_screen_coords(doc, row, column) {
Some(pos) => pos,
- None => return EventResult::Ignored,
+ None => return EventResult::Ignored(None),
};
let mut selection = doc.selection(view.id).clone();
@@ -928,7 +926,7 @@ impl EditorView {
match result {
Some(view_id) => cxt.editor.tree.focus = view_id,
- None => return EventResult::Ignored,
+ None => return EventResult::Ignored(None),
}
let offset = cxt.editor.config.scroll_lines.abs() as usize;
@@ -944,14 +942,14 @@ impl EditorView {
..
} => {
if !cxt.editor.config.middle_click_paste {
- return EventResult::Ignored;
+ return EventResult::Ignored(None);
}
let (view, doc) = current!(cxt.editor);
let range = doc.selection(view.id).primary();
if range.to() - range.from() <= 1 {
- return EventResult::Ignored;
+ return EventResult::Ignored(None);
}
commands::MappableCommand::yank_main_selection_to_primary_clipboard.execute(cxt);
@@ -988,7 +986,7 @@ impl EditorView {
return EventResult::Consumed(None);
}
}
- EventResult::Ignored
+ EventResult::Ignored(None)
}
MouseEvent {
@@ -1000,7 +998,7 @@ impl EditorView {
} => {
let editor = &mut cxt.editor;
if !editor.config.middle_click_paste {
- return EventResult::Ignored;
+ return EventResult::Ignored(None);
}
if modifiers == crossterm::event::KeyModifiers::ALT {
@@ -1023,10 +1021,10 @@ impl EditorView {
return EventResult::Consumed(None);
}
- EventResult::Ignored
+ EventResult::Ignored(None)
}
- _ => EventResult::Ignored,
+ _ => EventResult::Ignored(None),
}
}
}
@@ -1117,7 +1115,7 @@ impl Component for EditorView {
// if the command consumed the last view, skip the render.
// on the next loop cycle the Application will then terminate.
if cx.editor.should_close() {
- return EventResult::Ignored;
+ return EventResult::Ignored(None);
}
let (view, doc) = current!(cx.editor);
diff --git a/helix-term/src/ui/menu.rs b/helix-term/src/ui/menu.rs
index f9a0438c..1839da47 100644
--- a/helix-term/src/ui/menu.rs
+++ b/helix-term/src/ui/menu.rs
@@ -202,7 +202,7 @@ impl<T: Item + 'static> Component for Menu<T> {
fn handle_event(&mut self, event: Event, cx: &mut Context) -> EventResult {
let event = match event {
Event::Key(event) => event,
- _ => return EventResult::Ignored,
+ _ => return EventResult::Ignored(None),
};
let close_fn = EventResult::Consumed(Some(Box::new(|compositor: &mut Compositor, _| {
@@ -252,7 +252,7 @@ impl<T: Item + 'static> Component for Menu<T> {
// 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.
// EventResult::Consumed(None)
- EventResult::Ignored
+ EventResult::Ignored(None)
}
fn required_size(&mut self, viewport: (u16, u16)) -> Option<(u16, u16)> {
diff --git a/helix-term/src/ui/picker.rs b/helix-term/src/ui/picker.rs
index 9e236510..34709e8b 100644
--- a/helix-term/src/ui/picker.rs
+++ b/helix-term/src/ui/picker.rs
@@ -419,7 +419,7 @@ impl<T: 'static> Component for Picker<T> {
let key_event = match event {
Event::Key(event) => event,
Event::Resize(..) => return EventResult::Consumed(None),
- _ => return EventResult::Ignored,
+ _ => return EventResult::Ignored(None),
};
let close_fn = EventResult::Consumed(Some(Box::new(|compositor: &mut Compositor, _| {
diff --git a/helix-term/src/ui/popup.rs b/helix-term/src/ui/popup.rs
index 4d319423..45527482 100644
--- a/helix-term/src/ui/popup.rs
+++ b/helix-term/src/ui/popup.rs
@@ -1,5 +1,5 @@
use crate::{
- compositor::{Component, Compositor, Context, EventResult},
+ compositor::{Callback, Component, Context, EventResult},
ctrl, key,
};
use crossterm::event::Event;
@@ -18,6 +18,7 @@ pub struct Popup<T: Component> {
size: (u16, u16),
child_size: (u16, u16),
scroll: usize,
+ auto_close: bool,
id: &'static str,
}
@@ -33,6 +34,7 @@ impl<T: Component> Popup<T> {
size: (0, 0),
child_size: (0, 0),
scroll: 0,
+ auto_close: false,
id,
}
}
@@ -46,6 +48,11 @@ impl<T: Component> Popup<T> {
self
}
+ pub fn auto_close(mut self, auto_close: bool) -> Self {
+ self.auto_close = auto_close;
+ self
+ }
+
pub fn get_rel_position(&mut self, viewport: Rect, cx: &Context) -> (u16, u16) {
let position = self
.position
@@ -105,19 +112,19 @@ impl<T: Component> Component for Popup<T> {
Event::Key(event) => event,
Event::Resize(_, _) => {
// TODO: calculate inner area, call component's handle_event with that area
- return EventResult::Ignored;
+ return EventResult::Ignored(None);
}
- _ => return EventResult::Ignored,
+ _ => return EventResult::Ignored(None),
};
- 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)
@@ -126,7 +133,17 @@ 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 self.auto_close {
+ if let EventResult::Ignored(None) = contents_event_result {
+ return EventResult::Ignored(Some(close_fn));
+ }
+ }
+
+ 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.
diff --git a/helix-term/src/ui/prompt.rs b/helix-term/src/ui/prompt.rs
index cd8e14ee..c3402f02 100644
--- a/helix-term/src/ui/prompt.rs
+++ b/helix-term/src/ui/prompt.rs
@@ -438,7 +438,7 @@ impl Component for Prompt {
let event = match event {
Event::Key(event) => event,
Event::Resize(..) => return EventResult::Consumed(None),
- _ => return EventResult::Ignored,
+ _ => return EventResult::Ignored(None),
};
let close_fn = EventResult::Consumed(Some(Box::new(|compositor: &mut Compositor, _| {