use std::fmt;
use std::io;
use std::io::prelude::*;
#[derive(Clone)]
pub enum TuiInstr {
Signal(String),
Search(String),
Error(String, String),
}
impl TuiInstr {
pub fn height(&self) -> usize {
match self {
TuiInstr::Signal(_) => 3,
TuiInstr::Search(_) => 1,
TuiInstr::Error(_, _) => 1,
}
}
pub fn total_height(instrs: &[TuiInstr]) -> usize {
let mut h = 0;
for instr in instrs {
h += instr.height()
}
h
}
fn parse_line(line: &str) -> TuiInstr {
let v: Vec<&str> = line.splitn(2, ' ').collect();
if v.len() != 2 {
return TuiInstr::Error(line.to_string(), "Syntax Error".to_string());
}
let instr = v.first().unwrap();
let arg = v.last().unwrap().to_string();
match *instr {
"signal" => TuiInstr::Signal(arg),
"search" => TuiInstr::Search(arg),
_ => TuiInstr::Error(line.to_string(), format!("Unknown command '{}'", instr)),
}
}
pub fn parse<I: BufRead>(input: I) -> Vec<TuiInstr> {
let mut instrs = Vec::new();
for line in input.lines() {
let s = line.unwrap();
if let Some('#') = s.chars().next() {
continue;
}
if !s.is_empty() {
instrs.push(TuiInstr::parse_line(&s))
}
}
instrs
}
pub fn format_instrs<O: io::Write>(instrs: &[TuiInstr], output: &mut O) {
for instr in instrs {
let _ = writeln!(output, "{}", instr);
}
}
}
impl fmt::Display for TuiInstr {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
TuiInstr::Signal(s) => write!(f, "signal {}", s),
TuiInstr::Search(s) => write!(f, "search {}", s),
TuiInstr::Error(s, _) => write!(f, "{}", s),
}?;
Ok(())
}
}
impl PartialEq for TuiInstr {
fn eq(&self, other: &Self) -> bool {
match (self, other) {
(TuiInstr::Signal(a), TuiInstr::Signal(b)) => a == b,
(TuiInstr::Search(a), TuiInstr::Search(b)) => a == b,
(TuiInstr::Error(la, ma), TuiInstr::Error(lb, mb)) => la == lb && ma == mb,
_ => false,
}
}
}