diff options
author | Ben Bridle <ben@derelict.engineering> | 2025-04-27 12:19:16 +1200 |
---|---|---|
committer | Ben Bridle <ben@derelict.engineering> | 2025-04-27 12:19:48 +1200 |
commit | f8dbafda42e6395a69c30ea3fc95caa45313cb7a (patch) | |
tree | 4413b6f11e7eee6e94b016ac21459cc598f4e071 /src | |
download | inked-f8dbafda42e6395a69c30ea3fc95caa45313cb7a.zip |
Initial commit
Diffstat (limited to 'src')
-rw-r--r-- | src/colour.rs | 26 | ||||
-rw-r--r-- | src/fragment.rs | 109 | ||||
-rw-r--r-- | src/lib.rs | 16 | ||||
-rw-r--r-- | src/string.rs | 72 |
4 files changed, 223 insertions, 0 deletions
diff --git a/src/colour.rs b/src/colour.rs new file mode 100644 index 0000000..96f854d --- /dev/null +++ b/src/colour.rs @@ -0,0 +1,26 @@ +#[derive(Clone, Copy, Debug)] +pub enum Colour { + Black, + Red, + Green, + Yellow, + Blue, + Magenta, + Cyan, + White, +} + +impl From<Colour> for termcolor::Color { + fn from(c: Colour) -> Self { + match c { + Colour::Black => termcolor::Color::Black, + Colour::Red => termcolor::Color::Red, + Colour::Green => termcolor::Color::Green, + Colour::Yellow => termcolor::Color::Yellow, + Colour::Blue => termcolor::Color::Blue, + Colour::Magenta => termcolor::Color::Magenta, + Colour::Cyan => termcolor::Color::Cyan, + Colour::White => termcolor::Color::White, + } + } +} diff --git a/src/fragment.rs b/src/fragment.rs new file mode 100644 index 0000000..8663fd2 --- /dev/null +++ b/src/fragment.rs @@ -0,0 +1,109 @@ +use crate::*; + + +pub struct InkedFragment { + pub string: String, + pub colour: ColorSpec, +} + +impl InkedFragment { + pub fn from(string: impl Into<String>) -> Self { + Self { + string: string.into(), + colour: ColorSpec::new(), + } + } + + pub fn to_string(self) -> InkedString { + let mut string = InkedString::new(); + string.push(self); + string + } + + pub fn print(self) { self.to_string().print(); } + pub fn println(self) { self.to_string().println(); } + pub fn eprint(self) { self.to_string().eprint(); } + pub fn eprintln(self) { self.to_string().eprintln(); } + + // ---------------------------------------- + + pub fn set_colour(mut self, colour: Option<Colour>) -> Self { + match colour { + Some(colour) => self.colour.set_fg(Some(colour.into())), + None => self.colour.set_fg(None), + }; + self + } + + pub fn set_bold(mut self, bold: bool) -> Self { + self.colour.set_bold(bold); + self + } + + pub fn set_dim(mut self, dim: bool) -> Self { + self.colour.set_dimmed(dim); + self + } + + // ---------------------------------------- + + pub fn black(mut self) -> Self { + self.colour.set_fg(Some(Color::Black)); + self + } + + pub fn red(mut self) -> Self { + self.colour.set_fg(Some(Color::Red)); + self + } + + pub fn green(mut self) -> Self { + self.colour.set_fg(Some(Color::Green)); + self + } + + pub fn yellow(mut self) -> Self { + self.colour.set_fg(Some(Color::Yellow)); + self + } + + pub fn blue(mut self) -> Self { + self.colour.set_fg(Some(Color::Blue)); + self + } + + pub fn magenta(mut self) -> Self { + self.colour.set_fg(Some(Color::Magenta)); + self + } + + pub fn cyan(mut self) -> Self { + self.colour.set_fg(Some(Color::Cyan)); + self + } + + pub fn white(mut self) -> Self { + self.colour.set_fg(Some(Color::White)); + self + } + + pub fn bold(mut self) -> Self { + self.colour.set_bold(true); + self + } + + pub fn dim(mut self) -> Self { + self.colour.set_dimmed(true); + self + } +} + + +impl From<String> for InkedFragment { + fn from(string: std::string::String) -> Self { + Self { + string, + colour: ColorSpec::new(), + } + } +} diff --git a/src/lib.rs b/src/lib.rs new file mode 100644 index 0000000..f11f18f --- /dev/null +++ b/src/lib.rs @@ -0,0 +1,16 @@ +mod colour; +mod fragment; +mod string; + +pub use colour::*; +pub use fragment::*; +pub use string::*; + +use termcolor::*; + + +#[macro_export] macro_rules! ink { + ($($tokens:tt)*) => { + $crate::InkedFragment::from(format!($($tokens)*)) + }; +} diff --git a/src/string.rs b/src/string.rs new file mode 100644 index 0000000..7b34fc8 --- /dev/null +++ b/src/string.rs @@ -0,0 +1,72 @@ +use crate::*; + +use std::io::Write; +use std::sync::LazyLock; + + +static STDOUT_WRITER: LazyLock<BufferWriter> = LazyLock::new(|| + BufferWriter::stdout(ColorChoice::Auto) +); + +static STDERR_WRITER: LazyLock<BufferWriter> = LazyLock::new(|| + BufferWriter::stderr(ColorChoice::Auto) +); + + +pub struct InkedString { + pub fragments: Vec<InkedFragment>, +} + +impl InkedString { + pub fn new() -> Self { + Self { + fragments: Vec::new(), + } + } + + pub fn push(&mut self, fragment: impl Into<InkedFragment>) { + self.fragments.push(fragment.into()); + } + + pub fn append(&mut self, mut string: InkedString) { + self.fragments.append(&mut string.fragments); + } + + pub fn print(mut self) { + self.push(ink!("")); + self.write_string(&STDOUT_WRITER) + } + + pub fn println(mut self) { + self.push(ink!("\n")); + self.write_string(&STDOUT_WRITER) + } + + pub fn eprint(mut self) { + self.push(ink!("")); + self.write_string(&STDERR_WRITER) + } + + pub fn eprintln(mut self) { + self.push(ink!("\n")); + self.write_string(&STDERR_WRITER) + } + + fn write_string(self, writer: &LazyLock<BufferWriter>) { + let mut buffer = writer.buffer(); + for fragment in &self.fragments { + buffer.set_color(&fragment.colour).unwrap(); + write!(buffer, "{}", fragment.string).unwrap(); + } + writer.print(&buffer).unwrap() + } +} + + +impl From<String> for InkedString { + fn from(string: std::string::String) -> Self { + Self { + fragments: vec![ string.into() ], + } + } +} |