2 releases

0.1.1 Sep 3, 2023
0.1.0 Sep 3, 2023

#461 in Procedural macros

MIT license

48KB
1K SLoC

ext_format

A small, yet powerful, Rust crate for string interpolation. Inspired by Rust's macro rules, it provides two main macros: ext_format! and ext_format_unindent!
The ext_format_unindent! macro works exactly like ext_format!, but first trims leading whitespace, to make working with multiline strings less painful.

Installation

Add the following to your Cargo.toml:

[dependencies]
ext_format = "0.1.0"

Usage

Basic Interpolation

Use $ for basic interpolation:

let name = "Alice";
let output = ext_format!("Hello, $name!");

Binding new variable names

Use {name:new_name} to bind a new name to a variable.

let number = 42;
let output = ext_format!("Number: ${number:n} $n $n");
// Output: "Number: 42 42 42"

Basic Repetition

  • $($var)*: No separators
  • $($var),*: Character as a separator
  • $($var)(...)*: String as a separator (supports escaped characters)
let numbers = vec![1, 2, 3];
let output = ext_format!("Numbers: $($numbers),*");
// Output: "Numbers: 1, 2, 3"

For using newlines as separators:

let items = vec!["apple", "banana", "cherry"];
let output = ext_format!("Items:\n$($items)(\n)*");
// Output:
// Items:
// apple
// banana
// cherry

Repetition with Hidden Variables

Use @ to include variables that control the loop but aren't included in the output.

let items = vec!["apple", "banana"];
let counter = vec![1, 2];
let output = ext_format!("Items:\n$(@counter)$($items)\n)*");
// Output:
// Items:
// apple
// banana

Repetition with named Iteration Variables

Use {name:new_name} to bind a Name to a Variable.

let numbers = vec![1, 2, 3];
let output = ext_format!("Numbers: $(${numbers:number} $number),*");
// Output: "Numbers: 1 1, 2 2, 3 3"

Nested Repetitions

Repetitions can contain other repetitions, acting like nested for-loops:

let matrix = vec![vec![1, 2, 3], vec![4, 5, 6], vec![7, 8, 9]];
let output = ext_format!("Matrix:\n$(@{matrix:row}$($row) *)(\n)*");
// Output:
// Matrix:
// 1 2 3
// 4 5 6
// 7 8 9

Zipped Variables

Variables in a single repetition layer are automatically zipped together, meaning they iterate in lockstep.

let names = vec!["Alice", "Bob"];
let ages = vec![30, 40];
let output = ext_format!("Profiles:\n$($names $ages)\n)*");
// Profiles:
// Alice 30
// Bob 40

Multiline Strings

For multiline strings, ext_format_unindented can be used to avoid leading whitespace:

fn unindented() -> String {
    let matrix = vec![vec![1, 2, 3], vec![4, 5, 6], vec![7, 8, 9]];
    ext_format_unindented!(r#"
        void func3() {
            $(@{matrix:inner_matrix}printf("$($inner_matrix) *");)(\n    )*
        }
    "#)
}
let output = unindented();
// Output:
// void func3() {
//     printf("1 2 3");
//     printf("4 5 6");
//     printf("7 8 9");
// }

If the regular ext_format was used here, it would result in the following:

fn indented() -> String {
    let matrix = vec![vec![1, 2, 3], vec![4, 5, 6], vec![7, 8, 9]];
    ext_format!(r#"
        void func3() {
            $(@{matrix:inner_matrix}printf("$($inner_matrix) *");)(\n                    )*
        }
    "#)
}
let output = indented();
// Output:
//                void func3() {
//                    printf("1 2 3");
//                    printf("4 5 6");
//                    printf("7 8 9");
//                }

With the indentation of the resulting string depending on the indentation of the function itself.

License

This project is licensed under the MIT License. See the LICENSE.md file for details.

Dependencies

~250KB