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

     1  package management
     2  
     3  import (
     4  	"fmt"
     5  	"strings"
     6  
     7  	"github.com/lmorg/murex/lang"
     8  	"github.com/lmorg/murex/lang/ref"
     9  	"github.com/lmorg/murex/lang/types"
    10  	"github.com/lmorg/murex/utils/json"
    11  )
    12  
    13  type feType struct {
    14  	fn   func(*lang.Process, string, []string) error
    15  	desc string
    16  }
    17  
    18  var fe map[string]feType
    19  
    20  func init() {
    21  	lang.DefineFunction("fexec", cmdFexec, types.Any)
    22  
    23  	fe = map[string]feType{
    24  		"function": {
    25  			desc: "Execute a murex public function",
    26  			fn:   feFunction,
    27  		},
    28  
    29  		"private": {
    30  			desc: "Execute a murex private function",
    31  			fn:   fePrivate,
    32  		},
    33  
    34  		/*"event": {
    35  			desc: "event",
    36  			fn: func(p *lang.Process, cmd string, params []string) error {
    37  				return fmt.Errorf("TODO: function not written yet")
    38  			},
    39  		},*/
    40  
    41  		"builtin": {
    42  			desc: "Execute a murex builtin",
    43  			fn:   feBuiltin,
    44  		},
    45  
    46  		"help": {
    47  			desc: "Display help message",
    48  			fn:   feHelp,
    49  		},
    50  	}
    51  
    52  }
    53  
    54  func cmdFexec(p *lang.Process) error {
    55  	flag, err := p.Parameters.String(0)
    56  	if err != nil {
    57  		return err
    58  	}
    59  
    60  	if fe[flag].fn == nil {
    61  		return fmt.Errorf("invalid flag '%s'. Use 'help' for more help", flag)
    62  	}
    63  
    64  	cmd, err := p.Parameters.String(1)
    65  	if err != nil && flag != "help" {
    66  		return err
    67  	}
    68  
    69  	var params []string
    70  	if p.Parameters.Len() > 2 {
    71  		params = p.Parameters.StringArray()[2:]
    72  	}
    73  
    74  	return fe[flag].fn(p, cmd, params)
    75  }
    76  
    77  func feBlock(p *lang.Process, block []rune, cmd string, params []string, fileRef *ref.File) (err error) {
    78  	fork := p.Fork(lang.F_FUNCTION)
    79  	fork.Name.Set(cmd)
    80  	fork.Parameters.DefineParsed(params)
    81  	fork.FileRef = fileRef
    82  	p.ExitNum, err = fork.Execute(block)
    83  	return
    84  }
    85  
    86  func feFunction(p *lang.Process, cmd string, params []string) error {
    87  	block, err := lang.MxFunctions.Block(cmd)
    88  	if err != nil {
    89  		return err
    90  	}
    91  
    92  	return feBlock(p, block, cmd, params, p.FileRef)
    93  }
    94  
    95  func fePrivate(p *lang.Process, cmd string, params []string) error {
    96  	mod := strings.Split(cmd, "/")
    97  	if len(mod) > 1 && mod[0] == "" {
    98  		mod = mod[1:]
    99  	}
   100  
   101  	switch len(mod) {
   102  	case 0, 1:
   103  		mod = []string{"", cmd}
   104  
   105  	case 2:
   106  		// do nothing
   107  
   108  	default:
   109  		mod = []string{strings.Join(mod[0:len(mod)-1], "/"), mod[2]}
   110  	}
   111  
   112  	pvt := lang.PrivateFunctions.GetString(mod[1], mod[0])
   113  	if pvt == nil {
   114  		return lang.ErrPrivateNotFound(mod[0])
   115  	}
   116  
   117  	return feBlock(p, pvt.Block, mod[1], params, pvt.FileRef)
   118  }
   119  
   120  func feBuiltin(p *lang.Process, cmd string, params []string) error {
   121  	if lang.GoFunctions[cmd] == nil {
   122  		return fmt.Errorf("no builtin exists with the name `%s`", cmd)
   123  	}
   124  
   125  	fork := p.Fork(lang.F_DEFAULTS)
   126  	fork.Name.Set(cmd)
   127  	fork.Parameters.DefineParsed(params)
   128  	fork.FileRef = p.FileRef
   129  	return lang.GoFunctions[cmd](fork.Process)
   130  }
   131  
   132  func feHelp(p *lang.Process, _ string, _ []string) error {
   133  	p.Stdout.SetDataType(types.Json)
   134  
   135  	v := make(map[string]string)
   136  
   137  	for name := range fe {
   138  		v[name] = fe[name].desc
   139  	}
   140  
   141  	b, err := json.Marshal(v, p.Stdout.IsTTY())
   142  	if err != nil {
   143  		return err
   144  	}
   145  
   146  	_, err = p.Stdout.Write(b)
   147  	return err
   148  }