From 5312f22893d4e92e24e3503dadaa55b4a4037f1f Mon Sep 17 00:00:00 2001 From: Adam Huganir Date: Sun, 9 Jun 2024 15:31:02 -0400 Subject: [PATCH 1/4] added some file and path methods, added ls example --- .pre-commit-config.yaml | 11 +++- README.md | 13 +++++ docs/_data/README.data.yaml | 25 +++++++++ internal/template.go | 13 ++++- pkg/customFunctions.go | 107 ++++++++++++++++++++++++++++++++++++ testFiles/ls-like.tmpl | 7 +++ 6 files changed, 173 insertions(+), 3 deletions(-) create mode 100644 testFiles/ls-like.tmpl diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 5dff065..d21229a 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -15,10 +15,19 @@ repos: args: ["--fix", "lf"] + - repo: local + hooks: + - id: go-fmt + name: go format + language: system + entry: gofmt + types: + - go + args: ["-l", "-w"] + - repo: https://github.com/dnephin/pre-commit-golang rev: v0.5.1 hooks: - - id: go-fmt - id: go-build - id: go-mod-tidy - repo: local diff --git a/README.md b/README.md index bdc7f94..af95d22 100644 --- a/README.md +++ b/README.md @@ -100,6 +100,19 @@ alternate form using matching --data-match './talosPatches/.*\.yaml' \ <(echo "{{ . | toYaml }}") ``` +### Listing files in a directory + +For some reason you want to list the files in a directory and embed them in a file in a custom format: + +```gotemplate +{{- $files := fileGlob "./*/*" -}} +{{- range $path := $files }} +{{- $stat := fileStat $path }} +{{- $username := (env "USERNAME" | default (env "USER") )}} +{{- $usernameFString := printf "%s%d%s " "%-" (len $username) "s"}} + {{ printf "%-12s" $stat.Mode }}{{ printf $usernameFString $username }}{{ pathAbsolute $path}} +{{- end }} +``` ### Merging 2 data files and applying them to a template ```pwsh diff --git a/docs/_data/README.data.yaml b/docs/_data/README.data.yaml index 92890ad..077321f 100644 --- a/docs/_data/README.data.yaml +++ b/docs/_data/README.data.yaml @@ -91,6 +91,31 @@ examples: --data-match './talosPatches/.*\.yaml' \ <(echo "{{ . | toYaml }}") ``` + - |- + ### Listing files in a directory + + For some reason you want to list the files in a directory and embed them in a file in a custom format: + + ```template + {{- $files := fileGlob "./*/*" -}} + {{- range $path := $files }} + {{- $stat := fileStat $path }} + {{- $username := (env "USERNAME" | default (env "USER") )}} + {{- $usernameFString := printf "%s%d%s " "%-" (len $username) "s"}} + {{ printf "%-12s" $stat.Mode }}{{ printf $usernameFString $username }}{{ pathAbsolute $path}} + {{- end }} + ``` + ``` + -rw-rw-rw- adam C:\Users\adam\code\yet-unnamed-template-cli\.git\COMMIT_EDITMSG + -rw-rw-rw- adam C:\Users\adam\code\yet-unnamed-template-cli\.git\FETCH_HEAD + -rw-rw-rw- adam C:\Users\adam\code\yet-unnamed-template-cli\.git\HEAD + -rw-rw-rw- adam C:\Users\adam\code\yet-unnamed-template-cli\.git\ORIG_HEAD + -rw-rw-rw- adam C:\Users\adam\code\yet-unnamed-template-cli\.git\config + -rw-rw-rw- adam C:\Users\adam\code\yet-unnamed-template-cli\.git\description + drwxrwxrwx adam C:\Users\adam\code\yet-unnamed-template-cli\.git\hooks + ........ + ``` + - |- ### Merging 2 data files and applying them to a template diff --git a/internal/template.go b/internal/template.go index e0b2539..98c425a 100644 --- a/internal/template.go +++ b/internal/template.go @@ -23,8 +23,17 @@ func BuildTemplate(text string, sharedTemplateBuffers []*bytes.Buffer, name stri "mustToToml": yutc.MustToToml, "mustFromToml": yutc.MustFromToml, // "stringMap": yutc.stringMap, - "wrapText": yutc.WrapText, - "wrapComment": yutc.WrapComment, + "wrapText": yutc.WrapText, + "wrapComment": yutc.WrapComment, + "fileGlob": yutc.PathGlob, + "fileStat": yutc.PathStat, + "fileRead": yutc.FileRead, + "fileReadN": yutc.FileReadN, + "type": yutc.TypeOf, + "pathAbsolute": yutc.PathAbsolute, + "pathIsDir": yutc.PathIsDir, + "pathIsFile": yutc.PathIsFile, + "pathExists": yutc.PathExists, }) for _, sharedTemplateBuffer := range sharedTemplateBuffers { tmpl, err = tmpl.Parse(sharedTemplateBuffer.String()) diff --git a/pkg/customFunctions.go b/pkg/customFunctions.go index ff19a36..de1abee 100644 --- a/pkg/customFunctions.go +++ b/pkg/customFunctions.go @@ -6,6 +6,8 @@ import ( "github.com/isbm/textwrap" "github.com/pelletier/go-toml/v2" "gopkg.in/yaml.v3" + "os" + "path/filepath" "strings" ) @@ -89,3 +91,108 @@ func WrapComment(prefix string, width int, comment string) string { } return strings.Join(wrapped, "\n") } + +func PathAbsolute(path string) string { + path = pathCommonClean(path) + path, err := filepath.Abs(path) + if err != nil { + panic(err) + } + return path +} + +func PathGlob(path string) []string { + path = pathCommonClean(path) + files, err := filepath.Glob(path) + if err != nil { + panic(err) + } + return files +} + +func PathStat(path string) map[string]interface{} { + path = pathCommonClean(path) + stat, err := os.Stat(path) + if err != nil { + if os.IsNotExist(err) { + panic(errors.Join(fmt.Errorf("file not found: %s", path))) + } + if os.IsPermission(err) { + panic(errors.Join(fmt.Errorf("permission denied: %s", path))) + } + panic(errors.Join(fmt.Errorf("unknown error %v: %s", err, path))) + + } + return map[string]interface{}{ + "Name": stat.Name(), + "Size": stat.Size(), + "Mode": stat.Mode().String(), + "ModTime": stat.ModTime(), + "IsDir": stat.IsDir(), + "Sys": stat.Sys(), + } +} + +func pathCommonClean(path string) string { + return filepath.Clean(os.ExpandEnv(path)) +} + +func PathIsDir(path string) bool { + path = pathCommonClean(path) + stat, err := os.Stat(path) + if err != nil { + return false + } + return stat.IsDir() +} + +func PathIsFile(path string) bool { + path = pathCommonClean(path) + stat, err := os.Stat(path) + if err != nil { + return false + } + return !stat.IsDir() +} + +func PathExists(path string) bool { + path = pathCommonClean(path) + _, err := os.Stat(path) + return !os.IsNotExist(err) +} + +func FileRead(path string) string { + path = pathCommonClean(path) + info, err := os.Stat(path) + if err != nil { + if os.IsNotExist(err) { + return "" + } else { + panic(fmt.Errorf("file not found: %s", path)) + } + } + if info.IsDir() { + panic(fmt.Errorf("cannot read a directory: %s", path)) + } + nBytes := int(info.Size()) + return FileReadN(nBytes, path) +} + +func FileReadN(nBytes int, path string) string { + path = pathCommonClean(path) + f, err := os.Open(path) + if err != nil { + panic(err) + } + defer f.Close() + data := make([]byte, nBytes) + n, err := f.Read(data) + if err != nil { + panic(err) + } + return string(data[:n]) +} + +func TypeOf(v interface{}) string { + return fmt.Sprintf("%T", v) +} diff --git a/testFiles/ls-like.tmpl b/testFiles/ls-like.tmpl new file mode 100644 index 0000000..82fc20c --- /dev/null +++ b/testFiles/ls-like.tmpl @@ -0,0 +1,7 @@ +{{- $files := fileGlob "./*/*" -}} +{{- range $path := $files }} +{{- $stat := fileStat $path }} +{{- $username := (env "USERNAME" | default (env "USER") )}} +{{- $usernameFString := printf "%s%d%s " "%-" (len $username) "s"}} + {{ printf "%-12s" $stat.Mode }}{{ printf $usernameFString $username }}{{ pathAbsolute $path}} +{{- end }} From cd07aac5402b14c6890758a21274fe8b259d7711 Mon Sep 17 00:00:00 2001 From: Adam Huganir Date: Sun, 9 Jun 2024 15:32:17 -0400 Subject: [PATCH 2/4] render docs --- README.md | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index af95d22..43c83ac 100644 --- a/README.md +++ b/README.md @@ -104,7 +104,7 @@ alternate form using matching For some reason you want to list the files in a directory and embed them in a file in a custom format: -```gotemplate +```template {{- $files := fileGlob "./*/*" -}} {{- range $path := $files }} {{- $stat := fileStat $path }} @@ -113,6 +113,16 @@ For some reason you want to list the files in a directory and embed them in a fi {{ printf "%-12s" $stat.Mode }}{{ printf $usernameFString $username }}{{ pathAbsolute $path}} {{- end }} ``` +``` + -rw-rw-rw- adam C:\Users\adam\code\yet-unnamed-template-cli\.git\COMMIT_EDITMSG + -rw-rw-rw- adam C:\Users\adam\code\yet-unnamed-template-cli\.git\FETCH_HEAD + -rw-rw-rw- adam C:\Users\adam\code\yet-unnamed-template-cli\.git\HEAD + -rw-rw-rw- adam C:\Users\adam\code\yet-unnamed-template-cli\.git\ORIG_HEAD + -rw-rw-rw- adam C:\Users\adam\code\yet-unnamed-template-cli\.git\config + -rw-rw-rw- adam C:\Users\adam\code\yet-unnamed-template-cli\.git\description + drwxrwxrwx adam C:\Users\adam\code\yet-unnamed-template-cli\.git\hooks + ........ + ``` ### Merging 2 data files and applying them to a template ```pwsh From 72b301c021a89484f3d356278ac837b199e2d9c0 Mon Sep 17 00:00:00 2001 From: Adam Huganir Date: Sun, 9 Jun 2024 15:32:51 -0400 Subject: [PATCH 3/4] version bump --- internal/version.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/internal/version.go b/internal/version.go index 0f4c317..fdd3b9b 100644 --- a/internal/version.go +++ b/internal/version.go @@ -2,7 +2,7 @@ package internal import "fmt" -var yutcVersion = "0.0.6" +var yutcVersion = "0.1.1" func PrintVersion() { fmt.Println(GetVersion()) From d8adf7e27a5adf767b568da415fa445b4d40a615 Mon Sep 17 00:00:00 2001 From: Adam Huganir Date: Sun, 9 Jun 2024 15:36:56 -0400 Subject: [PATCH 4/4] changed some task targets --- Taskfile.yaml | 9 ++++----- pkg/customFunctions.go | 5 ----- 2 files changed, 4 insertions(+), 10 deletions(-) diff --git a/Taskfile.yaml b/Taskfile.yaml index 7dad22e..80d9f0a 100644 --- a/Taskfile.yaml +++ b/Taskfile.yaml @@ -43,13 +43,12 @@ tasks: cmd: |- go run ./cmd/yutc/yutc.go --help - run-test1: + run-tests: desc: "Run X" vars: ARGS: "" - deps: - - "build" run: always - dir: "./tests" cmd: |- - go run ../cmd/yutc/yutc.go --shared ./testTemplates/def1.tmpl --data ./testFiles/data1.yaml ./testTemplates/template1.tmpl + go test ./cmd/yutc + go test ./internal + go test ./pkg diff --git a/pkg/customFunctions.go b/pkg/customFunctions.go index de1abee..8f3cec2 100644 --- a/pkg/customFunctions.go +++ b/pkg/customFunctions.go @@ -71,11 +71,6 @@ func FromToml(s string) interface{} { } -func stringMap(v interface{}) (map[string]interface{}, error) { - // i don't feel like writing a recursive function right now - return nil, errors.New("not implemented") -} - // WrapText wraps text to a given width func WrapText(width int, text string) []string { wrapper := textwrap.NewTextWrap()