diff --git a/evaldo/builtins.go b/evaldo/builtins.go index cd1d3096..e1c30ab0 100644 --- a/evaldo/builtins.go +++ b/evaldo/builtins.go @@ -56,6 +56,12 @@ func MakeArgError(env1 *env.ProgramState, N int, typ []env.Type, fn string) *env return env.NewError("Function " + fn + " requires argument " + strconv.Itoa(N) + " to be of : " + types + ".") } +func MakeNativeArgError(env1 *env.ProgramState, N int, knd []string, fn string) *env.Error { + env1.FailureFlag = true + kinds := strings.Join(knd, ", ") + return env.NewError("Function " + fn + " requires native argument " + strconv.Itoa(N) + " to be of kind : " + kinds + ".") +} + func MakeRyeError(env1 *env.ProgramState, val env.Object, er *env.Error) *env.Error { switch val := val.(type) { case env.String: // todo .. make Error type .. make error construction micro dialect, return the error wrapping error that caused it diff --git a/evaldo/builtins_psutil.go b/evaldo/builtins_psutil.go index 549ed84b..129d4491 100644 --- a/evaldo/builtins_psutil.go +++ b/evaldo/builtins_psutil.go @@ -8,9 +8,11 @@ import ( "io/ioutil" "os" "path/filepath" + "regexp" "strings" "time" + "github.com/bitfield/script" "github.com/refaktor/rye/env" "github.com/shirou/gopsutil/v3/disk" @@ -56,7 +58,7 @@ var Builtins_devops = map[string]*env.Builtin{ } // TODO -- check if it exists default: - return *MakeArgError(ps, 1, []env.Type{env.UriType}, "cd") + return MakeArgError(ps, 1, []env.Type{env.UriType}, "cd") } }, }, @@ -70,12 +72,12 @@ var Builtins_devops = map[string]*env.Builtin{ newDir := filepath.Join(filepath.Dir(ps.WorkingPath), path.GetPath()) err := os.Mkdir(newDir, 0755) // Create directory with permissions 0755 if err != nil { - return *MakeBuiltinError(ps, "Error creating directory: "+err.Error(), "mkdir") + return MakeBuiltinError(ps, "Error creating directory: "+err.Error(), "mkdir") } else { return arg0 } default: - return *MakeArgError(ps, 1, []env.Type{env.UriType}, "mkdir") + return MakeArgError(ps, 1, []env.Type{env.UriType}, "mkdir") } }, }, @@ -93,15 +95,15 @@ var Builtins_devops = map[string]*env.Builtin{ err := os.Rename(old, new) if err != nil { fmt.Println("Error renaming file:", err) - return *MakeBuiltinError(ps, "Error renaming file: "+err.Error(), "mv") + return MakeBuiltinError(ps, "Error renaming file: "+err.Error(), "mv") } else { return arg1 } default: - return *MakeArgError(ps, 1, []env.Type{env.UriType}, "mkdir") + return MakeArgError(ps, 1, []env.Type{env.UriType}, "mkdir") } default: - return *MakeArgError(ps, 1, []env.Type{env.UriType}, "mkdir") + return MakeArgError(ps, 1, []env.Type{env.UriType}, "mkdir") } }, }, @@ -121,7 +123,7 @@ var Builtins_devops = map[string]*env.Builtin{ files, err := ioutil.ReadDir(ps.WorkingPath + "/") if err != nil { - return *MakeBuiltinError(ps, "Error reading directory:"+err.Error(), "ls") + return MakeBuiltinError(ps, "Error reading directory:"+err.Error(), "ls") } items := make([]env.Object, len(files)) @@ -136,6 +138,629 @@ var Builtins_devops = map[string]*env.Builtin{ }, }, + // SCRIPT PIPES + + "p-new-file": { + Argsn: 1, + Doc: "Creates a new pipe object from a file.", + Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object { + switch path := arg0.(type) { + case env.Uri: + p := script.File(path.GetPath()) + return *env.NewNative(ps.Idx, p, "script-pipe") + default: + return MakeArgError(ps, 1, []env.Type{env.UriType}, "p-new-file") + } + }, + }, + + "p-new-find-files": { + Argsn: 1, + Doc: "Creates a pipe object listing all the files in the directory and its subdirectories recursively, one per line.", + Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object { + switch path := arg0.(type) { + case env.Uri: + p := script.FindFiles(path.GetPath()) + return *env.NewNative(ps.Idx, p, "script-pipe") + default: + return MakeArgError(ps, 1, []env.Type{env.UriType}, "p-new-find-files") + } + }, + }, + + "p-new-list-files": { + Argsn: 1, + Doc: "Creates a pipe object listing all the files in the directory, one per line. Accepts and URI or glob pattern.", + Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object { + switch path := arg0.(type) { + case env.Uri: + p := script.ListFiles(path.GetPath()) + return *env.NewNative(ps.Idx, p, "script-pipe") + case env.String: + p := script.ListFiles(path.Value) + return *env.NewNative(ps.Idx, p, "script-pipe") + default: + return MakeArgError(ps, 1, []env.Type{env.UriType}, "p-new-list-files") + } + }, + }, + + "p-new-block": { + Argsn: 1, + Doc: "Creates a pipe object from a block of strings, one per line.", + Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object { + switch block := arg0.(type) { + case env.Block: + strs := make([]string, len(block.Series.S)) + for i, item := range block.Series.S { + switch s := item.(type) { + case env.String: + strs[i] = s.Value + default: + return MakeBuiltinError(ps, "Block must contain only strings", "p-new-block") + } + } + p := script.Slice(strs) + return *env.NewNative(ps.Idx, p, "script-pipe") + default: + return MakeArgError(ps, 1, []env.Type{env.BlockType}, "p-new-block") + } + }, + }, + + "p-new-echo": { + Argsn: 1, + Doc: "Creates a pipe object from a string.", + Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object { + switch s := arg0.(type) { + case env.String: + p := script.Echo(s.Value) + return *env.NewNative(ps.Idx, p, "script-pipe") + default: + return MakeArgError(ps, 1, []env.Type{env.StringType}, "p-new-echo") + } + }, + }, + + "p-new-if-exists": { + Argsn: 1, + Doc: "Creates a pipe object from a file if it exists, otherwise returns an empty pipe object.", + Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object { + switch path := arg0.(type) { + case env.Uri: + p := script.IfExists(path.GetPath()) + return *env.NewNative(ps.Idx, p, "script-pipe") + default: + return MakeArgError(ps, 1, []env.Type{env.UriType}, "p-new-if-exists") + } + }, + }, + + "p-new-exec": { + Argsn: 1, + Doc: "Creates a pipe object from a command that is executed.", + Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object { + switch cmd := arg0.(type) { + case env.String: + p := script.Exec(cmd.Value) + return *env.NewNative(ps.Idx, p, "script-pipe") + default: + return MakeArgError(ps, 1, []env.Type{env.StringType}, "p-new-exec") + } + }, + }, + + "p-exec": { + Argsn: 2, + Doc: "Executes a command by sending it the contents of the pipe as input and returns a pipe object.", + Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object { + switch p := arg0.(type) { + case env.Native: + switch pipe := p.Value.(type) { + case *script.Pipe: + switch cmd := arg1.(type) { + case env.String: + newPipe := pipe.Exec(cmd.Value) + return *env.NewNative(ps.Idx, newPipe, "script-pipe") + default: + return MakeArgError(ps, 2, []env.Type{env.StringType}, "p-exec") + } + default: + return MakeNativeArgError(ps, 1, []string{"script-pipe"}, "p-exec") + } + default: + return MakeArgError(ps, 1, []env.Type{env.NativeType}, "p-exec") + } + }, + }, + + "p-exec-for-each": { + Argsn: 2, + Doc: "Executes a command from a Go template for each line in the pipe and returns a pipe object with the output of each command.", + Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object { + switch p := arg0.(type) { + case env.Native: + switch pipe := p.Value.(type) { + case *script.Pipe: + switch cmd := arg1.(type) { + case env.String: + newPipe := pipe.ExecForEach(cmd.Value) + return *env.NewNative(ps.Idx, newPipe, "script-pipe") + default: + return MakeArgError(ps, 2, []env.Type{env.StringType}, "p-exec-for-each") + } + default: + return MakeNativeArgError(ps, 1, []string{"script-pipe"}, "p-exec-for-each") + } + default: + return MakeArgError(ps, 1, []env.Type{env.NativeType}, "p-exec-for-each") + } + }, + }, + + "p-string": { + Argsn: 1, + Doc: "Returns pipe contents as a string.", + Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object { + switch p := arg0.(type) { + case env.Native: + switch pipe := p.Value.(type) { + case *script.Pipe: + str, err := pipe.String() + if err != nil { + return MakeBuiltinError(ps, err.Error(), "p-string") + } + return *env.NewString(str) + default: + return MakeNativeArgError(ps, 1, []string{"script-pipe"}, "p-string") + } + default: + return MakeArgError(ps, 1, []env.Type{env.NativeType}, "p-string") + } + }, + }, + + "p-write-file": { + Argsn: 2, + Doc: "Writes pipe contents to a file and returns the number of bytes written.", + Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object { + switch p := arg0.(type) { + case env.Native: + switch pipe := p.Value.(type) { + case *script.Pipe: + switch path := arg1.(type) { + case env.Uri: + i, err := pipe.WriteFile(path.GetPath()) + if err != nil { + return MakeBuiltinError(ps, err.Error(), "p-write-file") + } + return *env.NewInteger(int64(i)) + default: + return MakeArgError(ps, 2, []env.Type{env.UriType}, "p-write-file") + } + default: + return MakeNativeArgError(ps, 1, []string{"script-pipe"}, "p-write-file") + } + default: + return MakeArgError(ps, 1, []env.Type{env.NativeType}, "p-write-file") + } + }, + }, + + "p-stdout": { + Argsn: 1, + Doc: "Prints pipe contents to stdout and returns the number of bytes written.", + Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object { + switch p := arg0.(type) { + case env.Native: + switch pipe := p.Value.(type) { + case *script.Pipe: + i, err := pipe.Stdout() + if err != nil { + return MakeBuiltinError(ps, err.Error(), "p-stdout") + } + return *env.NewInteger(int64(i)) + default: + return MakeNativeArgError(ps, 1, []string{"script-pipe"}, "p-stdout") + } + default: + return MakeArgError(ps, 1, []env.Type{env.NativeType}, "p-stdout") + } + }, + }, + + "p-first-n": { + Argsn: 2, + Doc: "Returns a pipe with the first n lines from the pipe.", + Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object { + switch p := arg0.(type) { + case env.Native: + switch pipe := p.Value.(type) { + case *script.Pipe: + switch n := arg1.(type) { + case env.Integer: + newPipe := pipe.First(int(n.Value)) + return *env.NewNative(ps.Idx, newPipe, "script-pipe") + default: + return MakeArgError(ps, 2, []env.Type{env.IntegerType}, "p-first-n") + } + default: + return MakeNativeArgError(ps, 1, []string{"script-pipe"}, "p-first-n") + } + default: + return MakeArgError(ps, 1, []env.Type{env.NativeType}, "p-first-n") + } + }, + }, + + "p-last-n": { + Argsn: 2, + Doc: "Returns a pipe with the last n lines from the pipe.", + Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object { + switch p := arg0.(type) { + case env.Native: + switch pipe := p.Value.(type) { + case *script.Pipe: + switch n := arg1.(type) { + case env.Integer: + newPipe := pipe.Last(int(n.Value)) + return *env.NewNative(ps.Idx, newPipe, "script-pipe") + default: + return MakeArgError(ps, 2, []env.Type{env.IntegerType}, "p-last-n") + } + default: + return MakeNativeArgError(ps, 1, []string{"script-pipe"}, "p-last-n") + } + default: + return MakeArgError(ps, 1, []env.Type{env.NativeType}, "p-last-n") + } + }, + }, + + "p-dirname": { + Argsn: 1, + Doc: "Reads paths from the pipe, one per line, and returns the directory component of each.", + Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object { + switch p := arg0.(type) { + case env.Native: + switch pipe := p.Value.(type) { + case *script.Pipe: + newPipe := pipe.Dirname() + return *env.NewNative(ps.Idx, newPipe, "script-pipe") + default: + return MakeNativeArgError(ps, 1, []string{"script-pipe"}, "p-dirname") + } + default: + return MakeArgError(ps, 1, []env.Type{env.NativeType}, "p-dirname") + } + }, + }, + + "p-basename": { + Argsn: 1, + Doc: "Reads paths from the pipe, one per line, and removes any leading directory components from each.", + Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object { + switch p := arg0.(type) { + case env.Native: + switch pipe := p.Value.(type) { + case *script.Pipe: + newPipe := pipe.Basename() + return *env.NewNative(ps.Idx, newPipe, "script-pipe") + default: + return MakeNativeArgError(ps, 1, []string{"script-pipe"}, "p-basename") + } + default: + return MakeArgError(ps, 1, []env.Type{env.NativeType}, "p-basename") + } + }, + }, + + "p-count-lines": { + Argsn: 1, + Doc: "Returns the number of lines in a pipe.", + Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object { + switch p := arg0.(type) { + case env.Native: + switch pipe := p.Value.(type) { + case *script.Pipe: + n, err := pipe.CountLines() + if err != nil { + return MakeBuiltinError(ps, err.Error(), "p-count-lines") + } + return *env.NewInteger(int64(n)) + default: + return MakeNativeArgError(ps, 1, []string{"script-pipe"}, "p-count-lines") + } + default: + return MakeArgError(ps, 1, []env.Type{env.NativeType}, "p-count-lines") + } + }, + }, + + "p-freq": { + Argsn: 1, + Doc: "Returns a pipe object with the frequency of each line in a pipe in descending order.", + Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object { + switch p := arg0.(type) { + case env.Native: + switch pipe := p.Value.(type) { + case *script.Pipe: + newPipe := pipe.Freq() + return *env.NewNative(ps.Idx, newPipe, "script-pipe") + default: + return MakeNativeArgError(ps, 1, []string{"script-pipe"}, "p-freq") + } + default: + return MakeArgError(ps, 1, []env.Type{env.NativeType}, "p-freq") + } + }, + }, + + "p-column": { + Argsn: 2, + Doc: "Returns a pipe object with the column of each line of input, where the first column is column 1, and columns are delimited by Unicode whitespace.", + Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object { + switch p := arg0.(type) { + case env.Native: + switch pipe := p.Value.(type) { + case *script.Pipe: + switch n := arg1.(type) { + case env.Integer: + newPipe := pipe.Column(int(n.Value)) + return *env.NewNative(ps.Idx, newPipe, "script-pipe") + default: + return MakeArgError(ps, 2, []env.Type{env.IntegerType}, "p-column") + } + default: + return MakeNativeArgError(ps, 1, []string{"script-pipe"}, "p-column") + } + default: + return MakeArgError(ps, 1, []env.Type{env.NativeType}, "p-column") + } + }, + }, + + "p-jq": { + Argsn: 2, + Doc: "Executes the jq command on the pipe whose contents are presumed to be JSON and returns a new pipe object with the output.", + Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object { + switch p := arg0.(type) { + case env.Native: + switch pipe := p.Value.(type) { + case *script.Pipe: + switch jq := arg1.(type) { + case env.String: + newPipe := pipe.JQ(jq.Value) + return *env.NewNative(ps.Idx, newPipe, "script-pipe") + default: + return MakeArgError(ps, 2, []env.Type{env.StringType}, "p-jq") + } + default: + return MakeNativeArgError(ps, 1, []string{"script-pipe"}, "p-jq") + } + default: + return MakeArgError(ps, 1, []env.Type{env.NativeType}, "p-jq") + } + }, + }, + + "p-match": { + Argsn: 2, + Doc: "Returns a pipe object with lines that match the string.", + Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object { + switch p := arg0.(type) { + case env.Native: + switch pipe := p.Value.(type) { + case *script.Pipe: + switch s := arg1.(type) { + case env.String: + newPipe := pipe.Match(s.Value) + return *env.NewNative(ps.Idx, newPipe, "script-pipe") + default: + return MakeArgError(ps, 2, []env.Type{env.StringType}, "p-match") + } + default: + return MakeNativeArgError(ps, 1, []string{"script-pipe"}, "p-match") + } + default: + return MakeArgError(ps, 1, []env.Type{env.NativeType}, "p-match") + } + }, + }, + + "p-match-regexp": { + Argsn: 2, + Doc: "Returns a pipe object with lines that match the regular expression.", + Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object { + switch p := arg0.(type) { + case env.Native: + switch pipe := p.Value.(type) { + case *script.Pipe: + switch r := arg1.(type) { + case env.Native: + switch regxp := r.Value.(type) { + case *regexp.Regexp: + newPipe := pipe.MatchRegexp(regxp) + return *env.NewNative(ps.Idx, newPipe, "script-pipe") + default: + return MakeNativeArgError(ps, 2, []string{"regexp"}, "p-match-regexp") + } + default: + return MakeArgError(ps, 2, []env.Type{env.NativeType}, "p-match-regexp") + } + default: + return MakeNativeArgError(ps, 1, []string{"script-pipe"}, "p-match-regexp") + } + default: + return MakeArgError(ps, 1, []env.Type{env.NativeType}, "p-match-regexp") + } + }, + }, + + "p-not-match": { + Argsn: 2, + Doc: "Returns a pipe object with lines that do not match the string.", + Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object { + switch p := arg0.(type) { + case env.Native: + switch pipe := p.Value.(type) { + case *script.Pipe: + switch s := arg1.(type) { + case env.String: + newPipe := pipe.Reject(s.Value) + return *env.NewNative(ps.Idx, newPipe, "script-pipe") + default: + return MakeArgError(ps, 2, []env.Type{env.StringType}, "p-not-match") + } + default: + return MakeNativeArgError(ps, 1, []string{"script-pipe"}, "p-not-match") + } + default: + return MakeArgError(ps, 1, []env.Type{env.NativeType}, "p-not-match") + } + }, + }, + + "p-not-match-regexp": { + Argsn: 2, + Doc: "Returns a pipe object with lines that do not match the regular expression.", + Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object { + switch p := arg0.(type) { + case env.Native: + switch pipe := p.Value.(type) { + case *script.Pipe: + switch r := arg1.(type) { + case env.Native: + switch regxp := r.Value.(type) { + case *regexp.Regexp: + newPipe := pipe.RejectRegexp(regxp) + return *env.NewNative(ps.Idx, newPipe, "script-pipe") + default: + return MakeNativeArgError(ps, 2, []string{"regexp"}, "p-not-match-regexp") + } + default: + return MakeArgError(ps, 2, []env.Type{env.NativeType}, "p-not-match-regexp") + } + default: + return MakeNativeArgError(ps, 1, []string{"script-pipe"}, "p-not-match-regexp") + } + default: + return MakeArgError(ps, 1, []env.Type{env.NativeType}, "p-not-match-regexp") + } + }, + }, + + "p-replace": { + Argsn: 3, + Doc: "Replaces all occurrences of a string with another string in the pipe and returns a new pipe object.", + Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object { + switch p := arg0.(type) { + case env.Native: + switch pipe := p.Value.(type) { + case *script.Pipe: + switch search := arg1.(type) { + case env.String: + switch replace := arg2.(type) { + case env.String: + newPipe := pipe.Replace(search.Value, replace.Value) + return *env.NewNative(ps.Idx, newPipe, "script-pipe") + default: + return MakeArgError(ps, 3, []env.Type{env.StringType}, "p-replace") + } + default: + return MakeArgError(ps, 2, []env.Type{env.StringType}, "p-replace") + } + default: + return MakeNativeArgError(ps, 1, []string{"script-pipe"}, "p-replace") + } + default: + return MakeArgError(ps, 1, []env.Type{env.NativeType}, "p-replace") + } + }, + }, + + "p-replace-regexp": { + Argsn: 3, + Doc: "Replaces all occurrences of strings that match the regexp pattern with a string in the pipe and returns a new pipe object.", + Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object { + switch p := arg0.(type) { + case env.Native: + switch pipe := p.Value.(type) { + case *script.Pipe: + switch searchR := arg1.(type) { + case env.Native: + switch searchRegexp := searchR.Value.(type) { + case *regexp.Regexp: + switch replace := arg2.(type) { + case env.String: + newPipe := pipe.ReplaceRegexp(searchRegexp, replace.Value) + return *env.NewNative(ps.Idx, newPipe, "script-pipe") + default: + return MakeArgError(ps, 3, []env.Type{env.StringType}, "p-replace-regexp") + } + default: + return MakeNativeArgError(ps, 2, []string{"regexp"}, "p-replace-regexp") + } + default: + return MakeArgError(ps, 2, []env.Type{env.NativeType}, "p-replace-regexp") + } + default: + return MakeNativeArgError(ps, 1, []string{"script-pipe"}, "p-replace-regexp") + } + default: + return MakeArgError(ps, 1, []env.Type{env.NativeType}, "p-replace-regexp") + } + }, + }, + + "p-block": { + Argsn: 1, + Doc: "Returns a block of strings with the contents of the pipe, one per line.", + Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object { + switch p := arg0.(type) { + case env.Native: + switch pipe := p.Value.(type) { + case *script.Pipe: + lines, err := pipe.Slice() + if err != nil { + return MakeBuiltinError(ps, err.Error(), "p-block") + } + items := make([]env.Object, len(lines)) + for i, line := range lines { + items[i] = *env.NewString(line) + } + return *env.NewBlock(*env.NewTSeries(items)) + default: + return MakeNativeArgError(ps, 1, []string{"script-pipe"}, "p-block") + } + default: + return MakeArgError(ps, 1, []env.Type{env.NativeType}, "p-block") + } + }, + }, + + "p-error": { + Argsn: 1, + Doc: "Returns the error from the pipe, if any.", + Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object { + switch p := arg0.(type) { + case env.Native: + switch pipe := p.Value.(type) { + case *script.Pipe: + err := pipe.Error() + if err != nil { + return *env.NewError(err.Error()) + } + return env.Void{} + default: + return MakeNativeArgError(ps, 1, []string{"script-pipe"}, "p-error") + } + default: + return MakeArgError(ps, 1, []env.Type{env.NativeType}, "p-error") + } + }, + }, + // GOPSUTIL "host-info?": { diff --git a/go.mod b/go.mod index 99ea4ef1..34907e20 100644 --- a/go.mod +++ b/go.mod @@ -10,6 +10,7 @@ require ( github.com/aws/aws-sdk-go-v2 v1.26.1 github.com/aws/aws-sdk-go-v2/config v1.27.10 github.com/aws/aws-sdk-go-v2/service/ses v1.22.4 + github.com/bitfield/script v0.22.0 github.com/blevesearch/bleve/v2 v2.4.0 github.com/blevesearch/bleve_index_api v1.1.6 github.com/drewlanenga/govector v0.0.0-20220726163947-b958ac08bc93 @@ -80,9 +81,10 @@ require ( github.com/golang/protobuf v1.5.2 // indirect github.com/golang/snappy v0.0.1 // indirect github.com/gorilla/securecookie v1.1.2 // indirect + github.com/itchyny/gojq v0.12.12 // indirect + github.com/itchyny/timefmt-go v0.1.5 // indirect github.com/jmespath/go-jmespath v0.4.0 // indirect github.com/json-iterator/go v1.1.11 // indirect - github.com/kr/pretty v0.1.0 // indirect github.com/labstack/gommon v0.4.1 // indirect github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 // indirect github.com/mattn/go-colorable v0.1.13 // indirect @@ -91,7 +93,7 @@ require ( github.com/modern-go/reflect2 v1.0.1 // indirect github.com/mschoch/smat v0.2.0 // indirect github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c // indirect - github.com/rivo/uniseg v0.2.0 // indirect + github.com/rivo/uniseg v0.4.4 // indirect github.com/shoenig/go-m1cpu v0.1.6 // indirect github.com/technoweenie/multipartstreamer v1.0.1 // indirect github.com/tklauser/go-sysconf v0.3.13 // indirect @@ -106,4 +108,5 @@ require ( gopkg.in/alexcesaro/quotedprintable.v3 v3.0.0-20150716171945-2caba252f4dc // indirect gopkg.in/gomail.v2 v2.0.0-20160411212932-81ebce5c23df // indirect gopkg.in/yaml.v2 v2.4.0 // indirect + mvdan.cc/sh/v3 v3.6.0 // indirect ) diff --git a/go.sum b/go.sum index be477a45..12889226 100644 --- a/go.sum +++ b/go.sum @@ -32,6 +32,8 @@ github.com/aws/aws-sdk-go-v2/service/sts v1.28.6 h1:cwIxeBttqPN3qkaAjcEcsh8NYr8n github.com/aws/aws-sdk-go-v2/service/sts v1.28.6/go.mod h1:FZf1/nKNEkHdGGJP/cI2MoIMquumuRK6ol3QQJNDxmw= github.com/aws/smithy-go v1.20.2 h1:tbp628ireGtzcHDDmLT/6ADHidqnwgF57XOXZe6tp4Q= github.com/aws/smithy-go v1.20.2/go.mod h1:krry+ya/rV9RDcV/Q16kpu6ypI4K2czasz0NC3qS14E= +github.com/bitfield/script v0.22.0 h1:LA7QHuEsXMPD52YLtxWrlqCCy+9FOpzNYfsRHC5Gsrc= +github.com/bitfield/script v0.22.0/go.mod h1:ms4w+9B8f2/W0mbsgWDVTtl7K94bYuZc3AunnJC4Ebs= github.com/bits-and-blooms/bitset v1.2.0 h1:Kn4yilvwNtMACtf1eYDlG8H77R07mZSPbMjLyS07ChA= github.com/bits-and-blooms/bitset v1.2.0/go.mod h1:gIdJ4wp64HaoK2YrL1Q5/N7Y16edYb8uY+O0FJTyyDA= github.com/blevesearch/bleve/v2 v2.4.0 h1:2xyg+Wv60CFHYccXc+moGxbL+8QKT/dZK09AewHgKsg= @@ -72,11 +74,15 @@ github.com/blevesearch/zapx/v16 v16.0.12 h1:Uccxvjmn+hQ6ywQP+wIiTpdq9LnAviGoryJO github.com/blevesearch/zapx/v16 v16.0.12/go.mod h1:MYnOshRfSm4C4drxx1LGRI+MVFByykJ2anDY1fxdk9Q= github.com/bmizerany/assert v0.0.0-20160611221934-b7ed37b82869 h1:DDGfHa7BWjL4YnC6+E63dPcxHo2sUxDIu8g3QgEJdRY= github.com/bmizerany/assert v0.0.0-20160611221934-b7ed37b82869/go.mod h1:Ekp36dRnpXw/yCqJaO+ZrUyxD+3VXMFFr56k5XYrpB4= +github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= +github.com/creack/pty v1.1.18/go.mod h1:MOBLtS5ELjhRRrroQr9kyvTxUAFNvYEK993ew/Vr4O4= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= 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/drewlanenga/govector v0.0.0-20220726163947-b958ac08bc93 h1:2VXZHsypUG1HaQcj/+nQc5TbZ4qZ5FSl7KN4s1BjFQY= github.com/drewlanenga/govector v0.0.0-20220726163947-b958ac08bc93/go.mod h1:AbP/uRrjZFATEwl0P2DHePteIMZRWHEJBWBmMmLdCkk= +github.com/frankban/quicktest v1.14.4 h1:g2rn0vABPOOXmZUj+vbmUp0lPoXEMuhTpIluN0XL9UY= +github.com/frankban/quicktest v1.14.4/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0= github.com/gliderlabs/ssh v0.3.7 h1:iV3Bqi942d9huXnzEF2Mt+CY9gLu8DNM4Obd+8bODRE= github.com/gliderlabs/ssh v0.3.7/go.mod h1:zpHEXBstFnQYtGnB8k8kQLol82umzn/2/snG7alWVD8= github.com/go-gomail/gomail v0.0.0-20160411212932-81ebce5c23df h1:Bao6dhmbTA1KFVxmJ6nBoMuOJit2yjEgLJpIMYpop0E= @@ -100,6 +106,7 @@ github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= github.com/golang/snappy v0.0.1 h1:Qgr9rKW7uDUkrbSmQeiDsGa8SjGyCOGtuasMWwvp2P4= github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= +github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= @@ -108,10 +115,15 @@ github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeN github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0= github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= +github.com/google/renameio/v2 v2.0.0/go.mod h1:BtmJXm5YlszgC+TD4HOEEUFgkJP3nLxehU6hfe7jRt4= github.com/gorilla/securecookie v1.1.2 h1:YCIWL56dvtr73r6715mJs5ZvhtnY73hBvEF8kXD8ePA= github.com/gorilla/securecookie v1.1.2/go.mod h1:NfCASbcHqRSY+3a8tlWJwsQap2VX5pwzwo4h3eOamfo= github.com/gorilla/sessions v1.2.2 h1:lqzMYz6bOfvn2WriPUjNByzeXIlVzURcPmgMczkmTjY= github.com/gorilla/sessions v1.2.2/go.mod h1:ePLdVu+jbEgHH+KWw8I1z2wqd0BAdAQh/8LRvBeoNcQ= +github.com/itchyny/gojq v0.12.12 h1:x+xGI9BXqKoJQZkr95ibpe3cdrTbY8D9lonrK433rcA= +github.com/itchyny/gojq v0.12.12/go.mod h1:j+3sVkjxwd7A7Z5jrbKibgOLn0ZfLWkV+Awxr/pyzJE= +github.com/itchyny/timefmt-go v0.1.5 h1:G0INE2la8S6ru/ZI5JecgyzbbJNs5lG1RcBqa7Jm6GE= +github.com/itchyny/timefmt-go v0.1.5/go.mod h1:nEP7L+2YmAbT2kZ2HfSs1d8Xtw9LY8D2stDBckWakZ8= github.com/jinzhu/copier v0.4.0 h1:w3ciUoD19shMCRargcpm0cm91ytaBhDvuRpz1ODO/U8= github.com/jinzhu/copier v0.4.0/go.mod h1:DfbEm0FYsaqBcKcFuvmOZb218JkPGtvSHsKg8S8hyyg= github.com/jmespath/go-jmespath v0.4.0 h1:BEgLn5cpjn8UN1mAw4NjwDrS35OdebyEtFe+9YPoQUg= @@ -120,11 +132,10 @@ github.com/jmespath/go-jmespath/internal/testify v1.5.1 h1:shLQSRRSCCPj3f2gpwzGw github.com/jmespath/go-jmespath/internal/testify v1.5.1/go.mod h1:L3OGu8Wl2/fWfCI6z80xFu9LTZmf1ZRjMHUOPmWr69U= github.com/json-iterator/go v1.1.11 h1:uVUAXhF2To8cbw/3xN3pxj6kk7TYKs98NIrTqPlMWAQ= github.com/json-iterator/go v1.1.11/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= -github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI= -github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= -github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= -github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE= -github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= +github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= +github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= +github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= +github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/labstack/echo v3.3.10+incompatible h1:pGRcYk231ExFAyoAjAfD85kQzRJCRI8bbnE7CX5OEgg= github.com/labstack/echo v3.3.10+incompatible/go.mod h1:0INS7j/VjnFxD4E2wkz67b8cVwCLbBmJyDaka6Cmk1s= github.com/labstack/gommon v0.4.1 h1:gqEff0p/hTENGMABzezPoPSRtIh1Cvw0ueMOe0/dfOk= @@ -136,9 +147,11 @@ github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0/go.mod h1:zJYVVT2 github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= +github.com/mattn/go-isatty v0.0.17/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= github.com/mattn/go-runewidth v0.0.3/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= +github.com/mattn/go-runewidth v0.0.14/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= github.com/mattn/go-runewidth v0.0.15 h1:UNAjwbU9l54TA3KzvqLGxwWjHmMgBUVhBiTjelZgg3U= github.com/mattn/go-runewidth v0.0.15/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= github.com/mattn/go-sqlite3 v1.14.22 h1:2gZY6PC6kBnID23Tichd1K+Z0oS6nE/XwU+Vz/5o4kU= @@ -154,6 +167,7 @@ github.com/mrz1836/postmark v1.6.4 h1:x5g0zjFE1q1wOgZ3N22rtGMyfKd3GBo4O874cAUw6b github.com/mrz1836/postmark v1.6.4/go.mod h1:6z5MxAH00Kj44owtQaryv9Pbqp5OKT3wWcRSydB0p0A= github.com/mschoch/smat v0.2.0 h1:8imxQsjDm8yFEAVBe7azKmKSgzSkZXDuKkSq9374khM= github.com/mschoch/smat v0.2.0/go.mod h1:kc9mz7DoBKqDyiRL7VZN8KvXQMWeTaVnttLRXOlotKw= +github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA= github.com/pkg/term v1.1.0 h1:xIAAdCMh3QIAy+5FrE8Ad8XoDhEU4ufwbaSozViP9kk= github.com/pkg/term v1.1.0/go.mod h1:E25nymQcrSllhX42Ok8MRm1+hyBdHY0dCeiKZ9jpNGw= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= @@ -164,8 +178,12 @@ github.com/refaktor/go-peg v0.0.0-20220116201714-31e3dfa8dc7d h1:FXrWUGgPRzhaZIB github.com/refaktor/go-peg v0.0.0-20220116201714-31e3dfa8dc7d/go.mod h1:iIkrsFobLIWX8kQ6Oqj4cl4nwdMSE92DWpWwk9YlG9s= github.com/refaktor/liner v1.2.10 h1:MjbQj9EfNuSFnNk9zan37xpkNIRpsWKenyIBg7FZdVw= github.com/refaktor/liner v1.2.10/go.mod h1:ziZSGVYZ4OzZ9kbeB254MtIrxxQlDibULRQGlDi1iK8= -github.com/rivo/uniseg v0.2.0 h1:S1pD9weZBuJdFmowNwbpi7BJ8TNftyUImj/0WQi72jY= github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= +github.com/rivo/uniseg v0.4.4 h1:8TfxU8dW6PdqD27gjM8MVNuicgxIjxpm4K7x4jp8sis= +github.com/rivo/uniseg v0.4.4/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88= +github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs= +github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjRBZyWFQ= +github.com/rogpeppe/go-internal v1.10.0/go.mod h1:UQnix2H7Ngw/k4C5ijL5+65zddjncjaFoBhdsK/akog= github.com/sashabaranov/go-openai v1.20.4 h1:095xQ/fAtRa0+Rj21sezVJABgKfGPNbyx/sAN/hJUmg= github.com/sashabaranov/go-openai v1.20.4/go.mod h1:lj5b/K+zjTSFxVLijLSTDZuP7adOgerWeFyZLUhAKRg= github.com/shirou/gopsutil/v3 v3.24.3 h1:eoUGJSmdfLzJ3mxIhmOAhgKEKgQkeOwKpz1NbhVnuPE= @@ -213,6 +231,7 @@ golang.org/x/crypto v0.21.0 h1:X31++rzVUdKhX5sWmSOFZxx8UW/ldWx55cbf08iNAMA= golang.org/x/crypto v0.21.0/go.mod h1:0BP7YvVV9gBbVKyeTG0Gyn+gZm94bibOW5BjDEYAOMs= golang.org/x/net v0.23.0 h1:7EYJ93RZ9vYSZAIb2x3lnuvqO5zneoD6IvWjuhfxjTs= golang.org/x/net v0.23.0/go.mod h1:JKghWKKOSdJwpW2GEx0Ja7fmaKnMsbu+MWVZTokSYmg= +golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.6.0 h1:5BMeUDZ7vkXGfEr1x9B4bRcTH4lpkTkpdh0T/J+qjbQ= golang.org/x/sync v0.6.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -221,11 +240,14 @@ golang.org/x/sys v0.0.0-20201204225414-ed752295db88/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20211117180635-dee7805ff2e1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.3.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.18.0 h1:DBdB3niSjOA/O0blCZBqDefyWNYveAYMNF1Wum0DYQ4= golang.org/x/sys v0.18.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/term v0.3.0/go.mod h1:q750SLmJuPmVoN1blW3UFBPREJfb1KmY3vwxfr+nFDA= golang.org/x/term v0.18.0 h1:FcHjZXDMxI8mM3nwhX9HlKop4C0YQvCVCdwYl2wOtE8= golang.org/x/term v0.18.0/go.mod h1:ILwASektA3OnRv7amZ1xhE/KTR+u50pbXfZ03+6Nx58= golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= @@ -245,3 +267,6 @@ gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +mvdan.cc/editorconfig v0.2.0/go.mod h1:lvnnD3BNdBYkhq+B4uBuFFKatfp02eB6HixDvEz91C0= +mvdan.cc/sh/v3 v3.6.0 h1:gtva4EXJ0dFNvl5bHjcUEvws+KRcDslT8VKheTYkbGU= +mvdan.cc/sh/v3 v3.6.0/go.mod h1:U4mhtBLZ32iWhif5/lD+ygy1zrgaQhUu+XFy7C8+TTA=