Màj des dépendances + refactorisation complète + correction du help

This commit is contained in:
Benjamin VAUDOUR 2024-02-25 14:42:47 +01:00
parent f0bc5f2273
commit 1c55c68d94
9 changed files with 200 additions and 224 deletions

View File

@ -99,6 +99,7 @@ func (c *Calc) StoreStack(k string) (err option.Option[error]) {
err = option.Some(ErrIsEmpty(errStack)) err = option.Some(ErrIsEmpty(errStack))
} else { } else {
c.registry.Set(k, c.Stack()...) c.registry.Set(k, c.Stack()...)
c.Reset()
} }
return return

View File

@ -1,9 +1,7 @@
package cli package cli
import ( import (
"errors"
"fmt" "fmt"
"regexp"
"strings" "strings"
"gitea.zaclys.com/bvaudour/gob/number" "gitea.zaclys.com/bvaudour/gob/number"
@ -11,13 +9,41 @@ import (
"gitea.zaclys.net/bvaudour/calc/calc" "gitea.zaclys.net/bvaudour/calc/calc"
) )
type Cli struct { type mstate struct {
c *calc.Calc
macros map[string]string
needMacro bool needMacro bool
macro []string macro []string
needAlt bool cmd []calc.MacroElement
alt []string }
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 { func New() *Cli {
@ -28,142 +54,48 @@ func New() *Cli {
return &c return &c
} }
func (c *Cli) beginMacro() (err option.Option[error]) { func (c *Cli) reset() {
if c.needMacro { c.mstate.reset()
return option.Some(errors.New("Les macros imbriquées ne sont pas supportées")) c.astate.reset()
}
c.needMacro = true
return
}
func (c *Cli) addMacro(arg string) (err option.Option[error]) {
if !c.needMacro {
return option.Some(errors.New("La macro na pas commencé…"))
}
c.macro = append(c.macro, arg)
return
}
func (c *Cli) endMacro(k string) (err option.Option[error]) {
macro, fields, needMacro := "[ ]", make([]string, len(c.macro)), c.needMacro
copy(fields, c.macro)
c.resetMacro()
if len(fields) > 0 {
macro = fmt.Sprintf("[ %s ]", strings.Join(fields, " "))
}
if !needMacro {
return option.Some(errors.New("La macro na pas commencé…"))
} else if c.needAlt {
return c.addAlt(fmt.Sprintf("%s%s", macro, k))
} else if len(fields) == 0 {
c.macros[k] = macro
c.c.StoreMacro(k, calc.MacroCommand(calc.NoAction))
return
}
cmds := make([]calc.MacroElement, len(fields))
for i, f := range fields {
result := c.parse(f)
if me, ok := result.Ok(); ok {
cmds[i] = me
} else if e, ok := result.Err(); ok {
return option.Some(e)
}
}
c.macros[k] = macro
c.c.StoreMacro(k, cmds...)
return
}
func (c *Cli) removeMacro(k string) (err option.Option[error]) {
if err = c.c.ResetMacro(k); !err.IsDefined() {
delete(c.macros, k)
}
return
}
func (c *Cli) removeMacros() (err option.Option[error]) {
if err = c.c.ResetMacros(); !err.IsDefined() {
c.macros = make(map[string]string)
}
return
}
func (c *Cli) beginAlt() (err option.Option[error]) {
if c.needAlt {
err = option.Some(errors.New("Les alternatives imbriquées ne sont pas supportées"))
} else {
c.needAlt = true
}
return
}
func (c *Cli) addAlt(arg string) (err option.Option[error]) {
if !c.needAlt {
return option.Some(errors.New("Lalternative nest pas commencée…"))
} else if len(c.alt) == 2 {
return option.Some(errors.New("Lalternative est pleine…"))
}
c.alt = append(c.alt, arg)
return
}
func (c *Cli) endAlt() (err option.Option[error]) {
if !c.needAlt || len(c.alt) != 2 {
return option.Some(errors.New("Lalternative nest pas pleine ou nest pas commencée…"))
}
r1, r2 := c.parse(c.alt[0]), c.parse(c.alt[1])
if me1, ok := r1.Ok(); ok {
if me2, ok := r2.Ok(); ok {
return c.c.If(me1, me2)
}
} else if e1, ok := r1.Err(); ok {
return option.Some(e1)
} else if e2, ok := r2.Err(); ok {
return option.Some(e2)
}
return
}
func (c *Cli) resetAlt() { c.needAlt, c.alt = false, c.alt[:0] }
func (c *Cli) resetMacro() { c.needMacro, c.macro = false, c.macro[:0] }
func (c *Cli) resetAll() {
c.resetAlt()
c.resetMacro()
c.c.Reset() c.c.Reset()
} }
func (c *Cli) parse(arg string) option.Result[calc.MacroElement] { func (c *Cli) parse(arg string) option.Result[calc.MacroElement] {
var me calc.MacroElement var me calc.MacroElement
needExec := !c.needAlt && !c.needMacro
if arg == "[" { var exec = func(err option.Option[error]) option.Result[calc.MacroElement] {
me = calc.MacroCommand(cliToCalcFunc(c, beginMacro)) var elt calc.MacroElement
} else if regexp.MustCompile(`^\]\w+$`).MatchString(arg) { if e, ok := err.Get(); ok {
me = calc.MacroCommand(cliToCalcFunc(c, storeMacro(arg[1:]))) return option.Err[calc.MacroElement](e)
} else if c.needMacro { }
me = calc.MacroCommand(cliToCalcFunc(c, addMacro(arg))) return option.Ok(elt)
} else if arg == "?" { }
me = calc.MacroCommand(cliToCalcFunc(c, conditional))
} else if c.needAlt { if cb, ok := otherFunctions[arg]; ok {
me = calc.MacroCommand(cliToCalcFunc(c, addConditional(arg))) if needExec {
} else if cb, exists := otherFunctions[arg]; exists { return exec(cb())
}
me = calc.MacroCommand(otherToCalcFunc(cb)) me = calc.MacroCommand(otherToCalcFunc(cb))
} else if cb, exists := searchCalcFunction(arg); exists { } else if cb, ok := searchCalcFunction(arg); ok {
if needExec {
return exec(cb(c.c))
}
me = calc.MacroCommand(cb) me = calc.MacroCommand(cb)
} else if cb, exists := searchCliFunction(arg); exists { } else if cb, ok, now := searchCliFunction(arg); ok {
if needExec || now {
return exec(cb(c))
}
me = calc.MacroCommand(cliToCalcFunc(c, cb)) me = calc.MacroCommand(cliToCalcFunc(c, cb))
} else { } else {
n, ok := number.Parse(arg).Get() n, ok := number.Parse(arg).Get()
if !ok { if !ok {
return option.Err[calc.MacroElement](fmt.Errorf("Commande inconnue: %s", arg)) return exec(option.Some(fmt.Errorf("Commande inconnue: %s", arg)))
} else if needExec {
c.c.Push(n)
} else {
me = calc.MacroNumber(n)
} }
me = calc.MacroNumber(n)
} }
return option.Ok(me) return option.Ok(me)
@ -174,26 +106,25 @@ func (c *Cli) Exec(arg string) {
if err, ok := result.Err(); ok { if err, ok := result.Err(); ok {
printError(err) printError(err)
c.resetAll() c.reset()
return return
} }
if element, ok := result.Ok(); ok { if element, ok := result.Ok(); ok && !element.IsNil() {
if n, ok := element.Left(); ok { if c.needMacro {
c.c.Push(n) c.macro = append(c.macro, arg)
} else if cb, ok := element.Right(); ok { c.cmd = append(c.cmd, element)
if err, ok := cb(c.c).Get(); ok { } else if c.needAlt {
printError(err) c.alt = append(c.alt, element)
c.resetAll()
return
}
} }
} }
if c.needAlt && len(c.alt) == 2 { if c.needAlt && len(c.alt) == 2 {
if err, ok := c.endAlt().Get(); ok { err := c.c.If(c.alt[0], c.alt[1])
printError(err) c.astate.reset()
c.resetAll() if e, ok := err.Get(); ok {
printError(e)
c.reset()
} }
} }
} }

11
calc/cli/errors.go Normal file
View File

@ -0,0 +1,11 @@
package cli
import (
"errors"
)
var (
errMacroOpen = errors.New("Les macros imbriquées ne sont pas supportées.")
errAltOpen = errors.New("Lalternative est déjà commencée.")
errMacroClosed = errors.New("La macro nest pas ouverte.")
)

View File

@ -17,6 +17,18 @@ type integer interface {
type CliFunc func(*Cli) option.Option[error] type CliFunc func(*Cli) option.Option[error]
type WordCliFunc func(string) CliFunc 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 { func stack2Str(numbers calc.Stack) string {
sl := make([]string, len(numbers)) sl := make([]string, len(numbers))
for i, n := range numbers { for i, n := range numbers {
@ -141,61 +153,6 @@ func printMacro(k string) CliFunc {
} }
} }
func resetMacro(k string) CliFunc {
return func(c *Cli) option.Option[error] {
return c.removeMacro(k)
}
}
func storeMacro(k string) CliFunc {
return func(c *Cli) option.Option[error] {
return c.endMacro(k)
}
}
func addMacro(v string) CliFunc {
return func(c *Cli) option.Option[error] {
return c.addMacro(v)
}
}
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) > 1 {
p = option.Some(uint64(args[0]))
}
return setPrecision(c, p, fix)
}
}
}
func beginMacro(c *Cli) option.Option[error] {
return c.beginMacro()
}
func conditional(c *Cli) option.Option[error] {
return c.beginAlt()
}
func addConditional(v string) CliFunc {
return func(c *Cli) option.Option[error] {
return c.addAlt(v)
}
}
func quit() (err option.Option[error]) { func quit() (err option.Option[error]) {
os.Exit(0) os.Exit(0)
return return
@ -216,14 +173,81 @@ func execMacro(k string) calc.CalcFunc {
} }
} }
func cliToCalcFunc(c *Cli, cb CliFunc) calc.CalcFunc { func setPrecision(c *calc.Calc, precision option.Option[uint64], fix bool) (err option.Option[error]) {
return func(_ *calc.Calc) option.Option[error] { c.SetPrecision(precision, option.Some(fix))
return cb(c) return
}
func fixPrecision(fix bool) calc.CalcFunc {
return func(c *calc.Calc) (err option.Option[error]) {
return setPrecision(c, option.None[uint64](), fix)
} }
} }
func otherToCalcFunc(cb func() option.Option[error]) calc.CalcFunc { func precision[N integer](fix bool) calc.IntCalcFunc[N] {
return func(_ *calc.Calc) option.Option[error] { return func(args ...N) calc.CalcFunc {
return cb() 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
} }
} }

View File

@ -37,6 +37,7 @@ var (
"inv": calc.Inv, "inv": calc.Inv,
"+": calc.Add, "+": calc.Add,
"-": calc.Sub, "-": calc.Sub,
"": calc.Sub,
"*": calc.Mul, "*": calc.Mul,
"×": calc.Mul, "×": calc.Mul,
"/": calc.Div, "/": calc.Div,
@ -92,9 +93,9 @@ var (
} }
intCalcFunctions = map[string]calc.IntCalcFunc[uint64]{ intCalcFunctions = map[string]calc.IntCalcFunc[uint64]{
`^c\d+$`: func(bases ...uint64) calc.CalcFunc { `^c\d+$`: func(base ...uint64) calc.CalcFunc {
if len(bases) > 0 { if len(base) > 0 {
return calc.ToBase(bases[0]) return calc.ToBase(base[0])
} }
return func(c *calc.Calc) (err option.Option[error]) { return } return func(c *calc.Calc) (err option.Option[error]) { return }
}, },
@ -108,14 +109,19 @@ var (
cliFunctions = map[string]CliFunc{ cliFunctions = map[string]CliFunc{
";P": printMacros, ";P": printMacros,
"[": beginMacro, "[": startMacro,
"?": conditional, "?": startAlt,
} }
wordCliFunctions = map[string]WordCliFunc{ wordCliFunctions = map[string]WordCliFunc{
`^;p\w+$`: printMacro, `^;p\w+$`: printMacro,
`^;c\w+$`: resetMacro, `^;c\w+$`: resetMacro,
`^\]\w+$`: storeMacro, `^\]\w+$`: endMacro,
}
needExec = map[string]bool{
"[": true,
`^\]\w+$`: true,
} }
) )
@ -146,7 +152,7 @@ func searchIntCalcFunction(arg string) (cb calc.CalcFunc, ok bool) {
return return
} }
func searchWordCliFunction(arg string) (cb CliFunc, ok bool) { func searchWordCliFunction(arg string) (cb CliFunc, ok, execNow bool) {
for k, f := range wordCliFunctions { for k, f := range wordCliFunctions {
if ok = regexp.MustCompile(k).MatchString(arg); ok { if ok = regexp.MustCompile(k).MatchString(arg); ok {
if arg[0] == ']' { if arg[0] == ']' {
@ -154,6 +160,7 @@ func searchWordCliFunction(arg string) (cb CliFunc, ok bool) {
} else { } else {
cb = f(arg[2:]) cb = f(arg[2:])
} }
execNow = needExec[k]
break break
} }
} }
@ -171,9 +178,11 @@ func searchCalcFunction(arg string) (cb calc.CalcFunc, ok bool) {
return return
} }
func searchCliFunction(arg string) (cb CliFunc, ok bool) { func searchCliFunction(arg string) (cb CliFunc, ok, execNow bool) {
if cb, ok = cliFunctions[arg]; !ok { if cb, ok = cliFunctions[arg]; !ok {
cb, ok = searchWordCliFunction(arg) cb, ok, execNow = searchWordCliFunction(arg)
} else {
execNow = needExec[arg]
} }
return return

View File

@ -17,7 +17,7 @@
{B}(<b>)[+|-]<n>{0} Nombre en base b {B}(<b>)[+|-]<n>{0} Nombre en base b
{T}Options dimpression{0} {T}Options dimpression{0}
{B}po{0} Imprime les options daffichage {B}op{0} Imprime les options daffichage
{B}of<n>{0} Affichage des nombres à virgules avec une précision fixe de n décimales {B}of<n>{0} Affichage des nombres à virgules avec une précision fixe de n décimales
{B}oa<n>{0} Affichage des nombres à virgules avec une précision auto (max n décimales) {B}oa<n>{0} Affichage des nombres à virgules avec une précision auto (max n décimales)
Les zéros non significatifs sont supprimés. Les zéros non significatifs sont supprimés.
@ -57,7 +57,7 @@
{B}--{0} Soustrait 1 {B}--{0} Soustrait 1
{B}inv{0} inverse le nombre {B}inv{0} inverse le nombre
{B}+{0} Addition {B}+{0} Addition
{B}-{0} Soustraction {B}-, {0} Soustraction
{B}*, ×{0} Multiplication {B}*, ×{0} Multiplication
{B}/, ÷{0} Division {B}/, ÷{0} Division
{B}//{0} Division entière {B}//{0} Division entière
@ -84,8 +84,8 @@
{B}c<n>{0} Conversion en base n {B}c<n>{0} Conversion en base n
{B}ci[<b>]{0} Conversion en entier. Si la base est définie, force la conversion de la base. {B}ci[<b>]{0} Conversion en entier. Si la base est définie, force la conversion de la base.
{B}cd[<b>]{0} Conversion en nombre décimal. Si la base est définie, force la conversion de la base. {B}cd[<b>]{0} Conversion en nombre décimal. Si la base est définie, force la conversion de la base.
{B}cf[<b>]{0} Conversion en nombre scientifique. Si la base est définie, force la conversion de la base. {B}cs[<b>]{0} Conversion en nombre scientifique. Si la base est définie, force la conversion de la base.
{B}cs[<b>]{0} Conversion en fraction. Si la base est définie, force la conversion de la base. {B}cf[<b>]{0} Conversion en fraction. Si la base est définie, force la conversion de la base.
{T}Arithmétique sur les bits{0} {T}Arithmétique sur les bits{0}
{B}>>{0} Déplace les bits vers la droite {B}>>{0} Déplace les bits vers la droite

View File

@ -114,7 +114,7 @@ var (
Sum = Reduce(number.Sum) Sum = Reduce(number.Sum)
Min = Reduce(number.Min) Min = Reduce(number.Min)
Max = Reduce(number.Max) Max = Reduce(number.Max)
Mean = Reduce(number.Min) Mean = Reduce(number.Mean)
Median = Reduce(number.Median) Median = Reduce(number.Median)
Mode = Reduce(number.Mode) Mode = Reduce(number.Mode)
Variance = Reduce(number.Variance) Variance = Reduce(number.Variance)

4
go.mod
View File

@ -3,6 +3,6 @@ module gitea.zaclys.net/bvaudour/calc
go 1.22.0 go 1.22.0
require ( require (
gitea.zaclys.com/bvaudour/gob v0.0.0-20240221091259-5b437644bd67 // indirect gitea.zaclys.com/bvaudour/gob v0.0.0-20240225133050-ec6a3ba492cc // indirect
gitea.zaclys.com/bvaudour/readline v0.0.0-20240221095017-721dfd1e4fe2 // indirect gitea.zaclys.com/bvaudour/readline v0.0.0-20240225134040-b1215d26587d // indirect
) )

8
go.sum
View File

@ -1,4 +1,4 @@
gitea.zaclys.com/bvaudour/gob v0.0.0-20240221091259-5b437644bd67 h1:Fe9g2grCWVsKCZktydlUNff4ihjRIWO2U7EBVHosdOw= gitea.zaclys.com/bvaudour/gob v0.0.0-20240225133050-ec6a3ba492cc h1:taHLOnrgyIlGYSs9cu+FXChAYtIeHoJg2D8to+UDgoA=
gitea.zaclys.com/bvaudour/gob v0.0.0-20240221091259-5b437644bd67/go.mod h1:Gw6x0KNKoXv6AMtRkaI+iWM2enVzwHikUSskuEzWQz4= gitea.zaclys.com/bvaudour/gob v0.0.0-20240225133050-ec6a3ba492cc/go.mod h1:Gw6x0KNKoXv6AMtRkaI+iWM2enVzwHikUSskuEzWQz4=
gitea.zaclys.com/bvaudour/readline v0.0.0-20240221095017-721dfd1e4fe2 h1:ImUUypyhZwtwYNRytCve7Os4ADayq8pgI9iVi7FkrZM= gitea.zaclys.com/bvaudour/readline v0.0.0-20240225134040-b1215d26587d h1:Xch3Agxkk/s8XHDv2QG2hb5O69nhuvlKQn7BedS+gSw=
gitea.zaclys.com/bvaudour/readline v0.0.0-20240221095017-721dfd1e4fe2/go.mod h1:KQcGQpPnklyZYVgjOj8KqiBUqEOoBj2L0Bp9VdIdmPI= gitea.zaclys.com/bvaudour/readline v0.0.0-20240225134040-b1215d26587d/go.mod h1:XUeoO+H5R/sX02vWsvILkqpYM4WRWQWHfsNl0GoDKBs=