diff --git a/src/proto/colors.rs b/src/proto/colors.rs new file mode 100644 index 0000000..7da5e61 --- /dev/null +++ b/src/proto/colors.rs @@ -0,0 +1,94 @@ +//! An extension trait that provides the ability to strip IRC colors from a string +use std::borrow::Cow; + +#[derive(PartialEq)] +enum ParserState { + Text, + ColorCode, + Foreground1, + Foreground2, + Comma, + Background1, +} +struct Parser { + state: ParserState, +} + +/// An extension trait giving strings a function to strip IRC colors +pub trait FormattedStringExt { + + /// Returns true if the string contains color, bold, underline or italics + fn is_formatted(&self) -> bool; + + /// Returns the string with all color, bold, underline and italics stripped + fn strip_formatting(&self) -> Cow; + +} + + +impl FormattedStringExt for str { + fn is_formatted(&self) -> bool { + self.contains('\x02') || // bold + self.contains('\x1F') || // underline + self.contains('\x16') || // reverse + self.contains('\x0F') || // normal + self.contains('\x03') // color + } + + fn strip_formatting(&self) -> Cow { + let mut parser = Parser { + state: ParserState::Text, + }; + + let result: Cow = self + .chars() + .filter(move |cur| { + match parser.state { + ParserState::Text if *cur == '\x03' => { + parser.state = ParserState::ColorCode; + false + }, + ParserState::Text => !['\x02', '\x1F', '\x16', '\x0F'].contains(cur), + ParserState::ColorCode if (*cur).is_digit(10) => { + parser.state = ParserState::Foreground1; + false + }, + ParserState::Foreground1 if (*cur).is_digit(6) => { + parser.state = ParserState::Foreground2; + false + }, + ParserState::Foreground1 if *cur == ',' => { + parser.state = ParserState::Comma; + false + }, + ParserState::Foreground2 if *cur == ',' => { + parser.state = ParserState::Comma; + false + }, + ParserState::Comma if ((*cur).is_digit(10)) => { + parser.state = ParserState::Background1; + false + }, + ParserState::Background1 if (*cur).is_digit(6) => { + parser.state = ParserState::Text; + false + } + _ => true + } + }) + .collect(); + + result + } + + +} + +impl FormattedStringExt for String { + fn is_formatted(&self) -> bool { + (&self[..]).is_formatted() + } + fn strip_formatting(&self) -> Cow { + (&self[..]).strip_formatting() + } +} diff --git a/src/proto/mod.rs b/src/proto/mod.rs index 6d46691..e27925d 100644 --- a/src/proto/mod.rs +++ b/src/proto/mod.rs @@ -3,6 +3,7 @@ pub mod caps; pub mod chan; pub mod command; +pub mod colors; pub mod irc; pub mod line; pub mod message; @@ -11,6 +12,7 @@ pub mod response; pub use self::caps::{Capability, NegotiationVersion}; pub use self::chan::ChannelExt; +pub use self::colors::FormattedStringExt; pub use self::command::{BatchSubCommand, CapSubCommand, Command}; pub use self::irc::IrcCodec; pub use self::message::Message;