OLD | NEW |
1 // Copyright 2011 The Go Authors. All rights reserved. | 1 // Copyright 2011 The Go Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style | 2 // Use of this source code is governed by a BSD-style |
3 // license that can be found in the LICENSE file. | 3 // license that can be found in the LICENSE file. |
4 | 4 |
5 package template | 5 package template |
6 | 6 |
7 import ( | 7 import ( |
8 "bytes" | 8 "bytes" |
9 "fmt" | 9 "fmt" |
10 "os" | 10 "os" |
| 11 "reflect" |
11 "runtime" | 12 "runtime" |
12 "strconv" | 13 "strconv" |
13 "strings" | 14 "strings" |
14 "unicode" | 15 "unicode" |
15 ) | 16 ) |
16 | 17 |
17 // Template is the representation of a parsed template. | 18 // Template is the representation of a parsed template. |
18 type Template struct { | 19 type Template struct { |
19 » name string | 20 » name string |
20 » root *listNode | 21 » root *listNode |
| 22 » funcs map[string]reflect.Value |
21 // Parsing. | 23 // Parsing. |
22 lex *lexer | 24 lex *lexer |
23 tokens <-chan item | 25 tokens <-chan item |
24 token item // token lookahead for parser | 26 token item // token lookahead for parser |
25 havePeek bool | 27 havePeek bool |
26 } | 28 } |
27 | 29 |
28 // next returns the next token. | 30 // next returns the next token. |
29 func (t *Template) next() item { | 31 func (t *Template) next() item { |
30 if t.havePeek { | 32 if t.havePeek { |
(...skipping 412 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
443 } | 445 } |
444 return fmt.Sprintf("({{with %s}} %s)", w.pipeline, w.list) | 446 return fmt.Sprintf("({{with %s}} %s)", w.pipeline, w.list) |
445 } | 447 } |
446 | 448 |
447 | 449 |
448 // Parsing. | 450 // Parsing. |
449 | 451 |
450 // New allocates a new template with the given name. | 452 // New allocates a new template with the given name. |
451 func New(name string) *Template { | 453 func New(name string) *Template { |
452 return &Template{ | 454 return &Template{ |
453 » » name: name, | 455 » » name: name, |
| 456 » » funcs: make(map[string]reflect.Value), |
454 } | 457 } |
455 } | 458 } |
456 | 459 |
| 460 // Funcs adds to the template's function map the elements of the |
| 461 // argument map. It panics if a value in the map is not a function. |
| 462 // The return value is the template, so calls can be chained; it will be |
| 463 // nil in the error case. |
| 464 func (t *Template) Funcs(funcMap FuncMap) *Template { |
| 465 addFuncs(t.funcs, funcMap) |
| 466 return t |
| 467 } |
| 468 |
457 // errorf formats the error and terminates processing. | 469 // errorf formats the error and terminates processing. |
458 func (t *Template) errorf(format string, args ...interface{}) { | 470 func (t *Template) errorf(format string, args ...interface{}) { |
| 471 t.root = nil |
459 format = fmt.Sprintf("template: %s:%d: %s", t.name, t.lex.lineNumber(),
format) | 472 format = fmt.Sprintf("template: %s:%d: %s", t.name, t.lex.lineNumber(),
format) |
460 panic(fmt.Errorf(format, args...)) | 473 panic(fmt.Errorf(format, args...)) |
461 } | 474 } |
462 | 475 |
463 // error terminates processing. | 476 // error terminates processing. |
464 func (t *Template) error(err os.Error) { | 477 func (t *Template) error(err os.Error) { |
465 t.errorf("%s", err) | 478 t.errorf("%s", err) |
466 } | 479 } |
467 | 480 |
468 // expect consumes the next token and guarantees it has the required type. | 481 // expect consumes the next token and guarantees it has the required type. |
(...skipping 12 matching lines...) Expand all Loading... |
481 | 494 |
482 // recover is the handler that turns panics into returns from the top | 495 // recover is the handler that turns panics into returns from the top |
483 // level of Parse or Execute. | 496 // level of Parse or Execute. |
484 func (t *Template) recover(errp *os.Error) { | 497 func (t *Template) recover(errp *os.Error) { |
485 e := recover() | 498 e := recover() |
486 if e != nil { | 499 if e != nil { |
487 if _, ok := e.(runtime.Error); ok { | 500 if _, ok := e.(runtime.Error); ok { |
488 panic(e) | 501 panic(e) |
489 } | 502 } |
490 t.stopParse() | 503 t.stopParse() |
491 t.root = nil | |
492 *errp = e.(os.Error) | 504 *errp = e.(os.Error) |
493 } | 505 } |
494 return | 506 return |
495 } | 507 } |
496 | 508 |
497 // startParse starts the template parsing from the lexer. | 509 // startParse starts the template parsing from the lexer. |
498 func (t *Template) startParse(lex *lexer, tokens <-chan item) { | 510 func (t *Template) startParse(lex *lexer, tokens <-chan item) { |
499 t.root = nil | 511 t.root = nil |
500 t.lex, t.tokens = lex, tokens | 512 t.lex, t.tokens = lex, tokens |
501 } | 513 } |
(...skipping 242 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
744 cmd.append(newString(s)) | 756 cmd.append(newString(s)) |
745 default: | 757 default: |
746 t.unexpected(token, "command") | 758 t.unexpected(token, "command") |
747 } | 759 } |
748 } | 760 } |
749 if len(cmd.args) == 0 { | 761 if len(cmd.args) == 0 { |
750 t.errorf("empty command") | 762 t.errorf("empty command") |
751 } | 763 } |
752 return cmd | 764 return cmd |
753 } | 765 } |
OLD | NEW |