|  | // Copyright 2017 The Go Authors. All rights reserved. | 
|  | // Use of this source code is governed by a BSD-style | 
|  | // license that can be found in the LICENSE file. | 
|  |  | 
|  | package number | 
|  |  | 
|  | import ( | 
|  | "fmt" | 
|  |  | 
|  | "golang.org/x/text/internal/number" | 
|  | "golang.org/x/text/language" | 
|  | ) | 
|  |  | 
|  | // An Option configures a Formatter. | 
|  | type Option option | 
|  |  | 
|  | type option func(tag language.Tag, f *number.Formatter) | 
|  |  | 
|  | // TODO: SpellOut requires support of the ICU RBNF format. | 
|  | // func SpellOut() Option | 
|  |  | 
|  | // NoSeparator causes a number to be displayed without grouping separators. | 
|  | func NoSeparator() Option { | 
|  | return func(t language.Tag, f *number.Formatter) { | 
|  | f.GroupingSize = [2]uint8{} | 
|  | } | 
|  | } | 
|  |  | 
|  | // MaxIntegerDigits limits the number of integer digits, eliminating the | 
|  | // most significant digits. | 
|  | func MaxIntegerDigits(max int) Option { | 
|  | return func(t language.Tag, f *number.Formatter) { | 
|  | if max >= 1<<8 { | 
|  | max = (1 << 8) - 1 | 
|  | } | 
|  | f.MaxIntegerDigits = uint8(max) | 
|  | } | 
|  | } | 
|  |  | 
|  | // MinIntegerDigits specifies the minimum number of integer digits, adding | 
|  | // leading zeros when needed. | 
|  | func MinIntegerDigits(min int) Option { | 
|  | return func(t language.Tag, f *number.Formatter) { | 
|  | if min >= 1<<8 { | 
|  | min = (1 << 8) - 1 | 
|  | } | 
|  | f.MinIntegerDigits = uint8(min) | 
|  | } | 
|  | } | 
|  |  | 
|  | // MaxFractionDigits specifies the maximum number of fractional digits. | 
|  | func MaxFractionDigits(max int) Option { | 
|  | return func(t language.Tag, f *number.Formatter) { | 
|  | if max >= 1<<15 { | 
|  | max = (1 << 15) - 1 | 
|  | } | 
|  | f.MaxFractionDigits = int16(max) | 
|  | } | 
|  | } | 
|  |  | 
|  | // MinFractionDigits specifies the minimum number of fractional digits. | 
|  | func MinFractionDigits(min int) Option { | 
|  | return func(t language.Tag, f *number.Formatter) { | 
|  | if min >= 1<<8 { | 
|  | min = (1 << 8) - 1 | 
|  | } | 
|  | f.MinFractionDigits = uint8(min) | 
|  | } | 
|  | } | 
|  |  | 
|  | // Precision sets the maximum number of significant digits. A negative value | 
|  | // means exact. | 
|  | func Precision(prec int) Option { | 
|  | return func(t language.Tag, f *number.Formatter) { | 
|  | f.SetPrecision(prec) | 
|  | } | 
|  | } | 
|  |  | 
|  | // Scale simultaneously sets MinFractionDigits and MaxFractionDigits to the | 
|  | // given value. | 
|  | func Scale(decimals int) Option { | 
|  | return func(t language.Tag, f *number.Formatter) { | 
|  | f.SetScale(decimals) | 
|  | } | 
|  | } | 
|  |  | 
|  | // IncrementString sets the incremental value to which numbers should be | 
|  | // rounded. For instance: Increment("0.05") will cause 1.44 to round to 1.45. | 
|  | // IncrementString also sets scale to the scale of the increment. | 
|  | func IncrementString(decimal string) Option { | 
|  | increment := 0 | 
|  | scale := 0 | 
|  | d := decimal | 
|  | p := 0 | 
|  | for ; p < len(d) && '0' <= d[p] && d[p] <= '9'; p++ { | 
|  | increment *= 10 | 
|  | increment += int(d[p]) - '0' | 
|  | } | 
|  | if p < len(d) && d[p] == '.' { | 
|  | for p++; p < len(d) && '0' <= d[p] && d[p] <= '9'; p++ { | 
|  | increment *= 10 | 
|  | increment += int(d[p]) - '0' | 
|  | scale++ | 
|  | } | 
|  | } | 
|  | if p < len(d) { | 
|  | increment = 0 | 
|  | scale = 0 | 
|  | } | 
|  | return func(t language.Tag, f *number.Formatter) { | 
|  | f.Increment = uint32(increment) | 
|  | f.IncrementScale = uint8(scale) | 
|  | f.SetScale(scale) | 
|  | } | 
|  | } | 
|  |  | 
|  | func noop(language.Tag, *number.Formatter) {} | 
|  |  | 
|  | // PatternOverrides allows users to specify alternative patterns for specific | 
|  | // languages. The Pattern will be overridden for all languages in a subgroup as | 
|  | // well. The function will panic for invalid input. It is best to create this | 
|  | // option at startup time. | 
|  | // PatternOverrides must be the first Option passed to a formatter. | 
|  | func PatternOverrides(patterns map[string]string) Option { | 
|  | // TODO: make it so that it does not have to be the first option. | 
|  | // TODO: use -x-nochild to indicate it does not override child tags. | 
|  | m := map[language.Tag]*number.Pattern{} | 
|  | for k, v := range patterns { | 
|  | tag := language.MustParse(k) | 
|  | p, err := number.ParsePattern(v) | 
|  | if err != nil { | 
|  | panic(fmt.Errorf("number: PatternOverrides: %v", err)) | 
|  | } | 
|  | m[tag] = p | 
|  | } | 
|  | return func(t language.Tag, f *number.Formatter) { | 
|  | // TODO: Use language grouping relation instead of parent relation. | 
|  | // TODO: Should parent implement the grouping relation? | 
|  | for lang := t; ; lang = t.Parent() { | 
|  | if p, ok := m[lang]; ok { | 
|  | f.Pattern = *p | 
|  | break | 
|  | } | 
|  | if lang == language.Und { | 
|  | break | 
|  | } | 
|  | } | 
|  | } | 
|  | } | 
|  |  | 
|  | // FormatWidth sets the total format width. | 
|  | func FormatWidth(n int) Option { | 
|  | if n <= 0 { | 
|  | return noop | 
|  | } | 
|  | return func(t language.Tag, f *number.Formatter) { | 
|  | f.FormatWidth = uint16(n) | 
|  | if f.PadRune == 0 { | 
|  | f.PadRune = ' ' | 
|  | } | 
|  | } | 
|  | } | 
|  |  | 
|  | // Pad sets the rune to be used for filling up to the format width. | 
|  | func Pad(r rune) Option { | 
|  | return func(t language.Tag, f *number.Formatter) { | 
|  | f.PadRune = r | 
|  | } | 
|  | } | 
|  |  | 
|  | // TODO: | 
|  | // - FormatPosition (using type aliasing?) | 
|  | // - Multiplier: find a better way to represent and figure out what to do | 
|  | //   with clashes with percent/permille. | 
|  | // - NumberingSystem(nu string): not accessable in number.Info now. Also, should | 
|  | //      this be keyed by language or generic? | 
|  | // - SymbolOverrides(symbols map[string]map[number.SymbolType]string) Option |