diff --git a/caddyconfig/caddyfile/dispenser.go b/caddyconfig/caddyfile/dispenser.go
index 0d2c7899b..66a3541c6 100755
--- a/caddyconfig/caddyfile/dispenser.go
+++ b/caddyconfig/caddyfile/dispenser.go
@@ -24,19 +24,16 @@ import (
 // except that it can do so with some notion of structure. An empty
 // Dispenser is invalid; call NewDispenser to make a proper instance.
 type Dispenser struct {
-	filename string
-	tokens   []Token
-	cursor   int
-	nesting  int
+	tokens  []Token
+	cursor  int
+	nesting int
 }
 
 // NewDispenser returns a Dispenser filled with the given tokens.
-// TODO: Get rid of the filename argument; it seems pointless here
-func NewDispenser(filename string, tokens []Token) *Dispenser {
+func NewDispenser(tokens []Token) *Dispenser {
 	return &Dispenser{
-		filename: filename,
-		tokens:   tokens,
-		cursor:   -1,
+		tokens: tokens,
+		cursor: -1,
 	}
 }
 
@@ -170,8 +167,8 @@ func (d *Dispenser) Val() string {
 	return d.tokens[d.cursor].Text
 }
 
-// Line gets the line number of the current token. If there is no token
-// loaded, it returns 0.
+// Line gets the line number of the current token.
+// If there is no token loaded, it returns 0.
 func (d *Dispenser) Line() int {
 	if d.cursor < 0 || d.cursor >= len(d.tokens) {
 		return 0
@@ -179,16 +176,12 @@ func (d *Dispenser) Line() int {
 	return d.tokens[d.cursor].Line
 }
 
-// File gets the filename of the current token. If there is no token loaded,
-// it returns the filename originally given when parsing started.
+// File gets the filename where the current token originated.
 func (d *Dispenser) File() string {
 	if d.cursor < 0 || d.cursor >= len(d.tokens) {
-		return d.filename
+		return ""
 	}
-	if tokenFilename := d.tokens[d.cursor].File; tokenFilename != "" {
-		return tokenFilename
-	}
-	return d.filename
+	return d.tokens[d.cursor].File
 }
 
 // Args is a convenience function that loads the next arguments
@@ -240,28 +233,22 @@ func (d *Dispenser) NewFromNextTokens() *Dispenser {
 	} else {
 		d.cursor--
 	}
-	return NewDispenser(d.filename, tkns)
+	return NewDispenser(tkns)
 }
 
 // Token returns the current token.
 func (d *Dispenser) Token() Token {
-	return d.TokenAt(d.cursor)
-}
-
-func (d *Dispenser) TokenAt(cursor int) Token {
-	if cursor < 0 || cursor >= len(d.tokens) {
+	if d.cursor < 0 || d.cursor >= len(d.tokens) {
 		return Token{}
 	}
-	return d.tokens[cursor]
-}
-
-// Cursor returns the current cursor (token index).
-func (d *Dispenser) Cursor() int {
-	return d.cursor
+	return d.tokens[d.cursor]
 }
 
+// Reset sets d's cursor to the beginning, as
+// if this was a new and unused dispenser.
 func (d *Dispenser) Reset() {
 	d.cursor = -1
+	d.nesting = 0
 }
 
 // ArgErr returns an argument error, meaning that another
diff --git a/caddyconfig/caddyfile/dispenser_test.go b/caddyconfig/caddyfile/dispenser_test.go
index 9860bedb8..07fbbeeea 100755
--- a/caddyconfig/caddyfile/dispenser_test.go
+++ b/caddyconfig/caddyfile/dispenser_test.go
@@ -308,9 +308,9 @@ func TestDispenser_ArgErr_Err(t *testing.T) {
 }
 
 func newTestDispenser(input string) *Dispenser {
-	tokens, err := allTokens(strings.NewReader(input))
+	tokens, err := allTokens("Testfile", strings.NewReader(input))
 	if err != nil && err != io.EOF {
 		log.Fatalf("getting all tokens from input: %v", err)
 	}
-	return NewDispenser("Testfile", tokens)
+	return NewDispenser(tokens)
 }
diff --git a/caddyconfig/caddyfile/parse.go b/caddyconfig/caddyfile/parse.go
index cc7ed25db..3356f256c 100755
--- a/caddyconfig/caddyfile/parse.go
+++ b/caddyconfig/caddyfile/parse.go
@@ -29,18 +29,18 @@ import (
 // an error. If you do not want to check for valid directives,
 // pass in nil instead.
 func Parse(filename string, input io.Reader) ([]ServerBlock, error) {
-	tokens, err := allTokens(input)
+	tokens, err := allTokens(filename, input)
 	if err != nil {
 		return nil, err
 	}
-	p := parser{Dispenser: NewDispenser(filename, tokens)}
+	p := parser{Dispenser: NewDispenser(tokens)}
 	return p.parseAll()
 }
 
 // allTokens lexes the entire input, but does not parse it.
 // It returns all the tokens from the input, unstructured
 // and in order.
-func allTokens(input io.Reader) ([]Token, error) {
+func allTokens(filename string, input io.Reader) ([]Token, error) {
 	l := new(lexer)
 	err := l.load(input)
 	if err != nil {
@@ -48,6 +48,7 @@ func allTokens(input io.Reader) ([]Token, error) {
 	}
 	var tokens []Token
 	for l.next() {
+		l.token.File = filename
 		tokens = append(tokens, l.token)
 	}
 	return tokens, nil
@@ -265,7 +266,7 @@ func (p *parser) doImport() error {
 		// list of matching filenames
 		absFile, err := filepath.Abs(p.Dispenser.File())
 		if err != nil {
-			return p.Errf("Failed to get absolute path of file: %s: %v", p.Dispenser.filename, err)
+			return p.Errf("Failed to get absolute path of file: %s: %v", p.Dispenser.File(), err)
 		}
 
 		var matches []string
@@ -327,7 +328,7 @@ func (p *parser) doSingleImport(importFile string) ([]Token, error) {
 		return nil, p.Errf("Could not import %s: is a directory", importFile)
 	}
 
-	importedTokens, err := allTokens(file)
+	importedTokens, err := allTokens(importFile, file)
 	if err != nil {
 		return nil, p.Errf("Could not read tokens while importing %s: %v", importFile, err)
 	}
@@ -336,7 +337,7 @@ func (p *parser) doSingleImport(importFile string) ([]Token, error) {
 	// (we use full, absolute path to avoid bugs: issue #1892)
 	filename, err := filepath.Abs(importFile)
 	if err != nil {
-		return nil, p.Errf("Failed to get absolute path of file: %s: %v", p.Dispenser.filename, err)
+		return nil, p.Errf("Failed to get absolute path of file: %s: %v", importFile, err)
 	}
 	for i := 0; i < len(importedTokens); i++ {
 		importedTokens[i].File = filename
@@ -497,7 +498,7 @@ func (sb ServerBlock) DispenseDirective(dir string) *Dispenser {
 			tokens = append(tokens, seg...)
 		}
 	}
-	return NewDispenser("", tokens)
+	return NewDispenser(tokens)
 }
 
 // Segment is a list of tokens which begins with a directive
@@ -513,9 +514,3 @@ func (s Segment) Directive() string {
 	}
 	return ""
 }
-
-// NewDispenser returns a dispenser for this
-// segment's tokens.
-func (s Segment) NewDispenser() *Dispenser {
-	return NewDispenser("", s)
-}
diff --git a/caddyconfig/caddyfile/parse_test.go b/caddyconfig/caddyfile/parse_test.go
index 19959de84..d4e22cc44 100755
--- a/caddyconfig/caddyfile/parse_test.go
+++ b/caddyconfig/caddyfile/parse_test.go
@@ -27,7 +27,7 @@ import (
 func TestAllTokens(t *testing.T) {
 	input := strings.NewReader("a b c\nd e")
 	expected := []string{"a", "b", "c", "d", "e"}
-	tokens, err := allTokens(input)
+	tokens, err := allTokens("TestAllTokens", input)
 
 	if err != nil {
 		t.Fatalf("Expected no error, got %v", err)
diff --git a/caddyconfig/httpcaddyfile/httptype.go b/caddyconfig/httpcaddyfile/httptype.go
index 42c1be592..e7e7c87cc 100644
--- a/caddyconfig/httpcaddyfile/httptype.go
+++ b/caddyconfig/httpcaddyfile/httptype.go
@@ -38,6 +38,10 @@ func init() {
 type ServerType struct {
 }
 
+// TODO: customize directive ordering
+
+// TODO: hide caddyfile when serving static files
+
 // Setup makes a config from the tokens.
 func (st ServerType) Setup(originalServerBlocks []caddyfile.ServerBlock,
 	options map[string]string) (*caddy.Config, []caddyconfig.Warning, error) {
@@ -88,7 +92,7 @@ func (st ServerType) Setup(originalServerBlocks []caddyfile.ServerBlock,
 			}
 			if dirFunc, ok := registeredDirectives[dir]; ok {
 				results, err := dirFunc(Helper{
-					Dispenser:   segment.NewDispenser(),
+					Dispenser:   caddyfile.NewDispenser(segment),
 					warnings:    &warnings,
 					matcherDefs: matcherDefs,
 				})