package cli import ( "fmt" "strings" "gitea.zaclys.com/bvaudour/gob/number" "gitea.zaclys.com/bvaudour/gob/option" "gitea.zaclys.net/bvaudour/calc/calc" ) type mstate struct { needMacro bool macro []string cmd []calc.MacroElement } func (s *mstate) reset() { s.needMacro = false s.macro = s.macro[:0] s.cmd = s.cmd[:0] } func (s mstate) strMacro() string { if len(s.macro) == 0 { return "[ ]" } return fmt.Sprintf("[ %s ]", strings.Join(s.macro, " ")) } type astate struct { needAlt bool alt []calc.MacroElement } func (s *astate) reset() { s.needAlt = false s.alt = s.alt[:0] } type Cli struct { c *calc.Calc macros map[string]string mstate astate } func New() *Cli { c := Cli{ c: calc.New(), macros: make(map[string]string), } return &c } func (c *Cli) reset() { c.mstate.reset() c.astate.reset() c.c.Reset() } func (c *Cli) parse(arg string) option.Result[calc.MacroElement] { var me calc.MacroElement needExec := !c.needAlt && !c.needMacro var exec = func(err option.Option[error]) option.Result[calc.MacroElement] { var elt calc.MacroElement if e, ok := err.Get(); ok { return option.Err[calc.MacroElement](e) } return option.Ok(elt) } if cb, ok := otherFunctions[arg]; ok { if needExec { return exec(cb()) } me = calc.MacroCommand(otherToCalcFunc(cb)) } else if cb, ok := searchCalcFunction(arg); ok { if needExec { return exec(cb(c.c)) } me = calc.MacroCommand(cb) } else if cb, ok, now := searchCliFunction(arg); ok { if needExec || now { return exec(cb(c)) } me = calc.MacroCommand(cliToCalcFunc(c, cb)) } else { n, ok := number.Parse(arg).Get() if !ok { return exec(option.Some(fmt.Errorf("Commande inconnue: %s", arg))) } else if needExec { c.c.Push(n) } else { me = calc.MacroNumber(n) } } return option.Ok(me) } func (c *Cli) Exec(arg string) { result := c.parse(arg) if err, ok := result.Err(); ok { printError(err) c.reset() return } if element, ok := result.Ok(); ok && !element.IsNil() { if c.needMacro { c.macro = append(c.macro, arg) c.cmd = append(c.cmd, element) } else if c.needAlt { c.alt = append(c.alt, element) } } if c.needAlt && len(c.alt) == 2 { err := c.c.If(c.alt[0], c.alt[1]) c.astate.reset() if e, ok := err.Get(); ok { printError(e) c.reset() } } } func (c *Cli) ExecAll(args string) { for _, arg := range strings.Fields(args) { c.Exec(arg) } }