github.com/mdaxf/iac@v0.0.0-20240519030858-58a061660378/vendor_skip/golang.org/x/text/message/message.go (about)

     1  // Copyright 2015 The Go Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  package message // import "golang.org/x/text/message"
     6  
     7  import (
     8  	"io"
     9  	"os"
    10  
    11  	// Include features to facilitate generated catalogs.
    12  	_ "golang.org/x/text/feature/plural"
    13  
    14  	"golang.org/x/text/internal/number"
    15  	"golang.org/x/text/language"
    16  	"golang.org/x/text/message/catalog"
    17  )
    18  
    19  // A Printer implements language-specific formatted I/O analogous to the fmt
    20  // package.
    21  type Printer struct {
    22  	// the language
    23  	tag language.Tag
    24  
    25  	toDecimal    number.Formatter
    26  	toScientific number.Formatter
    27  
    28  	cat catalog.Catalog
    29  }
    30  
    31  type options struct {
    32  	cat catalog.Catalog
    33  	// TODO:
    34  	// - allow %s to print integers in written form (tables are likely too large
    35  	//   to enable this by default).
    36  	// - list behavior
    37  	//
    38  }
    39  
    40  // An Option defines an option of a Printer.
    41  type Option func(o *options)
    42  
    43  // Catalog defines the catalog to be used.
    44  func Catalog(c catalog.Catalog) Option {
    45  	return func(o *options) { o.cat = c }
    46  }
    47  
    48  // NewPrinter returns a Printer that formats messages tailored to language t.
    49  func NewPrinter(t language.Tag, opts ...Option) *Printer {
    50  	options := &options{
    51  		cat: DefaultCatalog,
    52  	}
    53  	for _, o := range opts {
    54  		o(options)
    55  	}
    56  	p := &Printer{
    57  		tag: t,
    58  		cat: options.cat,
    59  	}
    60  	p.toDecimal.InitDecimal(t)
    61  	p.toScientific.InitScientific(t)
    62  	return p
    63  }
    64  
    65  // Sprint is like fmt.Sprint, but using language-specific formatting.
    66  func (p *Printer) Sprint(a ...interface{}) string {
    67  	pp := newPrinter(p)
    68  	pp.doPrint(a)
    69  	s := pp.String()
    70  	pp.free()
    71  	return s
    72  }
    73  
    74  // Fprint is like fmt.Fprint, but using language-specific formatting.
    75  func (p *Printer) Fprint(w io.Writer, a ...interface{}) (n int, err error) {
    76  	pp := newPrinter(p)
    77  	pp.doPrint(a)
    78  	n64, err := io.Copy(w, &pp.Buffer)
    79  	pp.free()
    80  	return int(n64), err
    81  }
    82  
    83  // Print is like fmt.Print, but using language-specific formatting.
    84  func (p *Printer) Print(a ...interface{}) (n int, err error) {
    85  	return p.Fprint(os.Stdout, a...)
    86  }
    87  
    88  // Sprintln is like fmt.Sprintln, but using language-specific formatting.
    89  func (p *Printer) Sprintln(a ...interface{}) string {
    90  	pp := newPrinter(p)
    91  	pp.doPrintln(a)
    92  	s := pp.String()
    93  	pp.free()
    94  	return s
    95  }
    96  
    97  // Fprintln is like fmt.Fprintln, but using language-specific formatting.
    98  func (p *Printer) Fprintln(w io.Writer, a ...interface{}) (n int, err error) {
    99  	pp := newPrinter(p)
   100  	pp.doPrintln(a)
   101  	n64, err := io.Copy(w, &pp.Buffer)
   102  	pp.free()
   103  	return int(n64), err
   104  }
   105  
   106  // Println is like fmt.Println, but using language-specific formatting.
   107  func (p *Printer) Println(a ...interface{}) (n int, err error) {
   108  	return p.Fprintln(os.Stdout, a...)
   109  }
   110  
   111  // Sprintf is like fmt.Sprintf, but using language-specific formatting.
   112  func (p *Printer) Sprintf(key Reference, a ...interface{}) string {
   113  	pp := newPrinter(p)
   114  	lookupAndFormat(pp, key, a)
   115  	s := pp.String()
   116  	pp.free()
   117  	return s
   118  }
   119  
   120  // Fprintf is like fmt.Fprintf, but using language-specific formatting.
   121  func (p *Printer) Fprintf(w io.Writer, key Reference, a ...interface{}) (n int, err error) {
   122  	pp := newPrinter(p)
   123  	lookupAndFormat(pp, key, a)
   124  	n, err = w.Write(pp.Bytes())
   125  	pp.free()
   126  	return n, err
   127  
   128  }
   129  
   130  // Printf is like fmt.Printf, but using language-specific formatting.
   131  func (p *Printer) Printf(key Reference, a ...interface{}) (n int, err error) {
   132  	pp := newPrinter(p)
   133  	lookupAndFormat(pp, key, a)
   134  	n, err = os.Stdout.Write(pp.Bytes())
   135  	pp.free()
   136  	return n, err
   137  }
   138  
   139  func lookupAndFormat(p *printer, r Reference, a []interface{}) {
   140  	p.fmt.Reset(a)
   141  	var id, msg string
   142  	switch v := r.(type) {
   143  	case string:
   144  		id, msg = v, v
   145  	case key:
   146  		id, msg = v.id, v.fallback
   147  	default:
   148  		panic("key argument is not a Reference")
   149  	}
   150  
   151  	if p.catContext.Execute(id) == catalog.ErrNotFound {
   152  		if p.catContext.Execute(msg) == catalog.ErrNotFound {
   153  			p.Render(msg)
   154  			return
   155  		}
   156  	}
   157  }
   158  
   159  type rawPrinter struct {
   160  	p *printer
   161  }
   162  
   163  func (p rawPrinter) Render(msg string)     { p.p.WriteString(msg) }
   164  func (p rawPrinter) Arg(i int) interface{} { return nil }
   165  
   166  // Arg implements catmsg.Renderer.
   167  func (p *printer) Arg(i int) interface{} { // TODO, also return "ok" bool
   168  	i--
   169  	if uint(i) < uint(len(p.fmt.Args)) {
   170  		return p.fmt.Args[i]
   171  	}
   172  	return nil
   173  }
   174  
   175  // Render implements catmsg.Renderer.
   176  func (p *printer) Render(msg string) {
   177  	p.doPrintf(msg)
   178  }
   179  
   180  // A Reference is a string or a message reference.
   181  type Reference interface {
   182  	// TODO: also allow []string
   183  }
   184  
   185  // Key creates a message Reference for a message where the given id is used for
   186  // message lookup and the fallback is returned when no matches are found.
   187  func Key(id string, fallback string) Reference {
   188  	return key{id, fallback}
   189  }
   190  
   191  type key struct {
   192  	id, fallback string
   193  }