Skip to content

Commit

Permalink
break style collection apart and disable fluent calls in Python
Browse files Browse the repository at this point in the history
  • Loading branch information
apparebit committed Aug 26, 2024
1 parent db5db98 commit 9f0708f
Show file tree
Hide file tree
Showing 2 changed files with 206 additions and 35 deletions.
62 changes: 60 additions & 2 deletions prettypretty/color/style.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -140,7 +140,7 @@ class TerminalColor_Gray(TerminalColor):
def color(self) -> GrayGradient: ...


class TerminalColor_Bits24(TerminalColor):
class TerminalColor_Full(TerminalColor):
"""24-bit RGB colors."""
def __new__(cls, color: TrueColor) -> Self: ...
@property
Expand All @@ -153,7 +153,7 @@ class TerminalColor:
Ansi = TerminalColor_Ansi
Embedded = TerminalColor_Embedded
Gray = TerminalColor_Gray
Bits24 = TerminalColor_Bits24
Full = TerminalColor_Full

@staticmethod
def from_8bit(color: int) -> TerminalColor: ...
Expand Down Expand Up @@ -256,6 +256,9 @@ class Formatting:
def formats(self) -> Iterator[Format]: ...
def __invert__(self) -> Self: ...
def __sub__(self, other: Self) -> Self: ...
def __hash__(self) -> int: ...
def __eq__(self, other: object) -> bool: ...
def __ne__(self, other: object) -> bool: ...


class Style_Reset(Style):
Expand All @@ -274,12 +277,67 @@ class Style_Background(Style):
def __new__(cls, background: TerminalColor) -> Self: ...


class Style_HiResFore(Style):
def __new__(cls, foreground: Color) -> Self: ...


class Style_HiResBack(Style):
def __new__(cls, background: Color) -> Self: ...


class Style:
"""The enum of all terminal styles."""
Reset = Style_Reset
Text = Style_Text
Foreground = Style_Foreground
Background = Style_Background
HiResFore = Style_HiResFore
HiResBack = Style_HiResBack

def fidelity(self) -> Fidelity: ...
def __hash__(self) -> int: ...
def __eq__(self, other: object) -> bool: ...
def __ne__(self, other: object) -> bool: ...


def style() -> StyleCollection: ...
# Create a new, empty style collection. Idiomatic use starts with this
# method, followed by fluent style selections.


class StyleCollection:
"""A combination of styles."""
def __new__(cls) -> Self: ...
# FIXME: Enable fluent invocations!
def reset(self) -> None: ...
def bold(self) -> None: ...
def thin(self) -> None: ...
def italic(self) -> None: ...
def underlined(self) -> None: ...
def blinking(self) -> None: ...
def reversed(self) -> None: ...
def hidden(self) -> None: ...
def stricken(self) -> None: ...
def foreground(
self,
color: (
TerminalColor | DefaultColor | AnsiColor | EmbeddedRgb
| GrayGradient | TrueColor | int
),
) -> None: ...
def background(
self,
color: (
TerminalColor | DefaultColor | AnsiColor | EmbeddedRgb
| GrayGradient | TrueColor | int
),
) -> None: ...
def hires_foreground(self, color: Color) -> None: ...
def hires_background(self, color: Color) -> None: ...
def fidelity(self) -> Fidelity: ...
def __hash__(self) -> int: ...
def __eq__(self, other: object) -> bool: ...
def __ne__(self, other: object) -> bool: ...


class RichText:
Expand Down
179 changes: 146 additions & 33 deletions src/style/format.rs
Original file line number Diff line number Diff line change
Expand Up @@ -447,31 +447,162 @@ pub struct StyleCollection {
styles: Vec<Style>,
}

/// Create a new, empty style collection.
#[cfg_attr(feature = "pyffi", pyfunction)]
pub fn style() -> StyleCollection {
StyleCollection::new()
}

impl StyleCollection {
/// Retrieve formatting to modify.
///
/// If the last style is formatting, this method removes it from this
/// collection and returns the unwrapped formatting. The expectation is that
/// the caller creates a new formatting based on the returned value and then
/// adds that formatting back into the style collection.
fn formatting(&mut self) -> Formatting {
if let Some(Style::Text(formatting)) = self.styles.last() {
let formatting = *formatting;
self.styles.pop();
formatting
} else {
Formatting::new()
}
}
}

