easy-sgr 0.1.1

An easy to use Select Graphics Rendition(SGR) library
Documentation
# easy-sgr

[![Build status](https://github.com/4lineclear/easy-sgr/actions/workflows/rust.yml/badge.svg)](https://github.com/4lineclear/easy-sgr/actions) [![Crates.io](https://img.shields.io/crates/v/easy-sgr)](https://crates.io/crates/easy-sgr) [![docs.rs](https://img.shields.io/docsrs/easy-sgr)](https://docs.rs/easy-sgr) [![License](https://img.shields.io/crates/l/easy-sgr)](https://github.com/4lineclear/easy-sgr/blob/main/LICENSE) [![Code Coverage](https://codecov.io/gh/4lineclear/easy-sgr/branch/main/graph/badge.svg?token=0Q30XAW0PV)](https://codecov.io/gh/4lineclear/easy-sgr)

An easy-to-use library for adding graphical ANSI codes or [`SGR`][SGR] escape sequences to your project.
Its main strengths are the multitude of methods that are provided,
and the lack of dependencies; compile times should be pretty good.

This library does not support the usage of non-[`SGR`][SGR] ANSI escape sequences

## Installation

Add this to your Cargo.toml:

```toml
[dependencies]
easy-sgr="0.1.1"
```

## Usage

### `Macros`

The method I would recommend when regarding ease-of-use is to use the macros provided,
through this library or the macro library [itself](https://docs.rs/easy-sgr/latest/easy_sgr_macros/).

This can be done without importing any other features of the library as such:

```toml
[dependencies]
easy-sgr = { version = "0.1.1", features = ["macro-only"] }
```

Or if you want to still use the other features, replace `"macro-only"` with `"macros"`.

And its usage is very simple:

```rust
use easy_sgr::println;

println!("{[italic red]}This should be italic & red!{[]}");
```

`{[]}` is interpreted as a reset here.

All the other `fmt` functions are also implemented, see
[`easy-sgr-macros`](https://docs.rs/easy-sgr/latest/easy_sgr_macros/) for more.

### `Color` and `Style` enums

The simplest runtime way to color text, using these two enums allows you to
work inline of a string literal when using a macro such as
`println!`, `writeln!` or `format!`:

```rust
use easy_sgr::{Color::*, Style::*};

println!("{Italic}{RedFg}This should be italic & red!{Reset}");
```

`Color` and `Style` are both enums that implement `Display`: when they
are printed a matching [`SGR`][SGR] code is written.

This method is the best when it comes to simplicity, but has drawbacks;
using it rewrites the sequence escape  `\x1b[` and the sequence end `m` repeatedly.
In this example this is what would be written:

```plain
\x1b[3m\x1b[31mThis should be italic & red!\x1b[0m
```

This would not be much of an issue for the vast majority of use cases.

### `EasySGR` trait

This is similar to the method above but uses the `EasySGR` trait.
This trait is implemented by anything that implements Into\<AnsiString\> including Style and Color.
Its main purpose is to provide functions for chaining [`SGR`][SGR] codes.

The example above can be achieved using it as such:

```rust
use easy_sgr::{ Color::*, EasySGR, Style::*};

let sgr = Italic.color(RedFg);

println!("{sgr}This should be italic & red!{Reset}");
```

Now the output would look something like this:

```plain
\x1b[31;3mThis should be italic & red!\x1b[0m
```

Instead of a rewriting the entire sequence, the separator character `;` is used instead.

Doing this avoids the issue of rewriting the Escape and End sequences,
though is more expensive to use as it allocates an `SGRString`.

### `SGRString` struct

`SGRString` is the type returned by all `EasySGR` functions, it encapsulates all
possible [`SGR`][SGR] sequences. You can use it to reproduce the previous examples as such:

```rust
use easy_sgr::{Color::*, EasySGR, Style::*};

let text = "This should be italic & red!"
    .to_sgr()
    .style(Italic)
    .color(RedFg);
println!("{text}");
```

You can forgo `.to_sgr()` as `.style(..)`, `.color(..)` and all other `EasySGR` functions
can be directly called on the string literal and other types that implement it.

The method above still uses the `EasySGR` trait, you can go without it like here:

```rust
use easy_sgr::{ColorKind, SGRString, StyleKind};

let mut text = SGRString::from("This should be italic & red!");
text.italic = StyleKind::Place;
text.foreground = ColorKind::Red;

println!("{text}")
```

### `SGRWriter` struct

The writer can also be used directly, instead of using the above methods:

```rust
use std::io::{stdout, Write};
use easy_sgr::{Color::*, EasySGR, SGRWriter, Style::*};

let mut writer = SGRWriter::from(stdout());
writer.sgr(&Italic.color(RedFg)).unwrap();
writer.write_inner("This should be italic & red!").unwrap();
writer.sgr(&Reset).unwrap();
```

or, when writing to a String

```rust
use easy_sgr::{Color::*, EasySGR, SGRWriter, Style::*};

let stylized_string = {
    let mut writer = SGRWriter::from(String::new());
    writer.sgr(&Italic.color(RedFg)).unwrap();
    writer.write_inner("This should be italic & red!").unwrap();
    writer.sgr(&Reset).unwrap();
    writer.internal()
};
```

## Features

### `partial`

This feature changes the way that the `discrete` module works,
enabling it causes it's types to not write the sequence escape and end.

This means to achieve the same affect as above you must do this:

```rust
use easy_sgr::{Color::*, Seq::*, Style::*};

println!("{Esc}{Italic};{RedFg}{End}This should be italic & red!{Esc}{Reset}{End}");
```

resulting in the string:

```plain
\x1b[3;31mThis should be italic & red!\x1b[0m
```

This feature exchanges ease of use for verbosity, resulting in more control.

## Structure

easy-sgr is split into three modules:

- discrete
    - Contains types that can be used inline of a string literal
    - The types, `Seq`, `Color` & `Style` are all able to function independently
    - They all implement the `DiscreteSGR` type to aid in this
    - The `DiscreteSGR` types can all work with an `SGRString`
- graphics
    - Centerpiece is `SGRString` & `EasySGR`
    - `SGRString` is a `String` with the ability to write [`SGR`][SGR] codes
    - `EasySGR` is a trait for chaining [`SGR`][SGR] codes to create a `SGRString`
    - `EasySGR` is blanket implemented by everything that implements `Into<SGRString>`
    - This includes:
        - `SGRString`
        - `Color`
        - `Style`
        - `&str`
        - `String`
        - `&String`
- writing
    - Implements `SGRWriter` & `SGRBuilder`
    - Used by other modules to do writing

Though no modules really will be seen in usage,
as all the types they contain are reexported.

[SGR]: https://en.wikipedia.org/wiki/ANSI_escape_code#SGR

## TODO for `1.0.0` release

- [ ] Add examples to docs
    - [x] `discrete`
    - [ ] `graphics`
    - [ ] `writing`
- [x] Macros (`east-sgr-macros`) (`0.1.0`)
- [ ] Add parser?
    - [ ] Add parsing from ansi codes
    - [ ] Add parsing for `SGRString`
- [ ] `EasySGR` implementation that doesn't allocate an `SGRString`