minijinja icon indicating copy to clipboard operation
minijinja copied to clipboard

Proper way to do string formatting

Open rdbo opened this issue 1 year ago • 1 comments

I tried the following ways to format a float to have 2 decimal place precision, but neither worked:

{{ "%.2f" % price }}

Result: invalid operation: tried to use % operator on unsupported types string and number

{{ "%.2f"|format(price) }}

Result: unknown filter: filter format is unknown

Is it possible to format strings like this without creating a custom filter? If so, what is the proper way to do it?

rdbo avatar Mar 09 '24 17:03 rdbo

Today a custom filter is the only thing you can do. I would love to have a formatting filter in minijinja-contrib but it's quite a bit of effort to create and I did not have the time yet. Happy to accept contributions.

mitsuhiko avatar Mar 09 '24 18:03 mitsuhiko

@mitsuhiko Have you thought about the syntax of the format spec for this filter? We can derive it from Rust's fmt and Python's format string syntax, which are very similar.

Alternatively, we could do this other way around by taking the format spec as argument(s) to the filter which is applied to any Value. Since unlike Rust and Python, where fmt allows interpolating string literal with formatted values, Minijinja itself is an interpolation engine; and since the purpose is to print the text and not pass it around as string value, Minijinja may not need to support string literal with format specs. For example,

{{ "Price is {.2f}, weight is {>3}kg" | fmt( price, weight ) }} vs. Price is {{ price | fmt(".2f") }}, weight is {{ weight | fmt(">3") }}kg

One benefit of the second approach is the filter implementation will be simpler, as it will have to work with only one (value, format-spec) pair. It might be able to produce better error messages too, compared to filter with ad-hoc parser (not minijinja's native parser) for the string literal with one or more format specs in it. One downside is it doesn't allow formatting the same value multiple times without repeating its name.

Also, one sub-option of the second alternative is, the fmt (or format) filter can take the spec using keyword args: e.g. fmt( width=3, align='>' ), instead of a custom syntax.

Any thoughts or preferences?

atsmtat avatar Aug 13 '25 01:08 atsmtat