github.com/lmorg/murex@v0.0.0-20240217211045-e081c89cd4ef/builtins/core/io/file.go (about) 1 package io 2 3 import ( 4 "fmt" 5 "io" 6 "os" 7 "time" 8 9 "github.com/lmorg/murex/lang" 10 "github.com/lmorg/murex/lang/types" 11 "github.com/lmorg/murex/utils/humannumbers" 12 ) 13 14 func init() { 15 lang.DefineMethod("pt", cmdPipeTelemetry, types.Any, types.Any) 16 lang.DefineMethod(">", cmdWriteFile, types.Any, types.Null) 17 lang.DefineMethod("fwrite", cmdWriteFile, types.Any, types.Null) 18 lang.DefineMethod(">>", cmdAppendFile, types.Any, types.Null) 19 lang.DefineMethod("fappend", cmdAppendFile, types.Any, types.Null) 20 } 21 22 func cmdPipeTelemetry(p *lang.Process) error { 23 dt := p.Stdin.GetDataType() 24 p.Stdout.SetDataType(dt) 25 quit := make(chan bool) 26 stats := func() { 27 written, _ := p.Stdin.Stats() 28 _, read := p.Stdout.Stats() 29 os.Stderr.WriteString( 30 fmt.Sprintf("Pipe telemetry: `%s` written %s -> pt -> `%s` read %s (Data type: %s)\n", 31 p.Previous.Name.String(), 32 humannumbers.Bytes(written), 33 p.Next.Name.String(), 34 humannumbers.Bytes(read), 35 dt), 36 ) 37 } 38 39 go func() { 40 for { 41 time.Sleep(1 * time.Second) 42 select { 43 case <-quit: 44 return 45 default: 46 stats() 47 } 48 49 } 50 }() 51 52 _, err := io.Copy(p.Stdout, p.Stdin) 53 quit <- true 54 stats() 55 return err 56 } 57 58 func cmdWriteFile(p *lang.Process) error { 59 p.Stdout.SetDataType(types.Null) 60 61 name, err := p.Parameters.String(0) 62 if err != nil { 63 return err 64 } 65 66 file, err := os.Create(name) 67 if err != nil { 68 return err 69 } 70 71 defer file.Close() 72 73 _, err = io.Copy(file, p.Stdin) 74 return err 75 } 76 77 func cmdAppendFile(p *lang.Process) error { 78 p.Stdout.SetDataType(types.Null) 79 80 name, err := p.Parameters.String(0) 81 if err != nil { 82 return err 83 } 84 85 file, err := os.OpenFile(name, os.O_APPEND|os.O_WRONLY|os.O_CREATE, 0664) 86 if err != nil { 87 return err 88 } 89 90 defer file.Close() 91 92 _, err = io.Copy(file, p.Stdin) 93 return err 94 }