github.com/lmorg/murex@v0.0.0-20240217211045-e081c89cd4ef/builtins/core/structs/formap.go (about)

     1  package structs
     2  
     3  import (
     4  	"github.com/lmorg/murex/lang"
     5  	"github.com/lmorg/murex/lang/stdio"
     6  	"github.com/lmorg/murex/lang/types"
     7  	"github.com/lmorg/murex/utils"
     8  	"github.com/lmorg/murex/utils/json"
     9  )
    10  
    11  func init() {
    12  	lang.DefineMethod("formap", cmdForMap, types.ReadMap, types.Any)
    13  }
    14  
    15  func cmdForMap(p *lang.Process) (err error) {
    16  	flag, _ := p.Parameters.String(0)
    17  	switch flag {
    18  	case "--jmap":
    19  		return cmdForMapJmap(p)
    20  
    21  	default:
    22  		return cmdForMapDefault(p)
    23  	}
    24  }
    25  
    26  func cmdForMapDefault(p *lang.Process) error {
    27  	//dt := p.Stdin.GetDataType()
    28  	p.Stdout.SetDataType(types.Generic)
    29  
    30  	block, err := p.Parameters.Block(2)
    31  	if err != nil {
    32  		return err
    33  	}
    34  
    35  	varKey, err := p.Parameters.String(0)
    36  	if err != nil {
    37  		return err
    38  	}
    39  
    40  	varVal, err := p.Parameters.String(1)
    41  	if err != nil {
    42  		return err
    43  	}
    44  
    45  	var (
    46  		varErr    error
    47  		iteration int
    48  	)
    49  	err = p.Stdin.ReadMap(p.Config, func(readmap *stdio.Map) {
    50  		if p.HasCancelled() {
    51  			return
    52  		}
    53  
    54  		if varKey != "!" {
    55  			varErr = p.Variables.Set(p, varKey, readmap.Key, types.String)
    56  			if varErr != nil {
    57  				p.Done()
    58  				return
    59  			}
    60  		}
    61  
    62  		if varVal != "!" {
    63  			varErr = p.Variables.Set(p, varVal, readmap.Value, readmap.DataType)
    64  			if varErr != nil {
    65  				p.Done()
    66  				return
    67  			}
    68  		}
    69  		iteration++
    70  		if !setMetaValues(p, iteration) {
    71  			return
    72  		}
    73  
    74  		fork := p.Fork(lang.F_PARENT_VARTABLE | lang.F_NO_STDIN)
    75  		fork.Execute(block)
    76  	})
    77  
    78  	if varErr != nil {
    79  		return varErr
    80  	}
    81  	return err
    82  }
    83  
    84  // Example usage:
    85  // <stdin> -> formap --jmap k v { $k } { out: $v[summary] } -> <stdout>
    86  func cmdForMapJmap(p *lang.Process) error {
    87  	//dt := p.Stdin.GetDataType()
    88  	p.Stdout.SetDataType(types.Json)
    89  
    90  	blockKey, err := p.Parameters.Block(3)
    91  	if err != nil {
    92  		return err
    93  	}
    94  
    95  	blockVal, err := p.Parameters.Block(4)
    96  	if err != nil {
    97  		return err
    98  	}
    99  
   100  	varKey, err := p.Parameters.String(1)
   101  	if err != nil {
   102  		return err
   103  	}
   104  
   105  	varVal, err := p.Parameters.String(2)
   106  	if err != nil {
   107  		return err
   108  	}
   109  
   110  	var (
   111  		m         = make(map[string]string)
   112  		varErr    error
   113  		iteration int
   114  	)
   115  	err = p.Stdin.ReadMap(p.Config, func(readmap *stdio.Map) {
   116  		if p.HasCancelled() {
   117  			return
   118  		}
   119  
   120  		if varKey != "!" {
   121  			varErr = p.Variables.Set(p, varKey, readmap.Key, types.String)
   122  			if varErr != nil {
   123  				p.Done()
   124  				return
   125  			}
   126  		}
   127  
   128  		if varVal != "!" {
   129  			varErr = p.Variables.Set(p, varVal, readmap.Value, readmap.DataType)
   130  			if varErr != nil {
   131  				p.Done()
   132  				return
   133  			}
   134  		}
   135  		iteration++
   136  		if !setMetaValues(p, iteration) {
   137  			return
   138  		}
   139  
   140  		forkKey := p.Fork(lang.F_PARENT_VARTABLE | lang.F_NO_STDIN | lang.F_CREATE_STDOUT)
   141  		forkKey.Execute(blockKey)
   142  		bKey, err := forkKey.Stdout.ReadAll()
   143  		if err != nil {
   144  			p.Stderr.Writeln([]byte(err.Error()))
   145  			p.Kill()
   146  		}
   147  
   148  		forkVal := p.Fork(lang.F_PARENT_VARTABLE | lang.F_NO_STDIN | lang.F_CREATE_STDOUT)
   149  		forkVal.Execute(blockVal)
   150  		bVal, err := forkVal.Stdout.ReadAll()
   151  		if err != nil {
   152  			p.Stderr.Writeln([]byte(err.Error()))
   153  			p.Kill()
   154  		}
   155  
   156  		m[string(utils.CrLfTrim(bKey))] = string(utils.CrLfTrim(bVal))
   157  	})
   158  
   159  	if err != nil {
   160  		return err
   161  	}
   162  
   163  	b, err := json.Marshal(m, p.Stdout.IsTTY())
   164  	if err != nil {
   165  		return err
   166  	}
   167  
   168  	_, err = p.Stdout.Write(b)
   169  	return err
   170  }