<h1 align="center">✨ Glyphs</h1>
<p align="center">
<strong>Beautiful ANSI escape sequences for Rust.</strong>
</p>
<p align="center">
<a href="https://crates.io/crates/glyphs"><img src="https://img.shields.io/crates/v/glyphs.svg?style=flat-square&logo=rust" alt="Crates.io"></a>
<a href="https://docs.rs/glyphs"><img src="https://img.shields.io/docsrs/glyphs?style=flat-square&logo=docs.rs" alt="Documentation"></a>
<a href="https://github.com/moltenlabs/glyphs/actions"><img src="https://img.shields.io/github/actions/workflow/status/moltenlabs/glyphs/ci.yml?style=flat-square&logo=github" alt="CI"></a>
<a href="#license"><img src="https://img.shields.io/badge/license-MIT%2FApache--2.0-blue?style=flat-square" alt="License"></a>
</p>
<p align="center">
<a href="#features">Features</a> •
<a href="#installation">Installation</a> •
<a href="#quick-start">Quick Start</a> •
<a href="#parsing">Parsing</a> •
<a href="#ecosystem">Ecosystem</a>
</p>
---
## What is Glyphs?
**Glyphs** is a Rust library for working with ANSI escape sequences. It lets you:
1. **Style terminal output** with a fluent, type-safe API
2. **Parse existing sequences** into human-readable descriptions
3. **Strip ANSI codes** from strings
4. **Control cursors and screens** with named constants
Think of it as the Rust equivalent of [sequin](https://github.com/charmbracelet/sequin) from Charmbracelet.
```rust
use glyphs::{style, Color, parse};
// Style text beautifully
let output = style("Hello, Terminal!")
.fg(Color::rgb(249, 115, 22)) // Molten Orange
.bold()
.to_string();
println!("{}", output);
// Parse mystery sequences
for segment in parse("\x1b[1;31mError\x1b[0m") {
println!("{:?}", segment);
// Escape: [SGR (style)] bold, red fg
// Text: "Error"
// Escape: [SGR (style)] reset
}
```
---
## Features
<table>
<tr>
<td width="50%">
### 🎨 Fluent Styling API
```rust
style("text")
.fg(Color::Red)
.bg(Color::Black)
.bold()
.italic()
.underline()
```
</td>
<td width="50%">
### 🔍 Sequence Parsing
```rust
parse("\x1b[31mred\x1b[0m")
// → [Escape(red fg), Text("red"), Escape(reset)]
```
</td>
</tr>
<tr>
<td width="50%">
### 🌈 Full Color Support
- Standard 16 colors
- 256-color palette
- True color (24-bit RGB)
- Hex color parsing
</td>
<td width="50%">
### 🧹 String Utilities
```rust
strip_ansi("\x1b[31mHello\x1b[0m") // "Hello"
visible_len("\x1b[31mHello\x1b[0m") // 5
```
</td>
</tr>
</table>
---
## Installation
```bash
cargo add glyphs
```
Or add to your `Cargo.toml`:
```toml
[dependencies]
glyphs = "0.1"
```
### With Molten Brand Colors
```toml
[dependencies]
glyphs = { version = "0.1", features = ["brand"] }
```
---
## Quick Start
### Basic Styling
```rust
use glyphs::{style, Color};
// Simple colors
let red = style("Error!").fg(Color::Red).to_string();
let warning = style("Warning").fg(Color::Yellow).bold().to_string();
// RGB colors
let custom = style("Custom")
.fg(Color::rgb(255, 128, 0))
.to_string();
// Hex colors
let hex = style("Hex")
.fg(Color::from_hex("#F97316"))
.to_string();
// 256-color palette
let palette = style("Palette")
.fg(Color::ansi256(208))
.to_string();
```
### Text Modifiers
```rust
use glyphs::{style, Color};
let styled = style("Important")
.bold() // Bold text
.italic() // Italic
.underline() // Underlined
.strikethrough() // Strikethrough
.dim() // Dimmed
.reverse() // Inverted colors
.blink() // Blinking (if supported)
.to_string();
```
### Combining Styles
```rust
use glyphs::{style, Color};
let fancy = style("🔥 Molten Labs")
.fg(Color::rgb(249, 115, 22))
.bold()
.underline()
.to_string();
println!("{}", fancy);
```
---
## Parsing
### Parse ANSI Sequences
Turn cryptic escape codes into readable descriptions:
```rust
use glyphs::{parse, ParsedSequence};
let input = "\x1b[1;38;2;249;115;22mMolten\x1b[0m";
for segment in parse(input) {
match segment {
ParsedSequence::Text(text) => {
println!("Text: {}", text);
}
ParsedSequence::Escape(escape) => {
println!("Escape: {}", escape.human_readable());
// "bold, fg: rgb(249, 115, 22)"
}
}
}
```
### Strip ANSI Codes
```rust
use glyphs::strip_ansi;
let styled = "\x1b[1;31mBold Red\x1b[0m Normal";
let plain = strip_ansi(styled);
assert_eq!(plain, "Bold Red Normal");
```
### Get Visible Length
```rust
use glyphs::visible_len;
let styled = "\x1b[31mHello\x1b[0m";
assert_eq!(visible_len(styled), 5); // Not 14!
```
---
## Cursor & Screen Control
### Cursor Movement
```rust
use glyphs::cursor;
// Move cursor
print!("{}", cursor::up(5)); // Move up 5 lines
print!("{}", cursor::down(3)); // Move down 3 lines
print!("{}", cursor::left(10)); // Move left 10 columns
print!("{}", cursor::right(10)); // Move right 10 columns
// Position cursor
print!("{}", cursor::goto(10, 20)); // Row 10, Column 20
print!("{}", cursor::column(1)); // Start of line
```
### Screen Control
```rust
use glyphs::sequences;
// Clear screen
print!("{}", sequences::CLEAR_SCREEN);
print!("{}", sequences::CLEAR_LINE);
// Cursor visibility
print!("{}", sequences::CURSOR_HIDE);
// ... do stuff ...
print!("{}", sequences::CURSOR_SHOW);
// Alternate screen buffer (for TUIs)
print!("{}", sequences::ALT_SCREEN_ENTER);
// ... your TUI ...
print!("{}", sequences::ALT_SCREEN_EXIT);
```
---
## Color Reference
### Standard Colors
| `Color::Black` | 30 | `Color::BrightBlack` |
| `Color::Red` | 31 | `Color::BrightRed` |
| `Color::Green` | 32 | `Color::BrightGreen` |
| `Color::Yellow` | 33 | `Color::BrightYellow` |
| `Color::Blue` | 34 | `Color::BrightBlue` |
| `Color::Magenta` | 35 | `Color::BrightMagenta` |
| `Color::Cyan` | 36 | `Color::BrightCyan` |
| `Color::White` | 37 | `Color::BrightWhite` |
### RGB & Hex
```rust
Color::rgb(255, 128, 0) // Orange
Color::from_hex("#F97316") // Molten Orange
Color::from_hex("7C3AED") // Goblin Purple (# optional)
```
### 256-Color Palette
```rust
Color::ansi256(0) // Black
Color::ansi256(196) // Bright red
Color::ansi256(208) // Orange
Color::ansi256(255) // White
```
---
## Modifier Reference
| `.bold()` | 1 | **Bold text** |
| `.dim()` | 2 | Dimmed text |
| `.italic()` | 3 | *Italic text* |
| `.underline()` | 4 | <u>Underlined</u> |
| `.blink()` | 5 | Blinking text |
| `.reverse()` | 7 | Inverted colors |
| `.hidden()` | 8 | Hidden text |
| `.strikethrough()` | 9 | ~~Strikethrough~~ |
---
## Ecosystem
Glyphs is part of the **Molten Labs** open source ecosystem:
| **[molten_brand](https://crates.io/crates/molten_brand)** | Design tokens & colors | ✅ Published |
| **[glyphs](https://crates.io/crates/glyphs)** | ANSI sequences (you are here) | ✅ Published |
| **[lacquer](https://crates.io/crates/lacquer)** | Terminal styling (like lipgloss) | ✅ Published |
| **cauldron** | TUI framework (like bubbletea) | 📋 Planned |
---
## Why "Glyphs"?
A **glyph** is a symbolic mark or character—like the hidden ANSI codes that transform plain text into beautiful terminal output. In the forge, we inscribe glyphs to add magic to our creations. ✨
---
## Performance
- **Zero allocations** for static styling
- **Compile-time** color constants
- **Efficient parsing** with minimal copies
- Suitable for hot paths and TUI rendering loops
---
## Contributing
We welcome contributions! Please see [CONTRIBUTING.md](CONTRIBUTING.md) for guidelines.
```bash
git clone https://github.com/moltenlabs/glyphs
cd glyphs
cargo test
```
---
## License
Licensed under either of:
- Apache License, Version 2.0 ([LICENSE-APACHE](LICENSE-APACHE))
- MIT license ([LICENSE-MIT](LICENSE-MIT))
at your option.
---
<p align="center">
<sub>Built with ✨ by <a href="https://github.com/moltenlabs">Molten Labs</a></sub>
</p>
<p align="center">
<sub><i>"Let them cook."</i></sub>
</p>