cursive_hjkl/
lib.rs

1use cursive_core as cursive;
2
3use cursive::{
4  event::{Event, EventResult, Key},
5  view::ViewWrapper,
6  View,
7};
8
9/// Wraps the inner view with HJKL directional controls.
10pub struct HjklToDirectionWrapperView<T> {
11  view: T,
12}
13
14impl<T> HjklToDirectionWrapperView<T> {
15  pub fn new(view: T) -> Self {
16    Self { view }
17  }
18
19  cursive::inner_getters!(self.view: T);
20}
21
22impl<T> ViewWrapper for HjklToDirectionWrapperView<T>
23where
24  T: View,
25{
26  cursive::wrap_impl!(self.view: T);
27
28  fn wrap_on_event(&mut self, ev: Event) -> EventResult {
29    let ev_result = self.view.on_event(ev.clone());
30    if !matches!(&ev_result, EventResult::Ignored) {
31      return ev_result;
32    }
33
34    // tuple enum variants are secretly 1-argument functions
35    // which means you can pull stuff like this
36    type EventCtor = fn(Key) -> Event;
37    let (ch, ctor) = match &ev {
38      Event::Char(c) => (
39        c,
40        if c.is_ascii_uppercase() {
41          Event::Shift
42        } else {
43          Event::Key
44        } as EventCtor,
45      ),
46      Event::CtrlChar(c) => (
47        c,
48        if c.is_ascii_uppercase() {
49          Event::CtrlShift
50        } else {
51          Event::Ctrl
52        } as EventCtor,
53      ),
54      Event::AltChar(c) => (
55        c,
56        if c.is_ascii_uppercase() {
57          Event::AltShift
58        } else {
59          Event::Alt
60        } as EventCtor,
61      ),
62      _ => return EventResult::Ignored,
63    };
64
65    let dir = match ch {
66      'h' => Key::Left,
67      'j' => Key::Down,
68      'k' => Key::Up,
69      'l' => Key::Right,
70      _ => return EventResult::Ignored,
71    };
72    let the_cooler_event = ctor(dir);
73    self.view.on_event(the_cooler_event)
74  }
75}
76
77#[cursive_core::blueprint(HjklToDirectionWrapperView::new(view))]
78struct Blueprint {
79  view: cursive_core::views::BoxedView,
80}
81
82cursive_core::manual_blueprint!(with hjkl_to_direction, |_config, _context| {
83    Ok(|view| HjklToDirectionWrapperView::new(view))
84});