summaryrefslogtreecommitdiff
path: root/src/pkg/template/template.go
diff options
context:
space:
mode:
Diffstat (limited to 'src/pkg/template/template.go')
-rw-r--r--src/pkg/template/template.go194
1 files changed, 97 insertions, 97 deletions
diff --git a/src/pkg/template/template.go b/src/pkg/template/template.go
index 85da9121c..c647a2d37 100644
--- a/src/pkg/template/template.go
+++ b/src/pkg/template/template.go
@@ -68,23 +68,23 @@ import (
// Errors returned during parsing and execution. Users may extract the information and reformat
// if they desire.
type Error struct {
- Line int;
- Msg string;
+ Line int;
+ Msg string;
}
func (e *Error) String() string {
- return fmt.Sprintf("line %d: %s", e.Line, e.Msg)
+ return fmt.Sprintf("line %d: %s", e.Line, e.Msg);
}
// Most of the literals are aces.
-var lbrace = []byte{ '{' }
-var rbrace = []byte{ '}' }
-var space = []byte{ ' ' }
-var tab = []byte{ '\t' }
+var lbrace = []byte{'{'}
+var rbrace = []byte{'}'}
+var space = []byte{' '}
+var tab = []byte{'\t'}
// The various types of "tokens", which are plain text or (usually) brace-delimited descriptors
const (
- tokAlternates = iota;
+ tokAlternates = iota;
tokComment;
tokEnd;
tokLiteral;
@@ -97,13 +97,13 @@ const (
// FormatterMap is the type describing the mapping from formatter
// names to the functions that implement them.
-type FormatterMap map[string] func(io.Writer, interface{}, string)
+type FormatterMap map[string]func(io.Writer, interface{}, string)
// Built-in formatters.
-var builtins = FormatterMap {
- "html" : HtmlFormatter,
- "str" : StringFormatter,
- "" : StringFormatter,
+var builtins = FormatterMap{
+ "html": HtmlFormatter,
+ "str": StringFormatter,
+ "": StringFormatter,
}
// The parsed state of a template is a vector of xxxElement structs.
@@ -111,7 +111,7 @@ var builtins = FormatterMap {
// Plain text.
type textElement struct {
- text []byte;
+ text []byte;
}
// A literal such as .meta-left or .meta-right
@@ -121,14 +121,14 @@ type literalElement struct {
// A variable to be evaluated
type variableElement struct {
- linenum int;
- name string;
+ linenum int;
+ name string;
formatter string; // TODO(r): implement pipelines
}
// A .section block, possibly with a .or
type sectionElement struct {
- linenum int; // of .section itself
+ linenum int; // of .section itself
field string; // cursor field for this block
start int; // first element
or int; // first element of .or block
@@ -137,9 +137,9 @@ type sectionElement struct {
// A .repeated block, possibly with a .or and a .alternates
type repeatedElement struct {
- sectionElement; // It has the same structure...
+ sectionElement; // It has the same structure...
altstart int; // ... except for alternates
- altend int;
+ altend int;
}
// Template is the type that represents a template definition.
@@ -147,11 +147,11 @@ type repeatedElement struct {
type Template struct {
fmap FormatterMap; // formatters for variables
// Used during parsing:
- ldelim, rdelim []byte; // delimiters; default {}
- buf []byte; // input text to process
- p int; // position in buf
- linenum int; // position in input
- error os.Error; // error during parsing (only)
+ ldelim, rdelim []byte; // delimiters; default {}
+ buf []byte; // input text to process
+ p int; // position in buf
+ linenum int; // position in input
+ error os.Error; // error during parsing (only)
// Parsed results:
elems *vector.Vector;
}
@@ -160,14 +160,14 @@ type Template struct {
// the data item descends into the fields associated with sections, etc.
// Parent is used to walk upwards to find variables higher in the tree.
type state struct {
- parent *state; // parent in hierarchy
+ parent *state; // parent in hierarchy
data reflect.Value; // the driver data for this section etc.
wr io.Writer; // where to send output
errors chan os.Error; // for reporting errors during execute
}
func (parent *state) clone(data reflect.Value) *state {
- return &state{parent, data, parent.wr, parent.errors}
+ return &state{parent, data, parent.wr, parent.errors};
}
// New creates a new template with the specified formatter map (which
@@ -197,21 +197,21 @@ func (t *Template) parseError(err string, args ...) {
// Is c a white space character?
func white(c uint8) bool {
- return c == ' ' || c == '\t' || c == '\r' || c == '\n'
+ return c == ' ' || c == '\t' || c == '\r' || c == '\n';
}
// Safely, does s[n:n+len(t)] == t?
func equal(s []byte, n int, t []byte) bool {
b := s[n:len(s)];
if len(t) > len(b) { // not enough space left for a match.
- return false
+ return false;
}
- for i , c := range t {
+ for i, c := range t {
if c != b[i] {
- return false
+ return false;
}
}
- return true
+ return true;
}
// nextItem returns the next item from the input buffer. If the returned
@@ -224,7 +224,7 @@ func (t *Template) nextItem() []byte {
sawLeft := false; // are we waiting for an opening delimiter?
special := false; // is this a {.foo} directive, which means trim white space?
// Delete surrounding white space if this {.foo} is the only thing on the line.
- trim_white := t.p == 0 || t.buf[t.p-1] == '\n';
+ trim_white := t.p == 0 || t.buf[t.p - 1] == '\n';
only_white := true; // we have seen only white space so far
var i int;
start := t.p;
@@ -237,23 +237,23 @@ Loop:
break Loop;
case white(t.buf[i]):
// white space, do nothing
- case !sawLeft && equal(t.buf, i, t.ldelim): // sawLeft checked because delims may be equal
+ case !sawLeft && equal(t.buf, i, t.ldelim): // sawLeft checked because delims may be equal
// anything interesting already on the line?
if !only_white {
break Loop;
}
// is it a directive or comment?
- j := i + len(t.ldelim); // position after delimiter
+ j := i+len(t.ldelim); // position after delimiter
if j+1 < len(t.buf) && (t.buf[j] == '.' || t.buf[j] == '#') {
special = true;
if trim_white && only_white {
start = i;
}
- } else if i > t.p { // have some text accumulated so stop before delimiter
+ } else if i > t.p { // have some text accumulated so stop before delimiter
break Loop;
}
sawLeft = true;
- i = j - 1;
+ i = j-1;
case equal(t.buf, i, t.rdelim):
if !sawLeft {
t.parseError("unmatched closing delimiter");
@@ -277,18 +277,18 @@ Loop:
if t.buf[i] == '\n' {
t.linenum++;
i++;
- break // stop after newline
+ break; // stop after newline
}
}
}
t.p = i;
- return item
+ return item;
}
// Turn a byte array into a white-space-split array of strings.
func words(buf []byte) []string {
s := make([]string, 0, 5);
- p := 0; // position in buf
+ p := 0; // position in buf
// one word per loop
for i := 0; ; i++ {
// skip white space
@@ -299,19 +299,19 @@ func words(buf []byte) []string {
for ; p < len(buf) && !white(buf[p]); p++ {
}
if start == p { // no text left
- break
+ break;
}
if i == cap(s) {
ns := make([]string, 2*cap(s));
for j := range s {
- ns[j] = s[j]
+ ns[j] = s[j];
}
s = ns;
}
- s = s[0:i+1];
- s[i] = string(buf[start:p])
+ s = s[0 : i+1];
+ s[i] = string(buf[start:p]);
}
- return s
+ return s;
}
// Analyze an item and return its token type and, if it's an action item, an array of
@@ -333,10 +333,10 @@ func (t *Template) analyze(item []byte) (tok int, w []string) {
// Comment
if item[len(t.ldelim)] == '#' {
tok = tokComment;
- return
+ return;
}
// Split into words
- w = words(item[len(t.ldelim): len(item)-len(t.rdelim)]); // drop final delimiter
+ w = words(item[len(t.ldelim) : len(item)-len(t.rdelim)]); // drop final delimiter
if len(w) == 0 {
t.parseError("empty directive");
return;
@@ -378,7 +378,7 @@ func (t *Template) analyze(item []byte) (tok int, w []string) {
return;
}
t.parseError("bad directive: %s", item);
- return
+ return;
}
// -- Parsing
@@ -390,7 +390,7 @@ func (t *Template) newVariable(name_formatter string) (v *variableElement) {
bar := strings.Index(name_formatter, "|");
if bar >= 0 {
name = name_formatter[0:bar];
- formatter = name_formatter[bar+1:len(name_formatter)];
+ formatter = name_formatter[bar+1 : len(name_formatter)];
}
// Probably ok, so let's build it.
v = &variableElement{t.linenum, name, formatter};
@@ -402,15 +402,15 @@ func (t *Template) newVariable(name_formatter string) (v *variableElement) {
// Is it in user-supplied map?
if t.fmap != nil {
if _, ok := t.fmap[formatter]; ok {
- return
+ return;
}
}
// Is it in builtin map?
if _, ok := builtins[formatter]; ok {
- return
+ return;
}
t.parseError("unknown formatter: %s", formatter);
- return
+ return;
}
// Grab the next item. If it's simple, just append it to the template.
@@ -418,7 +418,7 @@ func (t *Template) newVariable(name_formatter string) (v *variableElement) {
func (t *Template) parseSimple(item []byte) (done bool, tok int, w []string) {
tok, w = t.analyze(item);
if t.error != nil {
- return
+ return;
}
done = true; // assume for simplicity
switch tok {
@@ -446,7 +446,7 @@ func (t *Template) parseSimple(item []byte) (done bool, tok int, w []string) {
t.elems.Push(t.newVariable(w[0]));
return;
}
- return false, tok, w
+ return false, tok, w;
}
// parseRepeated and parseSection are mutually recursive
@@ -467,7 +467,7 @@ Loop:
if t.error != nil {
break;
}
- if len(item) == 0 {
+ if len(item) == 0 {
t.parseError("missing .end for .repeated section");
break;
}
@@ -476,7 +476,7 @@ Loop:
break;
}
if done {
- continue
+ continue;
}
switch tok {
case tokEnd:
@@ -508,10 +508,10 @@ Loop:
}
}
if t.error != nil {
- return nil
+ return nil;
}
if r.altend < 0 {
- r.altend = t.elems.Len()
+ r.altend = t.elems.Len();
}
r.end = t.elems.Len();
return r;
@@ -531,7 +531,7 @@ Loop:
if t.error != nil {
break;
}
- if len(item) == 0 {
+ if len(item) == 0 {
t.parseError("missing .end for .section");
break;
}
@@ -540,7 +540,7 @@ Loop:
break;
}
if done {
- continue
+ continue;
}
switch tok {
case tokEnd:
@@ -562,7 +562,7 @@ Loop:
}
}
if t.error != nil {
- return nil
+ return nil;
}
s.end = t.elems.Len();
return s;
@@ -572,14 +572,14 @@ func (t *Template) parse() {
for t.error == nil {
item := t.nextItem();
if t.error != nil {
- break
+ break;
}
if len(item) == 0 {
- break
+ break;
}
done, tok, w := t.parseSimple(item);
if done {
- continue
+ continue;
}
switch tok {
case tokOr, tokEnd, tokAlternates:
@@ -604,7 +604,7 @@ func (t *Template) parse() {
// it represents the actual named field.
func (st *state) findVar(s string) reflect.Value {
if s == "@" {
- return st.data
+ return st.data;
}
data := st.data;
elems := strings.Split(s, ".", 0);
@@ -612,26 +612,26 @@ func (st *state) findVar(s string) reflect.Value {
// Look up field; data must be a struct.
data = reflect.Indirect(data);
if data == nil {
- return nil
+ return nil;
}
typ, ok := data.Type().(*reflect.StructType);
if !ok {
- return nil
+ return nil;
}
field, ok := typ.FieldByName(elems[i]);
if !ok {
- return nil
+ return nil;
}
data = data.(*reflect.StructValue).FieldByIndex(field.Index);
}
- return data
+ return data;
}
// Is there no data to look at?
func empty(v reflect.Value) bool {
v = reflect.Indirect(v);
if v == nil {
- return true
+ return true;
}
switch v := v.(type) {
case *reflect.BoolValue:
@@ -653,7 +653,7 @@ func (t *Template) varValue(name string, st *state) reflect.Value {
field := st.findVar(name);
if field == nil {
if st.parent == nil {
- t.execError(st, t.linenum, "name not found: %s", name)
+ t.execError(st, t.linenum, "name not found: %s", name);
}
return t.varValue(name, st.parent);
}
@@ -677,7 +677,7 @@ func (t *Template) writeVariable(v *variableElement, st *state) {
fn(st.wr, val, formatter);
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);
}
// Execute element i. Return next index to execute.
@@ -701,13 +701,13 @@ func (t *Template) executeElement(i int, st *state) int {
}
e := t.elems.At(i);
t.execError(st, 0, "internal error: bad directive in execute: %v %T\n", reflect.NewValue(e).Interface(), e);
- return 0
+ return 0;
}
// Execute the template.
func (t *Template) execute(start, end int, st *state) {
for i := start; i < end; {
- i = t.executeElement(i, st)
+ i = t.executeElement(i, st);
}
}
@@ -723,17 +723,17 @@ func (t *Template) executeSection(s *sectionElement, st *state) {
if !empty(field) {
// Execute the normal block.
if end < 0 {
- end = s.end
+ end = s.end;
}
} else {
// Execute the .or block. If it's missing, do nothing.
start, end = s.or, s.end;
if start < 0 {
- return
+ return;
}
}
for i := start; i < end; {
- i = t.executeElement(i, st)
+ i = t.executeElement(i, st);
}
}
@@ -745,15 +745,15 @@ func iter(v reflect.Value) *reflect.ChanValue {
ft := fv.Type().(*reflect.FuncType);
// TODO(rsc): NumIn() should return 0 here, because ft is from a curried FuncValue.
if mth.Name != "Iter" || ft.NumIn() != 1 || ft.NumOut() != 1 {
- continue
+ continue;
}
ct, ok := ft.Out(0).(*reflect.ChanType);
if !ok || ct.Dir() & reflect.RecvDir == 0 {
- continue
+ continue;
}
- return fv.Call(nil)[0].(*reflect.ChanValue)
+ return fv.Call(nil)[0].(*reflect.ChanValue);
}
- return nil
+ return nil;
}
// Execute a .repeated section
@@ -766,10 +766,10 @@ func (t *Template) executeRepeated(r *repeatedElement, st *state) {
start, end := r.start, r.or;
if end < 0 {
- end = r.end
+ end = r.end;
}
if r.altstart >= 0 {
- end = r.altstart
+ end = r.altstart;
}
first := true;
@@ -780,38 +780,38 @@ func (t *Template) executeRepeated(r *repeatedElement, st *state) {
// .alternates between elements
if !first && r.altstart >= 0 {
for i := r.altstart; i < r.altend; {
- i = t.executeElement(i, newst)
+ i = t.executeElement(i, newst);
}
}
first = false;
for i := start; i < end; {
- i = t.executeElement(i, newst)
+ i = t.executeElement(i, newst);
}
}
} else if ch := iter(field); ch != nil {
for {
e := ch.Recv();
if ch.Closed() {
- break
+ break;
}
newst := st.clone(e);
// .alternates between elements
if !first && r.altstart >= 0 {
for i := r.altstart; i < r.altend; {
- i = t.executeElement(i, newst)
+ i = t.executeElement(i, newst);
}
}
first = false;
for i := start; i < end; {
- i = t.executeElement(i, newst)
+ i = t.executeElement(i, newst);
}
}
} else {
t.execError(st, r.linenum, ".repeated: cannot repeat %s (type %s)",
- r.field, field.Type());
+ r.field, field.Type());
}
if first {
@@ -820,21 +820,21 @@ func (t *Template) executeRepeated(r *repeatedElement, st *state) {
if start >= 0 {
newst := st.clone(field);
for i := start; i < end; {
- i = t.executeElement(i, newst)
+ i = t.executeElement(i, newst);
}
}
- return
+ return;
}
}
// A valid delimiter must contain no white space and be non-empty.
func validDelim(d []byte) bool {
if len(d) == 0 {
- return false
+ return false;
}
for _, c := range d {
if white(c) {
- return false
+ return false;
}
}
return true;
@@ -847,7 +847,7 @@ func validDelim(d []byte) bool {
// the error.
func (t *Template) Parse(s string) os.Error {
if !validDelim(t.ldelim) || !validDelim(t.rdelim) {
- return &Error{1, fmt.Sprintf("bad delimiter strings %q %q", t.ldelim, t.rdelim)}
+ return &Error{1, fmt.Sprintf("bad delimiter strings %q %q", t.ldelim, t.rdelim)};
}
t.buf = strings.Bytes(s);
t.p = 0;
@@ -889,16 +889,16 @@ func Parse(s string, fmap FormatterMap) (t *Template, err os.Error) {
t = New(fmap);
err = t.Parse(s);
if err != nil {
- t = nil
+ t = nil;
}
- return
+ return;
}
// MustParse is like Parse but panics if the template cannot be parsed.
func MustParse(s string, fmap FormatterMap) *Template {
- t , err := Parse(s, fmap);
+ t, err := Parse(s, fmap);
if err != nil {
panic("template parse error: ", err.String());
}
- return t
+ return t;
}