From 3ebe85eba635eb3b0a5afcb147598a80a3a42c40 Mon Sep 17 00:00:00 2001 From: refaktor Date: Wed, 4 Sep 2024 14:52:37 +0200 Subject: [PATCH] improvements to os and pipes, and to eyr implementation --- env/object.go | 9 + evaldo/builtins.go | 38 +- evaldo/builtins_eyr.go | 5 +- evaldo/builtins_os.go | 444 ++++++++++++++++ ...ltins_devops_not.go => builtins_os_not.go} | 0 .../{builtins_devops.go => builtins_pipes.go} | 492 ++---------------- evaldo/builtins_pipes_not.go | 10 + evaldo/evaldo.go | 4 +- evaldo/repl.go | 6 +- util/microliner.go | 8 +- 10 files changed, 537 insertions(+), 479 deletions(-) create mode 100644 evaldo/builtins_os.go rename evaldo/{builtins_devops_not.go => builtins_os_not.go} (100%) rename evaldo/{builtins_devops.go => builtins_pipes.go} (60%) create mode 100644 evaldo/builtins_pipes_not.go diff --git a/env/object.go b/env/object.go index 15239b3d..2a1e369d 100644 --- a/env/object.go +++ b/env/object.go @@ -274,6 +274,15 @@ func NewUri1(index *Idxs, path string) *Uri { return &nat } +func NewFileUri(index *Idxs, path string) *Uri { + scheme := "file" // + "-schema" // TODO -- this is just temporary .. so we test it further, make proper once at that level + idxSch := index.IndexWord(scheme) + kind := scheme + "-schema" + idxKind := index.IndexWord(kind) + nat := Uri{Word{idxSch}, path, Word{idxKind}} + return &nat +} + func NewUri(index *Idxs, scheme Word, path string) *Uri { scheme2 := strings.Split(path, "://") kindstr := strings.Split(path, "://")[0] + "-schema" // TODO -- this is just temporary .. so we test it further, make proper once at that level diff --git a/evaldo/builtins.go b/evaldo/builtins.go index 6f949cd7..d0493428 100644 --- a/evaldo/builtins.go +++ b/evaldo/builtins.go @@ -542,8 +542,10 @@ var builtins = map[string]*env.Builtin{ Pure: true, Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object { switch val := arg0.(type) { + case env.Integer: + return *env.NewFileUri(ps.Idx, strconv.Itoa(int(val.Value))) // TODO turn to switch case env.String: - return *env.NewUri1(ps.Idx, "file://"+val.Value) // TODO turn to switch + return *env.NewFileUri(ps.Idx, val.Value) // TODO turn to switch default: return MakeArgError(ps, 1, []env.Type{env.StringType}, "to-file") } @@ -2884,7 +2886,7 @@ var builtins = map[string]*env.Builtin{ }, }, - "ls": { + "lc": { Argsn: 0, Doc: "Lists words in current context", Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object { @@ -2893,7 +2895,7 @@ var builtins = map[string]*env.Builtin{ }, }, - "lsp": { + "lcp": { Argsn: 0, Doc: "Lists words in current context", Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object { @@ -2906,7 +2908,7 @@ var builtins = map[string]*env.Builtin{ }, }, - "ls\\": { + "lc\\": { Argsn: 1, Doc: "Lists words in current context with string filter", Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object { @@ -2922,7 +2924,7 @@ var builtins = map[string]*env.Builtin{ } }, }, - "lsp\\": { + "lcp\\": { Argsn: 1, Doc: "Lists words in current context with string filter", Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object { @@ -7855,7 +7857,8 @@ func RegisterBuiltins(ps *env.ProgramState) { RegisterBuiltins2(Builtins_ssh, ps, "ssh") RegisterBuiltins2(Builtins_console, ps, "console") RegisterBuiltinsInContext(Builtins_math, ps, "math") - RegisterBuiltinsInContext(Builtins_devops, ps, "os") + osctx := RegisterBuiltinsInContext(Builtins_os, ps, "os") + RegisterBuiltinsInSubContext(Builtins_pipes, ps, osctx, "pipes") // ## Archived modules // RegisterBuiltins2(Builtins_gtk, ps, "gtk") // RegisterBuiltins2(Builtins_nats, ps, "nats") @@ -7875,7 +7878,7 @@ func RegisterBuiltins2(builtins map[string]*env.Builtin, ps *env.ProgramState, n } } -func RegisterBuiltinsInContext(builtins map[string]*env.Builtin, ps *env.ProgramState, name string) { +func RegisterBuiltinsInContext(builtins map[string]*env.Builtin, ps *env.ProgramState, name string) *env.RyeCtx { BuiltinNames[name] = len(builtins) ctx := ps.Ctx @@ -7890,6 +7893,27 @@ func RegisterBuiltinsInContext(builtins map[string]*env.Builtin, ps *env.Program wordIdx := ps.Idx.IndexWord(name) ps.Ctx.Mod(wordIdx, *newctx) + + return newctx +} + +func RegisterBuiltinsInSubContext(builtins map[string]*env.Builtin, ps *env.ProgramState, parent *env.RyeCtx, name string) *env.RyeCtx { + BuiltinNames[name] = len(builtins) + + ctx := ps.Ctx + ps.Ctx = env.NewEnv(parent) // make new context with no parent + + for k, v := range builtins { + bu := env.NewBuiltin(v.Fn, v.Argsn, v.AcceptFailure, v.Pure, v.Doc+" ("+k+")") + registerBuiltin(ps, k, *bu) + } + newctx := ps.Ctx + ps.Ctx = ctx + + wordIdx := ps.Idx.IndexWord(name) + ps.Ctx.Mod(wordIdx, *newctx) + + return newctx } func registerBuiltin(ps *env.ProgramState, word string, builtin env.Builtin) { diff --git a/evaldo/builtins_eyr.go b/evaldo/builtins_eyr.go index 26548392..b92a23c1 100755 --- a/evaldo/builtins_eyr.go +++ b/evaldo/builtins_eyr.go @@ -301,8 +301,11 @@ func Eyr_EvalExpression(ps *env.ProgramState) *env.ProgramState { return ps } -func Eyr_EvalBlockInside(ps *env.ProgramState) *env.ProgramState { +func Eyr_EvalBlockInside(ps *env.ProgramState, inj env.Object, injnow bool) *env.ProgramState { // fmt.Println("** EVALB INSIDE") + if injnow { + ps.Stack.Push(ps, inj) + } for ps.Ser.Pos() < ps.Ser.Len() { // fmt.Println(ps.Ser.Pos()) ps = Eyr_EvalExpression(ps) diff --git a/evaldo/builtins_os.go b/evaldo/builtins_os.go new file mode 100644 index 00000000..4494d1f7 --- /dev/null +++ b/evaldo/builtins_os.go @@ -0,0 +1,444 @@ +//go:build !no_devops +// +build !no_devops + +package evaldo + +import ( + "fmt" + "os" + "path/filepath" + "strings" + "time" + + "github.com/refaktor/rye/env" + + "github.com/shirou/gopsutil/v3/disk" + "github.com/shirou/gopsutil/v3/host" + "github.com/shirou/gopsutil/v3/load" + "github.com/shirou/gopsutil/v3/mem" + "github.com/shirou/gopsutil/v3/process" +) + +// In request we return a raw-map, because it's very inside loop call, this is sparse call, and we get tons of fields, so it would be best +// to turn them to normal Rye map (which is now Env / later Context or something like it), and they query it from Rye. + +func FileExists(filePath string) int { + _, err := os.Stat(filePath) + if err != nil { + if os.IsNotExist(err) { + return 0 // fmt.Println("File does not exist") + } else { + return -1 // fmt.Println("Error checking file:", err) + } + } else { + return 1 + } +} + +var Builtins_os = map[string]*env.Builtin{ + + "cwd": { + Argsn: 0, + Doc: "Returns current working directory.", + Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object { + path, err := os.Getwd() + if err != nil { + return MakeBuiltinError(ps, err.Error(), "cwd") + } + return *env.NewUri1(ps.Idx, "file://"+path) + }, + }, + + "cd": { + Argsn: 1, + Doc: "Changes current directory.", + 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: + + err := os.Chdir(path.GetPath()) + if err != nil { + return MakeBuiltinError(ps, err.Error(), "cd") + } + return arg0 + default: + return MakeArgError(ps, 1, []env.Type{env.UriType}, "cd") + } + }, + }, + + /* "cd_": { + Argsn: 1, + Doc: "Changes current directory.", + 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: + new := filepath.Join(filepath.Dir(ps.WorkingPath), path.GetPath()) + res := FileExists(new) + if res == 1 { + ps.WorkingPath = filepath.Join(filepath.Dir(ps.WorkingPath), path.GetPath()) + return arg0 + } else if res == 0 { + return MakeBuiltinError(ps, "Path doesn't exist", "cd") + } else { + return MakeBuiltinError(ps, "Error determining if path exists", "cd") + } + // TODO -- check if it exists + default: + return MakeArgError(ps, 1, []env.Type{env.UriType}, "cd") + } + }, + }, */ + + "mkdir": { + Argsn: 1, + Doc: "Creates a directory.", + 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: + 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") + } else { + return arg0 + } + default: + return MakeArgError(ps, 1, []env.Type{env.UriType}, "mkdir") + } + }, + }, + + "mv": { + Argsn: 2, + Doc: "Creates a directory.", + 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: + switch path2 := arg1.(type) { + case env.Uri: + old := filepath.Join(filepath.Dir(ps.WorkingPath), path.GetPath()) + new := filepath.Join(filepath.Dir(ps.WorkingPath), path2.GetPath()) + err := os.Rename(old, new) + if err != nil { + fmt.Println("Error renaming file:", err) + return MakeBuiltinError(ps, "Error renaming file: "+err.Error(), "mv") + } else { + return arg1 + } + default: + return MakeArgError(ps, 1, []env.Type{env.UriType}, "mv") + } + default: + return MakeArgError(ps, 1, []env.Type{env.UriType}, "mv") + } + }, + }, + + /* "cwd_": { + Argsn: 0, + Doc: "Returns current working directory.", + Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object { + return *env.NewUri1(ps.Idx, "file://"+ps.WorkingPath) + }, + }, */ + + "ls": { + Argsn: 0, + Doc: "Returns current working directory.", + Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object { + + files, err := os.ReadDir(".") + if err != nil { + return MakeBuiltinError(ps, "Error reading directory:"+err.Error(), "ls") + } + + items := make([]env.Object, len(files)) + + for i, file := range files { + // fmt.Println(file.Name()) // Print only file/directory names + + items[i] = *env.NewUri1(ps.Idx, "file://"+file.Name()) + } + return *env.NewBlock(*env.NewTSeries(items)) + + }, + }, + + "host-info?": { + Argsn: 0, + Doc: "Get information about the host system.", + Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object { + v, err := host.Info() + if err != nil { + return MakeBuiltinError(ps, err.Error(), "host-info?") + } + r := env.NewDict(make(map[string]any, 10)) + r.Data["hostname"] = *env.NewString(v.Hostname) + r.Data["uptime"] = *env.NewInteger(int64(v.Uptime)) + r.Data["boot-time"] = *env.NewInteger(int64(v.BootTime)) + r.Data["procs"] = *env.NewInteger(int64(v.Procs)) + r.Data["os"] = *env.NewString(v.OS) + r.Data["platform"] = *env.NewString(v.Platform) + r.Data["platform-family"] = *env.NewString(v.PlatformFamily) + r.Data["platform-version"] = *env.NewString(v.PlatformVersion) + r.Data["kernel-version"] = *env.NewString(v.KernelVersion) + r.Data["virtualization-system"] = *env.NewString(v.VirtualizationSystem) + return *r + }, + }, + "users?": { + Argsn: 0, + Doc: "Get information about users as a spreadsheet.", + Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object { + users, err := host.Users() + if err != nil { + return MakeBuiltinError(ps, err.Error(), "users?") + } + fmt.Println(users) + s := env.NewSpreadsheet([]string{"User", "Terminal", "Host", "Started"}) + for _, user := range users { + vals := []any{ + *env.NewString(user.User), + *env.NewString(user.Terminal), + *env.NewString(user.Host), + *env.NewInteger(int64(user.Started)), + } + s.AddRow(*env.NewSpreadsheetRow(vals, s)) + } + return *s + }, + }, + "load-avg?": { + Argsn: 0, + Doc: "Get the load average as a dict representing load average over the last 1, 5, and 15 minutes.", + Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object { + v, err := load.Avg() + if err != nil { + return MakeBuiltinError(ps, err.Error(), "load-avg?") + } + r := env.NewDict(make(map[string]any, 3)) + r.Data["1"] = *env.NewDecimal(v.Load1) + r.Data["5"] = *env.NewDecimal(v.Load5) + r.Data["15"] = *env.NewDecimal(v.Load15) + return *r + }, + }, + "virtual-memory?": { + Argsn: 0, + Doc: "Get information about virtual memory usage.", + Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object { + v, err := mem.VirtualMemory() + if err != nil { + return MakeBuiltinError(ps, err.Error(), "virtual-memory?") + } + r := env.NewDict(make(map[string]any, 3)) + r.Data["total"] = *env.NewInteger(int64(v.Total)) + r.Data["free"] = *env.NewInteger(int64(v.Free)) + r.Data["used-percent"] = *env.NewDecimal(v.UsedPercent) + return *r + }, + }, + "disk-usage?": { + Argsn: 0, + Doc: "Get disk usage information as a spreadsheet.", + Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object { + partitions, err := disk.Partitions(true) + if err != nil { + return MakeBuiltinError(ps, err.Error(), "disk-usage?") + } + s := env.NewSpreadsheet([]string{"Filesystem", "Size", "Used", "Available", "Capacity", "iused", "ifree", "%iused", "Mounted on"}) + for _, partition := range partitions { + usage, err := disk.Usage(partition.Mountpoint) + if err != nil { + return MakeBuiltinError(ps, err.Error(), "disk-usage?") + } + vals := []any{ + *env.NewString(partition.Device), + *env.NewInteger(int64(usage.Total)), + *env.NewInteger(int64(usage.Used)), + *env.NewInteger(int64(usage.Free)), + *env.NewDecimal(usage.UsedPercent), + *env.NewInteger(int64(usage.InodesUsed)), + *env.NewInteger(int64(usage.InodesFree)), + *env.NewInteger(int64(usage.InodesUsedPercent)), + *env.NewString(usage.Path), + } + s.AddRow(*env.NewSpreadsheetRow(vals, s)) + } + return *s + }, + }, + "pids?": { + Argsn: 0, + Doc: "Get process pids as a block.", + Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object { + pids, err := process.Pids() + if err != nil { + return MakeBuiltinError(ps, err.Error(), "pids?") + } + + pids2 := make([]env.Object, len(pids)) + for i, p := range pids { + pids2[i] = env.NewInteger(int64(p)) + } + return *env.NewBlock(*env.NewTSeries(pids2)) + }, + }, + "processes?": { + Argsn: 0, + Doc: "Get information about all processes as a spreadsheet.", + Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object { + processes, err := process.Processes() + if err != nil { + return MakeBuiltinError(ps, err.Error(), "processes?") + } + s := proccesSpreadsheetBase() + for _, process := range processes { + processSpreadsheetAdd(s, process) + } + return *s + }, + }, + "process": { + Argsn: 1, + Doc: "Get information about process with a given PID.", + Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object { + switch pid := arg0.(type) { + case env.Integer: + process, err := process.NewProcess(int32(pid.Value)) + if err != nil { + return MakeBuiltinError(ps, err.Error(), "process") + } + s := proccesSpreadsheetBase() + processSpreadsheetAdd(s, process) + return s.Rows[0].ToDict() + default: + return *MakeArgError(ps, 1, []env.Type{env.IntegerType}, "process") + } + }, + }, +} + +func proccesSpreadsheetBase() *env.Spreadsheet { + return env.NewSpreadsheet([]string{ + "User", + "PID", + "Status", + "%CPU", + "%MEM", + "VZS", + "RSS", + "Num Threads", + "Num FDs", + "Num Open Files", + "Num Connections", + "Started at", + "CPU Time", + "Command", + }) +} + +func processSpreadsheetAdd(s *env.Spreadsheet, process *process.Process) { + var status env.String + stat, err := process.Status() + if err == nil { + status = *env.NewString(strings.Join(stat, " ")) + } else { + status = *env.NewString("???") + } + + var vzs env.Object + var rss env.Object + memInfo, err := process.MemoryInfo() + if err == nil { + vzs = *env.NewInteger(int64(memInfo.VMS)) + rss = *env.NewInteger(int64(memInfo.RSS)) + } else { + vzs = *env.NewString("???") + rss = *env.NewString("???") + } + + var numOpenFiles env.Object + openFiles, err := process.OpenFiles() + if err == nil { + numOpenFiles = *env.NewInteger(int64(len(openFiles))) + } else { + numOpenFiles = *env.NewString("???") + } + + var numConnections env.Object + connections, err := process.Connections() + if err == nil { + numConnections = *env.NewInteger(int64(len(connections))) + } else { + numConnections = *env.NewString("???") + } + + var startedAt env.Object + createTime, err := process.CreateTime() + if err == nil { + startedAt = *env.NewDate(time.UnixMilli(createTime)) + } else { + startedAt = *env.NewString("???") + } + + var cpuTime env.Object + times, err := process.Times() + if err == nil { + dur := time.Duration(times.User+times.System) * time.Second + cpuTime = *env.NewString(fmt.Sprintf("%02d:%02d.%02d", int(dur.Minutes()), int(dur.Seconds())%60, int(dur.Milliseconds())%1000)) + } else { + cpuTime = *env.NewString("???") + } + + vals := []any{ + maybeString(process.Username), + process.Pid, + status, + maybeFloat64(process.CPUPercent), + maybeFloat32(process.MemoryPercent), + vzs, + rss, + maybeInt32(process.NumThreads), + maybeInt32(process.NumFDs), + numOpenFiles, + numConnections, + startedAt, + cpuTime, + maybeString(process.Cmdline), + } + s.AddRow(*env.NewSpreadsheetRow(vals, s)) +} + +func maybeString(f func() (string, error)) env.Object { + s, err := f() + if err != nil { + return *env.NewString("???") + } + return *env.NewString(s) +} + +func maybeFloat64(f func() (float64, error)) env.Object { + s, err := f() + if err != nil { + return *env.NewString("???") + } + return *env.NewDecimal(s) +} + +func maybeFloat32(f func() (float32, error)) env.Object { + s, err := f() + if err != nil { + return *env.NewString("???") + } + return *env.NewDecimal(float64(s)) +} + +func maybeInt32(f func() (int32, error)) env.Object { + s, err := f() + if err != nil { + return *env.NewString("???") + } + return *env.NewInteger(int64(s)) +} diff --git a/evaldo/builtins_devops_not.go b/evaldo/builtins_os_not.go similarity index 100% rename from evaldo/builtins_devops_not.go rename to evaldo/builtins_os_not.go diff --git a/evaldo/builtins_devops.go b/evaldo/builtins_pipes.go similarity index 60% rename from evaldo/builtins_devops.go rename to evaldo/builtins_pipes.go index 5f7c97ce..f25fc210 100644 --- a/evaldo/builtins_devops.go +++ b/evaldo/builtins_pipes.go @@ -1,175 +1,19 @@ -//go:build !no_devops -// +build !no_devops +//go:build !no_pipes +// +build !no_pipes package evaldo import ( - "fmt" - "os" - "path/filepath" "regexp" - "strings" - "time" "github.com/refaktor/rye/env" "github.com/bitfield/script" - "github.com/shirou/gopsutil/v3/disk" - "github.com/shirou/gopsutil/v3/host" - "github.com/shirou/gopsutil/v3/load" - "github.com/shirou/gopsutil/v3/mem" - "github.com/shirou/gopsutil/v3/process" ) -// In request we return a raw-map, because it's very inside loop call, this is sparse call, and we get tons of fields, so it would be best -// to turn them to normal Rye map (which is now Env / later Context or something like it), and they query it from Rye. +var Builtins_pipes = map[string]*env.Builtin{ -func FileExists(filePath string) int { - _, err := os.Stat(filePath) - if err != nil { - if os.IsNotExist(err) { - return 0 // fmt.Println("File does not exist") - } else { - return -1 // fmt.Println("Error checking file:", err) - } - } else { - return 1 - } -} - -var Builtins_devops = map[string]*env.Builtin{ - - "cwd": { - Argsn: 0, - Doc: "Returns current working directory.", - Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object { - path, err := os.Getwd() - if err != nil { - return MakeBuiltinError(ps, err.Error(), "cwd") - } - return *env.NewUri1(ps.Idx, "file://"+path) - }, - }, - - "cd": { - Argsn: 1, - Doc: "Changes current directory.", - 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: - - err := os.Chdir(path.GetPath()) - if err != nil { - return MakeBuiltinError(ps, err.Error(), "cd") - } - return arg0 - default: - return MakeArgError(ps, 1, []env.Type{env.UriType}, "cd") - } - }, - }, - - "cd_": { - Argsn: 1, - Doc: "Changes current directory.", - 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: - new := filepath.Join(filepath.Dir(ps.WorkingPath), path.GetPath()) - res := FileExists(new) - if res == 1 { - ps.WorkingPath = filepath.Join(filepath.Dir(ps.WorkingPath), path.GetPath()) - return arg0 - } else if res == 0 { - return MakeBuiltinError(ps, "Path doesn't exist", "cd") - } else { - return MakeBuiltinError(ps, "Error determining if path exists", "cd") - } - // TODO -- check if it exists - default: - return MakeArgError(ps, 1, []env.Type{env.UriType}, "cd") - } - }, - }, - - "mkdir": { - Argsn: 1, - Doc: "Creates a directory.", - 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: - 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") - } else { - return arg0 - } - default: - return MakeArgError(ps, 1, []env.Type{env.UriType}, "mkdir") - } - }, - }, - - "mv": { - Argsn: 2, - Doc: "Creates a directory.", - 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: - switch path2 := arg1.(type) { - case env.Uri: - old := filepath.Join(filepath.Dir(ps.WorkingPath), path.GetPath()) - new := filepath.Join(filepath.Dir(ps.WorkingPath), path2.GetPath()) - err := os.Rename(old, new) - if err != nil { - fmt.Println("Error renaming file:", err) - return MakeBuiltinError(ps, "Error renaming file: "+err.Error(), "mv") - } else { - return arg1 - } - default: - return MakeArgError(ps, 1, []env.Type{env.UriType}, "mv") - } - default: - return MakeArgError(ps, 1, []env.Type{env.UriType}, "mv") - } - }, - }, - - "cwd_": { - Argsn: 0, - Doc: "Returns current working directory.", - Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object { - return *env.NewUri1(ps.Idx, "file://"+ps.WorkingPath) - }, - }, - - "lsd": { - Argsn: 0, - Doc: "Returns current working directory.", - Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object { - - files, err := os.ReadDir(".") - if err != nil { - return MakeBuiltinError(ps, "Error reading directory:"+err.Error(), "ls") - } - - items := make([]env.Object, len(files)) - - for i, file := range files { - // fmt.Println(file.Name()) // Print only file/directory names - - items[i] = *env.NewUri1(ps.Idx, "file://"+file.Name()) - } - return *env.NewBlock(*env.NewTSeries(items)) - - }, - }, - - // SCRIPT PIPES - - "(file)": { + "cat": { 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 { @@ -183,7 +27,7 @@ var Builtins_devops = map[string]*env.Builtin{ }, }, - "(find-files)": { + "find": { 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 { @@ -197,7 +41,7 @@ var Builtins_devops = map[string]*env.Builtin{ }, }, - "(list-files)": { + "list": { 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 { @@ -214,7 +58,7 @@ var Builtins_devops = map[string]*env.Builtin{ }, }, - "(block)": { + "from-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 { @@ -237,7 +81,7 @@ var Builtins_devops = map[string]*env.Builtin{ }, }, - "(echo)": { + "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 { @@ -251,7 +95,7 @@ var Builtins_devops = map[string]*env.Builtin{ }, }, - "(if-exists)": { + "cat\\opt": { 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 { @@ -265,7 +109,7 @@ var Builtins_devops = map[string]*env.Builtin{ }, }, - "(exec)": { + "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 { @@ -279,7 +123,7 @@ var Builtins_devops = map[string]*env.Builtin{ }, }, - "exec": { + "exec\\in": { 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 { @@ -303,7 +147,7 @@ var Builtins_devops = map[string]*env.Builtin{ }, }, - "exec-for-each": { + "exec\\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 { @@ -327,7 +171,7 @@ var Builtins_devops = map[string]*env.Builtin{ }, }, - "string": { + "into-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 { @@ -349,7 +193,7 @@ var Builtins_devops = map[string]*env.Builtin{ }, }, - "write-file": { + "into-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 { @@ -376,7 +220,7 @@ var Builtins_devops = map[string]*env.Builtin{ }, }, - "stdout": { + "out": { 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 { @@ -398,7 +242,7 @@ var Builtins_devops = map[string]*env.Builtin{ }, }, - "first-n": { + "head": { 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 { @@ -446,7 +290,7 @@ var Builtins_devops = map[string]*env.Builtin{ }, }, - "p-dirname": { + "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 { @@ -465,7 +309,7 @@ var Builtins_devops = map[string]*env.Builtin{ }, }, - "p-basename": { + "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 { @@ -484,7 +328,7 @@ var Builtins_devops = map[string]*env.Builtin{ }, }, - "p-count-lines": { + "wcl": { 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 { @@ -506,7 +350,7 @@ var Builtins_devops = map[string]*env.Builtin{ }, }, - "p-freq": { + "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 { @@ -525,7 +369,7 @@ var Builtins_devops = map[string]*env.Builtin{ }, }, - "p-column": { + "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 { @@ -549,7 +393,7 @@ var Builtins_devops = map[string]*env.Builtin{ }, }, - "p-jq": { + "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 { @@ -573,7 +417,7 @@ var Builtins_devops = map[string]*env.Builtin{ }, }, - "p-match": { + "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 { @@ -597,7 +441,7 @@ var Builtins_devops = map[string]*env.Builtin{ }, }, - "p-match-regexp": { + "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 { @@ -626,7 +470,7 @@ var Builtins_devops = map[string]*env.Builtin{ }, }, - "p-not-match": { + "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 { @@ -650,7 +494,7 @@ var Builtins_devops = map[string]*env.Builtin{ }, }, - "p-not-match-regexp": { + "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 { @@ -679,7 +523,7 @@ var Builtins_devops = map[string]*env.Builtin{ }, }, - "p-replace": { + "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 { @@ -708,7 +552,7 @@ var Builtins_devops = map[string]*env.Builtin{ }, }, - "p-replace-regexp": { + "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 { @@ -742,7 +586,7 @@ var Builtins_devops = map[string]*env.Builtin{ }, }, - "p-block": { + "into-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 { @@ -768,7 +612,7 @@ var Builtins_devops = map[string]*env.Builtin{ }, }, - "p-error": { + "error\\opt": { 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 { @@ -792,280 +636,4 @@ var Builtins_devops = map[string]*env.Builtin{ // GOPSUTIL - "host-info?": { - Argsn: 0, - Doc: "Get information about the host system.", - Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object { - v, err := host.Info() - if err != nil { - return MakeBuiltinError(ps, err.Error(), "host-info?") - } - r := env.NewDict(make(map[string]any, 10)) - r.Data["hostname"] = *env.NewString(v.Hostname) - r.Data["uptime"] = *env.NewInteger(int64(v.Uptime)) - r.Data["boot-time"] = *env.NewInteger(int64(v.BootTime)) - r.Data["procs"] = *env.NewInteger(int64(v.Procs)) - r.Data["os"] = *env.NewString(v.OS) - r.Data["platform"] = *env.NewString(v.Platform) - r.Data["platform-family"] = *env.NewString(v.PlatformFamily) - r.Data["platform-version"] = *env.NewString(v.PlatformVersion) - r.Data["kernel-version"] = *env.NewString(v.KernelVersion) - r.Data["virtualization-system"] = *env.NewString(v.VirtualizationSystem) - return *r - }, - }, - "users?": { - Argsn: 0, - Doc: "Get information about users as a spreadsheet.", - Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object { - users, err := host.Users() - if err != nil { - return MakeBuiltinError(ps, err.Error(), "users?") - } - fmt.Println(users) - s := env.NewSpreadsheet([]string{"User", "Terminal", "Host", "Started"}) - for _, user := range users { - vals := []any{ - *env.NewString(user.User), - *env.NewString(user.Terminal), - *env.NewString(user.Host), - *env.NewInteger(int64(user.Started)), - } - s.AddRow(*env.NewSpreadsheetRow(vals, s)) - } - return *s - }, - }, - "load-avg?": { - Argsn: 0, - Doc: "Get the load average as a dict representing load average over the last 1, 5, and 15 minutes.", - Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object { - v, err := load.Avg() - if err != nil { - return MakeBuiltinError(ps, err.Error(), "load-avg?") - } - r := env.NewDict(make(map[string]any, 3)) - r.Data["1"] = *env.NewDecimal(v.Load1) - r.Data["5"] = *env.NewDecimal(v.Load5) - r.Data["15"] = *env.NewDecimal(v.Load15) - return *r - }, - }, - "virtual-memory?": { - Argsn: 0, - Doc: "Get information about virtual memory usage.", - Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object { - v, err := mem.VirtualMemory() - if err != nil { - return MakeBuiltinError(ps, err.Error(), "virtual-memory?") - } - r := env.NewDict(make(map[string]any, 3)) - r.Data["total"] = *env.NewInteger(int64(v.Total)) - r.Data["free"] = *env.NewInteger(int64(v.Free)) - r.Data["used-percent"] = *env.NewDecimal(v.UsedPercent) - return *r - }, - }, - "disk-usage?": { - Argsn: 0, - Doc: "Get disk usage information as a spreadsheet.", - Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object { - partitions, err := disk.Partitions(true) - if err != nil { - return MakeBuiltinError(ps, err.Error(), "disk-usage?") - } - s := env.NewSpreadsheet([]string{"Filesystem", "Size", "Used", "Available", "Capacity", "iused", "ifree", "%iused", "Mounted on"}) - for _, partition := range partitions { - usage, err := disk.Usage(partition.Mountpoint) - if err != nil { - return MakeBuiltinError(ps, err.Error(), "disk-usage?") - } - vals := []any{ - *env.NewString(partition.Device), - *env.NewInteger(int64(usage.Total)), - *env.NewInteger(int64(usage.Used)), - *env.NewInteger(int64(usage.Free)), - *env.NewDecimal(usage.UsedPercent), - *env.NewInteger(int64(usage.InodesUsed)), - *env.NewInteger(int64(usage.InodesFree)), - *env.NewInteger(int64(usage.InodesUsedPercent)), - *env.NewString(usage.Path), - } - s.AddRow(*env.NewSpreadsheetRow(vals, s)) - } - return *s - }, - }, - "pids?": { - Argsn: 0, - Doc: "Get process pids as a block.", - Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object { - pids, err := process.Pids() - if err != nil { - return MakeBuiltinError(ps, err.Error(), "pids?") - } - - pids2 := make([]env.Object, len(pids)) - for i, p := range pids { - pids2[i] = env.NewInteger(int64(p)) - } - return *env.NewBlock(*env.NewTSeries(pids2)) - }, - }, - "processes?": { - Argsn: 0, - Doc: "Get information about all processes as a spreadsheet.", - Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object { - processes, err := process.Processes() - if err != nil { - return MakeBuiltinError(ps, err.Error(), "processes?") - } - s := proccesSpreadsheetBase() - for _, process := range processes { - processSpreadsheetAdd(s, process) - } - return *s - }, - }, - "process": { - Argsn: 1, - Doc: "Get information about process with a given PID.", - Fn: func(ps *env.ProgramState, arg0 env.Object, arg1 env.Object, arg2 env.Object, arg3 env.Object, arg4 env.Object) env.Object { - switch pid := arg0.(type) { - case env.Integer: - process, err := process.NewProcess(int32(pid.Value)) - if err != nil { - return MakeBuiltinError(ps, err.Error(), "process") - } - s := proccesSpreadsheetBase() - processSpreadsheetAdd(s, process) - return s.Rows[0].ToDict() - default: - return *MakeArgError(ps, 1, []env.Type{env.IntegerType}, "process") - } - }, - }, -} - -func proccesSpreadsheetBase() *env.Spreadsheet { - return env.NewSpreadsheet([]string{ - "User", - "PID", - "Status", - "%CPU", - "%MEM", - "VZS", - "RSS", - "Num Threads", - "Num FDs", - "Num Open Files", - "Num Connections", - "Started at", - "CPU Time", - "Command", - }) -} - -func processSpreadsheetAdd(s *env.Spreadsheet, process *process.Process) { - var status env.String - stat, err := process.Status() - if err == nil { - status = *env.NewString(strings.Join(stat, " ")) - } else { - status = *env.NewString("???") - } - - var vzs env.Object - var rss env.Object - memInfo, err := process.MemoryInfo() - if err == nil { - vzs = *env.NewInteger(int64(memInfo.VMS)) - rss = *env.NewInteger(int64(memInfo.RSS)) - } else { - vzs = *env.NewString("???") - rss = *env.NewString("???") - } - - var numOpenFiles env.Object - openFiles, err := process.OpenFiles() - if err == nil { - numOpenFiles = *env.NewInteger(int64(len(openFiles))) - } else { - numOpenFiles = *env.NewString("???") - } - - var numConnections env.Object - connections, err := process.Connections() - if err == nil { - numConnections = *env.NewInteger(int64(len(connections))) - } else { - numConnections = *env.NewString("???") - } - - var startedAt env.Object - createTime, err := process.CreateTime() - if err == nil { - startedAt = *env.NewDate(time.UnixMilli(createTime)) - } else { - startedAt = *env.NewString("???") - } - - var cpuTime env.Object - times, err := process.Times() - if err == nil { - dur := time.Duration(times.User+times.System) * time.Second - cpuTime = *env.NewString(fmt.Sprintf("%02d:%02d.%02d", int(dur.Minutes()), int(dur.Seconds())%60, int(dur.Milliseconds())%1000)) - } else { - cpuTime = *env.NewString("???") - } - - vals := []any{ - maybeString(process.Username), - process.Pid, - status, - maybeFloat64(process.CPUPercent), - maybeFloat32(process.MemoryPercent), - vzs, - rss, - maybeInt32(process.NumThreads), - maybeInt32(process.NumFDs), - numOpenFiles, - numConnections, - startedAt, - cpuTime, - maybeString(process.Cmdline), - } - s.AddRow(*env.NewSpreadsheetRow(vals, s)) -} - -func maybeString(f func() (string, error)) env.Object { - s, err := f() - if err != nil { - return *env.NewString("???") - } - return *env.NewString(s) -} - -func maybeFloat64(f func() (float64, error)) env.Object { - s, err := f() - if err != nil { - return *env.NewString("???") - } - return *env.NewDecimal(s) -} - -func maybeFloat32(f func() (float32, error)) env.Object { - s, err := f() - if err != nil { - return *env.NewString("???") - } - return *env.NewDecimal(float64(s)) -} - -func maybeInt32(f func() (int32, error)) env.Object { - s, err := f() - if err != nil { - return *env.NewString("???") - } - return *env.NewInteger(int64(s)) } diff --git a/evaldo/builtins_pipes_not.go b/evaldo/builtins_pipes_not.go new file mode 100644 index 00000000..451bc0e2 --- /dev/null +++ b/evaldo/builtins_pipes_not.go @@ -0,0 +1,10 @@ +//go:build no_devops +// +build no_devops + +package evaldo + +import ( + "github.com/refaktor/rye/env" +) + +var Builtins_devops = map[string]*env.Builtin{} diff --git a/evaldo/evaldo.go b/evaldo/evaldo.go index 1d71e63f..8f9e6673 100644 --- a/evaldo/evaldo.go +++ b/evaldo/evaldo.go @@ -49,7 +49,7 @@ func NewProgramState(ser env.TSeries, idx env.Idxs) *ProgramState { func EvalBlock(ps *env.ProgramState) *env.ProgramState { switch ps.Dialect { case env.EyrDialect: - return Eyr_EvalBlockInside(ps) // TODO ps.Stack is already in ps ... refactor + return Eyr_EvalBlockInside(ps, nil, false) // TODO ps.Stack is already in ps ... refactor default: return EvalBlockInj(ps, nil, false) } @@ -76,7 +76,7 @@ func EvalBlockInCtxInj(ps *env.ProgramState, ctx *env.RyeCtx, inj env.Object, in func EvalBlockInjMultiDialect(ps *env.ProgramState, inj env.Object, injnow bool) *env.ProgramState { // TODO temp name -- refactor switch ps.Dialect { case env.EyrDialect: - return Eyr_EvalBlockInside(ps) // TODO ps.Stack is already in ps ... refactor + return Eyr_EvalBlockInside(ps, inj, injnow) // TODO ps.Stack is already in ps ... refactor default: return EvalBlockInj(ps, inj, injnow) } diff --git a/evaldo/repl.go b/evaldo/repl.go index f500c13c..b6335904 100644 --- a/evaldo/repl.go +++ b/evaldo/repl.go @@ -171,8 +171,8 @@ func (r *Repl) recieveMessage(message string) { func (r *Repl) recieveLine(line string) string { res := r.evalLine(r.ps, line) - if r.showResults { - fmt.Print(res) + if r.showResults && len(res) > 0 { + fmt.Println(res) } return res } @@ -520,7 +520,7 @@ func DoRyeRepl_OLD(es *env.ProgramState, showResults bool) { // here because of // TEMP - make conditional // print the result if showResults { - fmt.Println("\033[38;5;37m" + es.Res.Inspect(*genv) + "\x1b[0m") + fmt.Println("\033[38;5;37m" + es.Res.Inspect(*genv) + "\x1b[0m..") } if es.Res != nil && shellEd.Mode != "" && !shellEd.Pause && es.Res == shellEd.Return { fmt.Println(" <- the correct value was returned") diff --git a/util/microliner.go b/util/microliner.go index dce127b5..5b0f4697 100644 --- a/util/microliner.go +++ b/util/microliner.go @@ -421,7 +421,7 @@ func (s *MLState) refreshSingleLine(prompt []rune, buf []rune, pos int) error { s.sendBack(string(prompt)) for i, tt := range texts { if i > 0 { - s.sendBack("\n\rx ") + s.sendBack("\nx ") } // tt2, inString := tt, false // RyeHighlight(tt, s.lastLineString, 6) tt2, inString := RyeHighlight(tt, s.lastLineString, cols) @@ -713,19 +713,19 @@ startOfHere: s.lastLineString = false // trace2("NL") if len(line) > 0 && unicode.IsSpace(line[len(line)-1]) { - s.sendBack(fmt.Sprintf("%s⏎\n\r%s", color_emph, reset)) + s.sendBack(fmt.Sprintf("%s⏎\n%s", color_emph, reset)) if s.inString { s.lastLineString = true } } else { - s.sendBack("\n\r") + s.sendBack("\n") } xx := s.enterLine(string(line)) pos = 0 if xx == "next line" { multiline = true } else { - s.sendBack("\n\r") + s.sendBack("") // WW? } line = make([]rune, 0) trace(line)