OSDN Git Service

new repo
[bytom/vapor.git] / vendor / golang.org / x / text / message / message.go
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         "golang.org/x/text/language"
12         "golang.org/x/text/message/catalog"
13 )
14
15 // TODO: allow more than one goroutine per printer. This will allow porting from
16 // fmt much less error prone.
17
18 // A Printer implements language-specific formatted I/O analogous to the fmt
19 // package. Only one goroutine may use a Printer at the same time.
20 type Printer struct {
21         // Wrap the fields in a hidden type to hide some of the implemented methods.
22         printer printer
23
24         // NOTE: limiting one goroutine per Printer allows for many optimizations
25         // and simplifications. We can consider removing this restriction down the
26         // road if it the benefits do not seem to outweigh the disadvantages.
27 }
28
29 type options struct {
30         cat *catalog.Catalog
31         // TODO:
32         // - allow %s to print integers in written form (tables are likely too large
33         //   to enable this by default).
34         // - list behavior
35         //
36 }
37
38 // An Option defines an option of a Printer.
39 type Option func(o *options)
40
41 // Catalog defines the catalog to be used.
42 func Catalog(c *catalog.Catalog) Option {
43         return func(o *options) { o.cat = c }
44 }
45
46 // NewPrinter returns a Printer that formats messages tailored to language t.
47 func NewPrinter(t language.Tag, opts ...Option) *Printer {
48         options := &options{
49                 cat: defaultCatalog,
50         }
51         for _, o := range opts {
52                 o(options)
53         }
54         p := &Printer{printer{
55                 tag: t,
56         }}
57         p.printer.toDecimal.InitDecimal(t)
58         p.printer.toScientific.InitScientific(t)
59         p.printer.catContext = options.cat.Context(t, &p.printer)
60         return p
61 }
62
63 // Sprint is like fmt.Sprint, but using language-specific formatting.
64 func (p *Printer) Sprint(a ...interface{}) string {
65         p.printer.reset()
66         p.printer.doPrint(a)
67         return p.printer.String()
68 }
69
70 // Fprint is like fmt.Fprint, but using language-specific formatting.
71 func (p *Printer) Fprint(w io.Writer, a ...interface{}) (n int, err error) {
72         p.printer.reset()
73         p.printer.doPrint(a)
74         n64, err := io.Copy(w, &p.printer.Buffer)
75         return int(n64), err
76 }
77
78 // Print is like fmt.Print, but using language-specific formatting.
79 func (p *Printer) Print(a ...interface{}) (n int, err error) {
80         return p.Fprint(os.Stdout, a...)
81 }
82
83 // Sprintln is like fmt.Sprintln, but using language-specific formatting.
84 func (p *Printer) Sprintln(a ...interface{}) string {
85         p.printer.reset()
86         p.printer.doPrintln(a)
87         return p.printer.String()
88 }
89
90 // Fprintln is like fmt.Fprintln, but using language-specific formatting.
91 func (p *Printer) Fprintln(w io.Writer, a ...interface{}) (n int, err error) {
92         p.printer.reset()
93         p.printer.doPrintln(a)
94         n64, err := io.Copy(w, &p.printer.Buffer)
95         return int(n64), err
96 }
97
98 // Println is like fmt.Println, but using language-specific formatting.
99 func (p *Printer) Println(a ...interface{}) (n int, err error) {
100         return p.Fprintln(os.Stdout, a...)
101 }
102
103 // Sprintf is like fmt.Sprintf, but using language-specific formatting.
104 func (p *Printer) Sprintf(key Reference, a ...interface{}) string {
105         lookupAndFormat(p, key, a)
106         return p.printer.String()
107 }
108
109 // Fprintf is like fmt.Fprintf, but using language-specific formatting.
110 func (p *Printer) Fprintf(w io.Writer, key Reference, a ...interface{}) (n int, err error) {
111         lookupAndFormat(p, key, a)
112         return w.Write(p.printer.Bytes())
113 }
114
115 // Printf is like fmt.Printf, but using language-specific formatting.
116 func (p *Printer) Printf(key Reference, a ...interface{}) (n int, err error) {
117         lookupAndFormat(p, key, a)
118         return os.Stdout.Write(p.printer.Bytes())
119 }
120
121 func lookupAndFormat(p *Printer, r Reference, a []interface{}) {
122         p.printer.reset()
123         p.printer.args = a
124         var id, msg string
125         switch v := r.(type) {
126         case string:
127                 id, msg = v, v
128         case key:
129                 id, msg = v.id, v.fallback
130         default:
131                 panic("key argument is not a Reference")
132         }
133
134         if p.printer.catContext.Execute(id) == catalog.ErrNotFound {
135                 if p.printer.catContext.Execute(msg) == catalog.ErrNotFound {
136                         p.printer.Render(msg)
137                         return
138                 }
139         }
140 }
141
142 // Arg implements catmsg.Renderer.
143 func (p *printer) Arg(i int) interface{} { // TODO, also return "ok" bool
144         i--
145         if uint(i) < uint(len(p.args)) {
146                 return p.args[i]
147         }
148         return nil
149 }
150
151 // Render implements catmsg.Renderer.
152 func (p *printer) Render(msg string) {
153         p.doPrintf(msg)
154 }
155
156 // A Reference is a string or a message reference.
157 type Reference interface {
158         // TODO: also allow []string
159 }
160
161 // Key creates a message Reference for a message where the given id is used for
162 // message lookup and the fallback is returned when no matches are found.
163 func Key(id string, fallback string) Reference {
164         return key{id, fallback}
165 }
166
167 type key struct {
168         id, fallback string
169 }