typst-oxifmt icon indicating copy to clipboard operation
typst-oxifmt copied to clipboard

Decimal padding not working for integers

Open manuelVo opened this issue 6 months ago • 3 comments

Formatting a number with a fixed amount of decimal places fails if an integer is passed to oxifmt.

Example:

#import "@preview/oxifmt:1.0.0": strfmt

#strfmt("{:.2}", 1)

This emits 1, where I would expect it to emit 1.00.

manuelVo avatar Oct 07 '25 14:10 manuelVo

This is consistent with Rust, which we base ourselves on, with which you'd need to convert to a float for it to behave as a float: https://play.rust-lang.org/?version=stable&mode=debug&edition=2024&code=fn+main%28%29+%7B%0A++++println%21%28%22a+%7B%3A.3%7D+b%22%2C+1%29%3B%0A++++println%21%28%22a+%7B%3A.3%7D+b%22%2C+1.0%29%3B%0A%7D

In your case this would mean using e.g. #strfmt("{:.2}", float(var)).

Not sure if this is really actionable without breaking consistency here...

PgBiel avatar Oct 07 '25 15:10 PgBiel

Honestly, I find this behavior questionable in rust as well, but I understand the desire to be consistent with their formatting. I guess if the behavior is to stay as-is it would at least be desirable to have this behavior documented (possibly with giving #strfmt("{:.2}", float(var)) as example to force float-notation even for integers.

manuelVo avatar Oct 07 '25 20:10 manuelVo

Just as I submitted this, an argument came to mind for why it might not be a good idea to copy this particular behavior from Rust: In Rust, types are always well-defined. When defining a float-format, the numbers passed to format! will usually be either all integer or all float. In typst however, this is not always the case, as you can quite liberally mix types. For example:

#let values = (1, 1.25, 1.7, 2)
for val in values {
  [#strfmt("{:.2}", val)#linebreak();]
}

will lead to inconsistent output because some values that are formatted will be int and others will be float, while in rust this inconsistency could never happen because the compiler would complain about the mixed types.

Of course, this is your package and so it's up to you to decide how to handle this. I just wanted to leave this as food for thought.

manuelVo avatar Oct 07 '25 20:10 manuelVo