Skip to content

Commit 378fdc4

Browse files
refactor(lib)!: create and expose a single Template object for users to interact with (#4)
1 parent 71798ef commit 378fdc4

File tree

5 files changed

+277
-42
lines changed

5 files changed

+277
-42
lines changed

benches/process.rs

Lines changed: 10 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,24 @@
11
use criterion::{Criterion, criterion_group, criterion_main};
22
use std::hint::black_box;
3-
use string_pipeline::process;
3+
use string_pipeline::Template;
44

55
fn criterion_benchmark(c: &mut Criterion) {
66
c.bench_function("process_simple", |b| {
77
b.iter(|| {
8-
process(
9-
black_box("/home/user/.cargo/bin"),
10-
// output: "bin"
11-
black_box("{split:/:-1}"),
12-
)
13-
.unwrap()
8+
Template::parse(black_box("{split:/:-1}"))
9+
.unwrap()
10+
.format(black_box("/home/user/.cargo/bin"))
11+
.unwrap()
1412
})
1513
});
1614

1715
c.bench_function("process_complex", |b| {
1816
b.iter(|| {
19-
process(
20-
black_box(" 18, 4.92, Unknown"),
21-
// output: "NUM: 18 - NUM: 4.92"
22-
black_box("{split:,:0..2|trim|prepend:num\\: |join: - |upper}"),
23-
)
17+
Template::parse(black_box(
18+
"{split:,:0..2|trim|prepend:num\\: |join: - |upper}",
19+
))
20+
.unwrap()
21+
.format(black_box("18, 4.92, Unknown"))
2422
.unwrap()
2523
})
2624
});

src/lib.rs

Lines changed: 64 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,70 @@
11
//! # string_pipeline
22
//!
33
//! A flexible, template-driven string transformation pipeline for Rust.
4+
//!
5+
//! This library provides a way to define a sequence of string operations using a concise template syntax,
6+
//! allowing for dynamic string manipulation based on user-defined templates.
7+
//!
8+
//! # Quick start
9+
//! ```rust
10+
//! use string_pipeline::Template;
11+
//!
12+
//! // Define a template with operations
13+
//! let template = Template::parse("{split:,:0..2|join: and }").unwrap();
14+
//!
15+
//! // Format a string using the template
16+
//! let result = template.format("a,b,c,d").unwrap();
17+
//!
18+
//! assert_eq!(result, "a and b");
19+
//! ```
20+
//!
21+
//! A more in-depth view of the template syntax can be found in the [Template::parse](Template::parse) method documentation.
22+
//!
23+
//! # More examples
24+
//! Get the second item in a comma-separated list:
25+
//! ```rust
26+
//! use string_pipeline::Template;
27+
//!
28+
//! let template = Template::parse("{split:,:1}").unwrap();
29+
//!
30+
//! let result = template.format("a,b,c").unwrap();
31+
//!
32+
//! assert_eq!(result, "b");
33+
//! ```
34+
//!
35+
//! Replace all spaces with underscores and uppercase:
36+
//! ```rust
37+
//! use string_pipeline::Template;
38+
//!
39+
//! let template = Template::parse("{replace:s/ /_/g|upper}").unwrap();
40+
//!
41+
//! let result = template.format("foo bar baz").unwrap();
42+
//!
43+
//! assert_eq!(result, "FOO_BAR_BAZ");
44+
//! ```
45+
//!
46+
//! Trim, split and append a suffix to each resulting item:
47+
//! ```rust
48+
//! use string_pipeline::Template;
49+
//!
50+
//! let template = Template::parse("{split:,:..|trim|append:!}").unwrap();
51+
//!
52+
//! let result = template.format(" a, b,c , d , e ").unwrap();
53+
//!
54+
//! assert_eq!(result, "a!,b!,c!,d!,e!");
55+
//! ```
56+
//!
57+
//! Strip ANSI escape codes:
58+
//! ```rust
59+
//! use string_pipeline::Template;
60+
//!
61+
//! let template = Template::parse("{strip_ansi}").unwrap();
62+
//!
63+
//! let result = template.format("\x1b[31mHello\x1b[0m").unwrap();
64+
//!
65+
//! assert_eq!(result, "Hello");
66+
//! ```
467
568
mod pipeline;
669

7-
pub use pipeline::apply_ops;
8-
pub use pipeline::parse_template;
9-
pub use pipeline::process;
10-
pub use pipeline::{RangeSpec, StringOp, Value};
70+
pub use pipeline::Template;

src/main.rs

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
use clap::Parser;
22
use std::io::{self, Read};
3-
use string_pipeline::process;
3+
use string_pipeline::Template;
44

55
#[derive(Parser)]
66
struct Cli {
@@ -33,10 +33,15 @@ fn main() {
3333
},
3434
};
3535

36-
match process(&input, &cli.template) {
36+
let template = Template::parse(&cli.template).unwrap_or_else(|e| {
37+
eprintln!("Error parsing template: {}", e);
38+
std::process::exit(1);
39+
});
40+
41+
match template.format(&input) {
3742
Ok(result) => println!("{}", result),
3843
Err(e) => {
39-
eprintln!("Error: {}", e);
44+
eprintln!("Error formatting input: {}", e);
4045
std::process::exit(1);
4146
}
4247
}

src/pipeline/mod.rs

Lines changed: 16 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,11 @@ use regex::Regex;
22
mod parser;
33
use strip_ansi_escapes::strip;
44

5+
pub use crate::pipeline::template::Template;
6+
mod template;
7+
58
#[derive(Debug, Clone)]
6-
pub enum Value {
9+
enum Value {
710
Str(String),
811
List(Vec<String>),
912
}
@@ -55,10 +58,6 @@ pub enum RangeSpec {
5558
Range(Option<isize>, Option<isize>, bool), // (start, end, inclusive)
5659
}
5760

58-
pub fn parse_template(template: &str) -> Result<(Vec<StringOp>, bool), String> {
59-
parser::parse_template(template)
60-
}
61-
6261
fn resolve_index(idx: isize, len: usize) -> usize {
6362
if len == 0 {
6463
return 0;
@@ -380,21 +379,20 @@ pub fn apply_ops(input: &str, ops: &[StringOp], debug: bool) -> Result<String, S
380379
})
381380
}
382381

383-
pub fn process(input: &str, template: &str) -> Result<String, String> {
384-
let (ops, debug) = parse_template(template)?;
385-
apply_ops(input, &ops, debug)
386-
}
387-
388382
#[cfg(test)]
389383
mod tests {
390-
use super::*;
384+
use super::Template;
385+
386+
fn process(input: &str, template: &str) -> Result<String, String> {
387+
let tmpl = Template::parse(template)?;
388+
tmpl.format(input)
389+
}
391390

392391
// Single Operation Tests - Organized by Operation Type
393392
mod single_operations {
394-
use super::*;
395393

396394
mod positive_tests {
397-
use super::*;
395+
use super::super::process;
398396

399397
// Split operation tests
400398
#[test]
@@ -979,7 +977,7 @@ mod tests {
979977
}
980978

981979
mod negative_tests {
982-
use super::*;
980+
use super::super::process;
983981

984982
// Split operation negative tests
985983
#[test]
@@ -1111,11 +1109,8 @@ mod tests {
11111109

11121110
// Two-Step Pipeline Tests
11131111
mod two_step_pipelines {
1114-
use super::*;
1115-
11161112
mod positive_tests {
1117-
use super::*;
1118-
1113+
use super::super::process;
11191114
// Split + Join combinations
11201115
#[test]
11211116
fn test_split_join_different_separators() {
@@ -1379,7 +1374,7 @@ mod tests {
13791374
}
13801375

13811376
mod negative_tests {
1382-
use super::*;
1377+
use super::super::process;
13831378

13841379
// Invalid pipeline combinations
13851380
#[test]
@@ -1430,10 +1425,8 @@ mod tests {
14301425

14311426
// Multi-Step Pipeline Tests
14321427
mod multi_step_pipelines {
1433-
use super::*;
1434-
14351428
mod positive_tests {
1436-
use super::*;
1429+
use super::super::process;
14371430

14381431
// Split + Transform + Join patterns
14391432
#[test]
@@ -2135,7 +2128,7 @@ mod tests {
21352128
}
21362129

21372130
mod negative_tests {
2138-
use super::*;
2131+
use super::super::process;
21392132

21402133
// Invalid three-step combinations
21412134
#[test]

0 commit comments

Comments
 (0)