Add infobox
This commit is contained in:
parent
6ccfa229ed
commit
8985c58fd3
11 changed files with 296 additions and 78 deletions
1
Cargo.lock
generated
1
Cargo.lock
generated
|
@ -419,6 +419,7 @@ dependencies = [
|
|||
"slotmap",
|
||||
"tokio",
|
||||
"toml",
|
||||
"unicode-width",
|
||||
"url",
|
||||
"which",
|
||||
]
|
||||
|
|
|
@ -16,6 +16,7 @@ use helix_core::{
|
|||
use helix_view::{
|
||||
document::{IndentStyle, Mode},
|
||||
editor::Action,
|
||||
info::Info,
|
||||
input::KeyEvent,
|
||||
keyboard::KeyCode,
|
||||
view::{View, PADDING},
|
||||
|
@ -33,6 +34,7 @@ use movement::Movement;
|
|||
|
||||
use crate::{
|
||||
compositor::{self, Component, Compositor},
|
||||
key,
|
||||
ui::{self, Picker, Popup, Prompt, PromptEvent},
|
||||
};
|
||||
|
||||
|
@ -3400,33 +3402,88 @@ fn select_register(cx: &mut Context) {
|
|||
})
|
||||
}
|
||||
|
||||
fn space_mode(cx: &mut Context) {
|
||||
cx.on_next_key(move |cx, event| {
|
||||
if let KeyEvent {
|
||||
code: KeyCode::Char(ch),
|
||||
..
|
||||
} = event
|
||||
{
|
||||
// TODO: temporarily show SPC in the mode list
|
||||
match ch {
|
||||
'f' => file_picker(cx),
|
||||
'b' => buffer_picker(cx),
|
||||
's' => symbol_picker(cx),
|
||||
'w' => window_mode(cx),
|
||||
'y' => yank_joined_to_clipboard(cx),
|
||||
'Y' => yank_main_selection_to_clipboard(cx),
|
||||
'p' => paste_clipboard_after(cx),
|
||||
'P' => paste_clipboard_before(cx),
|
||||
'R' => replace_selections_with_clipboard(cx),
|
||||
// ' ' => toggle_alternate_buffer(cx),
|
||||
// TODO: temporary since space mode took its old key
|
||||
' ' => keep_primary_selection(cx),
|
||||
_ => (),
|
||||
}
|
||||
macro_rules! mode_info {
|
||||
// TODO: how to use one expr for both pat and expr?
|
||||
// TODO: how to use replaced function name as str at compile time?
|
||||
// TODO: extend to support multiple keys, but first solve the other two
|
||||
{$name:literal, $cx:expr, $($key:expr => $func:expr; $funcs:literal),+,} => {
|
||||
mode_info! {
|
||||
$name, $cx,
|
||||
$($key; $key => $func; $funcs,)+
|
||||
}
|
||||
})
|
||||
};
|
||||
{$name:literal, $cx:expr, $($key:expr; $keyp:pat => $func:expr; $funcs:literal),+,} => {
|
||||
$cx.editor.autoinfo = Some(Info::key(
|
||||
$name,
|
||||
vec![
|
||||
$(
|
||||
(vec![$key], $funcs),
|
||||
)+
|
||||
],
|
||||
));
|
||||
$cx.on_next_key(move |cx, event| {
|
||||
match event {
|
||||
$(
|
||||
$keyp => $func(cx),
|
||||
)+
|
||||
_ => {}
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
fn space_mode(cx: &mut Context) {
|
||||
mode_info! {
|
||||
"space mode", cx,
|
||||
key!('f'); key!('f') => file_picker; "file picker",
|
||||
key!('b'); key!('b') => buffer_picker; "buffer picker",
|
||||
key!('s'); key!('s') => symbol_picker; "symbol picker",
|
||||
key!('w'); key!('w') => window_mode; "window mode",
|
||||
key!('y'); key!('y') => yank_joined_to_clipboard; "yank joined to clipboard",
|
||||
key!('Y'); key!('Y') => yank_main_selection_to_clipboard; "yank main selection to clipboard",
|
||||
key!('p'); key!('p') => paste_clipboard_after; "paste clipboard after",
|
||||
key!('P'); key!('P') => paste_clipboard_before; "paste clipboard before",
|
||||
key!('R'); key!('R') => replace_selections_with_clipboard; "replace selections with clipboard",
|
||||
key!(' '); key!(' ') => keep_primary_selection; "keep primary selection",
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: generated, delete it later
|
||||
// fn space_mode(cx: &mut Context) {
|
||||
// cx.editor.autoinfo = Some(Info::key(
|
||||
// "space",
|
||||
// vec![
|
||||
// (vec![key!('f')], "file picker"),
|
||||
// (vec![key!('b')], "buffer picker"),
|
||||
// (vec![key!('s')], "symbol picker"),
|
||||
// (vec![key!('w')], "window mode"),
|
||||
// (vec![key!('y')], "yank joined to clipboard"),
|
||||
// (vec![key!('Y')], "yank main selection to clipboard"),
|
||||
// (vec![key!('p')], "paste clipboard after"),
|
||||
// (vec![key!('P')], "paste clipboard before"),
|
||||
// (vec![key!('R')], "replace selections with clipboard"),
|
||||
// (vec![key!(' ')], "keep primary selection"),
|
||||
// ],
|
||||
// ));
|
||||
// cx.on_next_key(move |cx, event| {
|
||||
// match event {
|
||||
// key!('f') => file_picker(cx),
|
||||
// key!('b') => buffer_picker(cx),
|
||||
// key!('s') => symbol_picker(cx),
|
||||
// key!('w') => window_mode(cx),
|
||||
// key!('y') => yank_joined_to_clipboard(cx),
|
||||
// key!('Y') => yank_main_selection_to_clipboard(cx),
|
||||
// key!('p') => paste_clipboard_after(cx),
|
||||
// key!('P') => paste_clipboard_before(cx),
|
||||
// key!('R') => replace_selections_with_clipboard(cx),
|
||||
// // key!(' ') => toggle_alternate_buffer(cx),
|
||||
// // TODO: temporary since space mode took its old key
|
||||
// key!(' ') => keep_primary_selection(cx),
|
||||
// _ => {}
|
||||
// }
|
||||
// })
|
||||
// }
|
||||
|
||||
fn view_mode(cx: &mut Context) {
|
||||
cx.on_next_key(move |cx, event| {
|
||||
if let KeyEvent {
|
||||
|
|
|
@ -105,14 +105,14 @@ use std::{
|
|||
macro_rules! key {
|
||||
($key:ident) => {
|
||||
KeyEvent {
|
||||
code: KeyCode::$key,
|
||||
modifiers: KeyModifiers::NONE,
|
||||
code: helix_view::keyboard::KeyCode::$key,
|
||||
modifiers: helix_view::keyboard::KeyModifiers::NONE,
|
||||
}
|
||||
};
|
||||
($($ch:tt)*) => {
|
||||
KeyEvent {
|
||||
code: KeyCode::Char($($ch)*),
|
||||
modifiers: KeyModifiers::NONE,
|
||||
code: helix_view::keyboard::KeyCode::Char($($ch)*),
|
||||
modifiers: helix_view::keyboard::KeyModifiers::NONE,
|
||||
}
|
||||
};
|
||||
}
|
||||
|
@ -120,8 +120,8 @@ macro_rules! key {
|
|||
macro_rules! ctrl {
|
||||
($($ch:tt)*) => {
|
||||
KeyEvent {
|
||||
code: KeyCode::Char($($ch)*),
|
||||
modifiers: KeyModifiers::CONTROL,
|
||||
code: helix_view::keyboard::KeyCode::Char($($ch)*),
|
||||
modifiers: helix_view::keyboard::KeyModifiers::CONTROL,
|
||||
}
|
||||
};
|
||||
}
|
||||
|
@ -129,8 +129,8 @@ macro_rules! ctrl {
|
|||
macro_rules! alt {
|
||||
($($ch:tt)*) => {
|
||||
KeyEvent {
|
||||
code: KeyCode::Char($($ch)*),
|
||||
modifiers: KeyModifiers::ALT,
|
||||
code: helix_view::keyboard::KeyCode::Char($($ch)*),
|
||||
modifiers: helix_view::keyboard::KeyModifiers::ALT,
|
||||
}
|
||||
};
|
||||
}
|
||||
|
|
|
@ -717,6 +717,10 @@ impl Component for EditorView {
|
|||
self.render_view(doc, view, area, surface, &cx.editor.theme, is_focused);
|
||||
}
|
||||
|
||||
if let Some(info) = std::mem::take(&mut cx.editor.autoinfo) {
|
||||
info.render(area, surface, cx);
|
||||
}
|
||||
|
||||
// render status msg
|
||||
if let Some((status_msg, severity)) = &cx.editor.status_msg {
|
||||
use helix_view::editor::Severity;
|
||||
|
@ -735,8 +739,7 @@ impl Component for EditorView {
|
|||
}
|
||||
|
||||
if let Some(completion) = &self.completion {
|
||||
completion.render(area, surface, cx)
|
||||
// render completion here
|
||||
completion.render(area, surface, cx);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
24
helix-term/src/ui/info.rs
Normal file
24
helix-term/src/ui/info.rs
Normal file
|
@ -0,0 +1,24 @@
|
|||
use crate::compositor::{Component, Context};
|
||||
use helix_view::graphics::{Margin, Rect, Style};
|
||||
use helix_view::info::Info;
|
||||
use tui::buffer::Buffer as Surface;
|
||||
use tui::widgets::{Block, Borders, Widget};
|
||||
|
||||
impl Component for Info {
|
||||
fn render(&self, viewport: Rect, surface: &mut Surface, cx: &mut Context) {
|
||||
let block = Block::default().title(self.title).borders(Borders::ALL);
|
||||
let Info { width, height, .. } = self;
|
||||
let (w, h) = (*width + 2, *height + 2);
|
||||
// -2 to subtract command line + statusline. a bit of a hack, because of splits.
|
||||
let area = Rect::new(viewport.width - w, viewport.height - h - 2, w, h);
|
||||
let margin = Margin {
|
||||
vertical: 1,
|
||||
horizontal: 1,
|
||||
};
|
||||
let Rect { x, y, .. } = area.inner(&margin);
|
||||
for (y, line) in (y..).zip(self.text.lines()) {
|
||||
surface.set_string(x, y, line, Style::default());
|
||||
}
|
||||
block.render(area, surface);
|
||||
}
|
||||
}
|
|
@ -1,5 +1,6 @@
|
|||
mod completion;
|
||||
mod editor;
|
||||
mod info;
|
||||
mod markdown;
|
||||
mod menu;
|
||||
mod picker;
|
||||
|
|
|
@ -31,6 +31,7 @@ slotmap = "1"
|
|||
|
||||
encoding_rs = "0.8"
|
||||
chardetng = "0.1"
|
||||
unicode-width = "0.1"
|
||||
|
||||
serde = { version = "1.0", features = ["derive"] }
|
||||
toml = "0.5"
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
use crate::{
|
||||
clipboard::{get_clipboard_provider, ClipboardProvider},
|
||||
graphics::{CursorKind, Rect},
|
||||
info::Info,
|
||||
theme::{self, Theme},
|
||||
tree::Tree,
|
||||
Document, DocumentId, RegisterSelection, View, ViewId,
|
||||
|
@ -32,6 +33,7 @@ pub struct Editor {
|
|||
pub syn_loader: Arc<syntax::Loader>,
|
||||
pub theme_loader: Arc<theme::Loader>,
|
||||
|
||||
pub autoinfo: Option<Info>,
|
||||
pub status_msg: Option<(String, Severity)>,
|
||||
}
|
||||
|
||||
|
@ -64,6 +66,7 @@ impl Editor {
|
|||
theme_loader: themes,
|
||||
registers: Registers::default(),
|
||||
clipboard_provider: get_clipboard_provider(),
|
||||
autoinfo: None,
|
||||
status_msg: None,
|
||||
}
|
||||
}
|
||||
|
|
51
helix-view/src/info.rs
Normal file
51
helix-view/src/info.rs
Normal file
|
@ -0,0 +1,51 @@
|
|||
use crate::input::KeyEvent;
|
||||
use std::fmt::Write;
|
||||
use unicode_width::UnicodeWidthStr;
|
||||
|
||||
#[derive(Debug)]
|
||||
/// Info box used in editor. Rendering logic will be in other crate.
|
||||
pub struct Info {
|
||||
/// Title kept as static str for now.
|
||||
pub title: &'static str,
|
||||
/// Text body, should contains newline.
|
||||
pub text: String,
|
||||
/// Body width.
|
||||
pub width: u16,
|
||||
/// Body height.
|
||||
pub height: u16,
|
||||
}
|
||||
|
||||
impl Info {
|
||||
pub fn key(title: &'static str, body: Vec<(Vec<KeyEvent>, &'static str)>) -> Info {
|
||||
let keymaps_width: u16 = body
|
||||
.iter()
|
||||
.map(|r| r.0.iter().map(|e| e.width() as u16 + 2).sum::<u16>() - 2)
|
||||
.max()
|
||||
.unwrap();
|
||||
let mut text = String::new();
|
||||
let mut width = 0;
|
||||
let height = body.len() as u16;
|
||||
for (mut keyevents, desc) in body {
|
||||
let keyevent = keyevents.remove(0);
|
||||
let mut left = keymaps_width - keyevent.width() as u16;
|
||||
write!(text, "{}", keyevent).ok();
|
||||
for keyevent in keyevents {
|
||||
write!(text, ", {}", keyevent).ok();
|
||||
left -= 2 + keyevent.width() as u16;
|
||||
}
|
||||
for _ in 0..left {
|
||||
text.push(' ');
|
||||
}
|
||||
if keymaps_width + 2 + (desc.width() as u16) > width {
|
||||
width = keymaps_width + 2 + desc.width() as u16;
|
||||
}
|
||||
writeln!(text, " {}", &desc).ok();
|
||||
}
|
||||
Info {
|
||||
title,
|
||||
text,
|
||||
width,
|
||||
height,
|
||||
}
|
||||
}
|
||||
}
|
|
@ -13,6 +13,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 +60,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 +90,83 @@ impl fmt::Display for KeyEvent {
|
|||
}
|
||||
}
|
||||
|
||||
impl unicode_width::UnicodeWidthStr for KeyEvent {
|
||||
fn width(&self) -> usize {
|
||||
use 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();
|
||||
|
|
|
@ -5,6 +5,7 @@ pub mod clipboard;
|
|||
pub mod document;
|
||||
pub mod editor;
|
||||
pub mod graphics;
|
||||
pub mod info;
|
||||
pub mod input;
|
||||
pub mod keyboard;
|
||||
pub mod register_selection;
|
||||
|
|
Loading…
Reference in a new issue