Skip to content

Commit

Permalink
feat(cmd): Add --recursive flag
Browse files Browse the repository at this point in the history
  • Loading branch information
gabe565 committed Apr 10, 2024
1 parent 7dd4e2a commit 195d802
Show file tree
Hide file tree
Showing 8 changed files with 122 additions and 17 deletions.
35 changes: 33 additions & 2 deletions cmd/cmd.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (
"errors"
"fmt"
"io"
"io/fs"
"os"
"path/filepath"
"strings"
Expand Down Expand Up @@ -44,6 +45,11 @@ func NewCommand(version, commit string) *cobra.Command {
panic(err)
}

cmd.Flags().BoolVarP(&conf.Recursive, "recursive", "r", conf.Recursive, "Recursively update yaml files in the given directory")
if err := cmd.RegisterFlagCompletionFunc("recursive", util.BoolCompletion); err != nil {
panic(err)
}

cmd.Flags().StringVarP(&conf.Prefix, "prefix", "p", conf.Prefix, "Template comments must begin with this prefix. The beginning '#' is implied.")
if err := cmd.RegisterFlagCompletionFunc("prefix", cobra.NoFileCompletions); err != nil {
panic(err)
Expand Down Expand Up @@ -105,7 +111,7 @@ func preRun(cmd *cobra.Command, args []string) error {
conf.Prefix = "#" + conf.Prefix
}

if conf.Inplace && len(args) == 0 {
if len(args) == 0 && (conf.Inplace || conf.Recursive) {
return ErrNoFiles
}

Expand Down Expand Up @@ -152,7 +158,32 @@ func run(cmd *cobra.Command, args []string) error {
return nil
}

func openAndTemplate(cmd *cobra.Command, conf config.Config, p string) error {
func openAndTemplate(cmd *cobra.Command, conf config.Config, path string) error {
stat, err := os.Stat(path)
if err != nil {
return err
}

if stat.IsDir() {
return filepath.WalkDir(path, func(path string, d fs.DirEntry, err error) error {
if err != nil || d.IsDir() || !util.IsYaml(path) {
return err
}

if !conf.Inplace {
if _, err := io.WriteString(cmd.OutOrStdout(), "---\n"); err != nil {
return err
}
}

return openAndTemplateFile(cmd, conf, path)
})
}

return openAndTemplate(cmd, conf, path)
}

func openAndTemplateFile(cmd *cobra.Command, conf config.Config, p string) error {
f, err := os.Open(p)
if err != nil {
return err
Expand Down
14 changes: 12 additions & 2 deletions cmd/cmd_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,16 @@ func Test_preRun(t *testing.T) {
require.Error(t, err)
})

t.Run("recursive no files", func(t *testing.T) {
conf.Recursive = true
defer func() {
conf.Recursive = false
}()

err := preRun(NewCommand("", ""), []string{})
require.Error(t, err)
})

t.Run("completion flag enabled", func(t *testing.T) {
cmd := NewCommand("", "")
if err := cmd.Flags().Set(CompletionFlag, "zsh"); !assert.NoError(t, err) {
Expand Down Expand Up @@ -122,7 +132,7 @@ func Test_templateReader(t *testing.T) {
}
}

func Test_openAndTemplate(t *testing.T) {
func Test_openAndTemplateFile(t *testing.T) {
inplaceConf := config.New()
inplaceConf.Inplace = true

Expand Down Expand Up @@ -170,7 +180,7 @@ func Test_openAndTemplate(t *testing.T) {
var stdoutBuf strings.Builder
cmd.SetOut(&stdoutBuf)

err = openAndTemplate(cmd, tt.args.conf, p)
err = openAndTemplateFile(cmd, tt.args.conf, p)
tt.wantErr(t, err)

fileContents, err := os.ReadFile(p)
Expand Down
49 changes: 38 additions & 11 deletions cmd/flag_values.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,13 @@ package cmd
import (
"errors"
"io"
"io/fs"
"os"
"path/filepath"
"strings"

"github.com/clevyr/yampl/internal/config/flags"
"github.com/clevyr/yampl/internal/util"
"github.com/clevyr/yampl/internal/visitor"
"github.com/spf13/cobra"
"gopkg.in/yaml.v3"
Expand All @@ -28,28 +31,52 @@ func valueCompletion(_ *cobra.Command, args []string, _ string) ([]string, cobra
v := visitor.NewFindArgs(conf)

for _, path := range args {
f, err := os.Open(path)
stat, err := os.Stat(path)
if err != nil {
continue
}

decoder := yaml.NewDecoder(f)

for {
var n yaml.Node

if err := decoder.Decode(&n); err != nil {
if errors.Is(err, io.EOF) {
break
if stat.IsDir() {
err := filepath.WalkDir(path, func(path string, d fs.DirEntry, err error) error {
if err != nil || d.IsDir() || !util.IsYaml(path) {
return err
}

return valueCompletionFile(path, v)
})
if err != nil {
continue
}

if err := v.Run(&n); err != nil {
} else {
if err := valueCompletionFile(path, v); err != nil {
continue
}
}
}

return v.Values(), cobra.ShellCompDirectiveNoSpace | cobra.ShellCompDirectiveNoFileComp
}

func valueCompletionFile(path string, v *visitor.FindArgs) error {
f, err := os.Open(path)
if err != nil {
return err
}

decoder := yaml.NewDecoder(f)

for {
var n yaml.Node

if err := decoder.Decode(&n); err != nil {
if errors.Is(err, io.EOF) {
return nil
}
return err
}

if err := v.Run(&n); err != nil {
return err
}
}
}
1 change: 1 addition & 0 deletions docs/yampl.md
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ yampl [-i] [-p prefix] [-v key=value ...] [file ...]
--log-format string Log format (auto, color, plain, json) (default "color")
-l, --log-level string Log level (trace, debug, info, warn, error, fatal, panic) (default "info")
-p, --prefix string Template comments must begin with this prefix. The beginning '#' is implied. (default "#yampl")
-r, --recursive Recursively update yaml files in the given directory
--right-delim string Override template right delimiter (default "}}")
-s, --strip Strip template comments from output
-v, --value stringToString Define a template variable. Can be used more than once. (default [])
Expand Down
1 change: 1 addition & 0 deletions internal/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package config
type Config struct {
Values Values
Inplace bool
Recursive bool
Prefix string
LeftDelim string
RightDelim string
Expand Down
8 changes: 8 additions & 0 deletions internal/util/file.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package util

import "path/filepath"

func IsYaml(path string) bool {
ext := filepath.Ext(path)
return ext == ".yaml" || ext == ".yml"
}
27 changes: 27 additions & 0 deletions internal/util/file_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package util

import (
"testing"

"github.com/stretchr/testify/assert"
)

func TestIsYaml(t *testing.T) {
type args struct {
path string
}
tests := []struct {
name string
args args
want bool
}{
{"yaml", args{"test.yaml"}, true},
{"yml", args{"test.yml"}, true},
{"txt", args{"test.txt"}, false},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
assert.Equal(t, tt.want, IsYaml(tt.args.path))
})
}
}
4 changes: 2 additions & 2 deletions internal/visitor/find_args.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,8 @@ import (
"gopkg.in/yaml.v3"
)

func NewFindArgs(conf config.Config) FindArgs {
return FindArgs{
func NewFindArgs(conf config.Config) *FindArgs {
return &FindArgs{
conf: conf,
matchMap: make(map[string]MatchSlice),
}
Expand Down

0 comments on commit 195d802

Please sign in to comment.