github.com/xushiwei/go@v0.0.0-20130601165731-2b9d83f45bc9/src/cmd/fix/testdata/reflect.template.go.in (about) 1 // Copyright 2009 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 /* 6 Data-driven templates for generating textual output such as 7 HTML. 8 9 Templates are executed by applying them to a data structure. 10 Annotations in the template refer to elements of the data 11 structure (typically a field of a struct or a key in a map) 12 to control execution and derive values to be displayed. 13 The template walks the structure as it executes and the 14 "cursor" @ represents the value at the current location 15 in the structure. 16 17 Data items may be values or pointers; the interface hides the 18 indirection. 19 20 In the following, 'field' is one of several things, according to the data. 21 22 - The name of a field of a struct (result = data.field), 23 - The value stored in a map under that key (result = data[field]), or 24 - The result of invoking a niladic single-valued method with that name 25 (result = data.field()) 26 27 Major constructs ({} are the default delimiters for template actions; 28 [] are the notation in this comment for optional elements): 29 30 {# comment } 31 32 A one-line comment. 33 34 {.section field} XXX [ {.or} YYY ] {.end} 35 36 Set @ to the value of the field. It may be an explicit @ 37 to stay at the same point in the data. If the field is nil 38 or empty, execute YYY; otherwise execute XXX. 39 40 {.repeated section field} XXX [ {.alternates with} ZZZ ] [ {.or} YYY ] {.end} 41 42 Like .section, but field must be an array or slice. XXX 43 is executed for each element. If the array is nil or empty, 44 YYY is executed instead. If the {.alternates with} marker 45 is present, ZZZ is executed between iterations of XXX. 46 47 {field} 48 {field1 field2 ...} 49 {field|formatter} 50 {field1 field2...|formatter} 51 {field|formatter1|formatter2} 52 53 Insert the value of the fields into the output. Each field is 54 first looked for in the cursor, as in .section and .repeated. 55 If it is not found, the search continues in outer sections 56 until the top level is reached. 57 58 If the field value is a pointer, leading asterisks indicate 59 that the value to be inserted should be evaluated through the 60 pointer. For example, if x.p is of type *int, {x.p} will 61 insert the value of the pointer but {*x.p} will insert the 62 value of the underlying integer. If the value is nil or not a 63 pointer, asterisks have no effect. 64 65 If a formatter is specified, it must be named in the formatter 66 map passed to the template set up routines or in the default 67 set ("html","str","") and is used to process the data for 68 output. The formatter function has signature 69 func(wr io.Writer, formatter string, data ...interface{}) 70 where wr is the destination for output, data holds the field 71 values at the instantiation, and formatter is its name at 72 the invocation site. The default formatter just concatenates 73 the string representations of the fields. 74 75 Multiple formatters separated by the pipeline character | are 76 executed sequentially, with each formatter receiving the bytes 77 emitted by the one to its left. 78 79 The delimiter strings get their default value, "{" and "}", from 80 JSON-template. They may be set to any non-empty, space-free 81 string using the SetDelims method. Their value can be printed 82 in the output using {.meta-left} and {.meta-right}. 83 */ 84 package template 85 86 import ( 87 "bytes" 88 "container/vector" 89 "fmt" 90 "io" 91 "io/ioutil" 92 "os" 93 "reflect" 94 "strings" 95 "unicode" 96 "utf8" 97 ) 98 99 // Errors returned during parsing and execution. Users may extract the information and reformat 100 // if they desire. 101 type Error struct { 102 Line int 103 Msg string 104 } 105 106 func (e *Error) String() string { return fmt.Sprintf("line %d: %s", e.Line, e.Msg) } 107 108 // Most of the literals are aces. 109 var lbrace = []byte{'{'} 110 var rbrace = []byte{'}'} 111 var space = []byte{' '} 112 var tab = []byte{'\t'} 113 114 // The various types of "tokens", which are plain text or (usually) brace-delimited descriptors 115 const ( 116 tokAlternates = iota 117 tokComment 118 tokEnd 119 tokLiteral 120 tokOr 121 tokRepeated 122 tokSection 123 tokText 124 tokVariable 125 ) 126 127 // FormatterMap is the type describing the mapping from formatter 128 // names to the functions that implement them. 129 type FormatterMap map[string]func(io.Writer, string, ...interface{}) 130 131 // Built-in formatters. 132 var builtins = FormatterMap{ 133 "html": HTMLFormatter, 134 "str": StringFormatter, 135 "": StringFormatter, 136 } 137 138 // The parsed state of a template is a vector of xxxElement structs. 139 // Sections have line numbers so errors can be reported better during execution. 140 141 // Plain text. 142 type textElement struct { 143 text []byte 144 } 145 146 // A literal such as .meta-left or .meta-right 147 type literalElement struct { 148 text []byte 149 } 150 151 // A variable invocation to be evaluated 152 type variableElement struct { 153 linenum int 154 word []string // The fields in the invocation. 155 fmts []string // Names of formatters to apply. len(fmts) > 0 156 } 157 158 // A .section block, possibly with a .or 159 type sectionElement struct { 160 linenum int // of .section itself 161 field string // cursor field for this block 162 start int // first element 163 or int // first element of .or block 164 end int // one beyond last element 165 } 166 167 // A .repeated block, possibly with a .or and a .alternates 168 type repeatedElement struct { 169 sectionElement // It has the same structure... 170 altstart int // ... except for alternates 171 altend int 172 } 173 174 // Template is the type that represents a template definition. 175 // It is unchanged after parsing. 176 type Template struct { 177 fmap FormatterMap // formatters for variables 178 // Used during parsing: 179 ldelim, rdelim []byte // delimiters; default {} 180 buf []byte // input text to process 181 p int // position in buf 182 linenum int // position in input 183 // Parsed results: 184 elems *vector.Vector 185 } 186 187 // Internal state for executing a Template. As we evaluate the struct, 188 // the data item descends into the fields associated with sections, etc. 189 // Parent is used to walk upwards to find variables higher in the tree. 190 type state struct { 191 parent *state // parent in hierarchy 192 data reflect.Value // the driver data for this section etc. 193 wr io.Writer // where to send output 194 buf [2]bytes.Buffer // alternating buffers used when chaining formatters 195 } 196 197 func (parent *state) clone(data reflect.Value) *state { 198 return &state{parent: parent, data: data, wr: parent.wr} 199 } 200 201 // New creates a new template with the specified formatter map (which 202 // may be nil) to define auxiliary functions for formatting variables. 203 func New(fmap FormatterMap) *Template { 204 t := new(Template) 205 t.fmap = fmap 206 t.ldelim = lbrace 207 t.rdelim = rbrace 208 t.elems = new(vector.Vector) 209 return t 210 } 211 212 // Report error and stop executing. The line number must be provided explicitly. 213 func (t *Template) execError(st *state, line int, err string, args ...interface{}) { 214 panic(&Error{line, fmt.Sprintf(err, args...)}) 215 } 216 217 // Report error, panic to terminate parsing. 218 // The line number comes from the template state. 219 func (t *Template) parseError(err string, args ...interface{}) { 220 panic(&Error{t.linenum, fmt.Sprintf(err, args...)}) 221 } 222 223 // Is this an exported - upper case - name? 224 func isExported(name string) bool { 225 rune, _ := utf8.DecodeRuneInString(name) 226 return unicode.IsUpper(rune) 227 } 228 229 // -- Lexical analysis 230 231 // Is c a white space character? 232 func white(c uint8) bool { return c == ' ' || c == '\t' || c == '\r' || c == '\n' } 233 234 // Safely, does s[n:n+len(t)] == t? 235 func equal(s []byte, n int, t []byte) bool { 236 b := s[n:] 237 if len(t) > len(b) { // not enough space left for a match. 238 return false 239 } 240 for i, c := range t { 241 if c != b[i] { 242 return false 243 } 244 } 245 return true 246 } 247 248 // nextItem returns the next item from the input buffer. If the returned 249 // item is empty, we are at EOF. The item will be either a 250 // delimited string or a non-empty string between delimited 251 // strings. Tokens stop at (but include, if plain text) a newline. 252 // Action tokens on a line by themselves drop any space on 253 // either side, up to and including the newline. 254 func (t *Template) nextItem() []byte { 255 startOfLine := t.p == 0 || t.buf[t.p-1] == '\n' 256 start := t.p 257 var i int 258 newline := func() { 259 t.linenum++ 260 i++ 261 } 262 // Leading white space up to but not including newline 263 for i = start; i < len(t.buf); i++ { 264 if t.buf[i] == '\n' || !white(t.buf[i]) { 265 break 266 } 267 } 268 leadingSpace := i > start 269 // What's left is nothing, newline, delimited string, or plain text 270 switch { 271 case i == len(t.buf): 272 // EOF; nothing to do 273 case t.buf[i] == '\n': 274 newline() 275 case equal(t.buf, i, t.ldelim): 276 left := i // Start of left delimiter. 277 right := -1 // Will be (immediately after) right delimiter. 278 haveText := false // Delimiters contain text. 279 i += len(t.ldelim) 280 // Find the end of the action. 281 for ; i < len(t.buf); i++ { 282 if t.buf[i] == '\n' { 283 break 284 } 285 if equal(t.buf, i, t.rdelim) { 286 i += len(t.rdelim) 287 right = i 288 break 289 } 290 haveText = true 291 } 292 if right < 0 { 293 t.parseError("unmatched opening delimiter") 294 return nil 295 } 296 // Is this a special action (starts with '.' or '#') and the only thing on the line? 297 if startOfLine && haveText { 298 firstChar := t.buf[left+len(t.ldelim)] 299 if firstChar == '.' || firstChar == '#' { 300 // It's special and the first thing on the line. Is it the last? 301 for j := right; j < len(t.buf) && white(t.buf[j]); j++ { 302 if t.buf[j] == '\n' { 303 // Yes it is. Drop the surrounding space and return the {.foo} 304 t.linenum++ 305 t.p = j + 1 306 return t.buf[left:right] 307 } 308 } 309 } 310 } 311 // No it's not. If there's leading space, return that. 312 if leadingSpace { 313 // not trimming space: return leading white space if there is some. 314 t.p = left 315 return t.buf[start:left] 316 } 317 // Return the word, leave the trailing space. 318 start = left 319 break 320 default: 321 for ; i < len(t.buf); i++ { 322 if t.buf[i] == '\n' { 323 newline() 324 break 325 } 326 if equal(t.buf, i, t.ldelim) { 327 break 328 } 329 } 330 } 331 item := t.buf[start:i] 332 t.p = i 333 return item 334 } 335 336 // Turn a byte array into a white-space-split array of strings. 337 func words(buf []byte) []string { 338 s := make([]string, 0, 5) 339 p := 0 // position in buf 340 // one word per loop 341 for i := 0; ; i++ { 342 // skip white space 343 for ; p < len(buf) && white(buf[p]); p++ { 344 } 345 // grab word 346 start := p 347 for ; p < len(buf) && !white(buf[p]); p++ { 348 } 349 if start == p { // no text left 350 break 351 } 352 s = append(s, string(buf[start:p])) 353 } 354 return s 355 } 356 357 // Analyze an item and return its token type and, if it's an action item, an array of 358 // its constituent words. 359 func (t *Template) analyze(item []byte) (tok int, w []string) { 360 // item is known to be non-empty 361 if !equal(item, 0, t.ldelim) { // doesn't start with left delimiter 362 tok = tokText 363 return 364 } 365 if !equal(item, len(item)-len(t.rdelim), t.rdelim) { // doesn't end with right delimiter 366 t.parseError("internal error: unmatched opening delimiter") // lexing should prevent this 367 return 368 } 369 if len(item) <= len(t.ldelim)+len(t.rdelim) { // no contents 370 t.parseError("empty directive") 371 return 372 } 373 // Comment 374 if item[len(t.ldelim)] == '#' { 375 tok = tokComment 376 return 377 } 378 // Split into words 379 w = words(item[len(t.ldelim) : len(item)-len(t.rdelim)]) // drop final delimiter 380 if len(w) == 0 { 381 t.parseError("empty directive") 382 return 383 } 384 if len(w) > 0 && w[0][0] != '.' { 385 tok = tokVariable 386 return 387 } 388 switch w[0] { 389 case ".meta-left", ".meta-right", ".space", ".tab": 390 tok = tokLiteral 391 return 392 case ".or": 393 tok = tokOr 394 return 395 case ".end": 396 tok = tokEnd 397 return 398 case ".section": 399 if len(w) != 2 { 400 t.parseError("incorrect fields for .section: %s", item) 401 return 402 } 403 tok = tokSection 404 return 405 case ".repeated": 406 if len(w) != 3 || w[1] != "section" { 407 t.parseError("incorrect fields for .repeated: %s", item) 408 return 409 } 410 tok = tokRepeated 411 return 412 case ".alternates": 413 if len(w) != 2 || w[1] != "with" { 414 t.parseError("incorrect fields for .alternates: %s", item) 415 return 416 } 417 tok = tokAlternates 418 return 419 } 420 t.parseError("bad directive: %s", item) 421 return 422 } 423 424 // formatter returns the Formatter with the given name in the Template, or nil if none exists. 425 func (t *Template) formatter(name string) func(io.Writer, string, ...interface{}) { 426 if t.fmap != nil { 427 if fn := t.fmap[name]; fn != nil { 428 return fn 429 } 430 } 431 return builtins[name] 432 } 433 434 // -- Parsing 435 436 // Allocate a new variable-evaluation element. 437 func (t *Template) newVariable(words []string) *variableElement { 438 // After the final space-separated argument, formatters may be specified separated 439 // by pipe symbols, for example: {a b c|d|e} 440 441 // Until we learn otherwise, formatters contains a single name: "", the default formatter. 442 formatters := []string{""} 443 lastWord := words[len(words)-1] 444 bar := strings.IndexRune(lastWord, '|') 445 if bar >= 0 { 446 words[len(words)-1] = lastWord[0:bar] 447 formatters = strings.Split(lastWord[bar+1:], "|") 448 } 449 450 // We could remember the function address here and avoid the lookup later, 451 // but it's more dynamic to let the user change the map contents underfoot. 452 // We do require the name to be present, though. 453 454 // Is it in user-supplied map? 455 for _, f := range formatters { 456 if t.formatter(f) == nil { 457 t.parseError("unknown formatter: %q", f) 458 } 459 } 460 return &variableElement{t.linenum, words, formatters} 461 } 462 463 // Grab the next item. If it's simple, just append it to the template. 464 // Otherwise return its details. 465 func (t *Template) parseSimple(item []byte) (done bool, tok int, w []string) { 466 tok, w = t.analyze(item) 467 done = true // assume for simplicity 468 switch tok { 469 case tokComment: 470 return 471 case tokText: 472 t.elems.Push(&textElement{item}) 473 return 474 case tokLiteral: 475 switch w[0] { 476 case ".meta-left": 477 t.elems.Push(&literalElement{t.ldelim}) 478 case ".meta-right": 479 t.elems.Push(&literalElement{t.rdelim}) 480 case ".space": 481 t.elems.Push(&literalElement{space}) 482 case ".tab": 483 t.elems.Push(&literalElement{tab}) 484 default: 485 t.parseError("internal error: unknown literal: %s", w[0]) 486 } 487 return 488 case tokVariable: 489 t.elems.Push(t.newVariable(w)) 490 return 491 } 492 return false, tok, w 493 } 494 495 // parseRepeated and parseSection are mutually recursive 496 497 func (t *Template) parseRepeated(words []string) *repeatedElement { 498 r := new(repeatedElement) 499 t.elems.Push(r) 500 r.linenum = t.linenum 501 r.field = words[2] 502 // Scan section, collecting true and false (.or) blocks. 503 r.start = t.elems.Len() 504 r.or = -1 505 r.altstart = -1 506 r.altend = -1 507 Loop: 508 for { 509 item := t.nextItem() 510 if len(item) == 0 { 511 t.parseError("missing .end for .repeated section") 512 break 513 } 514 done, tok, w := t.parseSimple(item) 515 if done { 516 continue 517 } 518 switch tok { 519 case tokEnd: 520 break Loop 521 case tokOr: 522 if r.or >= 0 { 523 t.parseError("extra .or in .repeated section") 524 break Loop 525 } 526 r.altend = t.elems.Len() 527 r.or = t.elems.Len() 528 case tokSection: 529 t.parseSection(w) 530 case tokRepeated: 531 t.parseRepeated(w) 532 case tokAlternates: 533 if r.altstart >= 0 { 534 t.parseError("extra .alternates in .repeated section") 535 break Loop 536 } 537 if r.or >= 0 { 538 t.parseError(".alternates inside .or block in .repeated section") 539 break Loop 540 } 541 r.altstart = t.elems.Len() 542 default: 543 t.parseError("internal error: unknown repeated section item: %s", item) 544 break Loop 545 } 546 } 547 if r.altend < 0 { 548 r.altend = t.elems.Len() 549 } 550 r.end = t.elems.Len() 551 return r 552 } 553 554 func (t *Template) parseSection(words []string) *sectionElement { 555 s := new(sectionElement) 556 t.elems.Push(s) 557 s.linenum = t.linenum 558 s.field = words[1] 559 // Scan section, collecting true and false (.or) blocks. 560 s.start = t.elems.Len() 561 s.or = -1 562 Loop: 563 for { 564 item := t.nextItem() 565 if len(item) == 0 { 566 t.parseError("missing .end for .section") 567 break 568 } 569 done, tok, w := t.parseSimple(item) 570 if done { 571 continue 572 } 573 switch tok { 574 case tokEnd: 575 break Loop 576 case tokOr: 577 if s.or >= 0 { 578 t.parseError("extra .or in .section") 579 break Loop 580 } 581 s.or = t.elems.Len() 582 case tokSection: 583 t.parseSection(w) 584 case tokRepeated: 585 t.parseRepeated(w) 586 case tokAlternates: 587 t.parseError(".alternates not in .repeated") 588 default: 589 t.parseError("internal error: unknown section item: %s", item) 590 } 591 } 592 s.end = t.elems.Len() 593 return s 594 } 595 596 func (t *Template) parse() { 597 for { 598 item := t.nextItem() 599 if len(item) == 0 { 600 break 601 } 602 done, tok, w := t.parseSimple(item) 603 if done { 604 continue 605 } 606 switch tok { 607 case tokOr, tokEnd, tokAlternates: 608 t.parseError("unexpected %s", w[0]) 609 case tokSection: 610 t.parseSection(w) 611 case tokRepeated: 612 t.parseRepeated(w) 613 default: 614 t.parseError("internal error: bad directive in parse: %s", item) 615 } 616 } 617 } 618 619 // -- Execution 620 621 // Evaluate interfaces and pointers looking for a value that can look up the name, via a 622 // struct field, method, or map key, and return the result of the lookup. 623 func (t *Template) lookup(st *state, v reflect.Value, name string) reflect.Value { 624 for v != nil { 625 typ := v.Type() 626 if n := v.Type().NumMethod(); n > 0 { 627 for i := 0; i < n; i++ { 628 m := typ.Method(i) 629 mtyp := m.Type 630 if m.Name == name && mtyp.NumIn() == 1 && mtyp.NumOut() == 1 { 631 if !isExported(name) { 632 t.execError(st, t.linenum, "name not exported: %s in type %s", name, st.data.Type()) 633 } 634 return v.Method(i).Call(nil)[0] 635 } 636 } 637 } 638 switch av := v.(type) { 639 case *reflect.PtrValue: 640 v = av.Elem() 641 case *reflect.InterfaceValue: 642 v = av.Elem() 643 case *reflect.StructValue: 644 if !isExported(name) { 645 t.execError(st, t.linenum, "name not exported: %s in type %s", name, st.data.Type()) 646 } 647 return av.FieldByName(name) 648 case *reflect.MapValue: 649 if v := av.Elem(reflect.NewValue(name)); v != nil { 650 return v 651 } 652 return reflect.MakeZero(typ.(*reflect.MapType).Elem()) 653 default: 654 return nil 655 } 656 } 657 return v 658 } 659 660 // indirectPtr returns the item numLevels levels of indirection below the value. 661 // It is forgiving: if the value is not a pointer, it returns it rather than giving 662 // an error. If the pointer is nil, it is returned as is. 663 func indirectPtr(v reflect.Value, numLevels int) reflect.Value { 664 for i := numLevels; v != nil && i > 0; i++ { 665 if p, ok := v.(*reflect.PtrValue); ok { 666 if p.IsNil() { 667 return v 668 } 669 v = p.Elem() 670 } else { 671 break 672 } 673 } 674 return v 675 } 676 677 // Walk v through pointers and interfaces, extracting the elements within. 678 func indirect(v reflect.Value) reflect.Value { 679 loop: 680 for v != nil { 681 switch av := v.(type) { 682 case *reflect.PtrValue: 683 v = av.Elem() 684 case *reflect.InterfaceValue: 685 v = av.Elem() 686 default: 687 break loop 688 } 689 } 690 return v 691 } 692 693 // If the data for this template is a struct, find the named variable. 694 // Names of the form a.b.c are walked down the data tree. 695 // The special name "@" (the "cursor") denotes the current data. 696 // The value coming in (st.data) might need indirecting to reach 697 // a struct while the return value is not indirected - that is, 698 // it represents the actual named field. Leading stars indicate 699 // levels of indirection to be applied to the value. 700 func (t *Template) findVar(st *state, s string) reflect.Value { 701 data := st.data 702 flattenedName := strings.TrimLeft(s, "*") 703 numStars := len(s) - len(flattenedName) 704 s = flattenedName 705 if s == "@" { 706 return indirectPtr(data, numStars) 707 } 708 for _, elem := range strings.Split(s, ".") { 709 // Look up field; data must be a struct or map. 710 data = t.lookup(st, data, elem) 711 if data == nil { 712 return nil 713 } 714 } 715 return indirectPtr(data, numStars) 716 } 717 718 // Is there no data to look at? 719 func empty(v reflect.Value) bool { 720 v = indirect(v) 721 if v == nil { 722 return true 723 } 724 switch v := v.(type) { 725 case *reflect.BoolValue: 726 return v.Get() == false 727 case *reflect.StringValue: 728 return v.Get() == "" 729 case *reflect.StructValue: 730 return false 731 case *reflect.MapValue: 732 return false 733 case *reflect.ArrayValue: 734 return v.Len() == 0 735 case *reflect.SliceValue: 736 return v.Len() == 0 737 } 738 return false 739 } 740 741 // Look up a variable or method, up through the parent if necessary. 742 func (t *Template) varValue(name string, st *state) reflect.Value { 743 field := t.findVar(st, name) 744 if field == nil { 745 if st.parent == nil { 746 t.execError(st, t.linenum, "name not found: %s in type %s", name, st.data.Type()) 747 } 748 return t.varValue(name, st.parent) 749 } 750 return field 751 } 752 753 func (t *Template) format(wr io.Writer, fmt string, val []interface{}, v *variableElement, st *state) { 754 fn := t.formatter(fmt) 755 if fn == nil { 756 t.execError(st, v.linenum, "missing formatter %s for variable %s", fmt, v.word[0]) 757 } 758 fn(wr, fmt, val...) 759 } 760 761 // Evaluate a variable, looking up through the parent if necessary. 762 // If it has a formatter attached ({var|formatter}) run that too. 763 func (t *Template) writeVariable(v *variableElement, st *state) { 764 // Turn the words of the invocation into values. 765 val := make([]interface{}, len(v.word)) 766 for i, word := range v.word { 767 val[i] = t.varValue(word, st).Interface() 768 } 769 770 for i, fmt := range v.fmts[:len(v.fmts)-1] { 771 b := &st.buf[i&1] 772 b.Reset() 773 t.format(b, fmt, val, v, st) 774 val = val[0:1] 775 val[0] = b.Bytes() 776 } 777 t.format(st.wr, v.fmts[len(v.fmts)-1], val, v, st) 778 } 779 780 // Execute element i. Return next index to execute. 781 func (t *Template) executeElement(i int, st *state) int { 782 switch elem := t.elems.At(i).(type) { 783 case *textElement: 784 st.wr.Write(elem.text) 785 return i + 1 786 case *literalElement: 787 st.wr.Write(elem.text) 788 return i + 1 789 case *variableElement: 790 t.writeVariable(elem, st) 791 return i + 1 792 case *sectionElement: 793 t.executeSection(elem, st) 794 return elem.end 795 case *repeatedElement: 796 t.executeRepeated(elem, st) 797 return elem.end 798 } 799 e := t.elems.At(i) 800 t.execError(st, 0, "internal error: bad directive in execute: %v %T\n", reflect.NewValue(e).Interface(), e) 801 return 0 802 } 803 804 // Execute the template. 805 func (t *Template) execute(start, end int, st *state) { 806 for i := start; i < end; { 807 i = t.executeElement(i, st) 808 } 809 } 810 811 // Execute a .section 812 func (t *Template) executeSection(s *sectionElement, st *state) { 813 // Find driver data for this section. It must be in the current struct. 814 field := t.varValue(s.field, st) 815 if field == nil { 816 t.execError(st, s.linenum, ".section: cannot find field %s in %s", s.field, st.data.Type()) 817 } 818 st = st.clone(field) 819 start, end := s.start, s.or 820 if !empty(field) { 821 // Execute the normal block. 822 if end < 0 { 823 end = s.end 824 } 825 } else { 826 // Execute the .or block. If it's missing, do nothing. 827 start, end = s.or, s.end 828 if start < 0 { 829 return 830 } 831 } 832 for i := start; i < end; { 833 i = t.executeElement(i, st) 834 } 835 } 836 837 // Return the result of calling the Iter method on v, or nil. 838 func iter(v reflect.Value) *reflect.ChanValue { 839 for j := 0; j < v.Type().NumMethod(); j++ { 840 mth := v.Type().Method(j) 841 fv := v.Method(j) 842 ft := fv.Type().(*reflect.FuncType) 843 // TODO(rsc): NumIn() should return 0 here, because ft is from a curried FuncValue. 844 if mth.Name != "Iter" || ft.NumIn() != 1 || ft.NumOut() != 1 { 845 continue 846 } 847 ct, ok := ft.Out(0).(*reflect.ChanType) 848 if !ok || ct.Dir()&reflect.RecvDir == 0 { 849 continue 850 } 851 return fv.Call(nil)[0].(*reflect.ChanValue) 852 } 853 return nil 854 } 855 856 // Execute a .repeated section 857 func (t *Template) executeRepeated(r *repeatedElement, st *state) { 858 // Find driver data for this section. It must be in the current struct. 859 field := t.varValue(r.field, st) 860 if field == nil { 861 t.execError(st, r.linenum, ".repeated: cannot find field %s in %s", r.field, st.data.Type()) 862 } 863 field = indirect(field) 864 865 start, end := r.start, r.or 866 if end < 0 { 867 end = r.end 868 } 869 if r.altstart >= 0 { 870 end = r.altstart 871 } 872 first := true 873 874 // Code common to all the loops. 875 loopBody := func(newst *state) { 876 // .alternates between elements 877 if !first && r.altstart >= 0 { 878 for i := r.altstart; i < r.altend; { 879 i = t.executeElement(i, newst) 880 } 881 } 882 first = false 883 for i := start; i < end; { 884 i = t.executeElement(i, newst) 885 } 886 } 887 888 if array, ok := field.(reflect.ArrayOrSliceValue); ok { 889 for j := 0; j < array.Len(); j++ { 890 loopBody(st.clone(array.Elem(j))) 891 } 892 } else if m, ok := field.(*reflect.MapValue); ok { 893 for _, key := range m.Keys() { 894 loopBody(st.clone(m.Elem(key))) 895 } 896 } else if ch := iter(field); ch != nil { 897 for { 898 e, ok := ch.Recv() 899 if !ok { 900 break 901 } 902 loopBody(st.clone(e)) 903 } 904 } else { 905 t.execError(st, r.linenum, ".repeated: cannot repeat %s (type %s)", 906 r.field, field.Type()) 907 } 908 909 if first { 910 // Empty. Execute the .or block, once. If it's missing, do nothing. 911 start, end := r.or, r.end 912 if start >= 0 { 913 newst := st.clone(field) 914 for i := start; i < end; { 915 i = t.executeElement(i, newst) 916 } 917 } 918 return 919 } 920 } 921 922 // A valid delimiter must contain no white space and be non-empty. 923 func validDelim(d []byte) bool { 924 if len(d) == 0 { 925 return false 926 } 927 for _, c := range d { 928 if white(c) { 929 return false 930 } 931 } 932 return true 933 } 934 935 // checkError is a deferred function to turn a panic with type *Error into a plain error return. 936 // Other panics are unexpected and so are re-enabled. 937 func checkError(error *os.Error) { 938 if v := recover(); v != nil { 939 if e, ok := v.(*Error); ok { 940 *error = e 941 } else { 942 // runtime errors should crash 943 panic(v) 944 } 945 } 946 } 947 948 // -- Public interface 949 950 // Parse initializes a Template by parsing its definition. The string 951 // s contains the template text. If any errors occur, Parse returns 952 // the error. 953 func (t *Template) Parse(s string) (err os.Error) { 954 if t.elems == nil { 955 return &Error{1, "template not allocated with New"} 956 } 957 if !validDelim(t.ldelim) || !validDelim(t.rdelim) { 958 return &Error{1, fmt.Sprintf("bad delimiter strings %q %q", t.ldelim, t.rdelim)} 959 } 960 defer checkError(&err) 961 t.buf = []byte(s) 962 t.p = 0 963 t.linenum = 1 964 t.parse() 965 return nil 966 } 967 968 // ParseFile is like Parse but reads the template definition from the 969 // named file. 970 func (t *Template) ParseFile(filename string) (err os.Error) { 971 b, err := ioutil.ReadFile(filename) 972 if err != nil { 973 return err 974 } 975 return t.Parse(string(b)) 976 } 977 978 // Execute applies a parsed template to the specified data object, 979 // generating output to wr. 980 func (t *Template) Execute(wr io.Writer, data interface{}) (err os.Error) { 981 // Extract the driver data. 982 val := reflect.NewValue(data) 983 defer checkError(&err) 984 t.p = 0 985 t.execute(0, t.elems.Len(), &state{parent: nil, data: val, wr: wr}) 986 return nil 987 } 988 989 // SetDelims sets the left and right delimiters for operations in the 990 // template. They are validated during parsing. They could be 991 // validated here but it's better to keep the routine simple. The 992 // delimiters are very rarely invalid and Parse has the necessary 993 // error-handling interface already. 994 func (t *Template) SetDelims(left, right string) { 995 t.ldelim = []byte(left) 996 t.rdelim = []byte(right) 997 } 998 999 // Parse creates a Template with default parameters (such as {} for 1000 // metacharacters). The string s contains the template text while 1001 // the formatter map fmap, which may be nil, defines auxiliary functions 1002 // for formatting variables. The template is returned. If any errors 1003 // occur, err will be non-nil. 1004 func Parse(s string, fmap FormatterMap) (t *Template, err os.Error) { 1005 t = New(fmap) 1006 err = t.Parse(s) 1007 if err != nil { 1008 t = nil 1009 } 1010 return 1011 } 1012 1013 // ParseFile is a wrapper function that creates a Template with default 1014 // parameters (such as {} for metacharacters). The filename identifies 1015 // a file containing the template text, while the formatter map fmap, which 1016 // may be nil, defines auxiliary functions for formatting variables. 1017 // The template is returned. If any errors occur, err will be non-nil. 1018 func ParseFile(filename string, fmap FormatterMap) (t *Template, err os.Error) { 1019 b, err := ioutil.ReadFile(filename) 1020 if err != nil { 1021 return nil, err 1022 } 1023 return Parse(string(b), fmap) 1024 } 1025 1026 // MustParse is like Parse but panics if the template cannot be parsed. 1027 func MustParse(s string, fmap FormatterMap) *Template { 1028 t, err := Parse(s, fmap) 1029 if err != nil { 1030 panic("template.MustParse error: " + err.String()) 1031 } 1032 return t 1033 } 1034 1035 // MustParseFile is like ParseFile but panics if the file cannot be read 1036 // or the template cannot be parsed. 1037 func MustParseFile(filename string, fmap FormatterMap) *Template { 1038 b, err := ioutil.ReadFile(filename) 1039 if err != nil { 1040 panic("template.MustParseFile error: " + err.String()) 1041 } 1042 return MustParse(string(b), fmap) 1043 }