Introducing fancy-units - format numbers and units with style

I was going to suggest wrapping the quantity in a box but I really like your idea of using a non-breaking space as the quantity separator. The advantage of using a box is the complete freedom on the choice of the separator, whereas only two non-breaking spaces are (currently) available.

It looks like the width of the regular non-breaking space is actually closer to the default quantity-separator than the narrow version you suggested. The width of the narrow space is 0.125em, the width of the regular space is 0.25em and the width of the default separator is 0.2em. At that point it is really up to the user to select the preferred separator.

It’s in the back of my mind from some place that a narrow nbsp is the convention to separate numbers and units. But I don’t remember which style guide that is from…

If I’m not mistaken we can also create a “non breaking space” of arbitrary width this way - i.e with a show rule we can replace it with a glued-in h for spacing, which seems to work the same way.

#let sp = sym.space.nobreak.narrow
#show sp: sym.wj + h(0.2em) + sym.wj

Wikipedia also fills in that the figure space sym.space.fig is another non-breaking space, but it’s rather wide, so probably not the right one for this

2 Likes

Hello, I bumped into another thing:
= Heading text in bold #qty[val][unit] will render the units not styled appropriately as they should based on the heading style (e.g. bold). Is there an easy way how to implement the style of the context? Thank you!

I’m a huge fan of fancy units so far, very helpful package!

Fancy-units uses math mode, so you’ll have to change the weight of math in headings:

#show heading: it => {
  show math.equation: set text(weight: "bold")
  it
}
2 Likes

Hi I’m back with another question, can fancy-units do ranges as well? Something like “The typical values for this trait are #qty[3–6][%]”?

This is not implemented, but you can create a function that handles this for you. I included two different variants since I don’t know which format you are actually looking for

#import "@preview/fancy-units:0.1.1": num, unit, qty

#let qtyrange(..args, num1-body, num2-body, unit-body) = {
  $#qty(..args, num1-body, unit-body) "to" #qty(..args, num2-body, unit-body)$
}

#let qtyrange2(num1-body, num2-body, unit-body) = {
  $(#num(num1-body) - #num(num2-body))#unit(unit-body)$
}

#qtyrange[3][6][%] \
#qtyrange2[3][6][%]

In the latter case, passing arguments to the functions num() and unit() would require separate parameters for the respective functions.

I have not decided whether I actually want to add the range (and list and product) functions to the package. As the two examples above show, they can be easily created with the internal functions num(), unit() and qty(). And leaving the task to the user would allow maximum flexibility. Let me know what you think!

1 Like

Thanks for your prompt reply and the code! You’re right that function can be recreated easily ad hoc, but for broader consistency it might be useful to have it already implemented within fancy-units. For example, one could use a different font or text styling for units and for normal text around, so then the dash in ranges should match the units style rather the common text style.

Hi I’m back, I wanted to use order separation in numbers, but it’s not implemented in fancy units, right? To get 200,000 which is better readable than 200000.

Unfortunately, it’s not available in version 0.1. I already implemented the digit grouping on the dev branch, and it will definitely be part of version 0.2. This will take a few more weeks though, since I don’t have time to finalize the version + documentation at the moment.

2 Likes

Hello Janek, another question: Is it possible to write ±0.001 mg with fancy units, without the actual value? Just the error and unit? Thank you!

One way to do it:

#qty[#hide[0] +- 0.001][mg]

Thank you! Though this leaves the space still there and looks bit off

You can define an error quantity that adds the plus.minus sign to a regular quantity.

#let eqty(..args, num-body, unit-body) = {
  let pm = math.class("binary", sym.plus.minus)
  $pm #qty(..args, num-body, unit-body)$
}

#eqty[0.001][mg]

By default, the spacing will look different since plus.minus defaults to the class "vary". If there is nothing in front of the operator, it will be directly attached to the error. If you would like to keep the spacing from the regular format value ± error, you can change the class to "binary". See Class Function – Typst Documentation for some more information.

Actually adding this as a feature to the package could get quite complex. E.g. having only the error does not make sense in the “relative” notation 0.9(1). I already thought about making the value optional for the case #num[e5] where you only want to get the output 10^5 instead of 1x10^5. I haven’t done any actual work on it though.

1 Like

Thanks, works like a charm!

I’m using the dev version for some more customization options. I cant get the nobreak space to work, propably just missing the right syntax.

#configure(
  num-format: (
    format-exponent.with(separator: sym.dot),
    group-digits,
    format-num,
  ),
  // qty-format: (
  //format-qty.with(separator: sym.space.nobreak.narrow), //quad
  // format-qty,
  // ),
)

the commented part doesnt work for me, that extra quad was to verify visually.

Would be awesome, if someone can point me in the right direction.

Since there is only a single function available to format quantities at the moment, the qty-format only accepts a function and not an array. The configuration should work with the code below:

#configure(
  num-format: (
    format-exponent.with(separator: sym.dot),
    group-digits,
    format-num,
  ),
  qty-format: format-qty.with(separator: sym.space.nobreak.narrow)
)

If this did not solve your issue, please let me know the actual error message you are getting.

That was it, thank you so much for your time!

Hii Janek, it seems that typst 0.14 compiler breaks in fancy-units. I’m getting “Cannot add string and type” error, 0.13.1 works fine. Can you also see this error? I’m using the web app.

Could you let me know the number or unit you are using to get this error? The unit tests did not show any compilation error, which probably means I am still missing a few test cases.

Ummm well that might be a bit tricky to do, because it’s somewhere in my 100-page thesis :sweat_smile: Lemme do some tests, though my hunch is that it could be the unbreakable space or no space I used in few places to get better formatting