Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 19 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -363,9 +363,25 @@ Zero not only aligns numbers at the decimal point but also at the uncertainty an

## Units and Quantities

Numbers are frequently displayed together with a (physical) unit forming a so-called _quantity_. Zero has built-in support for formatting quantities through the `zi` module.
Numbers are frequently displayed together with a (physical) unit forming a so-called _quantity_. Zero has built-in support for formatting quantities through two different philosophies.
<!-- the `zi` module. -->

Zero takes a different approach to units than other packages: In order to avoid repetition ([DRY principle](https://en.wikipedia.org/wiki/Don%27t_repeat_yourself)) and to avoid accidental errors, every unit is
<!-- Zero takes a different approach to units than other packages: -->
### 1. The `quan` function
The function `quan`
Similar to `num`, the function `quan` takes one argument, specifying a value and a unit − or just one of them. A few examples:
- `quan[1.2 m/s]` - the space is optional
- `quan[-2.0+-.4e3 m/s]` - the value works just like `num`
- `quan[GHz]` - units can also go without a value
- `quan[600us]` - "u" is changed to "µ"

The precise syntax for specifying units is explained in the next section.
Units of the SI system and units that may be used in compliance with the SI system are automatically recognized and annotated with alt descriptions, see also [accessibility](#accessibility) below.


### 2. Predefined units

In order to avoid repetition ([DRY principle](https://en.wikipedia.org/wiki/Don%27t_repeat_yourself)) and to avoid accidental errors, every unit can be
- first _declared_ (or already predefined)
- and then used as a function to produce a quantity.

Expand All @@ -389,7 +405,7 @@ Take a look at the example below:
</p>


### Declaring a New Unit
#### Declaring a New Unit

All common single units as well as a few frequent combinations are already predefined in the `zi` module (e.g., `zi.m`, `zi.V`, `zi.m-s`).

Expand Down
4 changes: 2 additions & 2 deletions src/parsing.typ
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,9 @@
if (
body.has("children")
and body.children.len() != 0
and body.children.all(child => child.has("text"))
and body.children.all(child => child.has("text") or child == [ ])
) {
body.children.map(child => child.text).join()
body.children.map(child => if child == [ ] { " " } else { child.text }).join()
}
}

Expand Down
40 changes: 40 additions & 0 deletions src/quan.typ
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
#import "num.typ": num
#import "parsing.typ": content-to-string
#import "units.typ": parse-unit, qty, unit

#let quan(input) = {
if type(input) == content {
input = content-to-string(input)
assert(input != none, message: "")
}

let regex-beginning-of-unit = regex("[ a-zA-Zµ/]")


// We need to protect against detecting the e/E exponent notation as a unit
let e-position = lower(input).position("e")
let pos = if (
e-position != none
and input.at(e-position + 1, default: ".") in "+-1234567890.,"
) {
let pos = input.slice(e-position + 1).position(regex-beginning-of-unit)
if pos != none {
pos += e-position + 1
}
pos
} else {
input.position(regex-beginning-of-unit)
}

if pos == none {
num(input)
} else if pos == 0 {
unit(parse-unit(input))
} else {
qty(
input.slice(0, pos),
parse-unit(input.slice(pos)),
)
}
}

3 changes: 3 additions & 0 deletions src/units.typ
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,9 @@
}

let (symbol, exponent) = get-symbol-and-exponent(unit, per)
if symbol.starts-with("u") {
symbol = "µ" + symbol.slice(1)
}
if exponent.starts-with("-") {
per = not per
exponent = exponent.slice(1)
Expand Down
1 change: 1 addition & 0 deletions src/zero.typ
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,4 @@
#import "align-column.typ": align-column
#import "zi.typ"
#import "units.typ": set-unit
#import "quan.typ": quan
6 changes: 3 additions & 3 deletions tests/internal/parsing/test.typ
Original file line number Diff line number Diff line change
Expand Up @@ -36,9 +36,9 @@
// unparsable inputs
#assert.eq(to-normalized-numeral[], none)
#assert.eq(to-normalized-numeral[$a + b$], none)
#assert.eq(to-normalized-numeral[2 ], none)
#assert.eq(to-normalized-numeral[ 2], none)
#assert.eq(to-normalized-numeral[ 2343.23 ], none)
#assert.eq(to-normalized-numeral-table[2 ], none)
#assert.eq(to-normalized-numeral-table[ 2], none)
#assert.eq(to-normalized-numeral-table[ 2343.23 ], none)
#assert.eq(str(sym.plus), "+")


Expand Down
5 changes: 5 additions & 0 deletions tests/quan/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# generated by tytanic, do not edit

/diff/
/out/
/ref/
33 changes: 33 additions & 0 deletions tests/quan/ref.typ
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
#set page(width: auto, height: auto, margin: .5em)
#import "/src/zero.typ": *


#zi.m-s[12.3] \
#zi.electronvolt[12.3] \
#(zi.declare("/s"))[12.3] \
#zi.m-s[12.3] \
#zi.electronvolt[12.3] \
#(zi.declare("/s"))[12.3] \

#pagebreak()

#zi.electronvolt[12.3e-2] \
#(zi.declare("EHz"))[12.3e-2] \
#(zi.declare("EHz"))[12.3e-2] \
#zi.electronvolt[12.3e2] \
#(zi.declare("EHz"))[12.3e2] \
#(zi.declare("EHz"))[12.3e2] \
#zi.electronvolt[12.3e2] \
#(zi.declare("EHz"))[12.3e2] \
#(zi.declare("EHz"))[12.3e2] \

#pagebreak()

#(zi.declare("m muN^4/s^2"))[-12+-4e3]

#pagebreak()

#num[12+-23] \
#zi.astronomicalunit() \
#zi.m-s() \
#zi.us() \
35 changes: 35 additions & 0 deletions tests/quan/test.typ
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
#set page(width: auto, height: auto, margin: .5em)
#import "/src/zero.typ": *




#quan[12.3m/s] \
#quan[12.3eV] \
#quan[12.3/s] \
#quan[12.3 m/s] \
#quan[12.3 eV] \
#quan[12.3 /s] \

#pagebreak()

#quan[12.3e-2eV] \
#quan[12.3E-2EHz] \
#quan[12.3E-2 EHz] \
#quan[12.3e+2eV] \
#quan[12.3E+2EHz] \
#quan[12.3E+2 EHz] \
#quan[12.3e2eV] \
#quan[12.3E2EHz] \
#quan[12.3E2 EHz] \

#pagebreak()

#quan[-12.3+-4e3 m/s^2 muN^4]

#pagebreak()

#quan[12+-23] \
#quan[au] \
#quan[m/s] \
#quan[us] \
Loading