Skip to content

Commit 2278fa8

Browse files
committed
docs(readme): updated readme with the new features
1 parent 61d5a9d commit 2278fa8

File tree

3 files changed

+157
-109
lines changed

3 files changed

+157
-109
lines changed

README.md

Lines changed: 105 additions & 88 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ A flexible, composable string transformation CLI tool and Rust library. `string_
2727
- [Range Specifications](#range-specifications)
2828
- [Escaping](#escaping)
2929
- [Debug Mode](#debug-mode)
30-
- [Examples](#examples)
30+
- [More Examples](#more-examples)
3131
- [Testing](#testing)
3232
- [Contributing](#contributing)
3333
- [License](#license)
@@ -44,6 +44,10 @@ A flexible, composable string transformation CLI tool and Rust library. `string_
4444
- **Case conversion**: Uppercase and lowercase.
4545
- **Trim and strip**: Remove whitespace, custom characters, ansi sequences.
4646
- **Append and prepend**: Add text before or after.
47+
- **Map**: Apply a sub-pipeline to each list item.
48+
- **Sort, reverse, unique**: List operations for sorting, reversing, deduplication.
49+
- **Pad**: Pad strings or list items to a given width.
50+
- **Regex extract**: Extract regex matches or groups.
4751
- **Smart escaping**: Contextual pipe handling - no escaping needed in most cases.
4852
- **Flexible indices**: Python-like negative indices in ranges and slices with Rust-like syntax.
4953
- **Stdin support**: Read input from stdin when no input argument is provided.
@@ -57,7 +61,7 @@ Find the crate on [crates.io](https://crates.io/crates/string_pipeline):
5761

5862
```toml
5963
[dependencies]
60-
string_pipeline = "0.7.0"
64+
string_pipeline = "0.8.0"
6165
```
6266

6367
---
@@ -113,17 +117,31 @@ string-pipeline "{replace:s/ /_/g|upper}" "foo bar baz"
113117
string-pipeline "{split:,:..|trim|append:!}" " a, b,c , d , e "
114118
# Output: a!,b!,c!,d!,e!
115119

116-
# Using stdin for processing file content
117-
cat data.txt | string-pipeline "{split:\n:..|trim|prepend:- }"
120+
# Using map to uppercase each item
121+
string-pipeline "{split:,:..|map:{upper}}" "a,b,c"
122+
# Output: A,B,C
123+
124+
# Sort and join
125+
string-pipeline "{split:,:..|sort:desc|join:-}" "b,a,c"
126+
# Output: c-b-a
127+
128+
# Pad each item to width 3 with '*'
129+
string-pipeline "{split:,:..|map:{pad:3:*:both}}" "a,bb,c"
130+
# Output: *a*,bb*,*c*
131+
132+
# Extract numbers from each item
133+
string-pipeline "{split:,:..|map:{regex_extract:\d+}}" "a1,b22,c333"
134+
# Output: 1,22,333
118135
```
119136

120137
### As a Library
121138

122139
```rust
123-
use string_pipeline::process;
140+
use string_pipeline::Template;
124141

125142
fn main() {
126-
let result = process("a,b,c", "{split:,:..|join:\\n}").unwrap();
143+
let template = Template::parse("{split:,:..|join:\\n}").unwrap();
144+
let result = template.format("a,b,c").unwrap();
127145
assert_eq!(result, "a\nb\nc");
128146
}
129147
```
@@ -150,33 +168,45 @@ Arguments to operations are separated by `:`.
150168
- `replace:s/<pattern>/<replacement>/<flags>`
151169
- `upper`
152170
- `lower`
153-
- `trim`
171+
- `trim[:left|right|both]`
154172
- `strip:<chars>`
155173
- `append:<suffix>`
156174
- `prepend:<prefix>`
157175
- `strip_ansi`
158176
- `filter:<regex_pattern>`
159177
- `filter_not:<regex_pattern>`
160178
- `slice:<range>`
179+
- `map:{<operation_list>}`
180+
- `sort[:asc|desc]`
181+
- `reverse`
182+
- `unique`
183+
- `pad:<width>[:<char>][:left|right|both]`
184+
- `regex_extract:<pattern>[:<group>]`
161185

162186
#### Supported Operations
163187

164-
| Operation | Syntax | Description |
165-
| ---------- | ----------------------------------------- | ------------------------------------------- |
166-
| Split | `split:<sep>:<range>` | Split by separator, select by index/range |
167-
| Join | `join:<sep>` | Join a list with separator |
168-
| Substring | `substring:<range>` | Extract substrings |
169-
| Replace | `replace:s/<pattern>/<replacement>/<flags>` | Regex replace (sed-like) |
170-
| Uppercase | `upper` | Convert to uppercase |
171-
| Lowercase | `lower` | Convert to lowercase |
172-
| Trim | `trim` | Trim whitespace |
173-
| Strip | `strip:<chars>` | Trim custom characters |
174-
| Append | `append:<suffix>` | Append text |
175-
| Prepend | `prepend:<prefix>` | Prepend text |
176-
| StripAnsi | `strip_ansi` | Removes ansi escape sequences |
177-
| Filter | `filter:<regex_pattern>` | Keep only items matching regex pattern |
178-
| FilterNot | `filter_not:<regex_pattern>` | Remove items matching regex pattern |
179-
| Slice | `slice:<range>` | Select elements from a list |
188+
| Operation | Syntax | Description |
189+
| ------------ | ------------------------------------------- | --------------------------------------------------- |
190+
| Split | `split:<sep>:<range>` | Split by separator, select by index/range |
191+
| Join | `join:<sep>` | Join a list with separator |
192+
| Substring | `substring:<range>` | Extract substring(s) by character index/range |
193+
| Replace | `replace:s/<pattern>/<replacement>/<flags>` | Regex replace (sed-like, supports flags) |
194+
| Uppercase | `upper` | Convert to uppercase |
195+
| Lowercase | `lower` | Convert to lowercase |
196+
| Trim | `trim[:left\|right\|both]` | Trim whitespace (or side-specific) |
197+
| Strip | `strip:<chars>` | Strip custom characters from both ends |
198+
| Append | `append:<suffix>` | Append text |
199+
| Prepend | `prepend:<prefix>` | Prepend text |
200+
| StripAnsi | `strip_ansi` | Remove ANSI escape sequences |
201+
| Filter | `filter:<regex_pattern>` | Keep only items matching regex pattern |
202+
| FilterNot | `filter_not:<regex_pattern>` | Remove items matching regex pattern |
203+
| Slice | `slice:<range>` | Select elements from a list by index/range |
204+
| Map | `map:{<operation_list>}` | Apply a sub-pipeline to each list item |
205+
| Sort | `sort[:asc\|desc]` | Sort list ascending/descending |
206+
| Reverse | `reverse` | Reverse string or list |
207+
| Unique | `unique` | Remove duplicate items from a list |
208+
| Pad | `pad:<width>[:<char>][:left\|right\|both]` | Pad string/list items to width with char/side |
209+
| RegexExtract | `regex_extract:<pattern>[:<group>]` | Extract first match or group from string/list items |
180210

181211
#### Range Specifications
182212

@@ -190,7 +220,7 @@ Ranges use Rust-like syntax and support negative indices like Python:
190220
| `N..` | From N to end | `{split:,:2..}` → from 2nd to end |
191221
| `..N` | From start to N | `{split:,:..3}` → first 3 elements |
192222
| `..=N` | From start to N inclusive | `{split:,:..=2}` → first 3 elements |
193-
| `..` | All elements | `{split:,:..)` → all elements |
223+
| `..` | All elements | `{split:,:..}` → all elements |
194224

195225
Negative indices count from the end:
196226

@@ -221,9 +251,7 @@ The parser intelligently handles pipe characters (`|`) based on context:
221251

222252
---
223253

224-
## Examples
225-
226-
### Basic
254+
## More examples
227255

228256
```sh
229257
# Get the last item
@@ -262,83 +290,72 @@ string-pipeline "{upper|append:!}" "hello"
262290
string-pipeline "{prepend:\:foo}" "bar"
263291
# Output: :foobar
264292

265-
```
266-
267-
### Advanced
268-
269-
```sh
270-
# Complex chaining: split, select range, join, replace, uppercase
271-
string-pipeline "{split:,:0..2|join:-|replace:s/a/X/|upper}" "a,b,c"
272-
# Output: X-B
273-
274-
# Split, trim each item, then prepend
275-
echo " a , b , c " | string-pipeline "{split:,:..|trim|prepend:item_}"
276-
# Output: item_a,item_b,item_c
293+
# Map: uppercase each item
294+
string-pipeline "{split:,:..|map:{upper}}" "a,b,c"
295+
# Output: A,B,C
277296

278-
# Strip custom characters
279-
string-pipeline "{strip:xy}" "xyhelloxy"
280-
# Output: hello
281-
```
282-
283-
### Real-World
284-
285-
```sh
286-
# Process CSV-like data
287-
echo "name,age,city" | string-pipeline "{split:,:1..}"
288-
# Output: age,city
289-
290-
# Format file paths
291-
echo "/home/user/documents/file.txt" | string-pipeline "{split:/:-1}"
292-
# Output: file.txt
297+
# Sort, reverse, unique, pad, regex_extract
298+
string-pipeline "{split:,:..|sort:desc|join:-}" "b,a,c"
299+
# Output: c-b-a
293300

294-
# Extract file extension
295-
echo "document.pdf" | string-pipeline "{split:.:-1|upper}"
296-
# Output: PDF
301+
string-pipeline "{split:,:..|reverse}" "a,b,c"
302+
# Output: c,b,a
297303

298-
# Process log entries with timestamps
299-
echo "2023-01-01 ERROR Failed to connect" | string-pipeline "{split: :1..|join: |lower}"
300-
# Output: error failed to connect
304+
string-pipeline "{split:,:..|unique}" "a,b,a,c"
305+
# Output: a,b,c
301306

302-
# Clean colored git output
303-
git log --oneline --color=always | string-pipeline "{split:\n:..|strip_ansi|join:\n}"
307+
string-pipeline "{split:,:..|map:{pad:3:*:both}}" "a,bb,c"
308+
# Output: *a*,bb*,*c*
304309

305-
# Process ls colored output
306-
ls --color=always | string-pipeline "{strip_ansi}"
307-
308-
# Clean grep colored output
309-
grep --color=always "pattern" file.txt | string-pipeline "{strip_ansi|upper}"
310-
311-
# Chain with other operations
312-
echo -e "\x1b[31mred\x1b[0m,\x1b[32mgreen\x1b[0m" | \
313-
string-pipeline "{split:,:..|strip_ansi|upper|join: \| }"
314-
# Output: RED | GREEN
315-
316-
# Process log files with ANSI codes
317-
cat colored.log | string-pipeline "{split:\n:-10..|strip_ansi|join:\n}"
310+
string-pipeline "{split:,:..|map:{regex_extract:\\d+}}" "a1,b22,c333"
311+
# Output: 1,22,333
318312
```
319313

320314
### Debug Mode
321315

322316
```sh
323317
# Print debug info for each operation
324-
string-pipeline "{!split:,:..|upper|join:-}" "a,b,c"
325-
# DEBUG: Initial value: Str("a,b,c")
318+
string-pipeline "{!split:,:..|map:{trim|upper}}" "user123, admin456 ,guest789"
319+
# DEBUG: Initial value: Str("user123, admin456 ,guest789")
326320
# DEBUG: Applying operation 1: Split { sep: ",", range: Range(None, None, false) }
327321
# DEBUG: Result: List with 3 items:
328-
# DEBUG: [0]: "a"
329-
# DEBUG: [1]: "b"
330-
# DEBUG: [2]: "c"
322+
# DEBUG: [0]: "user123"
323+
# DEBUG: [1]: " admin456 "
324+
# DEBUG: [2]: "guest789"
331325
# DEBUG: ---
332-
# DEBUG: Applying operation 2: Upper
326+
# DEBUG: Applying operation 2: Map { operations: [Trim { direction: Both }, Upper] }
327+
# DEBUG: Map operation starting with 3 items
328+
# DEBUG: Map operations to apply: 2 steps
329+
# DEBUG: Step 1: Trim { direction: Both }
330+
# DEBUG: Step 2: Upper
331+
# DEBUG: Processing item 1 of 3: "user123"
332+
# DEBUG: Item 1/3 initial value: Str("user123")
333+
# DEBUG: Item 1/3 applying step 1: Trim { direction: Both }
334+
# DEBUG: Item 1/3 step 1 result: String("user123")
335+
# DEBUG: Item 1/3 applying step 2: Upper
336+
# DEBUG: Item 1/3 step 2 result: String("USER123")
337+
# DEBUG: Processing item 2 of 3: " admin456 "
338+
# DEBUG: Item 2/3 initial value: Str(" admin456 ")
339+
# DEBUG: Item 2/3 applying step 1: Trim { direction: Both }
340+
# DEBUG: Item 2/3 step 1 result: String("admin456")
341+
# DEBUG: Item 2/3 applying step 2: Upper
342+
# DEBUG: Item 2/3 step 2 result: String("ADMIN456")
343+
# DEBUG: Processing item 3 of 3: "guest789"
344+
# DEBUG: Item 3/3 initial value: Str("guest789")
345+
# DEBUG: Item 3/3 applying step 1: Trim { direction: Both }
346+
# DEBUG: Item 3/3 step 1 result: String("guest789")
347+
# DEBUG: Item 3/3 applying step 2: Upper
348+
# DEBUG: Item 3/3 step 2 result: String("GUEST789")
349+
# DEBUG: Map operation completed. Results:
350+
# DEBUG: Item 1: "USER123"
351+
# DEBUG: Item 2: "ADMIN456"
352+
# DEBUG: Item 3: "GUEST789"
333353
# DEBUG: Result: List with 3 items:
334-
# DEBUG: [0]: "A"
335-
# DEBUG: [1]: "B"
336-
# DEBUG: [2]: "C"
337-
# DEBUG: ---
338-
# DEBUG: Applying operation 3: Join { sep: "-" }
339-
# DEBUG: Result: String("A-B-C")
354+
# DEBUG: [0]: "USER123"
355+
# DEBUG: [1]: "ADMIN456"
356+
# DEBUG: [2]: "GUEST789"
340357
# DEBUG: ---
341-
# A-B-C
358+
# USER123,ADMIN456,GUEST789
342359
```
343360

344361
---

src/lib.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@
4747
//! ```rust
4848
//! use string_pipeline::Template;
4949
//!
50-
//! let template = Template::parse("{split:,:..|trim|append:!}").unwrap();
50+
//! let template = Template::parse("{split:,:..|map:{trim|append:!}}").unwrap();
5151
//!
5252
//! let result = template.format(" a, b,c , d , e ").unwrap();
5353
//!

0 commit comments

Comments
 (0)