use smallvec::smallvec;
use std::ops::Deref;
use kas::event::{VirtualKeyCode as VK, VirtualKeyCodes};
pub type CowStringL<'a> = std::borrow::Cow<'a, str>;
pub type CowString = CowStringL<'static>;
#[derive(Clone, Debug, Default, PartialEq)]
pub struct LabelString {
label: CowString,
}
impl LabelString {
pub fn parse(mut s: &str) -> Self {
let mut buf = String::with_capacity(s.len());
while let Some(mut i) = s.find("&") {
buf.push_str(&s[..i]);
i += "&".len();
s = &s[i..];
match s.chars().next() {
None => {
s = &s[0..0];
break;
}
Some(c) => {
buf.push(c);
let i = c.len_utf8();
s = &s[i..];
}
}
}
buf.push_str(s);
LabelString { label: buf.into() }
}
}
impl From<CowString> for LabelString {
fn from(input: CowString) -> Self {
if input.as_bytes().contains(&b'&') {
Self::parse(&input)
} else {
LabelString { label: input }
}
}
}
impl From<&'static str> for LabelString {
fn from(input: &'static str) -> Self {
CowString::from(input).into()
}
}
impl From<String> for LabelString {
fn from(input: String) -> Self {
CowString::from(input).into()
}
}
impl Deref for LabelString {
type Target = str;
fn deref(&self) -> &str {
&self.label
}
}
#[derive(Clone, Debug, Default, PartialEq)]
pub struct AccelString {
label: CowString,
underlined: CowString,
keys: VirtualKeyCodes,
}
impl AccelString {
pub fn parse(mut s: &str) -> Self {
let mut buf = String::with_capacity(s.len());
let underline = '\u{0332}';
let mut bufu = String::with_capacity(s.len() + underline.len_utf8() - "&".len());
let mut keys = VirtualKeyCodes::new();
while let Some(mut i) = s.find("&") {
buf.push_str(&s[..i]);
bufu.push_str(&s[..i]);
i += "&".len();
s = &s[i..];
match s.chars().next() {
None => {
s = &s[0..0];
break;
}
Some(c) => {
buf.push(c);
bufu.push(c);
let vkeys = find_vkeys(c);
if !vkeys.is_empty() {
keys.extend(vkeys);
bufu.push(underline);
}
let i = c.len_utf8();
s = &s[i..];
}
}
}
buf.push_str(s);
bufu.push_str(s);
AccelString {
label: buf.into(),
underlined: bufu.into(),
keys,
}
}
pub fn keys(&self) -> &[VK] {
&self.keys
}
pub fn get(&self, show_labels: bool) -> &str {
if show_labels {
&self.underlined
} else {
&self.label
}
}
}
impl From<CowString> for AccelString {
fn from(input: CowString) -> Self {
if input.as_bytes().contains(&b'&') {
Self::parse(&input)
} else {
AccelString {
label: input.clone(),
underlined: input,
keys: Default::default(),
}
}
}
}
impl From<&'static str> for AccelString {
fn from(input: &'static str) -> Self {
CowString::from(input).into()
}
}
impl From<String> for AccelString {
fn from(input: String) -> Self {
CowString::from(input).into()
}
}
fn find_vkeys(c: char) -> VirtualKeyCodes {
match c.to_ascii_uppercase() {
'\'' => smallvec![VK::Apostrophe],
'+' => smallvec![VK::Add],
',' => smallvec![VK::Comma],
'-' => smallvec![VK::Minus],
'.' => smallvec![VK::Period],
'/' => smallvec![VK::Slash],
'0' => smallvec![VK::Key0, VK::Numpad0],
'1' => smallvec![VK::Key1, VK::Numpad1],
'2' => smallvec![VK::Key2, VK::Numpad2],
'3' => smallvec![VK::Key3, VK::Numpad3],
'4' => smallvec![VK::Key4, VK::Numpad4],
'5' => smallvec![VK::Key5, VK::Numpad5],
'6' => smallvec![VK::Key6, VK::Numpad6],
'7' => smallvec![VK::Key7, VK::Numpad7],
'8' => smallvec![VK::Key8, VK::Numpad8],
'9' => smallvec![VK::Key9, VK::Numpad9],
':' => smallvec![VK::Colon],
';' => smallvec![VK::Semicolon],
'=' => smallvec![VK::Equals, VK::NumpadEquals],
'`' => smallvec![VK::Grave],
'A' => smallvec![VK::A],
'B' => smallvec![VK::B],
'C' => smallvec![VK::C],
'D' => smallvec![VK::D],
'E' => smallvec![VK::E],
'F' => smallvec![VK::F],
'G' => smallvec![VK::G],
'H' => smallvec![VK::H],
'I' => smallvec![VK::I],
'J' => smallvec![VK::J],
'K' => smallvec![VK::K],
'L' => smallvec![VK::L],
'M' => smallvec![VK::M],
'N' => smallvec![VK::N],
'O' => smallvec![VK::O],
'P' => smallvec![VK::P],
'Q' => smallvec![VK::Q],
'R' => smallvec![VK::R],
'S' => smallvec![VK::S],
'T' => smallvec![VK::T],
'U' => smallvec![VK::U],
'V' => smallvec![VK::V],
'W' => smallvec![VK::W],
'X' => smallvec![VK::X],
'Y' => smallvec![VK::Y],
'Z' => smallvec![VK::Z],
'[' => smallvec![VK::LBracket],
']' => smallvec![VK::RBracket],
'^' => smallvec![VK::Caret],
'÷' => smallvec![VK::Divide],
'×' => smallvec![VK::Multiply],
'−' => smallvec![VK::Subtract],
_ => smallvec![],
}
}