Printf with runes/graphemes

What is the expectation for fmt.printf? Should printf calculate width of mono space rune and grapheme characters behind the scenes, or is the programmer responsible for using “core:unicode/utf8”, etc, and calculate the actual mono space themselves and apply the delta to the width format in printf?

fmt.printfln("%-6s%s",  "μμμμμ", "hellope") // should be 1 space after 5 mu
fmt.printfln("%-7s%s",  "μμμμμ", "hellope") // should be 2 space after 5 mu
fmt.printfln("%-8s%s",  "μμμμμ", "hellope") // should be 3 space after 5 mu
fmt.printfln("%-9s%s",  "μμμμμ", "hellope") // should be 4 space after 5 mu
fmt.printfln("%-10s%s", "μμμμμ", "hellope") // should be 5 space after 5 mu
fmt.printfln("%-11s%s", "μμμμμ", "hellope this one finally produces space")

fmt.println(utf8.grapheme_count("μμμμμ"))
// prints 5 5 5
fmt.println(len("μμμμμ"))
// prints 10

Seems printf is only counting single byte runes, and not considering multi byte runes or graphemes.

1 Like

bug, fmt._pad() is not used in fmt.fmt_string(). fmt._pad() is for integers so the change is to just replace the len(s) in fmt.fmt_string() with utf8.rune_count_in_string(s)

PR here.

2 Likes

Thank you very much sir.

How long does it take typically for a PR like that to get approved and pushed to master for end users to receive?

It’s tiny enough change that probably it will be accepted pretty quickly. But you never know…

I just applied the fix above to my copy of fmt.odin. Maybe I missed something, but this is what I get now:

fmt.printfln("%-6s%s",  "μμμμμ", "hellope") // should be 1 space after 5 mu
// outputs
// μμμμμ0hellope
fmt.printfln("%-11s%s", "μμμμμ", "hellope")
// μμμμμ000000hellope

odin version dev-2026-02-nightly:0c360e51a

Your original format string was wrong. If you want to pad with space it’s "% -6s", note the space between the % and -.

I thought left and right pad with spaces is the default for strings/runes, which is how printf works for all other languages that I’m aware of. In Odin zero is default for left pad of ints/floats (though for consistency, I always thought all should default to space for left pad and 0 for right pad of numbers. It’s more common to left pad a number, or anything with spaces for formatting rather than 0’s).

https://pkg.odin-lang.org/core/fmt/

0 pad with leading zeros rather than spaces

Hmm. You are probably right… I’ll fixup the PR when I get back to my computer. I’ve seen the 0 pad then looked at the format spec and said “ah, it needs a space, that’s weird” :smile:

1 Like

Appreciate the attention to this issue. I use fmt alot and am really impressed with most of it’s internals. The % formatting needs to be consistent, since that is the part most will see without being aware of all the other awesome things under the hood.