254 lines
4.9 KiB
Go
254 lines
4.9 KiB
Go
package cli
|
|
|
|
import (
|
|
"errors"
|
|
"fmt"
|
|
"os"
|
|
"strings"
|
|
|
|
"gitea.zaclys.com/bvaudour/gob/option"
|
|
"gitea.zaclys.net/bvaudour/go-calc/calc"
|
|
)
|
|
|
|
type integer interface {
|
|
~int | ~int8 | ~int16 | ~int32 | ~int64 | ~uint | ~uint8 | ~uint16 | ~uint32 | ~uint64
|
|
}
|
|
|
|
type CliFunc func(*Cli) option.Option[error]
|
|
type WordCliFunc func(string) CliFunc
|
|
|
|
func cliToCalcFunc(c *Cli, cb CliFunc) calc.CalcFunc {
|
|
return func(_ *calc.Calc) option.Option[error] {
|
|
return cb(c)
|
|
}
|
|
}
|
|
|
|
func otherToCalcFunc(cb func() option.Option[error]) calc.CalcFunc {
|
|
return func(_ *calc.Calc) option.Option[error] {
|
|
return cb()
|
|
}
|
|
}
|
|
|
|
func stack2Str(numbers calc.Stack) string {
|
|
sl := make([]string, len(numbers))
|
|
for i, n := range numbers {
|
|
sl[i] = n.String()
|
|
}
|
|
return strings.Join(sl, " ")
|
|
}
|
|
|
|
func printResult(arg any) (result option.Option[error]) {
|
|
if _, e := fmt.Printf("\033[1;33m%s\033[m\n", arg); e != nil {
|
|
result = option.Some(e)
|
|
}
|
|
|
|
return
|
|
}
|
|
|
|
func printError(err error) (result option.Option[error]) {
|
|
if _, e := fmt.Printf("\033[1;31m%s\033[m\n", err); e != nil {
|
|
result = option.Some(e)
|
|
}
|
|
|
|
return
|
|
}
|
|
|
|
func printLine(k string, arg any) (result option.Option[error]) {
|
|
if _, e := fmt.Printf("\033[1;32m%s\033[m → \033[1;33m%s\033[m\n", k, arg); e != nil {
|
|
result = option.Some(e)
|
|
}
|
|
|
|
return
|
|
}
|
|
|
|
func printHelp() (result option.Option[error]) {
|
|
if _, e := fmt.Print(help); e != nil {
|
|
result = option.Some(e)
|
|
}
|
|
|
|
return
|
|
}
|
|
|
|
func printOption(c *calc.Calc) option.Option[error] {
|
|
p, f := c.Precision()
|
|
t := "auto"
|
|
if f {
|
|
t = "fixe"
|
|
}
|
|
|
|
return printResult(fmt.Sprintf("%d (%s)", p, t))
|
|
}
|
|
|
|
func printLast(c *calc.Calc) (err option.Option[error]) {
|
|
result := c.Last()
|
|
if n, ok := result.Ok(); ok {
|
|
err = printResult(n)
|
|
} else if e, ok := result.Err(); ok {
|
|
err = option.Some(e)
|
|
}
|
|
|
|
return
|
|
}
|
|
|
|
func printStack(c *calc.Calc) (err option.Option[error]) {
|
|
result := c.GetStack()
|
|
if s, ok := result.Ok(); ok {
|
|
err = printResult(stack2Str(s))
|
|
} else if e, ok := result.Err(); ok {
|
|
err = option.Some(e)
|
|
}
|
|
|
|
return
|
|
}
|
|
|
|
func printRegistries(c *calc.Calc) (err option.Option[error]) {
|
|
result := c.GetRegistries()
|
|
if r, ok := result.Ok(); ok {
|
|
for k, s := range r {
|
|
printLine(k, stack2Str(s))
|
|
}
|
|
} else if e, ok := result.Err(); ok {
|
|
err = option.Some(e)
|
|
}
|
|
|
|
return
|
|
}
|
|
|
|
func printRegistry(k string) calc.CalcFunc {
|
|
return func(c *calc.Calc) (err option.Option[error]) {
|
|
result := c.Registry(k)
|
|
if s, ok := result.Ok(); ok {
|
|
err = printResult(stack2Str(s))
|
|
} else if e, ok := result.Err(); ok {
|
|
err = option.Some(e)
|
|
}
|
|
|
|
return
|
|
}
|
|
}
|
|
|
|
func printMacros(c *Cli) (err option.Option[error]) {
|
|
result := c.c.GetMacros()
|
|
if e, ok := result.Err(); ok {
|
|
err = option.Some(e)
|
|
} else {
|
|
for k, m := range c.macros {
|
|
printLine(k, m)
|
|
}
|
|
}
|
|
|
|
return
|
|
}
|
|
|
|
func printMacro(k string) CliFunc {
|
|
return func(c *Cli) (err option.Option[error]) {
|
|
result := c.c.Macro(k)
|
|
if e, ok := result.Err(); ok {
|
|
err = option.Some(e)
|
|
} else {
|
|
err = printResult(c.macros[k])
|
|
}
|
|
|
|
return
|
|
}
|
|
}
|
|
|
|
func quit() (err option.Option[error]) {
|
|
os.Exit(0)
|
|
return
|
|
}
|
|
|
|
func execMacro(k string) calc.CalcFunc {
|
|
return func(c *calc.Calc) (err option.Option[error]) {
|
|
errs := c.ExecMacro(k)
|
|
if len(errs) > 0 {
|
|
sErrors := make([]string, len(errs))
|
|
for i, e := range errs {
|
|
sErrors[i] = e.Error()
|
|
}
|
|
err = option.Some(errors.New(strings.Join(sErrors, "\n")))
|
|
}
|
|
|
|
return
|
|
}
|
|
}
|
|
|
|
func setPrecision(c *calc.Calc, precision option.Option[uint64], fix bool) (err option.Option[error]) {
|
|
c.SetPrecision(precision, option.Some(fix))
|
|
return
|
|
}
|
|
|
|
func fixPrecision(fix bool) calc.CalcFunc {
|
|
return func(c *calc.Calc) (err option.Option[error]) {
|
|
return setPrecision(c, option.None[uint64](), fix)
|
|
}
|
|
}
|
|
|
|
func precision[N integer](fix bool) calc.IntCalcFunc[N] {
|
|
return func(args ...N) calc.CalcFunc {
|
|
return func(c *calc.Calc) (err option.Option[error]) {
|
|
var p option.Option[uint64]
|
|
if len(args) > 0 {
|
|
p = option.Some(uint64(args[0]))
|
|
}
|
|
|
|
return setPrecision(c, p, fix)
|
|
}
|
|
}
|
|
}
|
|
|
|
func startMacro(c *Cli) (err option.Option[error]) {
|
|
if c.needMacro {
|
|
return option.Some(errMacroOpen)
|
|
}
|
|
c.needMacro = true
|
|
|
|
return
|
|
}
|
|
|
|
func startAlt(c *Cli) (err option.Option[error]) {
|
|
if c.needAlt {
|
|
return option.Some(errAltOpen)
|
|
}
|
|
c.needAlt = true
|
|
|
|
return
|
|
}
|
|
|
|
func resetMacro(k string) CliFunc {
|
|
return func(c *Cli) (err option.Option[error]) {
|
|
if err = c.c.ResetMacro(k); !err.IsDefined() {
|
|
delete(c.macros, k)
|
|
}
|
|
|
|
return
|
|
}
|
|
}
|
|
|
|
func storeMacro(k string, macro string, cmd []calc.MacroElement) CliFunc {
|
|
return func(c *Cli) (err option.Option[error]) {
|
|
c.c.StoreMacro(k, cmd...)
|
|
c.macros[k] = macro
|
|
|
|
return
|
|
}
|
|
}
|
|
|
|
func endMacro(k string) CliFunc {
|
|
return func(c *Cli) (err option.Option[error]) {
|
|
if !c.needMacro {
|
|
return option.Some(errMacroClosed)
|
|
}
|
|
|
|
cb := storeMacro(k, c.strMacro(), c.cmd)
|
|
c.mstate.reset()
|
|
|
|
if !c.needAlt {
|
|
return cb(c)
|
|
}
|
|
c.alt = append(c.alt, calc.MacroCommand(cliToCalcFunc(c, cb)))
|
|
|
|
return
|
|
}
|
|
}
|