#![cfg(any(feature = "bash", feature = "fish", feature = "sh"))]
use std::borrow::Borrow;
#[derive(PartialEq)]
pub(crate) enum Char {
Bell,
Backspace,
Escape,
FormFeed,
NewLine,
CarriageReturn,
HorizontalTab,
VerticalTab,
Control(u8),
Backslash,
SingleQuote,
DoubleQuote,
Delete,
PrintableInert(u8),
Printable(u8),
Extended(u8),
}
impl Char {
pub fn from<T: Borrow<u8>>(ch: T) -> Self {
let ch = *ch.borrow();
use Char::*;
match ch {
BEL => Bell,
BS => Backspace,
ESC => Escape,
FF => FormFeed,
LF => NewLine,
CR => CarriageReturn,
TAB => HorizontalTab,
VT => VerticalTab,
0x00..=0x06 | 0x0E..=0x1A | 0x1C..=0x1F => Control(ch),
b'\\' => Backslash,
b'\'' => SingleQuote,
b'\"' => DoubleQuote,
DEL => Delete,
b'a'..=b'z' | b'A'..=b'Z' | b'0'..=b'9' => PrintableInert(ch),
b',' | b'.' | b'/' | b'_' | b'-' => PrintableInert(ch),
b'|' | b'&' | b';' | b'(' | b')' | b'<' | b'>' => Printable(ch),
b' ' | b'?' | b'[' | b']' | b'{' | b'}' | b'`' => Printable(ch),
b'~' | b'!' | b'$' | b'@' | b'+' | b'=' | b'*' => Printable(ch),
b'%' | b'#' | b':' | b'^' => Printable(ch),
0x80..=0xff => Extended(ch),
}
}
#[inline]
pub fn is_inert(&self) -> bool {
matches!(self, Char::PrintableInert(_))
}
#[inline]
#[cfg(feature = "sh")]
pub fn code(&self) -> u8 {
use Char::*;
match *self {
Bell => BEL,
Backspace => BS,
Escape => ESC,
FormFeed => FF,
NewLine => LF,
CarriageReturn => CR,
HorizontalTab => TAB,
VerticalTab => VT,
Control(ch) => ch,
Backslash => b'\\',
SingleQuote => b'\'',
DoubleQuote => b'"',
Delete => DEL,
PrintableInert(ch) => ch,
Printable(ch) => ch,
Extended(ch) => ch,
}
}
}
const BEL: u8 = 0x07; const BS: u8 = 0x08; const TAB: u8 = 0x09; const LF: u8 = 0x0A; const VT: u8 = 0x0B; const FF: u8 = 0x0C; const CR: u8 = 0x0D; const ESC: u8 = 0x1B; const DEL: u8 = 0x7F;
#[cfg(test)]
mod tests {
#[test]
#[cfg(feature = "sh")]
fn test_code() {
for ch in u8::MIN..=u8::MAX {
let char = super::Char::from(ch);
assert_eq!(ch, char.code());
}
}
}