#[cfg(not(feature = "pyffi"))]
impl StyleCollection {
/// Create a new empty style collection.
pub fn new() -> Self {
Self::default()
}

/// Push a style reset onto this collection.
pub fn reset(&mut self) -> &mut Self {
self.styles.push(Style::Reset());
self
}

/// Add bold formatting to this style collection.
///
/// If the latest style is formatting, this method modifies the latest
/// style. Otherwise, it pushes new formatting onto this style collection.
pub fn bold(&mut self) -> &mut Self {
let formatting = self.formatting();
self.styles.push(Style::Text(formatting.bold()));
self
}

/// Add thin formatting to this style collection.
///
/// If the latest style is formatting, this method modifies the latest
/// style. Otherwise, it pushes new formatting onto this style collection.
pub fn thin(&mut self) -> &mut Self {
let formatting = self.formatting();
self.styles.push(Style::Text(formatting.thin()));
self
}

/// Add italic formatting to this style collection.
///
/// If the latest style is formatting, this method modifies the latest
/// style. Otherwise, it pushes new formatting onto this style collection.
pub fn italic(&mut self) -> &mut Self {
let formatting = self.formatting();
self.styles.push(Style::Text(formatting.italic()));
self
}

/// Add underlined formatting to this style collection.
///
/// If the latest style is formatting, this method modifies the latest
/// style. Otherwise, it pushes new formatting onto this style collection.
pub fn underlined(&mut self) -> &mut Self {
let formatting = self.formatting();
self.styles.push(Style::Text(formatting.underlined()));
self
}

/// Add blinking formatting to this style collection.
///
/// If the latest style is formatting, this method modifies the latest
/// style. Otherwise, it pushes new formatting onto this style collection.
pub fn blinking(&mut self) -> &mut Self {
let formatting = self.formatting();
self.styles.push(Style::Text(formatting.blinking()));
self
}

/// Add reversed formatting to this style collection.
///
/// If the latest style is formatting, this method modifies the latest
/// style. Otherwise, it pushes new formatting onto this style collection.
pub fn reversed(&mut self) -> &mut Self {
let formatting = self.formatting();
self.styles.push(Style::Text(formatting.reversed()));
self
}

/// Add hidden formatting to this style collection.
///
/// If the latest style is formatting, this method modifies the latest
/// style. Otherwise, it pushes new formatting onto this style collection.
pub fn hidden(&mut self) -> &mut Self {
let formatting = self.formatting();
self.styles.push(Style::Text(formatting.hidden()));
self
}

/// Add stricken formatting to this style collection.
///
/// If the latest style is formatting, this method modifies the latest
/// style. Otherwise, it pushes new formatting onto this style collection.
pub fn stricken(&mut self) -> &mut Self {
let formatting = self.formatting();
self.styles.push(Style::Text(formatting.stricken()));
self
}

/// Push a foreground color onto this style collection.
pub fn foreground(&mut self, color: impl Into<TerminalColor>) {
self.styles.push(Style::Foreground(color.into()))
pub fn foreground(&mut self, color: impl Into<TerminalColor>) -> &mut Self {
self.styles.push(Style::Foreground(color.into()));
self
}

/// Push a background color onto this style collection.
pub fn background(&mut self, color: impl Into<TerminalColor>) {
self.styles.push(Style::Background(color.into()))
pub fn background(&mut self, color: impl Into<TerminalColor>) -> &mut Self {
self.styles.push(Style::Background(color.into()));
self
}
}

/// Create a new, empty style collection.
#[cfg_attr(feature = "pyffi", pyfunction)]
pub fn style() -> StyleCollection {
StyleCollection::new()
/// Push a high-resolution foreground color onto this style collection.
pub fn hires_foreground(&mut self, color: Color) -> &mut Self {
self.styles.push(Style::HiResFore(color));
self
}

/// Push a high-resolution background color oto this style collection.
pub fn hires_background(&mut self, color: Color) -> &mut Self {
self.styles.push(Style::HiResBack(color));
self
}

/// Determine the style collection's fidelity.
///
/// The fidelity of this style collection is the maximum fidelity of the
/// constituent styles.
pub fn fidelity(&self) -> Fidelity {
self.styles
.iter()
.map(Style::fidelity)
.max()
.unwrap_or(Fidelity::Plain)
}
}

#[cfg_attr(feature = "pyffi", pymethods)]
#[cfg(feature = "pyffi")]
#[pymethods]
impl StyleCollection {
/// Create a new empty style collection.
#[cfg(feature = "pyffi")]
Expand All @@ -482,23 +613,7 @@ impl StyleCollection {

/// Push a style reset onto this collection.
pub fn reset(&mut self) {
self.styles.push(Style::Reset())
}

/// Retrieve formatting to modify.
///
/// If the last style is formatting, this method removes it from this
/// collection and returns the unwrapped formatting. The expectation is that
/// the caller creates a new formatting based on the returned value and then
/// adds that formatting back into the style collection.
fn formatting(&mut self) -> Formatting {
if let Some(Style::Text(formatting)) = self.styles.last() {
let formatting = *formatting;
self.styles.pop();
formatting
} else {
Formatting::new()
}
self.styles.push(Style::Reset());
}

/// Add bold formatting to this style collection.
Expand Down Expand Up @@ -574,31 +689,29 @@ impl StyleCollection {
}

/// Push a foreground color onto this style collection.
#[cfg(feature = "pyffi")]
pub fn foreground(
&mut self,
#[pyo3(from_py_with = "crate::style::into_terminal_color")] color: TerminalColor,
) {
self.styles.push(Style::Foreground(color))
self.styles.push(Style::Foreground(color));
}

/// Push a background color onto this style collection.
#[cfg(feature = "pyffi")]
pub fn background(
&mut self,
#[pyo3(from_py_with = "crate::style::into_terminal_color")] color: TerminalColor,
) {
self.styles.push(Style::Background(color))
self.styles.push(Style::Background(color));
}

/// Push a high-resolution foreground color onto this style collection.
pub fn hires_foreground(&mut self, color: Color) {
self.styles.push(Style::HiResFore(color))
self.styles.push(Style::HiResFore(color));
}

/// Push a high-resolution background color oto this style collection.
pub fn hires_background(&mut self, color: Color) {
self.styles.push(Style::HiResBack(color))
self.styles.push(Style::HiResBack(color));
}

/// Determine the style collection's fidelity.
Expand Down

0 comments on commit 9f0708f

Please sign in to comment.