Skip to content

Commit

Permalink
operator ,@ ; outname ; overwrite ; update pick to use these
Browse files Browse the repository at this point in the history
Signed-off-by: Tony Worm <tony@hofstadter.io>
  • Loading branch information
verdverm committed Oct 16, 2021
1 parent dc8ec7b commit cc7c02d
Show file tree
Hide file tree
Showing 13 changed files with 391 additions and 43 deletions.
6 changes: 2 additions & 4 deletions cmd/cuetils/cmd/pick.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,14 +17,12 @@ func PickRun(pick string, globs []string) (err error) {
// you can safely comment this print out
// fmt.Println("not implemented")

picks, err := structural.Pick(pick, globs, flags.RootPflags)
results, err := structural.Pick(pick, globs, flags.RootPflags)
if err != nil {
return err
}

for _, p := range picks {
fmt.Printf("%s\n----------------------\n%s\n\n", p.Filename, p.Content)
}
err = structural.ProcessOutputs(results, flags.RootPflags)

return err
}
Expand Down
6 changes: 6 additions & 0 deletions structural/count.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,12 @@ import (
"github.com/hofstadter-io/cuetils/cmd/cuetils/flags"
)

type StatsResult struct {
Filename string
Count int
Depth int
}

type CountResult struct {
Filename string
Count int
Expand Down
77 changes: 73 additions & 4 deletions structural/input.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,16 +6,85 @@ import (
"os"
"path/filepath"
"sort"
"strings"

"cuelang.org/go/cue"
"cuelang.org/go/cue/load"
)

type Input struct {
Filename string
Filetype string // yaml, json, cue... toml?
Expression string // cue expression to select within document
Content []byte
Original string
Entrypoints []string
Filename string
Filetype string // yaml, json, cue... toml?
Expression string // cue expression to select within document
Content []byte
Value cue.Value
}

func ParseOperator(op string) (Input, error) {
i := Input{ Original: op, Filename: op }

// does the op look like a file or a CUE value?

// look for expression
if strings.Contains(i.Filename, "@") {
parts := strings.Split(op, "@")
if len(parts) != 2 {
return i, fmt.Errorf("more than on '@' found for input %q", i.Original)
}
i.Filename, i.Expression = parts[0], parts[1]
}
// look for entrypoints
if strings.Contains(i.Filename, ",") {
i.Entrypoints = strings.Split(i.Filename, ",")
i.Filename = ""
}

return i, nil
}

func LoadOperator(i Input, doLoad bool, ctx *cue.Context) (Input, error) {
if doLoad || i.Entrypoints != nil {
// handle entrypoints
if i.Entrypoints == nil {
i.Entrypoints = []string{i.Filename}
}
v, err := LoadInputs(i.Entrypoints, ctx)
if err != nil {
return i, err
}
i.Value = v
} else {
// handle stdin?

// handle single file
d, err := os.ReadFile(i.Filename)
if err != nil {
return i, err
}
// handle input types
ext := filepath.Ext(i.Filename)
switch ext {
case ".yml", ".yaml":
s := fmt.Sprintf(yamlMod, string(d))
d = []byte(s)
}

i.Content = d

i.Value = ctx.CompileBytes(i.Content, cue.Filename(i.Filename))
}

if i.Value.Err() != nil {
return i, i.Value.Err()
}

if i.Expression != "" {
i.Value = i.Value.LookupPath(cue.ParsePath(i.Expression))
}

return i, nil
}

// Loads the entrypoints using the context provided
Expand Down
83 changes: 83 additions & 0 deletions structural/output.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,15 @@ import (
"bytes"
"encoding/json"
"fmt"
"os"
"path/filepath"
"strings"

"cuelang.org/go/cue"
"cuelang.org/go/cue/format"
"cuelang.org/go/encoding/yaml"

"github.com/hofstadter-io/cuetils/cmd/cuetils/flags"
)

type GlobResult struct {
Expand All @@ -16,6 +21,84 @@ type GlobResult struct {
Value cue.Value
}

func ProcessOutputs(results []GlobResult, rflags flags.RootPflagpole) (err error) {
//if rflags.Accum != "" {
//results, err = AccumOutputs(results, rflags.Accum)
//if err != nil {
//return err
//}
//}
w := os.Stdout
for _, r := range results {
// Format
r.Content, err = FormatOutput(r.Value, rflags.Out)
if err != nil {
return err
}

// make outname
outname := ""
if rflags.Outname != "" {
outname = rflags.Outname
// look for interpolation syntax
if strings.Contains(outname, "<") {
dir, file := filepath.Split(r.Filename)
ext := filepath.Ext(file)
name := strings.TrimSuffix(file, ext)

outname = strings.Replace(outname, "<dir>", dir, -1)
outname = strings.Replace(outname, "<name>", name, -1)
outname = strings.Replace(outname, "<ext>", ext, -1)
outname = strings.Replace(outname, "<filename>", file, -1)
outname = strings.Replace(outname, "<filepath>", r.Filename, -1)
}
if strings.Contains(outname, "\\(") {
o := r.Value.Context().CompileString(outname, cue.Scope(r.Value))
outname, err = o.String()
if err != nil {
return err
}
}
}

// are we writing a file?
writeFile := false
if rflags.Overwrite || outname != "" {
writeFile = true
}
// now possibly fill filename
if outname == "" {
outname = r.Filename
}

// if yes, we need to override w
if writeFile {
_, err = os.Stat(outname)
// if no overwrite and exists, return err
if !rflags.Overwrite && err == nil {
return err
}
w, err = os.Create(outname)
if err != nil {
return err
}
}

// now do actual writing
if rflags.Headers {
fmt.Fprintf(w, "%s\n----------------------\n%s\n\n", outname, r.Content)
} else {
fmt.Fprintf(w, "%s\n", r.Content)
}
}

return nil
}

func AccumOutputs(results []GlobResult, accum string) ([]GlobResult, error) {
return results, nil
}

func FormatOutput(val cue.Value, format string) (string, error) {
switch format {
case "cue", "CUE":
Expand Down
31 changes: 11 additions & 20 deletions structural/pick.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,23 +20,19 @@ val: #P: _
pick: val.pick
`

func Pick(orig string, globs []string, rflags flags.RootPflagpole) ([]PickResult, error) {
// no globs, then stdin
if len(globs) == 0 {
globs = []string{"-"}
}

func Pick(orig string, globs []string, rflags flags.RootPflagpole) ([]GlobResult, error) {
cuest, err := NewCuest([]string{"pick"}, nil)
if err != nil {
return nil, err
}

ov, err := LoadInputs([]string{orig}, cuest.ctx)
operator, err := ParseOperator(orig)
if err != nil {
return nil, err
}
if ov.Err() != nil {
return nil, ov.Err()
operator, err = LoadOperator(operator, rflags.LoadOperands, cuest.ctx)
if err != nil {
return nil, err
}

inputs, err := ReadGlobs(globs)
Expand All @@ -53,9 +49,9 @@ func Pick(orig string, globs []string, rflags flags.RootPflagpole) ([]PickResult
val := cuest.ctx.CompileString(content, cue.Scope(cuest.orig))

// fill val with the orig value, so we only need to once before loop
val = val.FillPath(cue.ParsePath("val.#P"), ov)
val = val.FillPath(cue.ParsePath("val.#P"), operator.Value)

picks := make([]PickResult, 0)
results := make([]GlobResult, 0)
for _, input := range inputs {

iv := cuest.ctx.CompileBytes(input.Content, cue.Filename(input.Filename))
Expand All @@ -65,19 +61,14 @@ func Pick(orig string, globs []string, rflags flags.RootPflagpole) ([]PickResult

result := val.FillPath(cue.ParsePath("val.#X"), iv)

dv := result.LookupPath(cue.ParsePath("pick"))

out, err := FormatOutput(dv, rflags.Out)
if err != nil {
return nil, err
}
v := result.LookupPath(cue.ParsePath("pick"))

picks = append(picks, PickResult{
results = append(results, GlobResult{
Filename: input.Filename,
Content: out,
Value: v,
})

}

return picks, nil
return results, nil
}
101 changes: 91 additions & 10 deletions test/cli/cli_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,20 +7,101 @@ import (
"github.com/hofstadter-io/hof/script/runtime"
)

func TestCliTests(t *testing.T) {
func TestCliCount(t *testing.T) {
yagu.Mkdir(".workdir/tests")
runtime.Run(t, runtime.Params{
Dir: "testdata",
Glob: "*.txt",
Glob: "count_*.txt",
WorkdirRoot: ".workdir/tests",
})
}

func TestCliDepth(t *testing.T) {
yagu.Mkdir(".workdir/tests")
runtime.Run(t, runtime.Params{
Dir: "testdata",
Glob: "depth_*.txt",
WorkdirRoot: ".workdir/tests",
})
}

func TestCliDiff(t *testing.T) {
yagu.Mkdir(".workdir/tests")
runtime.Run(t, runtime.Params{
Dir: "testdata",
Glob: "diff_*.txt",
WorkdirRoot: ".workdir/tests",
})
}

func TestCliMask(t *testing.T) {
yagu.Mkdir(".workdir/tests")
runtime.Run(t, runtime.Params{
Dir: "testdata",
Glob: "mask_*.txt",
WorkdirRoot: ".workdir/tests",
})
}

func TestCliPatch(t *testing.T) {
yagu.Mkdir(".workdir/tests")
runtime.Run(t, runtime.Params{
Dir: "testdata",
Glob: "patch_*.txt",
WorkdirRoot: ".workdir/tests",
})
}

func TestCliPick(t *testing.T) {
yagu.Mkdir(".workdir/tests")
runtime.Run(t, runtime.Params{
Dir: "testdata",
Glob: "pick_*.txt",
WorkdirRoot: ".workdir/tests",
})
}

func TestCliReplace(t *testing.T) {
yagu.Mkdir(".workdir/tests")
runtime.Run(t, runtime.Params{
Dir: "testdata",
Glob: "replace_*.txt",
WorkdirRoot: ".workdir/tests",
})
}

func TestCliTransform(t *testing.T) {
yagu.Mkdir(".workdir/tests")
runtime.Run(t, runtime.Params{
Dir: "testdata",
Glob: "transform_*.txt",
WorkdirRoot: ".workdir/tests",
})
}

func TestCliUpsert(t *testing.T) {
yagu.Mkdir(".workdir/tests")
runtime.Run(t, runtime.Params{
Dir: "testdata",
Glob: "upsert_*.txt",
WorkdirRoot: ".workdir/tests",
})
}

//func TestCliBugs(t *testing.T) {
//yagu.Mkdir(".workdir/bugs")
//runtime.Run(t, runtime.Params{
//Dir: "testdata/bugs",
//Glob: "*.txt",
//WorkdirRoot: ".workdir/bugs",
//})
//}
func TestCliValidate(t *testing.T) {
yagu.Mkdir(".workdir/tests")
runtime.Run(t, runtime.Params{
Dir: "testdata",
Glob: "validate_*.txt",
WorkdirRoot: ".workdir/tests",
})
}

func TestCliBugs(t *testing.T) {
yagu.Mkdir(".workdir/bugs")
runtime.Run(t, runtime.Params{
Dir: "testdata/bugs",
Glob: "*.txt",
WorkdirRoot: ".workdir/bugs",
})
}
Loading

0 comments on commit cc7c02d

Please sign in to comment.