ansi-align 0.2.1

Text alignment library with ANSI escape sequence and Unicode support
Documentation
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
# ansi-align


[![Crates.io](https://img.shields.io/crates/v/ansi-align.svg)](https://crates.io/crates/ansi-align)
[![Documentation](https://docs.rs/ansi-align/badge.svg)](https://docs.rs/ansi-align)
[![License](https://img.shields.io/crates/l/ansi-align.svg)](https://github.com/sabry-awad97/ansi-align#license)
[![Build Status](https://img.shields.io/github/actions/workflow/status/sabry-awad97/ansi-align/ci.yml?branch=main)](https://github.com/sabry-awad97/ansi-align/actions)

A Rust library for aligning text with proper support for ANSI escape sequences and Unicode characters.

## Features


- **ANSI-aware alignment**: Correctly handles text containing ANSI escape sequences (colors, formatting)
- **Unicode support**: Properly calculates display width for Unicode characters including CJK characters
- **Multiple alignment options**: Left, center, and right alignment
- **Customizable**: Configure split strings and padding characters
- **Performance optimized**: Single-pass processing with efficient memory usage
- **Type-safe**: Uses a `Width` type for display width values

## Installation


Add this to your `Cargo.toml`:

```toml
[dependencies]
ansi-align = "0.2.1"
```

For CLI tool development with enhanced error handling:

```toml
[dev-dependencies]
ansi-align = "0.2.1"
thiserror = "2.0"
clap = { version = "4.5", features = ["derive", "color"] }
colored = "3.0"
```

## Quick Start


```rust
use ansi_align::{ansi_align, center, left, right};

// Basic alignment (defaults to center)
let text = "hello\nworld";
let centered = ansi_align(text);

// Specific alignment functions
let left_aligned = left("short\nlonger line");
let centered = center("short\nlonger line");
let right_aligned = right("short\nlonger line");
```

## Advanced Usage


### Custom Options


```rust
use ansi_align::{ansi_align_with_options, Alignment, AlignOptions};

let text = "line1|line2|line3";
let options = AlignOptions::new(Alignment::Right)
    .with_split("|")           // Custom line separator
    .with_pad('.');            // Custom padding character

let result = ansi_align_with_options(text, &options);
// Result: "..line1|..line2|..line3"
```

### ANSI Escape Sequences


The library correctly handles ANSI escape sequences by ignoring them during width calculation:

```rust
use ansi_align::center;

let colored_text = "\x1b[31mred\x1b[0m\n\x1b[32mgreen text\x1b[0m";
let aligned = center(colored_text);
// ANSI codes are preserved but don't affect alignment
```

### Unicode Characters


Wide Unicode characters (like CJK) are handled correctly:

```rust
use ansi_align::center;

let unicode_text = "古\n古古古";
let aligned = center(unicode_text);
// Properly accounts for double-width characters
```

## API Reference


### Core Functions


- `ansi_align(text: &str) -> String` - Center align text (default)
- `ansi_align_with_options(text: &str, opts: AlignOptions) -> String` - Align with custom options
- `left(text: &str) -> String` - Left align (no-op, returns original)
- `center(text: &str) -> String` - Center align text
- `right(text: &str) -> String` - Right align text

### Types


#### `Alignment`


```rust
pub enum Alignment {
    Left,
    Center,
    Right,
}
```

#### `Width`


A type-safe wrapper for display width values:

```rust
let width = Width::new(42);
let value = width.get(); // Returns usize
```

#### `AlignOptions`


Configuration for alignment behavior:

```rust
pub struct AlignOptions {
    pub align: Alignment,    // Alignment type
    pub split: String,       // Line separator (default: "\n")
    pub pad: char,          // Padding character (default: ' ')
}
```

Builder methods:

- `AlignOptions::new(align: Alignment)` - Create with alignment
- `.with_split(split: impl Into<String>)` - Set custom line separator
- `.with_pad(pad: char)` - Set custom padding character

## Performance


- **Left alignment**: Optimized as a no-op, returns input unchanged
- **Single pass**: Text is processed once for optimal performance
- **Efficient padding**: Uses optimized string creation for different padding sizes
- **Memory conscious**: Minimal allocations with capacity pre-calculation
- **String processing**: Optimized escape sequence handling reduces intermediate allocations
- **Width calculation**: Efficient iterator-based approach without unnecessary collections

## Architecture & Design


### Library Design Principles


- **Type Safety**: Custom types like `Width` prevent common errors
- **Zero-cost Abstractions**: Performance-critical paths have minimal overhead
- **Composability**: Functions can be easily combined and extended
- **Unicode First**: Proper handling of complex text from the ground up

### CLI Tool Architecture


The example CLI tool showcases production-ready Rust patterns:

```rust
// Custom error types with context
#[derive(Error, Debug)]

enum CliError {
    #[error("Failed to read file '{path}': {source}")]
    FileRead { path: String, source: std::io::Error },
    #[error("Failed to read from stdin: {0}")]
    StdinRead(std::io::Error),
    #[error("File not found: {0}")]
    FileNotFound(String),
}

// Configurable border rendering
struct BorderConfig {
    top_left: char,
    top_right: char,
    // ... other border characters
    padding: usize,
}

// Modular demo system
struct DemoSection {
    title: String,
    content: Box<dyn Fn()>,
}
```

### Border Customization


The CLI tool features a configurable border system:

```rust
// Default Unicode box drawing characters
struct BorderConfig {
    top_left: '┌',     // ┌
    top_right: '┐',    // ┐  
    bottom_left: '└',  // └
    bottom_right: '┘', // ┘
    horizontal: '─',   // ─
    vertical: '│',     // │
    padding: 1,        // Space padding
}
```

Example output with borders:
```
┌───────┐
│ Hello │
│ World │
│ Rust  │
└───────┘
```

### Key Improvements in v0.2.1


- **Enhanced Error Handling**: Replaced generic errors with specific, actionable error types
- **Performance Optimizations**: Reduced string allocations and improved processing efficiency  
- **Better Separation of Concerns**: Modular design with dedicated structs for different responsibilities
- **Improved Testability**: Broke down large functions into focused, testable units
- **Configuration System**: Extensible border styles and formatting options
- **Input Validation**: Proper file existence checking and argument validation
- **Modular Demo System**: Organized demo sections for better maintainability
- **Production Ready**: Robust error handling and edge case management

## CLI Tool


The crate includes a powerful, production-ready CLI tool with advanced features and robust error handling:

```bash
# Run the interactive demo to see all features

cargo run --example cli_tool -- --demo

# Align text from command line

cargo run --example cli_tool -- "Hello\nWorld\nRust" --align center --border

# Read from stdin with escape sequence processing

echo "Line 1\nLonger Line 2\nShort" | cargo run --example cli_tool -- - --align right --pad '.'

# Read from file with validation

cargo run --example cli_tool -- --file examples/sample.txt --align center --border

# Custom separator and padding

cargo run --example cli_tool -- "Name|Age|City" --split "|" --align center --pad '_'

# Quiet mode for scripting

cargo run --example cli_tool -- "data" --border --quiet
```

### CLI Features


- 🎨 **Beautiful output** with customizable colorful borders
- 📁 **Multiple input sources**: command line arguments, stdin, or files
- 🌈 **ANSI color preservation** maintains formatting in aligned output
- 🌏 **Full Unicode support** including CJK and emoji characters
- ⚙️ **Highly customizable** padding characters and line separators
- 📋 **Interactive demo** showcasing all alignment capabilities
- 🛡️ **Robust error handling** with descriptive error messages
-**Performance optimized** with minimal memory allocations
- 🔧 **Production ready** with proper validation and edge case handling
- 🤫 **Quiet mode** for integration with scripts and pipelines

### CLI Architecture


The CLI tool demonstrates modern Rust best practices:

- **Custom Error Types**: Uses `thiserror` for type-safe, descriptive error handling
- **Modular Design**: Separated concerns with dedicated structs for border rendering and demo sections
- **Performance Optimized**: Efficient string processing and memory usage
- **Configurable**: Extensible border styles and formatting options
- **Testable**: Small, focused functions with single responsibilities

### Enhanced Demo System


The CLI includes an interactive demo showcasing all features:

```bash
$ cargo run --example cli_tool -- --demo
🎨 ansi-align Demo - Beautiful Text Alignment

📝 Basic Alignment:
Left:
Hello
World
Rust

Center:
Hello
World
Rust

Right:
Hello
World
 Rust

🌈 ANSI Color Support:
Center aligned with colors:
 Red Text
Green Text
Blue Text

🌏 Unicode Support:
Right aligned Unicode:
    古古古
Hello 世界

⚙️ Custom Options:
Custom separator '|' and padding '.':
..Name|..Age|Location

📋 Menu Example:
Center aligned menu:
  🏠 Home
📋 About Us
📞 Contact
⚙️ Settings
```

### Error Handling


The CLI provides clear, actionable error messages:

```bash
# File not found

$ cargo run --example cli_tool -- --file nonexistent.txt
Error: File not found: nonexistent.txt

# Invalid file permissions

$ cargo run --example cli_tool -- --file /protected/file.txt  
Error: Failed to read file '/protected/file.txt': Permission denied
```

## Examples


### Simple Menu Alignment


```rust
use ansi_align::center;

let menu = "Home\nAbout Us\nContact\nServices";
let aligned_menu = center(menu);
println!("{}", aligned_menu);
```

### Code Block Alignment


```rust
use ansi_align::right;

let code = "if x:\n    return y\nelse:\n    return z";
let aligned_code = right(code);
println!("{}", aligned_code);
```

### Custom Separator and Padding


```rust
use ansi_align::{ansi_align_with_options, Alignment, AlignOptions};

let data = "Name|Age|City";
let options = AlignOptions::new(Alignment::Center)
    .with_split("|")
    .with_pad('_');

let result = ansi_align_with_options(data, options);
```

## Development


### Running Tests


```bash
cargo test
```

### Running the CLI Tool


```bash
# Interactive demo

cargo run --example cli_tool -- --demo

# Test with sample data

cargo run --example cli_tool -- "Hello\nWorld" --border --align center

# Test error handling

cargo run --example cli_tool -- --file nonexistent.txt
```

### Code Quality


The project follows Rust best practices:

- **Error Handling**: Uses `thiserror` for descriptive error types
- **Performance**: Optimized string processing and memory usage
- **Testing**: Comprehensive test coverage for edge cases
- **Documentation**: Extensive inline documentation and examples
- **Modularity**: Clean separation of concerns and reusable components

## Contributing


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.

## License


Licensed under either of

- Apache License, Version 2.0 ([LICENSE-APACHE]LICENSE-APACHE)
- MIT license ([LICENSE-MIT]LICENSE-MIT)

at your option.