go-calc/calc/cli/cli.go

137 lines
2.4 KiB
Go
Raw Normal View History

2024-02-21 10:42:56 +00:00
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 {
2024-02-21 10:42:56 +00:00
needMacro bool
macro []string
cmd []calc.MacroElement
2024-02-21 10:42:56 +00:00
}
func (s *mstate) reset() {
s.needMacro = false
s.macro = s.macro[:0]
s.cmd = s.cmd[:0]
2024-02-21 10:42:56 +00:00
}
func (s mstate) strMacro() string {
if len(s.macro) == 0 {
return "[ ]"
2024-02-21 10:42:56 +00:00
}
return fmt.Sprintf("[ %s ]", strings.Join(s.macro, " "))
2024-02-21 10:42:56 +00:00
}
type astate struct {
needAlt bool
alt []calc.MacroElement
2024-02-21 10:42:56 +00:00
}
func (s *astate) reset() {
s.needAlt = false
s.alt = s.alt[:0]
2024-02-21 10:42:56 +00:00
}
type Cli struct {
c *calc.Calc
macros map[string]string
mstate
astate
2024-02-21 10:42:56 +00:00
}
func New() *Cli {
c := Cli{
c: calc.New(),
macros: make(map[string]string),
2024-02-21 10:42:56 +00:00
}
return &c
2024-02-21 10:42:56 +00:00
}
func (c *Cli) reset() {
c.mstate.reset()
c.astate.reset()
2024-02-21 10:42:56 +00:00
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)
}
2024-02-21 10:42:56 +00:00
if cb, ok := otherFunctions[arg]; ok {
if needExec {
return exec(cb())
}
2024-02-21 10:42:56 +00:00
me = calc.MacroCommand(otherToCalcFunc(cb))
} else if cb, ok := searchCalcFunction(arg); ok {
if needExec {
return exec(cb(c.c))
}
2024-02-21 10:42:56 +00:00
me = calc.MacroCommand(cb)
} else if cb, ok, now := searchCliFunction(arg); ok {
if needExec || now {
return exec(cb(c))
}
2024-02-21 10:42:56 +00:00
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)
2024-02-21 10:42:56 +00:00
}
}
return option.Ok(me)
}
func (c *Cli) Exec(arg string) {
result := c.parse(arg)
if err, ok := result.Err(); ok {
printError(err)
c.reset()
2024-02-21 10:42:56 +00:00
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)
2024-02-21 10:42:56 +00:00
}
}
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()
2024-02-21 10:42:56 +00:00
}
}
}
func (c *Cli) ExecAll(args string) {
for _, arg := range strings.Fields(args) {
c.Exec(arg)
}
}