Skip to content

Commit

Permalink
Release v0.2.1 (#7)
Browse files Browse the repository at this point in the history
  • Loading branch information
PgBiel authored May 6, 2024
1 parent 3921473 commit 2100cff
Show file tree
Hide file tree
Showing 2 changed files with 40 additions and 34 deletions.
72 changes: 39 additions & 33 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
# typst-oxifmt (v0.2.0)
# typst-oxifmt (v0.2.1)

A Typst library that brings convenient string formatting and interpolation through the `strfmt` function. Its syntax is taken directly from Rust's `format!` syntax, so feel free to read its page for more information (https://doc.rust-lang.org/std/fmt/); however, this README should have enough information and examples for all expected uses of the library. Only a few things aren't supported from the Rust syntax, such as the `p` (pointer) format type, or the `.*` precision specifier.

A few extras (beyond the Rust-like syntax) will be added over time, though (feel free to drop suggestions at the repository: https://github.com/PgBiel/typst-oxifmt). The first "extra" so far is the `fmt-decimal-separator: "string"` parameter, which lets you customize the decimal separator for decimal numbers (floats) inserted into strings. E.g. `strfmt("Result: {}", 5.8, fmt-decimal-separator: ",")` will return the string `"Result: 5,8"` (comma instead of dot). See more below.

**Compatible with:** [Typst](https://github.com/typst/typst) v0.4.0, v0.5.0, v0.6.0
**Compatible with:** [Typst](https://github.com/typst/typst) v0.4.0+

## Table of Contents

Expand All @@ -21,22 +21,22 @@ A few extras (beyond the Rust-like syntax) will be added over time, though (feel

You can use this library through Typst's package manager (for Typst v0.6.0+):

```js
#import "@preview/oxifmt:0.2.0": strfmt
```typ
#import "@preview/oxifmt:0.2.1": strfmt
```

For older Typst versions, download the `oxifmt.typ` file either from Releases or directly from the repository. Then, move it to your project's folder, and write at the top of your Typst file(s):

```js
```typ
#import "oxifmt.typ": strfmt
```

Doing the above will give you access to the main function provided by this library (`strfmt`), which accepts a format string, followed by zero or more replacements to insert in that string (according to `{...}` formats inserted in that string), an optional `fmt-decimal-separator` parameter, and returns the formatted string, as described below.

Its syntax is almost identical to Rust's `format!` (as specified here: https://doc.rust-lang.org/std/fmt/). You can escape formats by duplicating braces (`{{` and `}}` become `{` and `}`). Here's an example (see more examples in the file `tests/strfmt-tests.typ`):

```js
#import "@preview/oxifmt:0.2.0": strfmt
```typ
#import "@preview/oxifmt:0.2.1": strfmt
#let s = strfmt("I'm {}. I have {num} cars. I'm {0}. {} is {{cool}}.", "John", "Carl", num: 10)
#assert.eq(s, "I'm John. I have 10 cars. I'm John. Carl is {cool}.")
Expand Down Expand Up @@ -73,8 +73,8 @@ You can use `{:spec}` to customize your output. See the Rust docs linked above f

Some examples:

```js
#import "@preview/oxifmt:0.2.0": strfmt
```typ
#import "@preview/oxifmt:0.2.1": strfmt
#let s1 = strfmt("{0:?}, {test:+012e}, {1:-<#8x}", "hi", -74, test: 569.4)
#assert.eq(s1, "\"hi\", +00005.694e2, -0x4a---")
Expand All @@ -89,90 +89,90 @@ Some examples:
### Examples

- **Inserting labels, text and numbers into strings:**
```js
#import "@preview/oxifmt:0.2.0": strfmt
```typ
#import "@preview/oxifmt:0.2.1": strfmt
#let s = strfmt("First: {}, Second: {}, Fourth: {3}, Banana: {banana} (brackets: {{escaped}})", 1, 2.1, 3, label("four"), banana: "Banana!!")
#assert.eq(s, "First: 1, Second: 2.1, Fourth: four, Banana: Banana!! (brackets: {escaped})")
```

- **Forcing `repr()` with `{:?}`** (which adds quotes around strings, and other things - basically represents a Typst value):
```js
#import "@preview/oxifmt:0.2.0": strfmt
```typ
#import "@preview/oxifmt:0.2.1": strfmt
#let s = strfmt("The value is: {:?} | Also the label is {:?}", "something", label("label"))
#assert.eq(s, "The value is: \"something\" | Also the label is <label>")
```

- **Inserting other types than numbers and strings** (for now, they will always use `repr()`, even without `{...:?}`, although that is more explicit):
```js
#import "@preview/oxifmt:0.2.0": strfmt
```typ
#import "@preview/oxifmt:0.2.1": strfmt
#let s = strfmt("Values: {:?}, {1:?}, {stuff:?}", (test: 500), ("a", 5.1), stuff: [a])
#assert.eq(s, "Values: (test: 500), (\"a\", 5.1), [a]")
```

- **Padding to a certain width with characters:** Use `{:x<8}`, where `x` is the **character to pad with** (e.g. space or `_`, but can be anything), `<` is the **alignment of the original text** relative to the padding (can be `<` for left aligned (padding goes to the right), `>` for right aligned (padded to its left) and `^` for center aligned (padded at both left and right)), and `8` is the **desired total width** (padding will add enough characters to reach this width; if the replacement string already has this width, no padding will be added):
```js
#import "@preview/oxifmt:0.2.0": strfmt
```typ
#import "@preview/oxifmt:0.2.1": strfmt
#let s = strfmt("Left5 {:_<5}, Right6 {:*>6}, Center10 {centered: ^10?}, Left3 {tleft:_<3}", "xx", 539, tleft: "okay", centered: [a])
#assert.eq(s, "Left5 xx___, Right6 ***539, Center10 [a] , Left3 okay")
#let s = strfmt("Left5 {:-<5}, Right6 {:=>6}, Center10 {centered: ^10?}, Left3 {tleft:_<3}", "xx", 539, tleft: "okay", centered: [a])
#assert.eq(s, "Left5 xx---, Right6 ===539, Center10 [a] , Left3 okay")
// note how 'okay' didn't suffer any padding at all (it already had at least the desired total width).
```

- **Padding numbers with zeroes to the left:** It's a similar functionality to the above, however you write `{:08}` for 8 characters (for instance) - note that any characters in the number's representation matter for width (including sign, dot and decimal part):
```js
#import "@preview/oxifmt:0.2.0": strfmt
```typ
#import "@preview/oxifmt:0.2.1": strfmt
#let s = strfmt("Left-padded7 numbers: {:07} {:07} {:07} {3:07}", 123, -344, 44224059, 45.32)
#assert.eq(s, "Left-padded7 numbers: 0000123 -000344 44224059 0045.32")
```

- **Defining padding-to width using parameters, not literals:** If you want the desired replacement width (the `8` in `{:08}` or `{: ^8}`) to be passed via parameter (instead of being hardcoded into the format string), you can specify `parameter$` in place of the width, e.g. `{:02$}` to take it from the third positional parameter, or `{:a>banana$}` to take it from the parameter named `banana` - note that the chosen parameter **must be an integer** (desired total width):
```js
#import "@preview/oxifmt:0.2.0": strfmt
```typ
#import "@preview/oxifmt:0.2.1": strfmt
#let s = strfmt("Padding depending on parameter: {0:02$} and {0:a>banana$}", 432, 0, 5, banana: 9)
#assert.eq(s, "Padding depending on parameter: 00432 aaaaaa432") // widths 5 and 9
```

- **Displaying `+` on positive numbers:** Just add a `+` at the "beginning", i.e., before the `#0` (if either is there), or after the custom fill and align (if it's there and not `0` - see [Grammar](#grammar) for the exact positioning), like so:
```js
#import "@preview/oxifmt:0.2.0": strfmt
```typ
#import "@preview/oxifmt:0.2.1": strfmt
#let s = strfmt("Some numbers: {:+} {:+08}; With fill and align: {:_<+8}; Negative (no-op): {neg:+}", 123, 456, 4444, neg: -435)
#assert.eq(s, "Some numbers: +123 +0000456; With fill and align: +4444___; Negative (no-op): -435")
```

- **Converting numbers to bases 2, 8 and 16:** Use one of the following specifier types (i.e., characters which always go at the very end of the format): `b` (binary), `o` (octal), `x` (lowercase hexadecimal) or `X` (uppercase hexadecimal). You can also add a `#` between `+` and `0` (see the exact position at the [Grammar](#grammar)) to display a **base prefix** before the number (i.e. `0b` for binary, `0o` for octal and `0x` for hexadecimal):
```js
#import "@preview/oxifmt:0.2.0": strfmt
```typ
#import "@preview/oxifmt:0.2.1": strfmt
#let s = strfmt("Bases (10, 2, 8, 16(l), 16(U):) {0} {0:b} {0:o} {0:x} {0:X} | W/ prefixes and modifiers: {0:#b} {0:+#09o} {0:_>+#9X}", 124)
#assert.eq(s, "Bases (10, 2, 8, 16(l), 16(U):) 124 1111100 174 7c 7C | W/ prefixes and modifiers: 0b1111100 +0o000174 ____+0x7C")
```

- **Picking float precision (right-extending with zeroes):** Add, at the end of the format (just before the spec type (such as `?`), if there's any), either `.precision` (hardcoded, e.g. `.8` for 8 decimal digits) or `.parameter$` (taking the precision value from the specified parameter, like with `width`):
```js
#import "@preview/oxifmt:0.2.0": strfmt
```typ
#import "@preview/oxifmt:0.2.1": strfmt
#let s = strfmt("{0:.8} {0:.2$} {0:.potato$}", 1.234, 0, 2, potato: 5)
#assert.eq(s, "1.23400000 1.23 1.23400")
```

- **Scientific notation:** Use `e` (lowercase) or `E` (uppercase) as specifier types (can be combined with precision):
```js
#import "@preview/oxifmt:0.2.0": strfmt
```typ
#import "@preview/oxifmt:0.2.1": strfmt
#let s = strfmt("{0:e} {0:E} {0:+.9e} | {1:e} | {2:.4E}", 124.2312, 50, -0.02)
#assert.eq(s, "1.242312e2 1.242312E2 +1.242312000e2 | 5e1 | -2.0000E-2")
```

- **Customizing the decimal separator on floats:** Just specify `fmt-decimal-separator: ","` (comma as an example):
```js
#import "@preview/oxifmt:0.2.0": strfmt
```typ
#import "@preview/oxifmt:0.2.1": strfmt
#let s = strfmt("{0} {0:.6} {0:.5e}", 1.432, fmt-decimal-separator: ",")
#assert.eq(s, "1,432 1,432000 1,43200e0")
Expand Down Expand Up @@ -214,6 +214,12 @@ The tests succeeded if you received no error messages from the last command (ple

## Changelog

### v0.2.1

- Fixed formatting of UTF-8 strings. Before, strings with multi-byte UTF-8 codepoints would cause formatting inconsistencies or even crashes. ([Issue #6](https://github.com/PgBiel/typst-oxifmt/issues/6))
- Fixed an inconsistency in negative number formatting. Now, it will always print a regular hyphen (e.g. '-2'), which is consistent with Rust's behavior; before, it would occasionally print a minus sign instead (as observed in a comment to [Issue #4](https://github.com/PgBiel/typst-oxifmt/issues/4)).
- Added compatibility with Typst 0.8.0's new type system.

### v0.2.0

- The package's name is now `oxifmt`!
Expand Down
2 changes: 1 addition & 1 deletion typst.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "oxifmt"
version = "0.2.0"
version = "0.2.1"
authors = ["PgBiel <https://github.com/PgBiel>"]
license = "MIT-0"
description = "Convenient Rust-like string formatting in Typst"
Expand Down

0 comments on commit 2100cff

Please sign in to comment.