diff options
| author | Skye <[email protected]> | 2017-05-31 04:30:03 +0100 |
|---|---|---|
| committer | Zeyla Hellyer <[email protected]> | 2017-05-30 20:30:03 -0700 |
| commit | 060b06ec62b1f4e4cc2c11b877fd988b7dcfe627 (patch) | |
| tree | c7ecaa61abfae69093a13920f53867f078a64928 /src/utils | |
| parent | Don't create group in help if no commands to show (diff) | |
| download | serenity-060b06ec62b1f4e4cc2c11b877fd988b7dcfe627.tar.xz serenity-060b06ec62b1f4e4cc2c11b877fd988b7dcfe627.zip | |
Add Content for MessageBuilder
Allow `push` and `push_safe` to use a flexible syntax for formatting.
Diffstat (limited to 'src/utils')
| -rw-r--r-- | src/utils/message_builder.rs | 203 | ||||
| -rw-r--r-- | src/utils/mod.rs | 3 |
2 files changed, 195 insertions, 11 deletions
diff --git a/src/utils/message_builder.rs b/src/utils/message_builder.rs index 164c856..9132f9d 100644 --- a/src/utils/message_builder.rs +++ b/src/utils/message_builder.rs @@ -1,5 +1,6 @@ use std::default::Default; -use std::fmt::{self, Write}; +use std::fmt::{self, Write, Display}; +use std::ops::Add; use ::model::{ChannelId, Emoji, Mentionable, RoleId, UserId}; /// The Message Builder is an ergonomic utility to easily build a message, @@ -192,8 +193,9 @@ impl MessageBuilder { /// /// assert_eq!(message.push("ing").0, "testing"); /// ``` - pub fn push(mut self, content: &str) -> Self { - self.0.push_str(content); + pub fn push<T: Into<Content>>(mut self, content: T) -> Self { + let content = content.into(); + self.0.push_str(&content.to_string()); self } @@ -354,7 +356,7 @@ impl MessageBuilder { /// /// assert_eq!(content, "hello\nworld"); /// ``` - pub fn push_line(mut self, content: &str) -> Self { + pub fn push_line<T: Into<Content>>(mut self, content: T) -> Self { self = self.push(content); self.0.push('\n'); @@ -463,13 +465,14 @@ impl MessageBuilder { /// Pushes text to your message, but normalizing content - that means /// ensuring that there's no unwanted formatting, mention spam etc. - pub fn push_safe(mut self, content: &str) -> Self { - let normalized = normalize(content) + pub fn push_safe<T: Into<Content>>(mut self, content: T) -> Self { + let mut content: Content = content.into(); + content.inner = normalize(&content.inner) .replace('*', "\\*") .replace('`', "\\`") .replace('_', "\\_"); - self.0.push_str(&normalized); + self.0.push_str(&content.to_string()); self } @@ -551,7 +554,7 @@ impl MessageBuilder { /// /// assert_eq!(content, "Hello @\u{200B}everyone\nHow are you?"); /// ``` - pub fn push_line_safe(mut self, content: &str) -> Self { + pub fn push_line_safe<T: Into<Content>>(mut self, content: T) -> Self { self = self.push_safe(content); self.0.push('\n'); @@ -703,7 +706,7 @@ impl MessageBuilder { } } -impl fmt::Display for MessageBuilder { +impl Display for MessageBuilder { /// Formats the message builder into a string. /// /// This is done by simply taking the internal value of the tuple-struct and @@ -723,6 +726,188 @@ impl fmt::Display for MessageBuilder { } } + +/// Formatting modifiers for MessageBuilder content pushes +/// +/// Provides an enum of formatting modifiers for a string, for combination with +/// string types and Content types. +/// +/// # Examples +/// +/// Create a new Content type which describes a bold-italic "text": +/// +/// ```rust,no_run +/// use serenity::utils::ContentModifier::{Bold, Italic}; +/// use serenity::utils::Content; +/// let content: Content = Bold + Italic + "text"; +/// ``` +pub enum ContentModifier { + Italic, + Bold, + Strikethrough, + Code, + Underline, +} + +/// Describes formatting on string content +#[derive(Default, Clone)] +pub struct Content { + pub italic: bool, + pub bold: bool, + pub strikethrough: bool, + pub inner: String, + pub code: bool, + pub underline: bool +} + +impl<T: ToString> Add<T> for Content { + type Output = Content; + + fn add(self, rhs: T) -> Content { + let mut nc = self.clone(); + nc.inner = nc.inner + &rhs.to_string(); + + nc + } +} + +impl<T: ToString> Add<T> for ContentModifier { + type Output = Content; + + fn add(self, rhs: T) -> Content { + let mut nc = self.to_content(); + nc.inner = nc.inner + &rhs.to_string(); + + nc + } +} + +impl Add<ContentModifier> for Content { + type Output = Content; + + fn add(self, rhs: ContentModifier) -> Content { + let mut nc = self.clone(); + nc.apply(&rhs); + + nc + } +} + +impl Add<ContentModifier> for ContentModifier { + type Output = Content; + + fn add(self, rhs: ContentModifier) -> Content { + let mut nc = self.to_content(); + nc.apply(&rhs); + + nc + } +} + +impl ContentModifier { + fn to_content(&self) -> Content { + let mut nc = Content::default(); + nc.apply(self); + + nc + } +} + +impl Content { + pub fn apply(&mut self, modifier: &ContentModifier) { + match *modifier { + ContentModifier::Italic => { + self.italic = true; + }, + ContentModifier::Bold => { + self.bold = true; + }, + ContentModifier::Strikethrough => { + self.strikethrough = true; + }, + ContentModifier::Code => { + self.code = true; + }, + ContentModifier::Underline => { + self.underline = true; + }, + } + } + + pub fn to_string(&self) -> String { + let capacity = self.inner.len() + + if self.bold { 4 } else { 0 } + + if self.italic { 2 } else { 0 } + + if self.strikethrough { 4 } else { 0 } + + if self.underline { 4 } else { 0 } + + if self.code { 2 } else { 0 }; + let mut new_str = String::with_capacity(capacity); + + if self.bold { + new_str.push_str("**"); + } + + if self.italic { + new_str.push('*'); + } + + if self.strikethrough { + new_str.push_str("~~"); + } + + if self.underline { + new_str.push_str("__"); + } + + if self.code { + new_str.push('`'); + } + + new_str.push_str(&self.inner); + + if self.code { + new_str.push('`'); + } + + if self.underline { + new_str.push_str("__"); + } + + if self.strikethrough { + new_str.push_str("~~"); + } + + if self.italic { + new_str.push('*'); + } + + if self.bold { + new_str.push_str("**"); + } + + new_str + } +} + +impl From<ContentModifier> for Content { + fn from(cm: ContentModifier) -> Content { + cm.to_content() + } +} + +impl<T: ToString> From<T> for Content { + fn from(stringer: T) -> Content { + Content { + italic: false, + bold: false, + strikethrough: false, + inner: stringer.to_string(), + code: false, + underline: false, + } + } +} + fn normalize(text: &str) -> String { // Remove invite links and popular scam websites, mostly to prevent the // current user from triggering various ad detectors and prevent embeds. diff --git a/src/utils/mod.rs b/src/utils/mod.rs index 0ca3e65..d3d728a 100644 --- a/src/utils/mod.rs +++ b/src/utils/mod.rs @@ -6,6 +6,7 @@ mod colour; mod message_builder; pub use self::colour::Colour; +pub use self::message_builder::{MessageBuilder, Content, ContentModifier}; // Note: Here for BC purposes. #[cfg(feature="builder")] @@ -19,8 +20,6 @@ use std::path::Path; use ::internal::prelude::*; use ::model::{EmojiIdentifier, EmojiId}; -pub use self::message_builder::MessageBuilder; - /// Determines if a name is NSFW. /// /// This checks that the name is either `"nsfw"` or, for names longer than that, |