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  }