Crate script_format

Source
Expand description

Simple DSL for formatting data based on Rhai.

This crate provides a custom DSL built on top of the Rhai scripting engine, designed specifically for formatting data. The DSL introduces a set of custom functions and operators to enhance the capabilities of Rhai when it comes to text formatting tasks.

§Key Features

  • Custom Operators: Extended with operators like ++, and, or, xor, contains, equals, require, then_emit, and or_emit for expressive scripts.
  • Message Emission: Use - to emit a single message and ++ to emit multiple messages.
  • Conditional Emission: The then_emit and or_emit operators allow conditional message emission based on boolean conditions.
  • Indentation Control: IND and SET_INDENT functions to manage indentation dynamically.
  • Flexible Data Handling: Supports arrays, maps, strings, and custom types.
  • Shortcuts: IND and NL constants can be used as shortcuts for IND(1) and NL(1) respectively.

§DSL Overview

  • - <message>: Emits a message.
  • <a> ++ <b>: Emits messages a and b.
  • then_emit(<condition>, <message>): Emits <message> if <condition> is true.
  • or_emit(<condition>, <message>): Emits <message> if <condition> is false.
  • SET_INDENT(<string>): Sets the current indent string.
  • IND(<count>): Generates indentation with the current indent string.
  • NL(<count>): Inserts newlines.
  • IND: Shortcut for IND(1).
  • NL: Shortcut for NL(1).

§DSL Example

We’re going to use the following script to format a person’s details:

SET_INDENT(".. ");                    // sets the current indent string to ".. "
- "Person Details:";                  // - emits a single message
- NL;                                 // NL emits a newline
IND ++ "Name: " ++ person.name ++ NL; // ++ emits the message and concatenates it
IND ++ "Age: " ++ person.age ++ NL;   // ++ automatically converts the values to strings
- IND(2);                             // custom operator IND indents the message
person.age > 18 then_emit("- Adult"); // custom operator then_emit emits a message conditionally
use script_format::{
    rhai::{CustomType, TypeBuilder},
    FormattingEngine,
};

#[derive(Clone, CustomType)]
struct Person {
    pub name: String,
    pub age: i32,
}

let mut engine = FormattingEngine::new(false);
engine.build_type::<Person>();

let person = Person {
    name: "Alice".into(),
    age: 30,
};

let script = r#"
SET_INDENT(".. ");                    // sets the current indent string to ".. "
- "Person Details:";                  // - emits a single message
- NL;                                 // NL emits a newline
IND ++ "Name: " ++ person.name ++ NL; // ++ emits the message and concatenates it
IND ++ "Age: " ++ person.age ++ NL;   // ++ automatically converts the values to strings
- IND(2);                             // custom operator IND indents the message
person.age > 18 then_emit("- Adult"); // custom operator then_emit emits a message conditionally
"#;

let expected = r#"
Person Details:
.. Name: Alice
.. Age: 30
.. .. - Adult
    "#
    .trim();

let result = engine.format("person", person, script);
assert_eq!(result.unwrap(), expected);

Expected Output:

Name: Alice
Age: 30 - Adult

This DSL is ideal for generating formatted text dynamically based on data inputs.

Re-exports§

pub use rhai;

Structs§

FormattingEngine
A wrapper around the Rhai Engine for formatting data using a dsl based on rhai.

Type Aliases§

ScriptResult
A type alias for the result of script execution within the FormattingEngine.