123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177 |
- // 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
|