diff --git a/README.md b/README.md index d4f2654..51dd907 100644 --- a/README.md +++ b/README.md @@ -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. + -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 + +### 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. @@ -389,7 +405,7 @@ Take a look at the example below:

-### 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`). diff --git a/src/parsing.typ b/src/parsing.typ index 317a794..f051a21 100644 --- a/src/parsing.typ +++ b/src/parsing.typ @@ -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() } } diff --git a/src/quan.typ b/src/quan.typ new file mode 100644 index 0000000..1779914 --- /dev/null +++ b/src/quan.typ @@ -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)), + ) + } +} + diff --git a/src/units.typ b/src/units.typ index 24a461d..28ad226 100644 --- a/src/units.typ +++ b/src/units.typ @@ -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) diff --git a/src/zero.typ b/src/zero.typ index 14ed87d..7a79f3b 100644 --- a/src/zero.typ +++ b/src/zero.typ @@ -4,3 +4,4 @@ #import "align-column.typ": align-column #import "zi.typ" #import "units.typ": set-unit +#import "quan.typ": quan diff --git a/tests/internal/parsing/test.typ b/tests/internal/parsing/test.typ index e2d4c82..0c43b05 100644 --- a/tests/internal/parsing/test.typ +++ b/tests/internal/parsing/test.typ @@ -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), "+") diff --git a/tests/quan/.gitignore b/tests/quan/.gitignore new file mode 100644 index 0000000..2e4c5d8 --- /dev/null +++ b/tests/quan/.gitignore @@ -0,0 +1,5 @@ +# generated by tytanic, do not edit + +/diff/ +/out/ +/ref/ diff --git a/tests/quan/ref.typ b/tests/quan/ref.typ new file mode 100644 index 0000000..2e445e0 --- /dev/null +++ b/tests/quan/ref.typ @@ -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() \ diff --git a/tests/quan/test.typ b/tests/quan/test.typ new file mode 100644 index 0000000..9dcc620 --- /dev/null +++ b/tests/quan/test.typ @@ -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] \