mirror of
https://github.com/golang/go
synced 2024-11-22 09:14:40 -07:00
template: change the signature of formatters for future development.
Make them more like Printf, with a ... final argument. This breaks code with existing formatters but not the templates that use them. R=rsc, gri CC=golang-dev https://golang.org/cl/3378041
This commit is contained in:
parent
009aebdba8
commit
d1524217df
@ -563,7 +563,7 @@ func writeText(w io.Writer, text []byte, html bool) {
|
|||||||
|
|
||||||
|
|
||||||
// Write anything to w; optionally html-escaped.
|
// Write anything to w; optionally html-escaped.
|
||||||
func writeAny(w io.Writer, x interface{}, html bool) {
|
func writeAny(w io.Writer, html bool, x interface{}) {
|
||||||
switch v := x.(type) {
|
switch v := x.(type) {
|
||||||
case []byte:
|
case []byte:
|
||||||
writeText(w, v, html)
|
writeText(w, v, html)
|
||||||
@ -584,23 +584,23 @@ func writeAny(w io.Writer, x interface{}, html bool) {
|
|||||||
|
|
||||||
|
|
||||||
// Template formatter for "html" format.
|
// Template formatter for "html" format.
|
||||||
func htmlFmt(w io.Writer, x interface{}, format string) {
|
func htmlFmt(w io.Writer, format string, x ...interface{}) {
|
||||||
writeAny(w, x, true)
|
writeAny(w, true, x[0])
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Template formatter for "html-esc" format.
|
// Template formatter for "html-esc" format.
|
||||||
func htmlEscFmt(w io.Writer, x interface{}, format string) {
|
func htmlEscFmt(w io.Writer, format string, x ...interface{}) {
|
||||||
var buf bytes.Buffer
|
var buf bytes.Buffer
|
||||||
writeAny(&buf, x, false)
|
writeAny(&buf, false, x[0])
|
||||||
template.HTMLEscape(w, buf.Bytes())
|
template.HTMLEscape(w, buf.Bytes())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Template formatter for "html-comment" format.
|
// Template formatter for "html-comment" format.
|
||||||
func htmlCommentFmt(w io.Writer, x interface{}, format string) {
|
func htmlCommentFmt(w io.Writer, format string, x ...interface{}) {
|
||||||
var buf bytes.Buffer
|
var buf bytes.Buffer
|
||||||
writeAny(&buf, x, false)
|
writeAny(&buf, false, x[0])
|
||||||
// TODO(gri) Provide list of words (e.g. function parameters)
|
// TODO(gri) Provide list of words (e.g. function parameters)
|
||||||
// to be emphasized by ToHTML.
|
// to be emphasized by ToHTML.
|
||||||
doc.ToHTML(w, buf.Bytes(), nil) // does html-escaping
|
doc.ToHTML(w, buf.Bytes(), nil) // does html-escaping
|
||||||
@ -608,13 +608,13 @@ func htmlCommentFmt(w io.Writer, x interface{}, format string) {
|
|||||||
|
|
||||||
|
|
||||||
// Template formatter for "" (default) format.
|
// Template formatter for "" (default) format.
|
||||||
func textFmt(w io.Writer, x interface{}, format string) {
|
func textFmt(w io.Writer, format string, x ...interface{}) {
|
||||||
writeAny(w, x, false)
|
writeAny(w, false, x[0])
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Template formatter for the various "url-xxx" formats.
|
// Template formatter for the various "url-xxx" formats.
|
||||||
func urlFmt(w io.Writer, x interface{}, format string) {
|
func urlFmt(w io.Writer, format string, x ...interface{}) {
|
||||||
var path string
|
var path string
|
||||||
var line int
|
var line int
|
||||||
|
|
||||||
@ -622,7 +622,7 @@ func urlFmt(w io.Writer, x interface{}, format string) {
|
|||||||
type positioner interface {
|
type positioner interface {
|
||||||
Pos() token.Position
|
Pos() token.Position
|
||||||
}
|
}
|
||||||
switch t := x.(type) {
|
switch t := x[0].(type) {
|
||||||
case string:
|
case string:
|
||||||
path = t
|
path = t
|
||||||
case positioner:
|
case positioner:
|
||||||
@ -676,14 +676,14 @@ var infoKinds = [nKinds]string{
|
|||||||
|
|
||||||
|
|
||||||
// Template formatter for "infoKind" format.
|
// Template formatter for "infoKind" format.
|
||||||
func infoKindFmt(w io.Writer, x interface{}, format string) {
|
func infoKindFmt(w io.Writer, format string, x ...interface{}) {
|
||||||
fmt.Fprintf(w, infoKinds[x.(SpotKind)]) // infoKind entries are html-escaped
|
fmt.Fprintf(w, infoKinds[x[0].(SpotKind)]) // infoKind entries are html-escaped
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Template formatter for "infoLine" format.
|
// Template formatter for "infoLine" format.
|
||||||
func infoLineFmt(w io.Writer, x interface{}, format string) {
|
func infoLineFmt(w io.Writer, format string, x ...interface{}) {
|
||||||
info := x.(SpotInfo)
|
info := x[0].(SpotInfo)
|
||||||
line := info.Lori()
|
line := info.Lori()
|
||||||
if info.IsIndex() {
|
if info.IsIndex() {
|
||||||
index, _ := searchIndex.get()
|
index, _ := searchIndex.get()
|
||||||
@ -702,8 +702,8 @@ func infoLineFmt(w io.Writer, x interface{}, format string) {
|
|||||||
|
|
||||||
|
|
||||||
// Template formatter for "infoSnippet" format.
|
// Template formatter for "infoSnippet" format.
|
||||||
func infoSnippetFmt(w io.Writer, x interface{}, format string) {
|
func infoSnippetFmt(w io.Writer, format string, x ...interface{}) {
|
||||||
info := x.(SpotInfo)
|
info := x[0].(SpotInfo)
|
||||||
text := `<span class="alert">no snippet text available</span>`
|
text := `<span class="alert">no snippet text available</span>`
|
||||||
if info.IsIndex() {
|
if info.IsIndex() {
|
||||||
index, _ := searchIndex.get()
|
index, _ := searchIndex.get()
|
||||||
@ -716,30 +716,30 @@ func infoSnippetFmt(w io.Writer, x interface{}, format string) {
|
|||||||
|
|
||||||
|
|
||||||
// Template formatter for "padding" format.
|
// Template formatter for "padding" format.
|
||||||
func paddingFmt(w io.Writer, x interface{}, format string) {
|
func paddingFmt(w io.Writer, format string, x ...interface{}) {
|
||||||
for i := x.(int); i > 0; i-- {
|
for i := x[0].(int); i > 0; i-- {
|
||||||
fmt.Fprint(w, `<td width="25"></td>`)
|
fmt.Fprint(w, `<td width="25"></td>`)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Template formatter for "time" format.
|
// Template formatter for "time" format.
|
||||||
func timeFmt(w io.Writer, x interface{}, format string) {
|
func timeFmt(w io.Writer, format string, x ...interface{}) {
|
||||||
template.HTMLEscape(w, []byte(time.SecondsToLocalTime(x.(int64)/1e9).String()))
|
template.HTMLEscape(w, []byte(time.SecondsToLocalTime(x[0].(int64)/1e9).String()))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Template formatter for "dir/" format.
|
// Template formatter for "dir/" format.
|
||||||
func dirslashFmt(w io.Writer, x interface{}, format string) {
|
func dirslashFmt(w io.Writer, format string, x ...interface{}) {
|
||||||
if x.(*os.FileInfo).IsDirectory() {
|
if x[0].(*os.FileInfo).IsDirectory() {
|
||||||
w.Write([]byte{'/'})
|
w.Write([]byte{'/'})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Template formatter for "localname" format.
|
// Template formatter for "localname" format.
|
||||||
func localnameFmt(w io.Writer, x interface{}, format string) {
|
func localnameFmt(w io.Writer, format string, x ...interface{}) {
|
||||||
_, localname := pathutil.Split(x.(string))
|
_, localname := pathutil.Split(x[0].(string))
|
||||||
template.HTMLEscape(w, []byte(localname))
|
template.HTMLEscape(w, []byte(localname))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -367,7 +367,7 @@ func main() {
|
|||||||
if i > 0 {
|
if i > 0 {
|
||||||
fmt.Println()
|
fmt.Println()
|
||||||
}
|
}
|
||||||
writeAny(os.Stdout, d, *html)
|
writeAny(os.Stdout, *html, d)
|
||||||
fmt.Println()
|
fmt.Println()
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
|
@ -16,12 +16,14 @@ import (
|
|||||||
// It is stored under the name "str" and is the default formatter.
|
// It is stored under the name "str" and is the default formatter.
|
||||||
// You can override the default formatter by storing your default
|
// You can override the default formatter by storing your default
|
||||||
// under the name "" in your custom formatter map.
|
// under the name "" in your custom formatter map.
|
||||||
func StringFormatter(w io.Writer, value interface{}, format string) {
|
func StringFormatter(w io.Writer, format string, value ...interface{}) {
|
||||||
if b, ok := value.([]byte); ok {
|
if len(value) == 1 {
|
||||||
|
if b, ok := value[0].([]byte); ok {
|
||||||
w.Write(b)
|
w.Write(b)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
fmt.Fprint(w, value)
|
}
|
||||||
|
fmt.Fprint(w, value...)
|
||||||
}
|
}
|
||||||
|
|
||||||
var (
|
var (
|
||||||
@ -60,11 +62,15 @@ func HTMLEscape(w io.Writer, s []byte) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// HTMLFormatter formats arbitrary values for HTML
|
// HTMLFormatter formats arbitrary values for HTML
|
||||||
func HTMLFormatter(w io.Writer, value interface{}, format string) {
|
func HTMLFormatter(w io.Writer, format string, value ...interface{}) {
|
||||||
b, ok := value.([]byte)
|
ok := false
|
||||||
|
var b []byte
|
||||||
|
if len(value) == 1 {
|
||||||
|
b, ok = value[0].([]byte)
|
||||||
|
}
|
||||||
if !ok {
|
if !ok {
|
||||||
var buf bytes.Buffer
|
var buf bytes.Buffer
|
||||||
fmt.Fprint(&buf, value)
|
fmt.Fprint(&buf, value...)
|
||||||
b = buf.Bytes()
|
b = buf.Bytes()
|
||||||
}
|
}
|
||||||
HTMLEscape(w, b)
|
HTMLEscape(w, b)
|
||||||
|
@ -55,9 +55,10 @@
|
|||||||
map passed to the template set up routines or in the default
|
map passed to the template set up routines or in the default
|
||||||
set ("html","str","") and is used to process the data for
|
set ("html","str","") and is used to process the data for
|
||||||
output. The formatter function has signature
|
output. The formatter function has signature
|
||||||
func(wr io.Writer, data interface{}, formatter string)
|
func(wr io.Writer, formatter string, data ...interface{})
|
||||||
where wr is the destination for output, data is the field
|
where wr is the destination for output, data holds the field
|
||||||
value, and formatter is its name at the invocation site.
|
values at the instantiation, and formatter is its name at
|
||||||
|
the invocation site.
|
||||||
*/
|
*/
|
||||||
package template
|
package template
|
||||||
|
|
||||||
@ -101,7 +102,7 @@ const (
|
|||||||
|
|
||||||
// FormatterMap is the type describing the mapping from formatter
|
// FormatterMap is the type describing the mapping from formatter
|
||||||
// names to the functions that implement them.
|
// names to the functions that implement them.
|
||||||
type FormatterMap map[string]func(io.Writer, interface{}, string)
|
type FormatterMap map[string]func(io.Writer, string, ...interface{})
|
||||||
|
|
||||||
// Built-in formatters.
|
// Built-in formatters.
|
||||||
var builtins = FormatterMap{
|
var builtins = FormatterMap{
|
||||||
@ -690,13 +691,13 @@ func (t *Template) writeVariable(v *variableElement, st *state) {
|
|||||||
// is it in user-supplied map?
|
// is it in user-supplied map?
|
||||||
if t.fmap != nil {
|
if t.fmap != nil {
|
||||||
if fn, ok := t.fmap[formatter]; ok {
|
if fn, ok := t.fmap[formatter]; ok {
|
||||||
fn(st.wr, val, formatter)
|
fn(st.wr, formatter, val)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// is it in builtin map?
|
// is it in builtin map?
|
||||||
if fn, ok := builtins[formatter]; ok {
|
if fn, ok := builtins[formatter]; ok {
|
||||||
fn(st.wr, val, formatter)
|
fn(st.wr, formatter, val)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
t.execError(st, v.linenum, "missing formatter %s for variable %s", formatter, v.name)
|
t.execError(st, v.linenum, "missing formatter %s for variable %s", formatter, v.name)
|
||||||
|
@ -76,9 +76,12 @@ func plus1(v interface{}) string {
|
|||||||
return fmt.Sprint(i + 1)
|
return fmt.Sprint(i + 1)
|
||||||
}
|
}
|
||||||
|
|
||||||
func writer(f func(interface{}) string) func(io.Writer, interface{}, string) {
|
func writer(f func(interface{}) string) func(io.Writer, string, ...interface{}) {
|
||||||
return func(w io.Writer, v interface{}, format string) {
|
return func(w io.Writer, format string, v ...interface{}) {
|
||||||
io.WriteString(w, f(v))
|
if len(v) != 1 {
|
||||||
|
panic("test writer expected one arg")
|
||||||
|
}
|
||||||
|
io.WriteString(w, f(v[0]))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -601,7 +604,7 @@ func TestHTMLFormatterWithByte(t *testing.T) {
|
|||||||
s := "Test string."
|
s := "Test string."
|
||||||
b := []byte(s)
|
b := []byte(s)
|
||||||
var buf bytes.Buffer
|
var buf bytes.Buffer
|
||||||
HTMLFormatter(&buf, b, "")
|
HTMLFormatter(&buf, "", b)
|
||||||
bs := buf.String()
|
bs := buf.String()
|
||||||
if bs != s {
|
if bs != s {
|
||||||
t.Errorf("munged []byte, expected: %s got: %s", s, bs)
|
t.Errorf("munged []byte, expected: %s got: %s", s, bs)
|
||||||
|
Loading…
Reference in New Issue
Block a user