Rename Input to InputEvent and add paste events

This commit is contained in:
Joscha 2023-04-27 21:10:34 +02:00
parent fdc46aa3b8
commit 6ce2afbc9f
4 changed files with 105 additions and 70 deletions

100
cove-input/src/event.rs Normal file
View file

@ -0,0 +1,100 @@
use crossterm::event::KeyEvent;
use crate::KeyBinding;
enum Mode {
Record,
Key(KeyEvent),
Paste(String),
}
impl Mode {
fn from_crossterm_event(event: crossterm::event::Event) -> Option<Self> {
use crossterm::event::Event::*;
match event {
Key(event) => Some(Self::Key(event)),
Paste(string) => Some(Self::Paste(string)),
_ => None,
}
}
}
pub enum Entry {
Space,
Category(String),
Binding(KeyBinding, String),
}
pub struct InputEvent {
mode: Mode,
entries: Vec<Entry>,
}
impl InputEvent {
pub fn new_recording() -> Self {
Self {
mode: Mode::Record,
entries: vec![],
}
}
pub fn from_crossterm_event(event: crossterm::event::Event) -> Option<Self> {
Some(Self {
mode: Mode::from_crossterm_event(event)?,
entries: vec![],
})
}
fn recording(&self) -> bool {
matches!(self.mode, Mode::Record)
}
pub fn space<S: ToString>(&mut self) {
if self.recording() {
self.entries.push(Entry::Space);
}
}
pub fn category<S: ToString>(&mut self, name: S) {
if self.recording() {
self.entries.push(Entry::Category(name.to_string()));
}
}
pub fn key_event(&self) -> Option<KeyEvent> {
if let Mode::Key(event) = &self.mode {
Some(*event)
} else {
None
}
}
pub fn paste_event(&self) -> Option<&str> {
if let Mode::Paste(string) = &self.mode {
Some(string)
} else {
None
}
}
pub fn matches_key_binding<S: ToString>(
&mut self,
binding: &KeyBinding,
description: S,
) -> bool {
if self.recording() {
self.entries
.push(Entry::Binding(binding.clone(), description.to_string()));
}
if let Some(event) = self.key_event() {
binding.matches(event)
} else {
false
}
}
pub fn entries(&self) -> &[Entry] {
&self.entries
}
}

View file

@ -1,65 +0,0 @@
use crossterm::event::KeyEvent;
use crate::KeyBinding;
pub enum Entry {
Space,
Category(String),
Binding(KeyBinding, String),
}
pub struct Input {
event: Option<KeyEvent>,
record_entries: bool,
entries: Vec<Entry>,
}
impl Input {
pub fn new_from_event(event: KeyEvent) -> Self {
Self {
event: Some(event),
record_entries: false,
entries: vec![],
}
}
pub fn new_recording() -> Self {
Self {
event: None,
record_entries: true,
entries: vec![],
}
}
pub fn space<S: ToString>(&mut self) {
if self.record_entries {
self.entries.push(Entry::Space);
}
}
pub fn category<S: ToString>(&mut self, name: S) {
if self.record_entries {
self.entries.push(Entry::Category(name.to_string()));
}
}
pub fn matches<S: ToString>(&mut self, binding: &KeyBinding, description: S) -> bool {
let matches = if let Some(event) = self.event {
binding.matches(event)
} else {
false
};
if self.record_entries {
self.entries
.push(Entry::Binding(binding.clone(), description.to_string()));
}
matches
}
pub fn entries(&self) -> &[Entry] {
&self.entries
}
}

View file

@ -1,14 +1,14 @@
mod input;
mod event;
mod keys;
pub use cove_macro::KeyGroup;
pub use input::*;
pub use event::*;
pub use keys::*;
/// A group of related key bindings.
pub trait KeyGroup {
type Event;
fn event(&self, input: &mut Input) -> Option<Self::Event>;
fn match_input_event(&self, event: &mut InputEvent) -> Option<Self::Event>;
}

View file

@ -38,7 +38,7 @@ pub fn derive_impl(input: DeriveInput) -> syn::Result<TokenStream> {
let description = decapitalize(&docstring);
let description = description.strip_suffix('.').unwrap_or(&description);
match_cases.push(quote!{
() if input.matches(&self.#field_ident, #description) => Some(Self::Event::#variant_ident),
() if event.matches_key_binding(&self.#field_ident, #description) => Some(Self::Event::#variant_ident),
});
}
}
@ -52,7 +52,7 @@ pub fn derive_impl(input: DeriveInput) -> syn::Result<TokenStream> {
impl ::cove_input::KeyGroup for #struct_ident {
type Event = #enum_ident;
fn event(&self, input: &mut ::cove_input::Input) -> Option<Self::Event> {
fn match_input_event(&self, event: &mut ::cove_input::InputEvent) -> Option<Self::Event> {
match () {
#( #match_cases )*
() => None,