| Crates.io | ansi-escape-sequences |
| lib.rs | ansi-escape-sequences |
| version | 0.1.0 |
| created_at | 2025-09-08 08:50:45.913372+00 |
| updated_at | 2025-09-08 08:50:45.913372+00 |
| description | High-performance Rust library for detecting, matching, and processing ANSI escape sequences in terminal text with zero-allocation static regex patterns |
| homepage | https://github.com/sabry-awad97/ansi-escape-sequences |
| repository | https://github.com/sabry-awad97/ansi-escape-sequences |
| max_upload_size | |
| id | 1829012 |
| size | 87,454 |
A high-performance, zero-allocation Rust library for detecting, matching, and processing ANSI escape sequences in terminal text. This crate provides comprehensive support for ANSI/VT100 terminal control sequences with optimized regex patterns and convenient APIs.
regex crateLazyLock for optimal memory usageAdd this to your Cargo.toml:
[dependencies]
ansi-escape-sequences = "0.1"
use ansi_escape_sequences::{ansi_regex, strip_ansi, has_ansi};
// Check if text contains ANSI sequences
let colored_text = "\u{001B}[31mHello\u{001B}[0m World";
assert!(has_ansi(colored_text));
// Strip all ANSI sequences
let clean_text = strip_ansi(colored_text);
assert_eq!(clean_text, "Hello World");
// Get a regex for custom processing
let regex = ansi_regex(None);
let matches: Vec<_> = regex.find_iter(colored_text).collect();
assert_eq!(matches.len(), 2); // Found 2 ANSI sequences
use ansi_regex::{ansi_regex, ansi_regex_owned, AnsiRegexOptions};
// Match only the first ANSI sequence
let options = AnsiRegexOptions::new().only_first();
let regex = ansi_regex(Some(options));
// Global matching (default behavior)
let options = AnsiRegexOptions::new().global();
let regex = ansi_regex(Some(options));
// Get an owned regex instance (useful for storing in structs)
let owned_regex = ansi_regex_owned(None);
// Find all ANSI sequences with detailed information
let sequences = AnsiRegexOptions::find_ansi_sequences(colored_text);
for seq in sequences {
println!("Found ANSI sequence: {:?} at position {}",
seq.as_str(), seq.start());
}
ANSI escape sequences are special character sequences used to control terminal formatting, cursor positioning, and other terminal behaviors. They typically start with the ESC character (\u{001B} or \x1B) followed by specific control characters.
ESC[ followed by parameters and a final character
\u{001B}[31m (red foreground color)\u{001B}[2J (clear screen)ESC] followed by data and terminated by ST
\u{001B}]0;Window Title\u{0007} (set window title)\u{009B} (CSI)LazyLock and reusedhas_ansi() stops at first match for optimal performancehas_ansi() for quick detection before processingonly_first() option when you only need to detect presenceansi_regex()) are faster than owned instancesThis library recognizes and matches:
ESC[ + parameters + final byte (colors, cursor movement, screen clearing)ESC] + data + string terminator (window titles, hyperlinks)\u{009B} for CSI)\u{0007}), ESC\ (\u{001B}\u{005C}), ST (\u{009C});) and colon (:) separated parametersansi_regex(options: Option<AnsiRegexOptions>) -> &'static RegexReturns a static reference to a pre-compiled regex for maximum performance.
ansi_regex_owned(options: Option<AnsiRegexOptions>) -> RegexReturns an owned regex instance, useful for storing in structs or when static references aren't suitable.
strip_ansi(text: &str) -> StringRemoves all ANSI escape sequences from text, returning clean plain text.
has_ansi(text: &str) -> boolFast detection of ANSI sequences - returns true if any are found.
AnsiRegexOptionsnew() - Create default options (global matching)only_first() - Configure for first-match-only (more efficient for detection)global() - Configure for global matching (finds all sequences)find_ansi_sequences(text: &str) - Extract all ANSI sequences with position infouse ansi_regex::{ansi_regex, ansi_regex_owned, strip_ansi, has_ansi, AnsiRegexOptions};
// Quick detection
let text = "\u{001B}[31mcolored\u{001B}[0m text";
if has_ansi(text) {
let clean = strip_ansi(text);
println!("Cleaned: {}", clean);
}
// Custom processing with static regex
let regex = ansi_regex(None);
let count = regex.find_iter(text).count();
// Owned regex for struct storage
struct TextProcessor {
ansi_regex: regex::Regex,
}
impl TextProcessor {
fn new() -> Self {
Self {
ansi_regex: ansi_regex_owned(None),
}
}
}
// Detailed sequence analysis
let sequences = AnsiRegexOptions::find_ansi_sequences(text);
for seq in sequences {
println!("ANSI sequence '{}' at position {}", seq.as_str(), seq.start());
}
The library includes a comprehensive example showcasing real-world usage patterns:
cargo run --example comprehensive_demo
This demo covers:
use ansi_regex::{ansi_regex, strip_ansi, has_ansi, AnsiRegexOptions};
// Log file processing
fn clean_log_file(content: &str) -> String {
content.lines()
.map(|line| if has_ansi(line) { strip_ansi(line) } else { line.to_string() })
.collect::<Vec<_>>()
.join("\n")
}
// Terminal output analysis
fn analyze_terminal_output(output: &str) {
let sequences = AnsiRegexOptions::find_ansi_sequences(output);
println!("Found {} ANSI sequences", sequences.len());
for seq in sequences {
let seq_type = if seq.as_str().contains('m') { "Color/Style" }
else if seq.as_str().contains('H') { "Cursor Position" }
else { "Other" };
println!(" {}: {}", seq_type, seq.as_str());
}
}
// Web application: Convert ANSI to HTML
fn ansi_to_html(text: &str) -> String {
let regex = ansi_regex(None);
regex.replace_all(text, |caps: ®ex::Captures| {
match caps.get(0).unwrap().as_str() {
"\u{001B}[31m" => "<span style='color: red'>",
"\u{001B}[32m" => "<span style='color: green'>",
"\u{001B}[0m" => "</span>",
_ => "",
}
}).to_string()
}
For detailed API documentation, visit docs.rs/ansi-escape-sequences.
Contributions are welcome! Please feel free to submit a Pull Request. For major changes, please open an issue first to discuss what you would like to change.
This project is licensed under either of
at your option.
This library is inspired by the JavaScript ansi-regex library and aims to provide similar functionality for Rust applications.