137 lines
2.4 KiB
Go
137 lines
2.4 KiB
Go
package cli
|
|
|
|
import (
|
|
"fmt"
|
|
"strings"
|
|
|
|
"gitea.zaclys.com/bvaudour/gob/number"
|
|
"gitea.zaclys.com/bvaudour/gob/option"
|
|
"gitea.zaclys.net/bvaudour/go-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)
|
|
}
|
|
}
|