Merge pull request #385 from radim/master

Support glob character in import
This commit is contained in:
Matt Holt 2015-12-29 16:21:26 -07:00
commit 6a27968f73
5 changed files with 60 additions and 10 deletions

View File

@ -0,0 +1,6 @@
glob0.host0 {
dir2 arg1
}
glob0.host1 {
}

View File

@ -0,0 +1,4 @@
glob1.host0 {
dir1
dir2 arg1
}

View File

@ -0,0 +1,3 @@
glob2.host0 {
dir2 arg1
}

View File

@ -176,19 +176,52 @@ func (p *parser) directives() error {
} }
// doImport swaps out the import directive and its argument // doImport swaps out the import directive and its argument
// (a total of 2 tokens) with the tokens in the file specified. // (a total of 2 tokens) with the tokens in the specified file
// When the function returns, the cursor is on the token before // or globbing pattern. When the function returns, the cursor
// where the import directive was. In other words, call Next() // is on the token before where the import directive was. In
// to access the first token that was imported. // other words, call Next() to access the first token that was
// imported.
func (p *parser) doImport() error { func (p *parser) doImport() error {
if !p.NextArg() { if !p.NextArg() {
return p.ArgErr() return p.ArgErr()
} }
importFile := p.Val() importPattern := p.Val()
if p.NextArg() { if p.NextArg() {
return p.Err("Import allows only one file to import") return p.Err("Import allows only one expression, either file or glob pattern")
} }
matches, err := filepath.Glob(importPattern)
if err != nil {
return p.Errf("Failed to use import pattern %s - %s", importPattern, err.Error())
}
if len(matches) == 0 {
return p.Errf("No files matching the import pattern %s", importPattern)
}
// Splice out the import directive and its argument (2 tokens total)
// and insert the imported tokens in their place.
tokensBefore := p.tokens[:p.cursor-1]
tokensAfter := p.tokens[p.cursor+1:]
// cursor was advanced one position to read filename; rewind it
p.cursor--
p.tokens = tokensBefore
for _, importFile := range matches {
if err := p.doSingleImport(importFile); err != nil {
return err
}
}
p.tokens = append(p.tokens, append(tokensAfter)...)
return nil
}
// doSingleImport lexes the individual files matching the
// globbing pattern from of the import directive.
func (p *parser) doSingleImport(importFile string) error {
file, err := os.Open(importFile) file, err := os.Open(importFile)
if err != nil { if err != nil {
return p.Errf("Could not import %s - %v", importFile, err) return p.Errf("Could not import %s - %v", importFile, err)
@ -203,10 +236,7 @@ func (p *parser) doImport() error {
// Splice out the import directive and its argument (2 tokens total) // Splice out the import directive and its argument (2 tokens total)
// and insert the imported tokens in their place. // and insert the imported tokens in their place.
tokensBefore := p.tokens[:p.cursor-1] p.tokens = append(p.tokens, append(importedTokens)...)
tokensAfter := p.tokens[p.cursor+1:]
p.tokens = append(tokensBefore, append(importedTokens, tokensAfter...)...)
p.cursor-- // cursor was advanced one position to read the filename; rewind it
return nil return nil
} }

View File

@ -329,6 +329,13 @@ func TestParseAll(t *testing.T) {
[]address{{"host1.com", "http"}, {"host2.com", "http"}}, []address{{"host1.com", "http"}, {"host2.com", "http"}},
[]address{{"host3.com", "https"}, {"host4.com", "https"}}, []address{{"host3.com", "https"}, {"host4.com", "https"}},
}}, }},
{`import import_glob*.txt`, false, [][]address{
[]address{{"glob0.host0", ""}},
[]address{{"glob0.host1", ""}},
[]address{{"glob1.host0", ""}},
[]address{{"glob2.host0", ""}},
}},
} { } {
p := testParser(test.input) p := testParser(test.input)
blocks, err := p.parseAll() blocks, err := p.parseAll()