Documentation
¶
Overview ¶
Package format is a pure-Go (no cgo) implementation of Ruby's format-string engine — the computation behind Kernel#sprintf, Kernel#format, and String#% — compatible with MRI (CRuby) 4.0 byte-for-byte.
It is the formatting backend for go-embedded-ruby (rbgo) but is a standalone, reusable module with no dependency on the Ruby runtime, mirroring the way go-ruby-regexp provides Onigmo and go-ruby-erb provides ERB.
Entry points ¶
Sprintf is the convenience form taking plain Go values:
out, err := format.Sprintf("%05.2f -> 0x%x", 3.14159, 255)
// out == "03.14 -> 0xff"
Format is the explicit form for hosts (rbgo) that already hold typed values:
out, err := format.Format("%<name>s is %<age>d", nil, named)
Argument model ¶
A plain Go caller may pass int, int64, *big.Int, float64, string, bool, nil, []any, and Symbol; a *NamedArgs, map[string]Value, or map[string]any supplies the hash backing %<name>s and %{name} references. A host that holds its own value objects (an interpreter) implements the Value interface so its objects are formatted directly, without an intermediate copy.
Coverage ¶
Every MRI conversion is implemented:
- d, i, u — signed decimal integer
- f — fixed-point float
- e, E — scientific float
- g, G — shortest float, trailing zeros trimmed (kept under #)
- a, A — hexadecimal float
- s — to_s
- p — inspect
- x, X — hexadecimal integer
- o — octal integer
- b, B — binary integer
- c — character (code point or one-character string)
- %% — a literal percent
with the -, +, space, 0, and # flags; numeric, *, and named width/precision; %n$ absolute argument references; %<name> and %{name} hash references; arbitrary- precision Bignum integers; Ruby's two's-complement ".." notation for negative x/o/b values; the Inf/-Inf/NaN spellings; and the MRI ArgumentError, KeyError, and TypeError messages — all validated against the live CRuby oracle by a broad differential test, with a deterministic golden corpus so the oracle-free CI lanes still exercise the full surface.
Package format implements Ruby's format-string engine — the computation behind Kernel#sprintf, Kernel#format, and String#% — as a standalone, pure-Go (no cgo) library compatible with MRI (CRuby) 4.0.
It is the formatting backend for go-embedded-ruby (rbgo) but depends on nothing from the Ruby runtime: a host binds it by passing its own values through the small Value interface (see value.go), or a plain Go caller passes int/int64/*big.Int/float64/string/bool/nil/[]any and a NamedArgs/map for named references.
Every conversion, flag, width/precision form, named/numbered reference, and the MRI ArgumentError/KeyError/TypeError messages are matched against CRuby byte-for-byte (see the differential test suite).
Code generated from the MRI oracle; DO NOT EDIT. Regenerate with: GEN_GOLDEN=1 go test -run TestGenGolden
Index ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func Format ¶
Format is the explicit-arg form of Sprintf: positional Values plus the named hash for %<name>/%{name} references (nil when there are none). It is the primary entry point for hosts (rbgo) that already hold Values.
func Sprintf ¶
Sprintf formats per Ruby's Kernel#sprintf / Kernel#format / String#%. The arguments are the Ruby values to format, given either as plain Go values (int, int64, *big.Int, float64, string, bool, nil, []any, Symbol) or as Values; a *NamedArgs or map[string]any/map[string]Value supplies the hash for %<name>s and %{name} references. It returns the formatted string or an *Error carrying the Ruby exception class and message MRI would raise.
Types ¶
type Error ¶
Error is the error returned by Sprintf/Format. Class names the Ruby exception class MRI would raise ("ArgumentError", "KeyError", "TypeError") so a host (rbgo) can re-raise the matching Ruby exception; Message is MRI's message text. Error() renders "Class: Message" for standalone Go callers.
type NamedArgs ¶
type NamedArgs struct {
// contains filtered or unexported fields
}
NamedArgs supplies the hash backing %<name>s and %{name} references. It is an ordered name->Value map; callers that do not care about iteration order may pass a plain map[string]any to Sprintf, which is wrapped automatically.
func NewNamedArgs ¶
NewNamedArgs builds a NamedArgs from a name->Value map. Iteration order is the sorted key order, which only affects ToS/Inspect of the hash itself.
type Symbol ¶
type Symbol string
Symbol is the plain-Go representation of a Ruby Symbol argument, so a Go caller can pass format.Symbol("name") and get :name from %p and name from %s.
type Value ¶
type Value interface {
// Kind reports which family of conversions the value natively satisfies.
Kind() Kind
// ToS is the Ruby to_s rendering, used by %s and as the textual value of
// %{name} references.
ToS() string
// Inspect is the Ruby inspect rendering, used by %p.
Inspect() string
// ClassName names the value's Ruby class for TypeError messages
// ("Integer", "Float", "String", "Symbol", "Array", "Hash", "nil", ...).
ClassName() string
// Int returns the value as an arbitrary-precision integer for the integer
// conversions (d/i/u/x/X/o/b/B/c). ok is false when the value cannot be
// interpreted as an integer at all (e.g. a Hash); a String that is not a
// valid Integer() literal reports ok true with a non-nil parse error so the
// caller can raise ArgumentError rather than TypeError.
Int() (z *big.Int, err error, ok bool)
// Float returns the value as a float64 for the float conversions
// (f/e/E/g/G/a/A). The contract mirrors Int.
Float() (f float64, err error, ok bool)
}
Value is the argument model for the formatter. It is the bridge between a host language's value space (most notably rbgo's Ruby objects) and what the conversions need: an integer (possibly a Bignum), a float, a string, a symbol, nil, or a composite (array/hash) that the %s/%p conversions render.
Callers may pass plain Go values to Sprintf/Format — int, int64, *big.Int, float64, string, bool, nil, []any, NamedArgs/map — which are adapted to this interface internally (see toValue). Implementing Value directly lets a host (rbgo) format its own objects without an intermediate copy: a Ruby object wrapper need only report its kind plus a to_s and an inspect string and, for numbers, an integer/float view.
