Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
G
go
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Kirill Smelkov
go
Commits
b8c66429
Commit
b8c66429
authored
Jul 08, 2011
by
Rob Pike
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
exp/template: parse variables and declarations
R=golang-dev, adg CC=golang-dev
https://golang.org/cl/4631099
parent
ee14989e
Changes
3
Show whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
120 additions
and
60 deletions
+120
-60
src/pkg/exp/template/exec.go
src/pkg/exp/template/exec.go
+8
-8
src/pkg/exp/template/parse.go
src/pkg/exp/template/parse.go
+106
-52
src/pkg/exp/template/parse_test.go
src/pkg/exp/template/parse_test.go
+6
-0
No files found.
src/pkg/exp/template/exec.go
View file @
b8c66429
...
@@ -82,14 +82,14 @@ func (s *state) walk(data reflect.Value, n node) {
...
@@ -82,14 +82,14 @@ func (s *state) walk(data reflect.Value, n node) {
switch
n
:=
n
.
(
type
)
{
switch
n
:=
n
.
(
type
)
{
case
*
actionNode
:
case
*
actionNode
:
s
.
line
=
n
.
line
s
.
line
=
n
.
line
s
.
printValue
(
n
,
s
.
evalPipeline
(
data
,
n
.
pipe
line
))
s
.
printValue
(
n
,
s
.
evalPipeline
(
data
,
n
.
pipe
))
case
*
listNode
:
case
*
listNode
:
for
_
,
node
:=
range
n
.
nodes
{
for
_
,
node
:=
range
n
.
nodes
{
s
.
walk
(
data
,
node
)
s
.
walk
(
data
,
node
)
}
}
case
*
ifNode
:
case
*
ifNode
:
s
.
line
=
n
.
line
s
.
line
=
n
.
line
s
.
walkIfOrWith
(
nodeIf
,
data
,
n
.
pipe
line
,
n
.
list
,
n
.
elseList
)
s
.
walkIfOrWith
(
nodeIf
,
data
,
n
.
pipe
,
n
.
list
,
n
.
elseList
)
case
*
rangeNode
:
case
*
rangeNode
:
s
.
line
=
n
.
line
s
.
line
=
n
.
line
s
.
walkRange
(
data
,
n
)
s
.
walkRange
(
data
,
n
)
...
@@ -102,7 +102,7 @@ func (s *state) walk(data reflect.Value, n node) {
...
@@ -102,7 +102,7 @@ func (s *state) walk(data reflect.Value, n node) {
s
.
walkTemplate
(
data
,
n
)
s
.
walkTemplate
(
data
,
n
)
case
*
withNode
:
case
*
withNode
:
s
.
line
=
n
.
line
s
.
line
=
n
.
line
s
.
walkIfOrWith
(
nodeWith
,
data
,
n
.
pipe
line
,
n
.
list
,
n
.
elseList
)
s
.
walkIfOrWith
(
nodeWith
,
data
,
n
.
pipe
,
n
.
list
,
n
.
elseList
)
default
:
default
:
s
.
errorf
(
"unknown node: %s"
,
n
)
s
.
errorf
(
"unknown node: %s"
,
n
)
}
}
...
@@ -110,7 +110,7 @@ func (s *state) walk(data reflect.Value, n node) {
...
@@ -110,7 +110,7 @@ func (s *state) walk(data reflect.Value, n node) {
// walkIfOrWith walks an 'if' or 'with' node. The two control structures
// walkIfOrWith walks an 'if' or 'with' node. The two control structures
// are identical in behavior except that 'with' sets dot.
// are identical in behavior except that 'with' sets dot.
func
(
s
*
state
)
walkIfOrWith
(
typ
nodeType
,
data
reflect
.
Value
,
pipe
[]
*
command
Node
,
list
,
elseList
*
listNode
)
{
func
(
s
*
state
)
walkIfOrWith
(
typ
nodeType
,
data
reflect
.
Value
,
pipe
*
pipe
Node
,
list
,
elseList
*
listNode
)
{
val
:=
s
.
evalPipeline
(
data
,
pipe
)
val
:=
s
.
evalPipeline
(
data
,
pipe
)
truth
,
ok
:=
isTrue
(
val
)
truth
,
ok
:=
isTrue
(
val
)
if
!
ok
{
if
!
ok
{
...
@@ -152,7 +152,7 @@ func isTrue(val reflect.Value) (truth, ok bool) {
...
@@ -152,7 +152,7 @@ func isTrue(val reflect.Value) (truth, ok bool) {
}
}
func
(
s
*
state
)
walkRange
(
data
reflect
.
Value
,
r
*
rangeNode
)
{
func
(
s
*
state
)
walkRange
(
data
reflect
.
Value
,
r
*
rangeNode
)
{
val
:=
s
.
evalPipeline
(
data
,
r
.
pipe
line
)
val
:=
s
.
evalPipeline
(
data
,
r
.
pipe
)
down
:=
s
.
down
(
data
)
down
:=
s
.
down
(
data
)
switch
val
.
Kind
()
{
switch
val
.
Kind
()
{
case
reflect
.
Array
,
reflect
.
Slice
:
case
reflect
.
Array
,
reflect
.
Slice
:
...
@@ -188,7 +188,7 @@ func (s *state) walkTemplate(data reflect.Value, t *templateNode) {
...
@@ -188,7 +188,7 @@ func (s *state) walkTemplate(data reflect.Value, t *templateNode) {
if
tmpl
==
nil
{
if
tmpl
==
nil
{
s
.
errorf
(
"template %q not in set"
,
name
)
s
.
errorf
(
"template %q not in set"
,
name
)
}
}
data
=
s
.
evalPipeline
(
data
,
t
.
pipe
line
)
data
=
s
.
evalPipeline
(
data
,
t
.
pipe
)
newState
:=
*
s
newState
:=
*
s
newState
.
tmpl
=
tmpl
newState
.
tmpl
=
tmpl
newState
.
walk
(
data
,
tmpl
.
root
)
newState
.
walk
(
data
,
tmpl
.
root
)
...
@@ -198,9 +198,9 @@ func (s *state) walkTemplate(data reflect.Value, t *templateNode) {
...
@@ -198,9 +198,9 @@ func (s *state) walkTemplate(data reflect.Value, t *templateNode) {
// values from the data structure by examining fields, calling methods, and so on.
// values from the data structure by examining fields, calling methods, and so on.
// The printing of those values happens only through walk functions.
// The printing of those values happens only through walk functions.
func
(
s
*
state
)
evalPipeline
(
data
reflect
.
Value
,
pipe
[]
*
command
Node
)
reflect
.
Value
{
func
(
s
*
state
)
evalPipeline
(
data
reflect
.
Value
,
pipe
*
pipe
Node
)
reflect
.
Value
{
value
:=
zero
value
:=
zero
for
_
,
cmd
:=
range
pipe
{
for
_
,
cmd
:=
range
pipe
.
cmds
{
value
=
s
.
evalCommand
(
data
,
cmd
,
value
)
// previous value is this one's final arg.
value
=
s
.
evalCommand
(
data
,
cmd
,
value
)
// previous value is this one's final arg.
// If the object has type interface{}, dig down one level to the thing inside.
// If the object has type interface{}, dig down one level to the thing inside.
if
value
.
Kind
()
==
reflect
.
Interface
&&
value
.
Type
()
.
NumMethod
()
==
0
{
if
value
.
Kind
()
==
reflect
.
Interface
&&
value
.
Type
()
.
NumMethod
()
==
0
{
...
...
src/pkg/exp/template/parse.go
View file @
b8c66429
...
@@ -23,33 +23,39 @@ type Template struct {
...
@@ -23,33 +23,39 @@ type Template struct {
// Parsing only; cleared after parse.
// Parsing only; cleared after parse.
set
*
Set
set
*
Set
lex
*
lexer
lex
*
lexer
token
item
//
token lookahead for parser
token
[
2
]
item
// two-
token lookahead for parser
havePeek
bool
peekCount
int
}
}
// next returns the next token.
// next returns the next token.
func
(
t
*
Template
)
next
()
item
{
func
(
t
*
Template
)
next
()
item
{
if
t
.
havePeek
{
if
t
.
peekCount
>
0
{
t
.
havePeek
=
false
t
.
peekCount
--
}
else
{
}
else
{
t
.
token
=
t
.
lex
.
nextItem
()
t
.
token
[
0
]
=
t
.
lex
.
nextItem
()
}
}
return
t
.
token
return
t
.
token
[
t
.
peekCount
]
}
}
// backup backs the input stream up one token.
// backup backs the input stream up one token.
func
(
t
*
Template
)
backup
()
{
func
(
t
*
Template
)
backup
()
{
t
.
havePeek
=
true
t
.
peekCount
++
}
// backup2 backs the input stream up two tokens
func
(
t
*
Template
)
backup2
(
t1
item
)
{
t
.
token
[
1
]
=
t1
t
.
peekCount
=
2
}
}
// peek returns but does not consume the next token.
// peek returns but does not consume the next token.
func
(
t
*
Template
)
peek
()
item
{
func
(
t
*
Template
)
peek
()
item
{
if
t
.
havePeek
{
if
t
.
peekCount
>
0
{
return
t
.
token
return
t
.
token
[
t
.
peekCount
-
1
]
}
}
t
.
token
=
t
.
lex
.
nextItem
()
t
.
peekCount
=
1
t
.
havePeek
=
true
t
.
token
[
0
]
=
t
.
lex
.
nextItem
()
return
t
.
token
return
t
.
token
[
0
]
}
}
// A node is an element in the parse tree. The interface is trivial.
// A node is an element in the parse tree. The interface is trivial.
...
@@ -76,9 +82,11 @@ const (
...
@@ -76,9 +82,11 @@ const (
nodeIf
nodeIf
nodeList
nodeList
nodeNumber
nodeNumber
nodePipe
nodeRange
nodeRange
nodeString
nodeString
nodeTemplate
nodeTemplate
nodeVariable
nodeWith
nodeWith
)
)
...
@@ -122,23 +130,42 @@ func (t *textNode) String() string {
...
@@ -122,23 +130,42 @@ func (t *textNode) String() string {
return
fmt
.
Sprintf
(
"(text: %q)"
,
t
.
text
)
return
fmt
.
Sprintf
(
"(text: %q)"
,
t
.
text
)
}
}
//
actionNode holds an action (something bounded by delimiters).
//
pipeNode holds a pipeline with optional declaration
type
action
Node
struct
{
type
pipe
Node
struct
{
nodeType
nodeType
line
int
line
int
pipeline
[]
*
commandNode
decl
*
variableNode
cmds
[]
*
commandNode
}
}
func
newAction
(
line
int
,
pipeline
[]
*
commandNode
)
*
actionNode
{
func
newPipeline
(
line
int
,
decl
*
variableNode
)
*
pipeNode
{
return
&
actionNode
{
nodeType
:
nodeAction
,
line
:
line
,
pipeline
:
pipeline
}
return
&
pipeNode
{
nodeType
:
nodePipe
,
line
:
line
,
decl
:
decl
}
}
func
(
p
*
pipeNode
)
append
(
command
*
commandNode
)
{
p
.
cmds
=
append
(
p
.
cmds
,
command
)
}
func
(
p
*
pipeNode
)
String
()
string
{
if
p
.
decl
!=
nil
{
return
fmt
.
Sprintf
(
"%s := %v"
,
p
.
decl
.
ident
,
p
.
cmds
)
}
return
fmt
.
Sprintf
(
"%v"
,
p
.
cmds
)
}
// actionNode holds an action (something bounded by delimiters).
type
actionNode
struct
{
nodeType
line
int
pipe
*
pipeNode
}
}
func
(
a
*
actionNode
)
append
(
command
*
commandNode
)
{
func
newAction
(
line
int
,
pipe
*
pipeNode
)
*
actionNode
{
a
.
pipeline
=
append
(
a
.
pipeline
,
command
)
return
&
actionNode
{
nodeType
:
nodeAction
,
line
:
line
,
pipe
:
pipe
}
}
}
func
(
a
*
actionNode
)
String
()
string
{
func
(
a
*
actionNode
)
String
()
string
{
return
fmt
.
Sprintf
(
"(action: %v)"
,
a
.
pipe
line
)
return
fmt
.
Sprintf
(
"(action: %v)"
,
a
.
pipe
)
}
}
// commandNode holds a command (a pipeline inside an evaluating action).
// commandNode holds a command (a pipeline inside an evaluating action).
...
@@ -173,6 +200,20 @@ func (i *identifierNode) String() string {
...
@@ -173,6 +200,20 @@ func (i *identifierNode) String() string {
return
fmt
.
Sprintf
(
"I=%s"
,
i
.
ident
)
return
fmt
.
Sprintf
(
"I=%s"
,
i
.
ident
)
}
}
// variableNode holds a variable.
type
variableNode
struct
{
nodeType
ident
string
}
func
newVariable
(
ident
string
)
*
variableNode
{
return
&
variableNode
{
nodeType
:
nodeVariable
,
ident
:
ident
}
}
func
(
v
*
variableNode
)
String
()
string
{
return
fmt
.
Sprintf
(
"V=%s"
,
v
.
ident
)
}
// dotNode holds the special identifier '.'. It is represented by a nil pointer.
// dotNode holds the special identifier '.'. It is represented by a nil pointer.
type
dotNode
bool
type
dotNode
bool
...
@@ -370,44 +411,44 @@ func (e *elseNode) String() string {
...
@@ -370,44 +411,44 @@ func (e *elseNode) String() string {
return
"{{else}}"
return
"{{else}}"
}
}
// ifNode represents an {{if}} action and its commands.
// ifNode represents an {{if}} action and its commands.
// TODO: what should evaluation look like? is a pipe
line
enough?
// TODO: what should evaluation look like? is a pipe enough?
type
ifNode
struct
{
type
ifNode
struct
{
nodeType
nodeType
line
int
line
int
pipe
line
[]
*
command
Node
pipe
*
pipe
Node
list
*
listNode
list
*
listNode
elseList
*
listNode
elseList
*
listNode
}
}
func
newIf
(
line
int
,
pipe
line
[]
*
command
Node
,
list
,
elseList
*
listNode
)
*
ifNode
{
func
newIf
(
line
int
,
pipe
*
pipe
Node
,
list
,
elseList
*
listNode
)
*
ifNode
{
return
&
ifNode
{
nodeType
:
nodeIf
,
line
:
line
,
pipe
line
:
pipelin
e
,
list
:
list
,
elseList
:
elseList
}
return
&
ifNode
{
nodeType
:
nodeIf
,
line
:
line
,
pipe
:
pip
e
,
list
:
list
,
elseList
:
elseList
}
}
}
func
(
i
*
ifNode
)
String
()
string
{
func
(
i
*
ifNode
)
String
()
string
{
if
i
.
elseList
!=
nil
{
if
i
.
elseList
!=
nil
{
return
fmt
.
Sprintf
(
"({{if %s}} %s {{else}} %s)"
,
i
.
pipe
line
,
i
.
list
,
i
.
elseList
)
return
fmt
.
Sprintf
(
"({{if %s}} %s {{else}} %s)"
,
i
.
pipe
,
i
.
list
,
i
.
elseList
)
}
}
return
fmt
.
Sprintf
(
"({{if %s}} %s)"
,
i
.
pipe
line
,
i
.
list
)
return
fmt
.
Sprintf
(
"({{if %s}} %s)"
,
i
.
pipe
,
i
.
list
)
}
}
// rangeNode represents a {{range}} action and its commands.
// rangeNode represents a {{range}} action and its commands.
type
rangeNode
struct
{
type
rangeNode
struct
{
nodeType
nodeType
line
int
line
int
pipe
line
[]
*
command
Node
pipe
*
pipe
Node
list
*
listNode
list
*
listNode
elseList
*
listNode
elseList
*
listNode
}
}
func
newRange
(
line
int
,
pipe
line
[]
*
command
Node
,
list
,
elseList
*
listNode
)
*
rangeNode
{
func
newRange
(
line
int
,
pipe
*
pipe
Node
,
list
,
elseList
*
listNode
)
*
rangeNode
{
return
&
rangeNode
{
nodeType
:
nodeRange
,
line
:
line
,
pipe
line
:
pipelin
e
,
list
:
list
,
elseList
:
elseList
}
return
&
rangeNode
{
nodeType
:
nodeRange
,
line
:
line
,
pipe
:
pip
e
,
list
:
list
,
elseList
:
elseList
}
}
}
func
(
r
*
rangeNode
)
String
()
string
{
func
(
r
*
rangeNode
)
String
()
string
{
if
r
.
elseList
!=
nil
{
if
r
.
elseList
!=
nil
{
return
fmt
.
Sprintf
(
"({{range %s}} %s {{else}} %s)"
,
r
.
pipe
line
,
r
.
list
,
r
.
elseList
)
return
fmt
.
Sprintf
(
"({{range %s}} %s {{else}} %s)"
,
r
.
pipe
,
r
.
list
,
r
.
elseList
)
}
}
return
fmt
.
Sprintf
(
"({{range %s}} %s)"
,
r
.
pipe
line
,
r
.
list
)
return
fmt
.
Sprintf
(
"({{range %s}} %s)"
,
r
.
pipe
,
r
.
list
)
}
}
// templateNode represents a {{template}} action.
// templateNode represents a {{template}} action.
...
@@ -415,35 +456,35 @@ type templateNode struct {
...
@@ -415,35 +456,35 @@ type templateNode struct {
nodeType
nodeType
line
int
line
int
name
node
name
node
pipe
line
[]
*
command
Node
pipe
*
pipe
Node
}
}
func
newTemplate
(
line
int
,
name
node
,
pipe
line
[]
*
command
Node
)
*
templateNode
{
func
newTemplate
(
line
int
,
name
node
,
pipe
*
pipe
Node
)
*
templateNode
{
return
&
templateNode
{
nodeType
:
nodeTemplate
,
line
:
line
,
name
:
name
,
pipe
line
:
pipelin
e
}
return
&
templateNode
{
nodeType
:
nodeTemplate
,
line
:
line
,
name
:
name
,
pipe
:
pip
e
}
}
}
func
(
t
*
templateNode
)
String
()
string
{
func
(
t
*
templateNode
)
String
()
string
{
return
fmt
.
Sprintf
(
"{{template %s %s}}"
,
t
.
name
,
t
.
pipe
line
)
return
fmt
.
Sprintf
(
"{{template %s %s}}"
,
t
.
name
,
t
.
pipe
)
}
}
// withNode represents a {{with}} action and its commands.
// withNode represents a {{with}} action and its commands.
type
withNode
struct
{
type
withNode
struct
{
nodeType
nodeType
line
int
line
int
pipe
line
[]
*
command
Node
pipe
*
pipe
Node
list
*
listNode
list
*
listNode
elseList
*
listNode
elseList
*
listNode
}
}
func
newWith
(
line
int
,
pipe
line
[]
*
command
Node
,
list
,
elseList
*
listNode
)
*
withNode
{
func
newWith
(
line
int
,
pipe
*
pipe
Node
,
list
,
elseList
*
listNode
)
*
withNode
{
return
&
withNode
{
nodeType
:
nodeWith
,
line
:
line
,
pipe
line
:
pipelin
e
,
list
:
list
,
elseList
:
elseList
}
return
&
withNode
{
nodeType
:
nodeWith
,
line
:
line
,
pipe
:
pip
e
,
list
:
list
,
elseList
:
elseList
}
}
}
func
(
w
*
withNode
)
String
()
string
{
func
(
w
*
withNode
)
String
()
string
{
if
w
.
elseList
!=
nil
{
if
w
.
elseList
!=
nil
{
return
fmt
.
Sprintf
(
"({{with %s}} %s {{else}} %s)"
,
w
.
pipe
line
,
w
.
list
,
w
.
elseList
)
return
fmt
.
Sprintf
(
"({{with %s}} %s {{else}} %s)"
,
w
.
pipe
,
w
.
list
,
w
.
elseList
)
}
}
return
fmt
.
Sprintf
(
"({{with %s}} %s)"
,
w
.
pipe
line
,
w
.
list
)
return
fmt
.
Sprintf
(
"({{with %s}} %s)"
,
w
.
pipe
,
w
.
list
)
}
}
...
@@ -631,17 +672,29 @@ func (t *Template) action() (n node) {
...
@@ -631,17 +672,29 @@ func (t *Template) action() (n node) {
// Pipeline:
// Pipeline:
// field or command
// field or command
// pipeline "|" pipeline
// pipeline "|" pipeline
func
(
t
*
Template
)
pipeline
(
context
string
)
(
pipe
[]
*
commandNode
)
{
func
(
t
*
Template
)
pipeline
(
context
string
)
(
pipe
*
pipeNode
)
{
var
decl
*
variableNode
// Is there a declaration?
if
v
:=
t
.
peek
();
v
.
typ
==
itemVariable
{
t
.
next
()
if
ce
:=
t
.
peek
();
ce
.
typ
==
itemColonEquals
{
t
.
next
()
decl
=
newVariable
(
v
.
val
)
}
else
{
t
.
backup2
(
v
)
}
}
pipe
=
newPipeline
(
t
.
lex
.
lineNumber
(),
decl
)
for
{
for
{
switch
token
:=
t
.
next
();
token
.
typ
{
switch
token
:=
t
.
next
();
token
.
typ
{
case
itemRightDelim
:
case
itemRightDelim
:
if
len
(
pipe
)
==
0
{
if
len
(
pipe
.
cmds
)
==
0
{
t
.
errorf
(
"missing value for %s"
,
context
)
t
.
errorf
(
"missing value for %s"
,
context
)
}
}
return
return
case
itemBool
,
itemComplex
,
itemDot
,
itemField
,
itemIdentifier
,
itemNumber
,
itemRawString
,
itemString
:
case
itemBool
,
itemComplex
,
itemDot
,
itemField
,
itemIdentifier
,
item
Variable
,
item
Number
,
itemRawString
,
itemString
:
t
.
backup
()
t
.
backup
()
pipe
=
append
(
pipe
,
t
.
command
())
pipe
.
append
(
t
.
command
())
default
:
default
:
t
.
unexpected
(
token
,
context
)
t
.
unexpected
(
token
,
context
)
}
}
...
@@ -649,7 +702,7 @@ func (t *Template) pipeline(context string) (pipe []*commandNode) {
...
@@ -649,7 +702,7 @@ func (t *Template) pipeline(context string) (pipe []*commandNode) {
return
return
}
}
func
(
t
*
Template
)
parseControl
(
context
string
)
(
lineNum
int
,
pipe
[]
*
command
Node
,
list
,
elseList
*
listNode
)
{
func
(
t
*
Template
)
parseControl
(
context
string
)
(
lineNum
int
,
pipe
*
pipe
Node
,
list
,
elseList
*
listNode
)
{
lineNum
=
t
.
lex
.
lineNumber
()
lineNum
=
t
.
lex
.
lineNumber
()
pipe
=
t
.
pipeline
(
context
)
pipe
=
t
.
pipeline
(
context
)
var
next
node
var
next
node
...
@@ -732,8 +785,7 @@ func (t *Template) templateControl() node {
...
@@ -732,8 +785,7 @@ func (t *Template) templateControl() node {
default
:
default
:
t
.
unexpected
(
token
,
"template invocation"
)
t
.
unexpected
(
token
,
"template invocation"
)
}
}
pipeline
:=
t
.
pipeline
(
"template"
)
return
newTemplate
(
t
.
lex
.
lineNumber
(),
name
,
t
.
pipeline
(
"template"
))
return
newTemplate
(
t
.
lex
.
lineNumber
(),
name
,
pipeline
)
}
}
// command:
// command:
...
@@ -758,6 +810,8 @@ Loop:
...
@@ -758,6 +810,8 @@ Loop:
cmd
.
append
(
newIdentifier
(
token
.
val
))
cmd
.
append
(
newIdentifier
(
token
.
val
))
case
itemDot
:
case
itemDot
:
cmd
.
append
(
newDot
())
cmd
.
append
(
newDot
())
case
itemVariable
:
cmd
.
append
(
newVariable
(
token
.
val
))
case
itemField
:
case
itemField
:
cmd
.
append
(
newField
(
token
.
val
))
cmd
.
append
(
newField
(
token
.
val
))
case
itemBool
:
case
itemBool
:
...
...
src/pkg/exp/template/parse_test.go
View file @
b8c66429
...
@@ -146,10 +146,16 @@ var parseTests = []parseTest{
...
@@ -146,10 +146,16 @@ var parseTests = []parseTest{
`[(action: [(command: [F=[X]])])]`
},
`[(action: [(command: [F=[X]])])]`
},
{
"simple command"
,
"{{printf}}"
,
noError
,
{
"simple command"
,
"{{printf}}"
,
noError
,
`[(action: [(command: [I=printf])])]`
},
`[(action: [(command: [I=printf])])]`
},
{
"variable invocation"
,
"{{$x 23}}"
,
noError
,
"[(action: [(command: [V=$x N=23])])]"
},
{
"multi-word command"
,
"{{printf `%d` 23}}"
,
noError
,
{
"multi-word command"
,
"{{printf `%d` 23}}"
,
noError
,
"[(action: [(command: [I=printf S=`%d` N=23])])]"
},
"[(action: [(command: [I=printf S=`%d` N=23])])]"
},
{
"pipeline"
,
"{{.X|.Y}}"
,
noError
,
{
"pipeline"
,
"{{.X|.Y}}"
,
noError
,
`[(action: [(command: [F=[X]]) (command: [F=[Y]])])]`
},
`[(action: [(command: [F=[X]]) (command: [F=[Y]])])]`
},
{
"pipeline with decl"
,
"{{$x := .X|.Y}}"
,
noError
,
`[(action: $x := [(command: [F=[X]]) (command: [F=[Y]])])]`
},
{
"declaration"
,
"{{.X|.Y}}"
,
noError
,
`[(action: [(command: [F=[X]]) (command: [F=[Y]])])]`
},
{
"simple if"
,
"{{if .X}}hello{{end}}"
,
noError
,
{
"simple if"
,
"{{if .X}}hello{{end}}"
,
noError
,
`[({{if [(command: [F=[X]])]}} [(text: "hello")])]`
},
`[({{if [(command: [F=[X]])]}} [(text: "hello")])]`
},
{
"if with else"
,
"{{if .X}}true{{else}}false{{end}}"
,
noError
,
{
"if with else"
,
"{{if .X}}true{{else}}false{{end}}"
,
noError
,
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment