Keats / tera

A template engine for Rust based on Jinja2/Django
http://keats.github.io/tera/
MIT License
3.43k stars 279 forks source link

tera for templating formated text-files. #835

Closed migmedia closed 1 year ago

migmedia commented 1 year ago

Hi,

is it possible to control the generated whitespace with tera? The goal are aligned csv-files or markdown-like tables. For example I need to right-align some numbers and texts. In Rust i can use the write!("{:<10}", 12.345); macro. But I would like to use a templating-system for that purpose.

Micha

Keats commented 1 year ago

You can control whitespace with {{- ... -}} and {%- ... -%}: https://tera.netlify.app/docs/#whitespace-control Is that enough for your usecase?

migmedia commented 1 year ago

No, that's just the basis to work. I need the inverse-function of trim_start and trim_end.

I need something like this for an imaginary markdown-table:

| No |    *Name*   |     Score | 
|----|-------------|-----------|
{% for member in team | slice(end=10) %}
| {{- loop.index ~ '.' | left_align(length=4) -}} | {{- member.name | center(length=20) -}} | {{- member.score | right_align(length=10) -}} |
{% endfor %}

In fact I have to generate a ascii-report and need an easy end-user-compatible way to adjust / translate the output.

Micha

migmedia commented 1 year ago

I have decided to add this kind of filters to my local project.

/// Right-aligns the token to a given length.   
///
/// # Example
///
/// ```
/// use tera::{Context, Tera};
/// use tera_text_filters::right_align;
///
/// let mut ctx = Context::new();
/// ctx.insert("i", "some text");
///
/// let mut tera = Tera::default();
/// tera.register_filter("right_align", right_align);
///
/// let i = "{{ i | right_align(length=20) }}";
/// let rendered = tera.render_str(i, &ctx).unwrap();
/// assert_eq!(rendered, "        some text");
/// ```
pub fn right_align<S: BuildHasher>(
    value: &Value,
    args: &HashMap<String, Value, S>,
) -> tera::Result<Value> {
    let text: String = try_get_value!("right_align", "value", String, value);
    let len = match args.get("length") {
        Some(length) => {
            try_get_value!("right_align", "length", usize, length)
        }
        None => {
            return Err(Error::msg(
                "Filter `right_align` expected an arg called `length`",
            ))
        }
    };
    Ok(to_value(format!("{text:>len$}")).unwrap())
}

PS: It grew up to a small crate: github / crates.io