use crate::Error;
use std::borrow::Cow;
use std::fmt;
use std::str::FromStr;
const SEPARATOR: &str = ":";
const NUMBER_256: &str = "256";
const CLIPBOARD: &str = "clipboard";
const CCOLOUR: &str = "ccolour";
const CSTYLE: &str = "cstyle";
const EXTKEYS: &str = "extkeys";
const FOCUS: &str = "focus";
const HYPERLINKS: &str = "hyperlinks";
const IGNOREFKEYS: &str = "ignorefkeys";
const MARGINS: &str = "margins";
const MOUSE: &str = "mouse";
const OSC7: &str = "osc7";
const OVERLINE: &str = "overline";
const RECTFILL: &str = "rectfill";
const RGB: &str = "RGB";
const SIXEL: &str = "sixel";
const STRIKETHROUGH: &str = "strikethrough";
const SYNC: &str = "sync";
const TITLE: &str = "title";
const USSTYLE: &str = "usstyle";
#[derive(Default, PartialEq, Clone, Debug)]
pub struct TerminalFeatures<'a> {
pub terminal_type: Cow<'a, str>,
pub colours256: bool,
pub clipboard: bool,
pub ccolour: bool,
pub cstyle: bool,
pub extkeys: bool,
pub focus: bool,
pub hyperlinks: bool,
pub ignorefkeys: bool,
pub margins: bool,
pub mouse: bool,
pub osc7: bool,
pub overline: bool,
pub rectfill: bool,
pub rgb: bool,
pub sixel: bool,
pub strikethrough: bool,
pub sync: bool,
pub title: bool,
pub usstyle: bool,
}
impl<'a> fmt::Display for TerminalFeatures<'a> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
let mut v = Vec::new();
if self.colours256 {
v.push(NUMBER_256);
}
if self.clipboard {
v.push(CLIPBOARD);
}
if self.clipboard {
v.push(CLIPBOARD);
}
if self.ccolour {
v.push(CCOLOUR);
}
if self.cstyle {
v.push(CSTYLE);
}
if self.extkeys {
v.push(EXTKEYS);
}
if self.focus {
v.push(FOCUS);
}
if self.hyperlinks {
v.push(HYPERLINKS);
}
if self.ignorefkeys {
v.push(IGNOREFKEYS);
}
if self.margins {
v.push(MARGINS);
}
if self.mouse {
v.push(MOUSE);
}
if self.osc7 {
v.push(OSC7);
}
if self.overline {
v.push(OVERLINE);
}
if self.rectfill {
v.push(RECTFILL);
}
if self.rgb {
v.push(RGB);
}
if self.sixel {
v.push(SIXEL);
}
if self.strikethrough {
v.push(STRIKETHROUGH);
}
if self.sync {
v.push(SYNC);
}
if self.title {
v.push(TITLE);
}
if self.usstyle {
v.push(USSTYLE);
}
let s = v.join(":");
write!(f, "{}:{}", self.terminal_type, s)
}
}
impl<'a> TerminalFeatures<'a> {
pub fn new() -> Self {
Default::default()
}
pub fn terminal_type<S: Into<Cow<'a, str>>>(&mut self, terminal_type: S) -> &mut Self {
self.terminal_type = terminal_type.into();
self
}
pub fn _256(&mut self, flag: bool) -> &mut Self {
self.colours256 = flag;
self
}
pub fn clipboard(&mut self, flag: bool) -> &mut Self {
self.clipboard = flag;
self
}
pub fn ccolour(&mut self, flag: bool) -> &mut Self {
self.ccolour = flag;
self
}
pub fn cstyle(&mut self, flag: bool) -> &mut Self {
self.cstyle = flag;
self
}
pub fn extkeys(&mut self, flag: bool) -> &mut Self {
self.extkeys = flag;
self
}
pub fn focus(&mut self, flag: bool) -> &mut Self {
self.focus = flag;
self
}
pub fn hyperlinks(&mut self, flag: bool) -> &mut Self {
self.hyperlinks = flag;
self
}
pub fn ignorefkeys(&mut self, flag: bool) -> &mut Self {
self.ignorefkeys = flag;
self
}
pub fn margins(&mut self, flag: bool) -> &mut Self {
self.margins = flag;
self
}
pub fn mouse(&mut self, flag: bool) -> &mut Self {
self.mouse = flag;
self
}
pub fn osc7(&mut self, flag: bool) -> &mut Self {
self.osc7 = flag;
self
}
pub fn overline(&mut self, flag: bool) -> &mut Self {
self.overline = flag;
self
}
pub fn rectfill(&mut self, flag: bool) -> &mut Self {
self.rectfill = flag;
self
}
pub fn rgb(&mut self, flag: bool) -> &mut Self {
self.rgb = flag;
self
}
pub fn sixel(&mut self, flag: bool) -> &mut Self {
self.sixel = flag;
self
}
pub fn strikethrough(&mut self, flag: bool) -> &mut Self {
self.strikethrough = flag;
self
}
pub fn sync(&mut self, flag: bool) -> &mut Self {
self.sync = flag;
self
}
pub fn title(&mut self, flag: bool) -> &mut Self {
self.title = flag;
self
}
pub fn usstyle(&mut self, flag: bool) -> &mut Self {
self.usstyle = flag;
self
}
}
impl<'a> FromStr for TerminalFeatures<'a> {
type Err = Error;
fn from_str(s: &str) -> Result<Self, Self::Err> {
let mut tf = TerminalFeatures::default();
let v: Vec<&str> = s.trim().splitn(2, SEPARATOR).collect();
tf.terminal_type = v[0].to_owned().into();
let v: Vec<&str> = v[1].split(SEPARATOR).collect();
for feature in v {
match feature {
NUMBER_256 => tf.colours256 = true,
CLIPBOARD => tf.clipboard = true,
CCOLOUR => tf.ccolour = true,
CSTYLE => tf.cstyle = true,
EXTKEYS => tf.extkeys = true,
FOCUS => tf.focus = true,
HYPERLINKS => tf.hyperlinks = true,
IGNOREFKEYS => tf.ignorefkeys = true,
MARGINS => tf.margins = true,
MOUSE => tf.mouse = true,
OSC7 => tf.osc7 = true,
OVERLINE => tf.overline = true,
RECTFILL => tf.rectfill = true,
RGB => tf.rgb = true,
SIXEL => tf.sixel = true,
STRIKETHROUGH => tf.strikethrough = true,
SYNC => tf.sync = true,
TITLE => tf.title = true,
USSTYLE => tf.usstyle = true,
_ => return Err(Error::ParseTerminalFeatures),
}
}
Ok(tf)
}
}