diff options
Diffstat (limited to 'vendor/anstyle/src/effect.rs')
-rw-r--r-- | vendor/anstyle/src/effect.rs | 369 |
1 files changed, 369 insertions, 0 deletions
diff --git a/vendor/anstyle/src/effect.rs b/vendor/anstyle/src/effect.rs new file mode 100644 index 0000000..56b3e61 --- /dev/null +++ b/vendor/anstyle/src/effect.rs @@ -0,0 +1,369 @@ +/// A set of text effects +/// +/// # Examples +/// +/// ```rust +/// let effects = anstyle::Effects::BOLD | anstyle::Effects::UNDERLINE; +/// ``` +#[derive(Copy, Clone, Default, PartialEq, Eq, PartialOrd, Ord, Hash)] +pub struct Effects(u16); + +impl Effects { + const PLAIN: Self = Effects(0); + + pub const BOLD: Self = Effects(1 << 0); + pub const DIMMED: Self = Effects(1 << 1); + /// Not widely supported. Sometimes treated as inverse or blink + pub const ITALIC: Self = Effects(1 << 2); + /// Style extensions exist for Kitty, VTE, mintty and iTerm2. + pub const UNDERLINE: Self = Effects(1 << 3); + pub const DOUBLE_UNDERLINE: Self = Effects(1 << 4); + pub const CURLY_UNDERLINE: Self = Effects(1 << 5); + pub const DOTTED_UNDERLINE: Self = Effects(1 << 6); + pub const DASHED_UNDERLINE: Self = Effects(1 << 7); + pub const BLINK: Self = Effects(1 << 8); + /// Swap foreground and background colors; inconsistent emulation + pub const INVERT: Self = Effects(1 << 9); + pub const HIDDEN: Self = Effects(1 << 10); + /// Characters legible but marked as if for deletion. Not supported in Terminal.app + pub const STRIKETHROUGH: Self = Effects(1 << 11); + + /// No effects enabled + /// + /// # Examples + /// + /// ```rust + /// let effects = anstyle::Effects::new(); + /// ``` + #[inline] + pub const fn new() -> Self { + Self::PLAIN + } + + /// Check if no effects are enabled + /// + /// # Examples + /// + /// ```rust + /// let effects = anstyle::Effects::new(); + /// assert!(effects.is_plain()); + /// + /// let effects = anstyle::Effects::BOLD | anstyle::Effects::UNDERLINE; + /// assert!(!effects.is_plain()); + /// ``` + #[inline] + pub const fn is_plain(self) -> bool { + self.0 == Self::PLAIN.0 + } + + /// Returns `true` if all of the effects in `other` are contained within `self`. + /// + /// # Examples + /// + /// ```rust + /// let effects = anstyle::Effects::BOLD | anstyle::Effects::UNDERLINE; + /// assert!(effects.contains(anstyle::Effects::BOLD)); + /// + /// let effects = anstyle::Effects::new(); + /// assert!(!effects.contains(anstyle::Effects::BOLD)); + /// ``` + #[inline(always)] + pub const fn contains(self, other: Effects) -> bool { + (other.0 & self.0) == other.0 + } + + /// Inserts the specified effects in-place. + /// + /// # Examples + /// + /// ```rust + /// let effects = anstyle::Effects::new().insert(anstyle::Effects::new()); + /// assert!(effects.is_plain()); + /// + /// let effects = anstyle::Effects::new().insert(anstyle::Effects::BOLD); + /// assert!(effects.contains(anstyle::Effects::BOLD)); + /// ``` + #[inline(always)] + #[must_use] + pub const fn insert(mut self, other: Effects) -> Self { + self.0 |= other.0; + self + } + + /// Removes the specified effects in-place. + /// + /// # Examples + /// + /// ```rust + /// let effects = (anstyle::Effects::BOLD | anstyle::Effects::UNDERLINE).remove(anstyle::Effects::BOLD); + /// assert!(!effects.contains(anstyle::Effects::BOLD)); + /// assert!(effects.contains(anstyle::Effects::UNDERLINE)); + /// ``` + #[inline(always)] + #[must_use] + pub const fn remove(mut self, other: Effects) -> Self { + self.0 &= !other.0; + self + } + + /// Reset all effects in-place + /// ```rust + /// let effects = (anstyle::Effects::BOLD | anstyle::Effects::UNDERLINE).clear(); + /// assert!(!effects.contains(anstyle::Effects::BOLD)); + /// assert!(!effects.contains(anstyle::Effects::UNDERLINE)); + /// ``` + #[inline(always)] + #[must_use] + pub const fn clear(self) -> Self { + Self::new() + } + + /// Enable or disable the specified effects depending on the passed value. + /// + /// # Examples + /// + /// ```rust + /// let effects = anstyle::Effects::new().set(anstyle::Effects::BOLD, true); + /// assert!(effects.contains(anstyle::Effects::BOLD)); + /// ``` + #[inline] + #[must_use] + pub const fn set(self, other: Self, enable: bool) -> Self { + if enable { + self.insert(other) + } else { + self.remove(other) + } + } + + /// Iterate over enabled effects + #[inline(always)] + pub fn iter(self) -> EffectIter { + EffectIter { + index: 0, + effects: self, + } + } + + /// Iterate over enabled effect indices + #[inline(always)] + pub(crate) fn index_iter(self) -> EffectIndexIter { + EffectIndexIter { + index: 0, + effects: self, + } + } + + /// Render the ANSI code + #[inline] + pub fn render(self) -> impl core::fmt::Display + Copy + Clone { + EffectsDisplay(self) + } + + #[inline] + #[cfg(feature = "std")] + pub(crate) fn write_to(self, write: &mut dyn std::io::Write) -> std::io::Result<()> { + for index in self.index_iter() { + write.write_all(METADATA[index].escape.as_bytes())?; + } + Ok(()) + } +} + +/// # Examples +/// +/// ```rust +/// let effects = anstyle::Effects::new(); +/// assert_eq!(format!("{:?}", effects), "Effects()"); +/// +/// let effects = anstyle::Effects::BOLD | anstyle::Effects::UNDERLINE; +/// assert_eq!(format!("{:?}", effects), "Effects(BOLD | UNDERLINE)"); +/// ``` +impl core::fmt::Debug for Effects { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + write!(f, "Effects(")?; + for (i, index) in self.index_iter().enumerate() { + if i != 0 { + write!(f, " | ")?; + } + write!(f, "{}", METADATA[index].name)?; + } + write!(f, ")")?; + Ok(()) + } +} + +/// # Examples +/// +/// ```rust +/// let effects = anstyle::Effects::BOLD | anstyle::Effects::UNDERLINE; +/// assert_eq!(format!("{:?}", effects), "Effects(BOLD | UNDERLINE)"); +/// ``` +impl core::ops::BitOr for Effects { + type Output = Self; + + #[inline(always)] + fn bitor(self, rhs: Self) -> Self { + self.insert(rhs) + } +} + +/// # Examples +/// +/// ```rust +/// let mut effects = anstyle::Effects::BOLD; +/// effects |= anstyle::Effects::UNDERLINE; +/// assert_eq!(format!("{:?}", effects), "Effects(BOLD | UNDERLINE)"); +/// ``` +impl core::ops::BitOrAssign for Effects { + #[inline] + fn bitor_assign(&mut self, other: Self) { + *self = self.insert(other); + } +} + +/// # Examples +/// +/// ```rust +/// let effects = (anstyle::Effects::BOLD | anstyle::Effects::UNDERLINE) - anstyle::Effects::BOLD; +/// assert_eq!(format!("{:?}", effects), "Effects(UNDERLINE)"); +/// ``` +impl core::ops::Sub for Effects { + type Output = Self; + + #[inline] + fn sub(self, other: Self) -> Self { + self.remove(other) + } +} + +/// # Examples +/// +/// ```rust +/// let mut effects = anstyle::Effects::BOLD | anstyle::Effects::UNDERLINE; +/// effects -= anstyle::Effects::BOLD; +/// assert_eq!(format!("{:?}", effects), "Effects(UNDERLINE)"); +/// ``` +impl core::ops::SubAssign for Effects { + #[inline] + fn sub_assign(&mut self, other: Self) { + *self = self.remove(other); + } +} + +pub(crate) struct Metadata { + pub(crate) name: &'static str, + pub(crate) escape: &'static str, +} + +pub(crate) const METADATA: [Metadata; 12] = [ + Metadata { + name: "BOLD", + escape: escape!("1"), + }, + Metadata { + name: "DIMMED", + escape: escape!("2"), + }, + Metadata { + name: "ITALIC", + escape: escape!("3"), + }, + Metadata { + name: "UNDERLINE", + escape: escape!("4"), + }, + Metadata { + name: "DOUBLE_UNDERLINE", + escape: escape!("21"), + }, + Metadata { + name: "CURLY_UNDERLINE", + escape: escape!("4:3"), + }, + Metadata { + name: "DOTTED_UNDERLINE", + escape: escape!("4:4"), + }, + Metadata { + name: "DASHED_UNDERLINE", + escape: escape!("4:5"), + }, + Metadata { + name: "BLINK", + escape: escape!("5"), + }, + Metadata { + name: "INVERT", + escape: escape!("7"), + }, + Metadata { + name: "HIDDEN", + escape: escape!("8"), + }, + Metadata { + name: "STRIKETHROUGH", + escape: escape!("9"), + }, +]; + +#[derive(Copy, Clone, Default, Debug)] +struct EffectsDisplay(Effects); + +impl core::fmt::Display for EffectsDisplay { + #[inline] + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + for index in self.0.index_iter() { + METADATA[index].escape.fmt(f)?; + } + Ok(()) + } +} + +#[derive(Clone, Debug, PartialEq, Eq)] +pub struct EffectIter { + index: usize, + effects: Effects, +} + +impl Iterator for EffectIter { + type Item = Effects; + + fn next(&mut self) -> Option<Self::Item> { + while self.index < METADATA.len() { + let index = self.index; + self.index += 1; + + let effect = Effects(1 << index); + if self.effects.contains(effect) { + return Some(effect); + } + } + + None + } +} + +#[derive(Clone, Debug, PartialEq, Eq)] +pub(crate) struct EffectIndexIter { + index: usize, + effects: Effects, +} + +impl Iterator for EffectIndexIter { + type Item = usize; + + fn next(&mut self) -> Option<Self::Item> { + while self.index < METADATA.len() { + let index = self.index; + self.index += 1; + + let effect = Effects(1 << index); + if self.effects.contains(effect) { + return Some(index); + } + } + + None + } +} |