aboutsummaryrefslogtreecommitdiff
path: root/helix-view/src/input.rs
diff options
context:
space:
mode:
authorNathan Vegdahl2021-07-06 03:27:49 +0000
committerNathan Vegdahl2021-07-06 03:27:49 +0000
commit85d5b399de70ff075a455ce2858549d1ed012fe3 (patch)
tree4824fcb47f39551d3b31a62931adaf0ee406c02b /helix-view/src/input.rs
parent6e15c9b8745e9708ee5271c8701d41a8393cb038 (diff)
parent3c31f501164080998975883eb6f93c49bd8d3efb (diff)
Merge branch 'master' into great_line_ending_and_cursor_range_cleanup
Diffstat (limited to 'helix-view/src/input.rs')
-rw-r--r--helix-view/src/input.rs165
1 files changed, 121 insertions, 44 deletions
diff --git a/helix-view/src/input.rs b/helix-view/src/input.rs
index 5f61ce14..2847bb69 100644
--- a/helix-view/src/input.rs
+++ b/helix-view/src/input.rs
@@ -1,5 +1,6 @@
//! Input event handling, currently backed by crossterm.
use anyhow::{anyhow, Error};
+use helix_core::unicode::width::UnicodeWidthStr;
use serde::de::{self, Deserialize, Deserializer};
use std::fmt;
@@ -13,6 +14,32 @@ pub struct KeyEvent {
pub modifiers: KeyModifiers,
}
+pub(crate) mod keys {
+ pub(crate) const BACKSPACE: &str = "backspace";
+ pub(crate) const ENTER: &str = "ret";
+ pub(crate) const LEFT: &str = "left";
+ pub(crate) const RIGHT: &str = "right";
+ pub(crate) const UP: &str = "up";
+ pub(crate) const DOWN: &str = "down";
+ pub(crate) const HOME: &str = "home";
+ pub(crate) const END: &str = "end";
+ pub(crate) const PAGEUP: &str = "pageup";
+ pub(crate) const PAGEDOWN: &str = "pagedown";
+ pub(crate) const TAB: &str = "tab";
+ pub(crate) const BACKTAB: &str = "backtab";
+ pub(crate) const DELETE: &str = "del";
+ pub(crate) const INSERT: &str = "ins";
+ pub(crate) const NULL: &str = "null";
+ pub(crate) const ESC: &str = "esc";
+ pub(crate) const SPACE: &str = "space";
+ pub(crate) const LESS_THAN: &str = "lt";
+ pub(crate) const GREATER_THAN: &str = "gt";
+ pub(crate) const PLUS: &str = "plus";
+ pub(crate) const MINUS: &str = "minus";
+ pub(crate) const SEMICOLON: &str = "semicolon";
+ pub(crate) const PERCENT: &str = "percent";
+}
+
impl fmt::Display for KeyEvent {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> std::fmt::Result {
f.write_fmt(format_args!(
@@ -34,28 +61,29 @@ impl fmt::Display for KeyEvent {
},
))?;
match self.code {
- KeyCode::Backspace => f.write_str("backspace")?,
- KeyCode::Enter => f.write_str("ret")?,
- KeyCode::Left => f.write_str("left")?,
- KeyCode::Right => f.write_str("right")?,
- KeyCode::Up => f.write_str("up")?,
- KeyCode::Down => f.write_str("down")?,
- KeyCode::Home => f.write_str("home")?,
- KeyCode::End => f.write_str("end")?,
- KeyCode::PageUp => f.write_str("pageup")?,
- KeyCode::PageDown => f.write_str("pagedown")?,
- KeyCode::Tab => f.write_str("tab")?,
- KeyCode::BackTab => f.write_str("backtab")?,
- KeyCode::Delete => f.write_str("del")?,
- KeyCode::Insert => f.write_str("ins")?,
- KeyCode::Null => f.write_str("null")?,
- KeyCode::Esc => f.write_str("esc")?,
- KeyCode::Char('<') => f.write_str("lt")?,
- KeyCode::Char('>') => f.write_str("gt")?,
- KeyCode::Char('+') => f.write_str("plus")?,
- KeyCode::Char('-') => f.write_str("minus")?,
- KeyCode::Char(';') => f.write_str("semicolon")?,
- KeyCode::Char('%') => f.write_str("percent")?,
+ KeyCode::Backspace => f.write_str(keys::BACKSPACE)?,
+ KeyCode::Enter => f.write_str(keys::ENTER)?,
+ KeyCode::Left => f.write_str(keys::LEFT)?,
+ KeyCode::Right => f.write_str(keys::RIGHT)?,
+ KeyCode::Up => f.write_str(keys::UP)?,
+ KeyCode::Down => f.write_str(keys::DOWN)?,
+ KeyCode::Home => f.write_str(keys::HOME)?,
+ KeyCode::End => f.write_str(keys::END)?,
+ KeyCode::PageUp => f.write_str(keys::PAGEUP)?,
+ KeyCode::PageDown => f.write_str(keys::PAGEDOWN)?,
+ KeyCode::Tab => f.write_str(keys::TAB)?,
+ KeyCode::BackTab => f.write_str(keys::BACKTAB)?,
+ KeyCode::Delete => f.write_str(keys::DELETE)?,
+ KeyCode::Insert => f.write_str(keys::INSERT)?,
+ KeyCode::Null => f.write_str(keys::NULL)?,
+ KeyCode::Esc => f.write_str(keys::ESC)?,
+ KeyCode::Char(' ') => f.write_str(keys::SPACE)?,
+ KeyCode::Char('<') => f.write_str(keys::LESS_THAN)?,
+ KeyCode::Char('>') => f.write_str(keys::GREATER_THAN)?,
+ KeyCode::Char('+') => f.write_str(keys::PLUS)?,
+ KeyCode::Char('-') => f.write_str(keys::MINUS)?,
+ KeyCode::Char(';') => f.write_str(keys::SEMICOLON)?,
+ KeyCode::Char('%') => f.write_str(keys::PERCENT)?,
KeyCode::F(i) => f.write_fmt(format_args!("F{}", i))?,
KeyCode::Char(c) => f.write_fmt(format_args!("{}", c))?,
};
@@ -63,34 +91,83 @@ impl fmt::Display for KeyEvent {
}
}
+impl UnicodeWidthStr for KeyEvent {
+ fn width(&self) -> usize {
+ use helix_core::unicode::width::UnicodeWidthChar;
+ let mut width = match self.code {
+ KeyCode::Backspace => keys::BACKSPACE.len(),
+ KeyCode::Enter => keys::ENTER.len(),
+ KeyCode::Left => keys::LEFT.len(),
+ KeyCode::Right => keys::RIGHT.len(),
+ KeyCode::Up => keys::UP.len(),
+ KeyCode::Down => keys::DOWN.len(),
+ KeyCode::Home => keys::HOME.len(),
+ KeyCode::End => keys::END.len(),
+ KeyCode::PageUp => keys::PAGEUP.len(),
+ KeyCode::PageDown => keys::PAGEDOWN.len(),
+ KeyCode::Tab => keys::TAB.len(),
+ KeyCode::BackTab => keys::BACKTAB.len(),
+ KeyCode::Delete => keys::DELETE.len(),
+ KeyCode::Insert => keys::INSERT.len(),
+ KeyCode::Null => keys::NULL.len(),
+ KeyCode::Esc => keys::ESC.len(),
+ KeyCode::Char(' ') => keys::SPACE.len(),
+ KeyCode::Char('<') => keys::LESS_THAN.len(),
+ KeyCode::Char('>') => keys::GREATER_THAN.len(),
+ KeyCode::Char('+') => keys::PLUS.len(),
+ KeyCode::Char('-') => keys::MINUS.len(),
+ KeyCode::Char(';') => keys::SEMICOLON.len(),
+ KeyCode::Char('%') => keys::PERCENT.len(),
+ KeyCode::F(1..=9) => 2,
+ KeyCode::F(_) => 3,
+ KeyCode::Char(c) => c.width().unwrap_or(0),
+ };
+ if self.modifiers.contains(KeyModifiers::SHIFT) {
+ width += 2;
+ }
+ if self.modifiers.contains(KeyModifiers::ALT) {
+ width += 2;
+ }
+ if self.modifiers.contains(KeyModifiers::CONTROL) {
+ width += 2;
+ }
+ width
+ }
+
+ fn width_cjk(&self) -> usize {
+ self.width()
+ }
+}
+
impl std::str::FromStr for KeyEvent {
type Err = Error;
fn from_str(s: &str) -> Result<Self, Self::Err> {
let mut tokens: Vec<_> = s.split('-').collect();
let code = match tokens.pop().ok_or_else(|| anyhow!("Missing key code"))? {
- "backspace" => KeyCode::Backspace,
- "space" => KeyCode::Char(' '),
- "ret" => KeyCode::Enter,
- "lt" => KeyCode::Char('<'),
- "gt" => KeyCode::Char('>'),
- "plus" => KeyCode::Char('+'),
- "minus" => KeyCode::Char('-'),
- "semicolon" => KeyCode::Char(';'),
- "percent" => KeyCode::Char('%'),
- "left" => KeyCode::Left,
- "right" => KeyCode::Right,
- "up" => KeyCode::Down,
- "home" => KeyCode::Home,
- "end" => KeyCode::End,
- "pageup" => KeyCode::PageUp,
- "pagedown" => KeyCode::PageDown,
- "tab" => KeyCode::Tab,
- "backtab" => KeyCode::BackTab,
- "del" => KeyCode::Delete,
- "ins" => KeyCode::Insert,
- "null" => KeyCode::Null,
- "esc" => KeyCode::Esc,
+ keys::BACKSPACE => KeyCode::Backspace,
+ keys::ENTER => KeyCode::Enter,
+ keys::LEFT => KeyCode::Left,
+ keys::RIGHT => KeyCode::Right,
+ keys::UP => KeyCode::Up,
+ keys::DOWN => KeyCode::Down,
+ keys::HOME => KeyCode::Home,
+ keys::END => KeyCode::End,
+ keys::PAGEUP => KeyCode::PageUp,
+ keys::PAGEDOWN => KeyCode::PageDown,
+ keys::TAB => KeyCode::Tab,
+ keys::BACKTAB => KeyCode::BackTab,
+ keys::DELETE => KeyCode::Delete,
+ keys::INSERT => KeyCode::Insert,
+ keys::NULL => KeyCode::Null,
+ keys::ESC => KeyCode::Esc,
+ keys::SPACE => KeyCode::Char(' '),
+ keys::LESS_THAN => KeyCode::Char('<'),
+ keys::GREATER_THAN => KeyCode::Char('>'),
+ keys::PLUS => KeyCode::Char('+'),
+ keys::MINUS => KeyCode::Char('-'),
+ keys::SEMICOLON => KeyCode::Char(';'),
+ keys::PERCENT => KeyCode::Char('%'),
single if single.len() == 1 => KeyCode::Char(single.chars().next().unwrap()),
function if function.len() > 1 && function.starts_with('F') => {
let function: String = function.chars().skip(1).collect();