How to register a custom formatter as a library author?

Hi,
Here is a snippet I made to format a [3]u8 as a css hexcode:

package main
import "core:fmt"
import "core:io"

Color :: [3]u8

color_formatter :: proc(fi: ^fmt.Info, arg: any, verb: rune) -> bool {
    color := (cast(^Color)(arg.data))

    io.write_byte(fi.writer, '#', &fi.n)

    fi.width_set = true
    fi.width = 2

    fmt.fmt_int(fi, u64(color.r), false, 8, 'x')
    fmt.fmt_int(fi, u64(color.g), false, 8, 'x')
    fmt.fmt_int(fi, u64(color.b), false, 8, 'x')

    return true
}


main :: proc() {
  fmt.set_user_formatters(new(map[typeid]fmt.User_Formatter))
  err := fmt.register_user_formatter(Color, color_formatter)
  ensure(err == .None)
  color := Color{0, 123, 255}
  fmt.println(color) // #007bff
}

Assuming I want to make a library for color transformations, how could I register my custom formatter without the user having to call fmt.set_user_formatters(new(map[typeid]fmt.User_Formatter))?

I could design the library, so the user implicitly calls it with an init function or something, but it will assert if they themselves decide to call set_user_formatters later, as it was called already.

Firstly, Color :: distinct [3]u8 otherwise ALL uses of [3]u8 are going to be formatted incorrectly.

Secondly, the point of the custom formatters is for the user not the library creator, per se. You can provide many calls that make it easier for the user to use, but I would not try to force it on them at all.

Thirdly, there are usually better ways to do this without needing to custom formatters like this:

Foo :: struct {
    color: [3]u8 `fmt:"x"`,
}
1 Like

So the most reasonable thing is to provide helpers and a formatter and let the user decide? I feel stupid for not thinking of that. Thanks for telling me.

Struct field tags were the first thing I tried, but I ruled it out when I couldn’t get the formatting right. color = [0, 7b, ff] is not quite #007bff, but it seems tags can’t specify printf strings: #%02x%02x%02x.
Can they? That would be very cool