summaryrefslogtreecommitdiff
path: root/caddyconfig/caddyfile/dispenser.go
diff options
context:
space:
mode:
Diffstat (limited to 'caddyconfig/caddyfile/dispenser.go')
-rwxr-xr-xcaddyconfig/caddyfile/dispenser.go75
1 files changed, 54 insertions, 21 deletions
diff --git a/caddyconfig/caddyfile/dispenser.go b/caddyconfig/caddyfile/dispenser.go
index 938c985..de67ee1 100755
--- a/caddyconfig/caddyfile/dispenser.go
+++ b/caddyconfig/caddyfile/dispenser.go
@@ -123,18 +123,39 @@ func (d *Dispenser) NextLine() bool {
// NextBlock can be used as the condition of a for loop
// to load the next token as long as it opens a block or
-// is already in a block. It returns true if a token was
-// loaded, or false when the block's closing curly brace
-// was loaded and thus the block ended. Nested blocks are
-// not supported.
-func (d *Dispenser) NextBlock() bool {
- if d.nesting > 0 {
- d.Next()
+// is already in a block nested more than initialNestingLevel.
+// In other words, a loop over NextBlock() will iterate
+// all tokens in the block assuming the next token is an
+// open curly brace, until the matching closing brace.
+// The open and closing brace tokens for the outer-most
+// block will be consumed internally and omitted from
+// the iteration.
+//
+// Proper use of this method looks like this:
+//
+// for nesting := d.Nesting(); d.NextBlock(nesting); {
+// }
+//
+// However, in simple cases where it is known that the
+// Dispenser is new and has not already traversed state
+// by a loop over NextBlock(), this will do:
+//
+// for d.NextBlock(0) {
+// }
+//
+// As with other token parsing logic, a loop over
+// NextBlock() should be contained within a loop over
+// Next(), as it is usually prudent to skip the initial
+// token.
+func (d *Dispenser) NextBlock(initialNestingLevel int) bool {
+ if d.nesting > initialNestingLevel {
+ if !d.Next() {
+ return false // should be EOF error
+ }
if d.Val() == "}" {
d.nesting--
- return false
}
- return true
+ return d.nesting > initialNestingLevel
}
if !d.nextOnSameLine() { // block must open on same line
return false
@@ -143,19 +164,18 @@ func (d *Dispenser) NextBlock() bool {
d.cursor-- // roll back if not opening brace
return false
}
- d.Next()
+ d.Next() // consume open curly brace
if d.Val() == "}" {
- // open and then closed right away
- return false
+ return false // open and then closed right away
}
d.nesting++
return true
}
-// Nested returns true if the token is currently nested
-// inside a block (i.e. an open curly brace was consumed).
-func (d *Dispenser) Nested() bool {
- return d.nesting > 0
+// Nesting returns the current nesting level. Necessary
+// if using NextBlock()
+func (d *Dispenser) Nesting() int {
+ return d.nesting
}
// Val gets the text of the current token. If there is no token
@@ -230,19 +250,32 @@ func (d *Dispenser) RemainingArgs() []string {
// NewFromNextTokens returns a new dispenser with a copy of
// the tokens from the current token until the end of the
// "directive" whether that be to the end of the line or
-// the end of a block that starts at the end of the line.
+// the end of a block that starts at the end of the line;
+// in other words, until the end of the segment.
func (d *Dispenser) NewFromNextTokens() *Dispenser {
tkns := []Token{d.Token()}
for d.NextArg() {
tkns = append(tkns, d.Token())
}
- for d.NextBlock() {
- for d.Nested() {
+ var openedBlock bool
+ for nesting := d.Nesting(); d.NextBlock(nesting); {
+ if !openedBlock {
+ // because NextBlock() consumes the initial open
+ // curly brace, we rewind here to append it, since
+ // our case is special in that we want to include
+ // all the tokens including surrounding curly braces
+ // for a new dispenser to have
+ d.Prev()
tkns = append(tkns, d.Token())
- d.NextBlock()
+ d.Next()
+ openedBlock = true
}
+ tkns = append(tkns, d.Token())
+ }
+ if openedBlock {
+ // include closing brace accordingly
+ tkns = append(tkns, d.Token())
}
- tkns = append(tkns, d.Token())
return NewDispenser(tkns)
}