1 unstable release
Uses new Rust 2024
| 0.1.0 | Sep 8, 2025 |
|---|
#642 in Text processing
47,618 downloads per month
Used in 2 crates
(via worktrunk)
77KB
852 lines
π¨ wrap-ansi
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.
β¨ Key Features
| 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 |
π Quick Start
Add this to your Cargo.toml:
[dependencies]
wrap-ansi = "0.1.0"
Basic Text Wrapping
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
ANSI Colors & Styles
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
Advanced Configuration
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
π API Reference
Core Functions
wrap_ansi(string, columns, options) -> String
The 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 ifNone)
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 information
Errors:
InvalidColumnWidth(usize)- Column width must be > 0InputTooLarge(usize, usize)- Input exceeds 10MB limit
Configuration Options
WrapOptions
Fine-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)
}
WrapOptionsBuilder
Fluent 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 finalWrapOptions
π― Use Cases
Perfect for:
- CLI Applications: Format help text, error messages, and output
- Terminal UIs: Create responsive layouts that adapt to terminal width
- Documentation Tools: Generate formatted text with preserved styling
- Log Processing: Wrap log entries while maintaining color coding
- Code Formatters: Handle syntax-highlighted code with proper wrapping
π Advanced Features
Wrapping Modes
| 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 |
ANSI Sequence Support
β
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
Unicode & Internationalization
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));
π§ Error Handling
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);
}
}
π Performance
- Zero-copy operations where possible
- Pre-compiled regex patterns for ANSI sequence parsing
- Efficient string operations with capacity pre-allocation
- DoS protection with configurable input size limits (10MB default)
- Minimal allocations through careful memory management
π€ Compatibility
- Rust Edition: 2024
- MSRV: 1.70.0
- Platforms: All platforms supported by Rust
- Terminal Compatibility: Works with all ANSI-compatible terminals
π Examples
Check out the examples directory for comprehensive usage examples:
cargo run --example improved_features
The example demonstrates:
- Builder pattern usage
- Error handling patterns
- ANSI color preservation
- Hyperlink support
- Unicode text handling
- Complex ANSI sequences
π Dependencies
ansi-escape-sequences- ANSI sequence detection and strippingregex- Pattern matching for ANSI sequencesstring-width- Unicode-aware string width calculationthiserror- Error handling derive macros
π License
Licensed under either of
- Apache License, Version 2.0 (LICENSE-APACHE)
- MIT License (LICENSE-MIT)
at your option.
π€ Contributing
Contributions are welcome! Please feel free to submit a Pull Request.
π Acknowledgments
This library is inspired by and aims to be compatible with the JavaScript wrap-ansi library by Sindre Sorhus and the Chalk team.
Dependencies
~2.7β4.5MB
~74K SLoC