diff --git a/README.md b/README.md index 7c7ba7e..92788ca 100644 --- a/README.md +++ b/README.md @@ -408,12 +408,17 @@ The following fragments are predefined: * `{{outName}}` is the base name of the output file being written, including any extensions * `{{outRoot}}` is the base name of the output file being written without any extensions * `{{outParent}}` is the directory name of the output file being written, without the preceeding path +* `{{importPath}}` produces the import path of the output file +* `{{importParent}}` produces the parent of the import path of the output file The template* fragments refer to the top level file, the one sent to the got command to process, while the include* fragments refer to the file being processed currently. For example, if the "a.tmpl" file included the "b.tmpl" file, then {{includeName}} in the b.tmpl file would produce "b.tmpl", while {{templateName}} in the b.tmpl file would produce "a.tmpl". +importPath and importParent are used to generate import paths to files that are relative +to the output file, since go does not support relative import paths. + #### Example ``` diff --git a/go.mod b/go.mod index 29eca1c..49347cd 100644 --- a/go.mod +++ b/go.mod @@ -1,7 +1,7 @@ module github.com/goradd/got require ( - github.com/goradd/gofile v1.1.1 + github.com/goradd/gofile v1.2.0 github.com/stretchr/testify v1.8.4 ) diff --git a/go.sum b/go.sum index 160deb6..d93f8af 100644 --- a/go.sum +++ b/go.sum @@ -1,7 +1,7 @@ github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/goradd/gofile v1.1.1 h1:Qi7L4WvIK+LjTujpZRRux4BZ8/OFhnQzMRASM/akFGo= -github.com/goradd/gofile v1.1.1/go.mod h1:ZjSvnGak2csGsJgEu8AgQc06eaoonhg2MzbqXON9o1M= +github.com/goradd/gofile v1.2.0 h1:sCHG3icAFGO8gwl5Yy8llvhlIl8k5uaYa6uE23Z56MA= +github.com/goradd/gofile v1.2.0/go.mod h1:ZjSvnGak2csGsJgEu8AgQc06eaoonhg2MzbqXON9o1M= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= diff --git a/internal/got/lexer.go b/internal/got/lexer.go index 6a3f18b..345f23f 100644 --- a/internal/got/lexer.go +++ b/internal/got/lexer.go @@ -66,18 +66,18 @@ func lexFile(fileName string, incRoot := namedBlocks[blockIncludeRoot].text incParent := namedBlocks[blockIncludeParent].text - namedBlocks[blockIncludePath] = namedBlockEntry{fp, 0, locationRef{}} - namedBlocks[blockIncludeName] = namedBlockEntry{filepath.Base(fp), 0, locationRef{}} - namedBlocks[blockIncludeRoot] = namedBlockEntry{root, 0, locationRef{}} - namedBlocks[blockIncludeParent] = namedBlockEntry{filepath.Base(filepath.Dir(fp)), 0, locationRef{}} + namedBlocks[blockIncludePath] = namedBlockEntry{fp, 0, locationRef{}, nil} + namedBlocks[blockIncludeName] = namedBlockEntry{filepath.Base(fp), 0, locationRef{}, nil} + namedBlocks[blockIncludeRoot] = namedBlockEntry{root, 0, locationRef{}, nil} + namedBlocks[blockIncludeParent] = namedBlockEntry{filepath.Base(filepath.Dir(fp)), 0, locationRef{}, nil} l.run() // restore - namedBlocks[blockIncludePath] = namedBlockEntry{incPath, 0, locationRef{}} - namedBlocks[blockIncludeName] = namedBlockEntry{incName, 0, locationRef{}} - namedBlocks[blockIncludeRoot] = namedBlockEntry{incRoot, 0, locationRef{}} - namedBlocks[blockIncludeParent] = namedBlockEntry{incParent, 0, locationRef{}} + namedBlocks[blockIncludePath] = namedBlockEntry{incPath, 0, locationRef{}, nil} + namedBlocks[blockIncludeName] = namedBlockEntry{incName, 0, locationRef{}, nil} + namedBlocks[blockIncludeRoot] = namedBlockEntry{incRoot, 0, locationRef{}, nil} + namedBlocks[blockIncludeParent] = namedBlockEntry{incParent, 0, locationRef{}, nil} }() return l } @@ -483,6 +483,12 @@ func processParams(name string, in namedBlockEntry, params []string) (out string var i int var s string + if in.f != nil { + // A processing function is being used + out, err = in.f(in.text, params) + return + } + if len(params) == 1 && params[0] == "" && in.paramCount == 0 { @@ -895,7 +901,7 @@ func (l *lexer) addNamedBlock(name string, text string, paramCount int) error { blockName: l.blockName, lineNum: l.lineNum, offset: l.lineRuneNum, - }} + }, nil} return nil } diff --git a/internal/got/runner.go b/internal/got/runner.go index 1fb61f4..943af96 100644 --- a/internal/got/runner.go +++ b/internal/got/runner.go @@ -6,6 +6,7 @@ import ( "log" "os" "os/exec" + "path" "path/filepath" "strings" @@ -28,12 +29,16 @@ const ( blockIncludeName = "includeName" blockIncludeRoot = "includeRoot" blockIncludeParent = "includeParent" + + blockImportPath = "importPath" + blockImportParent = "importParent" ) type namedBlockEntry struct { text string paramCount int ref locationRef + f func(string, []string) (string, error) // process text at the time the fragment is used } var modules map[string]string @@ -153,10 +158,10 @@ func processFile(file, outDir string, asts []astType, runImports bool) error { } // Default named block values - namedBlocks[blockIncludePath] = namedBlockEntry{"", 0, locationRef{}} - namedBlocks[blockIncludeName] = namedBlockEntry{"", 0, locationRef{}} - namedBlocks[blockIncludeRoot] = namedBlockEntry{"", 0, locationRef{}} - namedBlocks[blockIncludeParent] = namedBlockEntry{"", 0, locationRef{}} + namedBlocks[blockIncludePath] = namedBlockEntry{"", 0, locationRef{}, nil} + namedBlocks[blockIncludeName] = namedBlockEntry{"", 0, locationRef{}, nil} + namedBlocks[blockIncludeRoot] = namedBlockEntry{"", 0, locationRef{}, nil} + namedBlocks[blockIncludeParent] = namedBlockEntry{"", 0, locationRef{}, nil} file, _ = filepath.Abs(file) root := strings.TrimSuffix(filepath.Base(file), filepath.Ext(file)) @@ -168,10 +173,10 @@ func processFile(file, outDir string, asts []astType, runImports bool) error { root = strings.TrimSuffix(root, ext) } - namedBlocks[blockTemplatePath] = namedBlockEntry{file, 0, locationRef{}} - namedBlocks[blockTemplateName] = namedBlockEntry{filepath.Base(file), 0, locationRef{}} - namedBlocks[blockTemplateRoot] = namedBlockEntry{root, 0, locationRef{}} - namedBlocks[blockTemplateParent] = namedBlockEntry{filepath.Base(filepath.Dir(file)), 0, locationRef{}} + namedBlocks[blockTemplatePath] = namedBlockEntry{file, 0, locationRef{}, nil} + namedBlocks[blockTemplateName] = namedBlockEntry{filepath.Base(file), 0, locationRef{}, nil} + namedBlocks[blockTemplateRoot] = namedBlockEntry{root, 0, locationRef{}, nil} + namedBlocks[blockTemplateParent] = namedBlockEntry{filepath.Base(filepath.Dir(file)), 0, locationRef{}, nil} newPath, _ = filepath.Abs(newPath) root = strings.TrimSuffix(filepath.Base(newPath), filepath.Ext(newPath)) @@ -183,10 +188,16 @@ func processFile(file, outDir string, asts []astType, runImports bool) error { root = strings.TrimSuffix(root, ext) } - namedBlocks[blockOutPath] = namedBlockEntry{newPath, 0, locationRef{}} - namedBlocks[blockOutName] = namedBlockEntry{filepath.Base(newPath), 0, locationRef{}} - namedBlocks[blockOutRoot] = namedBlockEntry{root, 0, locationRef{}} - namedBlocks[blockOutParent] = namedBlockEntry{filepath.Base(filepath.Dir(newPath)), 0, locationRef{}} + namedBlocks[blockOutPath] = namedBlockEntry{newPath, 0, locationRef{}, nil} + namedBlocks[blockOutName] = namedBlockEntry{filepath.Base(newPath), 0, locationRef{}, nil} + namedBlocks[blockOutRoot] = namedBlockEntry{root, 0, locationRef{}, nil} + namedBlocks[blockOutParent] = namedBlockEntry{filepath.Base(filepath.Dir(newPath)), 0, locationRef{}, nil} + + // These two are slow functions, so we cannot call them on every file, + // but rather just when they are needed, so we use a processing function + // that gets called at the time the nameBlock is invoked. + namedBlocks[blockImportPath] = namedBlockEntry{newPath, 0, locationRef{}, importPath} + namedBlocks[blockImportParent] = namedBlockEntry{newPath, 0, locationRef{}, importParent} a, err := buildAst(file, namedBlocks) if err != nil { @@ -373,3 +384,16 @@ func fileIsNewer(path1, path2 string) bool { modTime2 := file2.ModTime() return modTime1.After(modTime2) } + +func importPath(outPath string, params []string) (string, error) { + return sys.ImportPath(outPath) +} + +func importParent(outPath string, params []string) (string, error) { + out, err := sys.ImportPath(outPath) + if err != nil { + return "", err + } + dir := path.Dir(out) + return dir, err +} diff --git a/internal/testdata/expected/TestPredefines.out b/internal/testdata/expected/TestPredefines.out index 546a753..daf12b2 100755 --- a/internal/testdata/expected/TestPredefines.out +++ b/internal/testdata/expected/TestPredefines.out @@ -7,6 +7,8 @@ template runner.inc runner inc +github.com/goradd/got/internal/testdata/template +github.com/goradd/got/internal/testdata testPredefines.tpl.got diff --git a/internal/testdata/src/testPredefines.tpl.got b/internal/testdata/src/testPredefines.tpl.got index c9dfb8d..090e834 100644 --- a/internal/testdata/src/testPredefines.tpl.got +++ b/internal/testdata/src/testPredefines.tpl.got @@ -15,6 +15,9 @@ {{includeName}} {{includeRoot}} {{includeParent}} +{{# test processing functions }} +{{importPath}} +{{importParent}} {{: "predef.inc" }}