go-calc/calc/cli/functions.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
}
}