Packages

Beautiful, expressive and composable color and text formatting for CLI in Gleam.

Current section

Files

Jump to
chromatic src chromatic.gleam
Raw

src/chromatic.gleam

//// # Chromatic
//// Composable text formatting for CLI in Gleam.
////
//// ## Usage
////
//// The best way to use this is through Gleam's pipelines.
////
//// Check it out!
////
//// ```gleam
//// import chromatic.{bold, italic, magenta, rainbow}
////
//// pub fn main() {
//// io.println(
//// "Hello "
//// <> "Gleam"
//// |> magenta
//// |> italic
//// |> bold
//// <> ", this is "
//// <> "Chromatic"
//// |> rainbow
//// |> bold,
//// )
//// }
////```
////
import gleam/string
import gleam/list
const ansi_escape = "\u{001b}["
const ansi_clear = "\u{001b}[0m"
/// ANSI escape helper, adds a ANSI code to the provided string.
/// Unlike the `decorate_ansi` function not terminate with the clear sequence.
pub fn decorate_ansi_raw(string: String, code: String) {
ansi_escape <> code <> "m" <> string
}
/// ANSI escape helper, adds a ANSI code to the provided string.
/// This also terminates the string with the clear sequence so it doesn't affect
/// other strings.
pub fn decorate_ansi(string: String, code: String) {
decorate_ansi_raw(string, code)
|> auto_clear
}
fn auto_clear(string: String) {
let result = case string.ends_with(string, ansi_clear) {
True -> string
False -> string <> ansi_clear
}
result
}
/// Set text color to black.
pub fn black(string: String) {
decorate_ansi(string, "30")
}
/// Set text color to red.
pub fn red(string: String) {
decorate_ansi(string, "31")
}
/// Set text color to green.
pub fn green(string: String) {
decorate_ansi(string, "32")
}
/// Set text color to yellow.
pub fn yellow(string: String) {
decorate_ansi(string, "33")
}
/// Set text color to blue.
pub fn blue(string: String) {
decorate_ansi(string, "34")
}
/// Set text color to magenta.
pub fn magenta(string: String) {
decorate_ansi(string, "35")
}
/// Set text color to cyan.
pub fn cyan(string: String) {
decorate_ansi(string, "36")
}
/// Set text color to an off-white color,
/// for a lighter white try `bright_white`
pub fn white(string: String) {
decorate_ansi(string, "37")
}
/// Set text color to gray.
pub fn gray(string: String) {
decorate_ansi(string, "90")
}
/// Set text color to a lighter red.
pub fn bright_red(string: String) {
decorate_ansi(string, "91")
}
/// Set text color to a lighter green.
pub fn bright_green(string: String) {
decorate_ansi(string, "92")
}
/// Set text color to a lighter yellow.
pub fn bright_yellow(string: String) {
decorate_ansi(string, "93")
}
/// Set text color to a lighter blue.
pub fn bright_blue(string: String) {
decorate_ansi(string, "94")
}
/// Set text color to a lighter magenta.
pub fn bright_magenta(string: String) {
decorate_ansi(string, "95")
}
/// Set text color to a lighter cyan.
pub fn bright_cyan(string: String) {
decorate_ansi(string, "96")
}
/// Set text color to a bright white color
pub fn bright_white(string: String) {
decorate_ansi(string, "97")
}
/// Set background color to black.
pub fn bg_black(string: String) {
decorate_ansi(string, "40")
}
/// Set background color to red.
pub fn bg_red(string: String) {
decorate_ansi(string, "41")
}
/// Set background color to green.
pub fn bg_green(string: String) {
decorate_ansi(string, "42")
}
/// Set background color to yellow.
pub fn bg_yellow(string: String) {
decorate_ansi(string, "43")
}
/// Set background color to blue.
pub fn bg_blue(string: String) {
decorate_ansi(string, "44")
}
/// Set background color to magenta.
pub fn bg_magenta(string: String) {
decorate_ansi(string, "45")
}
/// Set background color to cyan.
pub fn bg_cyan(string: String) {
decorate_ansi(string, "46")
}
/// Set's background to an off-white color,
/// for a lighter white try `bg_bright_white`
pub fn bg_white(string: String) {
decorate_ansi(string, "47")
}
/// Set background color to gray.
pub fn bg_gray(string: String) {
decorate_ansi(string, "100")
}
/// Set background color to a lighter red.
pub fn bg_bright_red(string: String) {
decorate_ansi(string, "101")
}
/// Set background color to a lighter green.
pub fn bg_bright_green(string: String) {
decorate_ansi(string, "102")
}
/// Set background color to a lighter yellow.
pub fn bg_bright_yellow(string: String) {
decorate_ansi(string, "103")
}
/// Set background color to a lighter blue.
pub fn bg_bright_blue(string: String) {
decorate_ansi(string, "104")
}
/// Set background color to a lighter magenta.
pub fn bg_bright_magenta(string: String) {
decorate_ansi(string, "105")
}
/// Set background color to a lighter cyan.
pub fn bg_bright_cyan(string: String) {
decorate_ansi(string, "106")
}
/// Set background color to a bright white color
pub fn bg_bright_white(string: String) {
decorate_ansi(string, "107")
}
/// Set text style to bold
pub fn bold(string: String) {
decorate_ansi(string, "1")
}
/// Set text style to italic
pub fn italic(string: String) {
decorate_ansi(string, "3")
}
/// Set text style to underlined
pub fn underline(string: String) {
decorate_ansi(string, "4")
}
/// Propagate style from this string until next reset.
/// Must be the last function in the pipeline.
pub fn bleed(string: String) {
let result = case string.ends_with(string, ansi_clear) {
True -> string.drop_right(from: string, up_to: string.length(ansi_clear))
False -> string
}
result
}
/// Print this to clear any styles that are bleeding through.
pub fn clear_str() {
ansi_clear
}
/// Clears any previously added styles that would have bled into it.
///
/// Only necessary if you've used `bleed`.
///
/// Like `bleed` needs to be the last function in the pipeline
pub fn clear(string: String) {
ansi_clear <> string
}
/// Rainbow text with an integer offset
pub fn offset_rainbow(string: String, offset: Int) {
let #(str, _, _) =
string.to_graphemes(string)
|> list.fold(#("", False, offset), fn(acc, char) {
let #(str, in, color) = acc
let new_in = case in {
True -> char != "m"
False -> char == "\u{001b}"
}
let maybe_color = case in || new_in {
True -> #(str <> char, new_in, color)
False -> {
let colored = case color % 6 {
// Red
0 -> decorate_ansi_raw(char, "31")
// Yellow
1 -> decorate_ansi_raw(char, "33")
// Green
2 -> decorate_ansi_raw(char, "32")
// Cyan
3 -> decorate_ansi_raw(char, "36")
// Blue
4 -> decorate_ansi_raw(char, "34")
// Magenta
5 -> decorate_ansi_raw(char, "35")
_ -> ""
}
#(str <> colored, new_in, color + 1)
}
}
maybe_color
})
str
}
// Rainbow text!
pub fn rainbow(string: String) {
offset_rainbow(string, 0)
}