| Crates.io | wrap-ansi |
| lib.rs | wrap-ansi |
| version | 0.1.0 |
| created_at | 2025-09-08 09:44:05.921647+00 |
| updated_at | 2025-09-08 09:44:05.921647+00 |
| description | A high-performance, Unicode-aware Rust library for intelligently wrapping text while preserving ANSI escape sequences, colors, styles, and hyperlinks |
| homepage | https://github.com/sabry-awad97/wrap-ansi |
| repository | https://github.com/sabry-awad97/wrap-ansi |
| max_upload_size | |
| id | 1829051 |
| size | 95,327 |
A high-performance, Unicode-aware Rust library for intelligently wrapping text while preserving ANSI escape sequences, colors, styles, and hyperlinks.
This library is a faithful Rust port of the popular JavaScript wrap-ansi library, designed for terminal applications, CLI tools, and any software that needs to display formatted text in constrained widths.
| Feature | Description |
|---|---|
| π¨ ANSI-Aware Wrapping | Preserves colors, styles, and formatting across line breaks |
| π Hyperlink Support | Maintains clickable OSC 8 hyperlinks when wrapping |
| π Unicode Ready | Correctly handles CJK characters, emojis, and combining marks |
| β‘ High Performance | Optimized algorithms with pre-compiled regex patterns |
| π οΈ Flexible Options | Hard/soft wrapping, trimming, word boundaries control |
| π Memory Safe | Built-in protection against DoS attacks with input size limits |
| π Rich API | Fluent builder pattern and comprehensive error handling |
Add this to your Cargo.toml:
[dependencies]
wrap-ansi = "0.1.0"
use wrap_ansi::wrap_ansi;
let text = "The quick brown fox jumps over the lazy dog";
let wrapped = wrap_ansi(text, 20, None);
println!("{}", wrapped);
// Output:
// The quick brown fox
// jumps over the lazy
// dog
use wrap_ansi::wrap_ansi;
// Colors are preserved across line breaks!
let colored = "\u{001B}[31mThis is red text that will be wrapped properly\u{001B}[39m";
let wrapped = wrap_ansi(colored, 15, None);
println!("{}", wrapped);
// Each line will have proper color codes: \u{001B}[31m...\u{001B}[39m
use wrap_ansi::{wrap_ansi, WrapOptions};
// Using the builder pattern for clean configuration
let options = WrapOptions::builder()
.hard_wrap(true) // Break long words
.trim_whitespace(false) // Preserve whitespace
.word_wrap(true) // Respect word boundaries
.build();
let text = "supercalifragilisticexpialidocious word";
let wrapped = wrap_ansi(text, 10, Some(options));
println!("{}", wrapped);
// Output:
// supercalif
// ragilistic
// expialidoc
// ious word
wrap_ansi(string, columns, options) -> StringThe main wrapping function that handles text with ANSI escape sequences.
Parameters:
string: &str - Input text (may contain ANSI escape sequences)columns: usize - Target column width for wrappingoptions: Option<WrapOptions> - Optional configuration (uses defaults if None)Returns: Wrapped text with preserved ANSI sequences
wrap_ansi_checked(string, columns, options) -> Result<String, WrapError>Safe version with comprehensive error handling and input validation.
Parameters: Same as wrap_ansi
Returns:
Ok(String) - Successfully wrapped textErr(WrapError) - Detailed error informationErrors:
InvalidColumnWidth(usize) - Column width must be > 0InputTooLarge(usize, usize) - Input exceeds 10MB limitWrapOptionsFine-grained control over wrapping behavior:
pub struct WrapOptions {
pub trim: bool, // Remove leading/trailing whitespace (default: true)
pub hard: bool, // Break long words at boundary (default: false)
pub word_wrap: bool, // Respect word boundaries (default: true)
}
WrapOptionsBuilderFluent builder interface for creating options:
let options = WrapOptions::builder()
.hard_wrap(true)
.trim_whitespace(false)
.word_wrap(true)
.build();
Builder Methods:
.hard_wrap(bool) - Configure hard wrapping behavior.trim_whitespace(bool) - Configure whitespace trimming.word_wrap(bool) - Configure word boundary respect.build() - Build the final WrapOptionsPerfect for:
| Mode | Behavior | Use Case |
|---|---|---|
| Soft Wrap (default) | Long words move to next line intact | Natural text flow |
| Hard Wrap | Long words break at column boundary | Strict width constraints |
| Character Wrap | Break anywhere, ignore word boundaries | Monospace layouts |
β
Foreground Colors: Standard (30-37) and bright (90-97)
β
Background Colors: Standard (40-47) and bright (100-107)
β
Text Styles: Bold, italic, underline, strikethrough
β
Color Resets: Proper handling of reset sequences (39, 49)
β
Hyperlinks: OSC 8 sequences for clickable terminal links
β
Custom SGR: Support for any Select Graphic Rendition codes
use wrap_ansi::{wrap_ansi, WrapOptions};
// CJK characters are properly counted as 2 columns
let chinese = "δ½ ε₯½δΈηοΌθΏζ―δΈδΈͺζ΅θ―";
let wrapped = wrap_ansi(chinese, 8, None);
// Emojis and combining characters work correctly
let emoji = "Hello π World π with emojis";
let options = WrapOptions::builder().hard_wrap(true).build();
let wrapped = wrap_ansi(emoji, 10, Some(options));
For applications requiring robust error handling:
use wrap_ansi::{wrap_ansi_checked, WrapError};
let text = "Hello, world!";
match wrap_ansi_checked(text, 0, None) {
Ok(wrapped) => println!("Wrapped: {}", wrapped),
Err(WrapError::InvalidColumnWidth(width)) => {
eprintln!("Invalid width: {}", width);
}
Err(WrapError::InputTooLarge(size, max)) => {
eprintln!("Input too large: {} bytes (max: {})", size, max);
}
}
Check out the examples directory for comprehensive usage examples:
cargo run --example improved_features
The example demonstrates:
ansi-escape-sequences - ANSI sequence detection and strippingregex - Pattern matching for ANSI sequencesstring-width - Unicode-aware string width calculationthiserror - Error handling derive macrosLicensed under either of
at your option.
Contributions are welcome! Please feel free to submit a Pull Request.
This library is inspired by and aims to be compatible with the JavaScript wrap-ansi library by Sindre Sorhus and the Chalk team.