sal/text/README.md
Mahmoud-Emad a7a7353aa1
Some checks failed
Rhai Tests / Run Rhai Tests (push) Has been cancelled
feat: Add sal-text crate
- Add a new crate `sal-text` for text manipulation utilities.
- Integrate `sal-text` into the main `sal` crate.
- Remove the previous `text` module from `sal`.  This improves
  organization and allows for independent development of the
  `sal-text` library.
2025-06-19 14:43:27 +03:00

3.5 KiB

SAL Text - Text Processing and Manipulation Utilities

SAL Text provides a comprehensive collection of text processing utilities for both Rust applications and Rhai scripting environments.

Features

  • Text Indentation: Remove common leading whitespace (dedent) and add prefixes (prefix)
  • String Normalization: Sanitize strings for filenames (name_fix) and paths (path_fix)
  • Text Replacement: Powerful TextReplacer for regex and literal replacements
  • Template Rendering: TemplateBuilder using Tera engine for dynamic text generation

Rust API

Text Indentation

use sal_text::{dedent, prefix};

// Remove common indentation
let indented = "    line 1\n    line 2\n        line 3";
let dedented = dedent(indented);
assert_eq!(dedented, "line 1\nline 2\n    line 3");

// Add prefix to each line
let text = "line 1\nline 2";
let prefixed = prefix(text, "> ");
assert_eq!(prefixed, "> line 1\n> line 2");

String Normalization

use sal_text::{name_fix, path_fix};

// Sanitize filename
let unsafe_name = "User's File [Draft].txt";
let safe_name = name_fix(unsafe_name);
assert_eq!(safe_name, "user_s_file_draft_.txt");

// Sanitize path (preserves directory structure)
let unsafe_path = "/path/to/User's File.txt";
let safe_path = path_fix(unsafe_path);
assert_eq!(safe_path, "/path/to/user_s_file.txt");

Text Replacement

use sal_text::TextReplacer;

// Simple literal replacement
let replacer = TextReplacer::builder()
    .pattern("hello")
    .replacement("hi")
    .build()
    .expect("Failed to build replacer");

let result = replacer.replace("hello world, hello universe");
assert_eq!(result, "hi world, hi universe");

// Regex replacement
let replacer = TextReplacer::builder()
    .pattern(r"\d+")
    .replacement("NUMBER")
    .regex(true)
    .build()
    .expect("Failed to build replacer");

let result = replacer.replace("There are 123 items");
assert_eq!(result, "There are NUMBER items");

// Chained operations
let replacer = TextReplacer::builder()
    .pattern("world")
    .replacement("universe")
    .and()
    .pattern(r"\d+")
    .replacement("NUMBER")
    .regex(true)
    .build()
    .expect("Failed to build replacer");

Template Rendering

use sal_text::TemplateBuilder;

let result = TemplateBuilder::open("template.txt")
    .expect("Failed to open template")
    .add_var("name", "World")
    .add_var("count", 42)
    .render()
    .expect("Failed to render template");

Rhai Scripting

All functionality is available in Rhai scripts when using herodo:

// Text indentation
let dedented = dedent("    hello\n    world");
let prefixed = prefix("line1\nline2", "> ");

// String normalization
let safe_name = name_fix("User's File [Draft].txt");
let safe_path = path_fix("/path/to/User's File.txt");

// Text replacement
let builder = text_replacer_new();
builder = pattern(builder, "hello");
builder = replacement(builder, "hi");
builder = regex(builder, false);

let replacer = build(builder);
let result = replace(replacer, "hello world");

// Template rendering
let template = template_builder_open("template.txt");
template = add_var(template, "name", "World");
let result = render(template);

Testing

Run the comprehensive test suite:

# Unit tests
cargo test

# Rhai integration tests
cargo run --bin herodo tests/rhai/run_all_tests.rhai

Dependencies

  • regex: For regex-based text replacement
  • tera: For template rendering
  • serde: For template variable serialization
  • rhai: For Rhai scripting integration

License

Apache-2.0