re-organized command structure, added 'dup' command

This commit is contained in:
2023-11-12 11:28:12 +01:00
parent 0782b0920b
commit e78e4f84f4
2 changed files with 216 additions and 73 deletions

91
calc.go
View File

@@ -20,7 +20,6 @@ package main
import ( import (
"errors" "errors"
"fmt" "fmt"
"os"
"regexp" "regexp"
"strconv" "strconv"
"strings" "strings"
@@ -47,25 +46,13 @@ type Calc struct {
Funcalls Funcalls Funcalls Funcalls
BatchFuncalls Funcalls BatchFuncalls Funcalls
Commands Commands
Vars map[string]float64 Vars map[string]float64
} }
// help for lua functions will be added dynamically // help for lua functions will be added dynamically
const Help string = `Available commands: const Help string = `
batch toggle batch mode (nobatch turns it off)
debug toggle debug output (nodebug turns it off)
showstack toggle show last 5 items of the stack (noshowtack turns it off)
dump display the stack contents
clear clear the whole stack
shift remove the last element of the stack
reverse reverse the stack elements
swap exchange the last two elements
vars show list of variables
history display calculation history
help|? show this message
quit|exit|c-d|c-c exit program
Operators: Operators:
basic operators: + - x * / ^ (* is an alias of x) basic operators: + - x * / ^ (* is an alias of x)
@@ -94,7 +81,7 @@ Register variables:
// commands, constants and operators, defined here to feed completion // commands, constants and operators, defined here to feed completion
// and our mode switch in Eval() dynamically // and our mode switch in Eval() dynamically
const ( const (
Commands string = `dump reverse clear shift undo help history manual exit quit swap debug undebug nodebug batch nobatch showstack noshowstack vars` //Commands string = `dump reverse clear shift undo help history manual exit quit swap debug undebug nodebug batch nobatch showstack noshowstack vars`
Constants string = `Pi Phi Sqrt2 SqrtE SqrtPi SqrtPhi Ln2 Log2E Ln10 Log10E` Constants string = `Pi Phi Sqrt2 SqrtE SqrtPi SqrtPhi Ln2 Log2E Ln10 Log10E`
) )
@@ -107,7 +94,6 @@ func GetCompleteCustomFunctions() func(string) []string {
completions = append(completions, luafunc) completions = append(completions, luafunc)
} }
completions = append(completions, strings.Split(Commands, " ")...)
completions = append(completions, strings.Split(Constants, " ")...) completions = append(completions, strings.Split(Constants, " ")...)
return completions return completions
@@ -126,6 +112,10 @@ func (c *Calc) GetCompleteCustomFuncalls() func(string) []string {
completions = append(completions, function) completions = append(completions, function)
} }
for command := range c.Commands {
completions = append(completions, command)
}
return completions return completions
} }
@@ -151,6 +141,8 @@ func NewCalc() *Calc {
// pre-calculate mode switching arrays // pre-calculate mode switching arrays
c.Constants = strings.Split(Constants, " ") c.Constants = strings.Split(Constants, " ")
c.SetCommands()
return &c return &c
} }
@@ -275,10 +267,19 @@ func (c *Calc) Eval(line string) {
} }
// management commands // management commands
if _, ok := c.Commands[item]; ok {
c.Commands[item].Func(c)
continue
}
switch item { switch item {
case "?": case "?":
fallthrough fallthrough
case "help": case "help":
fmt.Println("Available commands:")
for name, command := range c.Commands {
fmt.Printf("%-20s %s\n", name, command.Help)
}
fmt.Println(Help) fmt.Println(Help)
if len(LuaFuncs) > 0 { if len(LuaFuncs) > 0 {
fmt.Println("Lua functions:") fmt.Println("Lua functions:")
@@ -286,62 +287,6 @@ func (c *Calc) Eval(line string) {
fmt.Printf("%-20s %s\n", name, function.help) fmt.Printf("%-20s %s\n", name, function.help)
} }
} }
case "dump":
c.stack.Dump()
case "debug":
c.ToggleDebug()
case "nodebug":
fallthrough
case "undebug":
c.debug = false
c.stack.debug = false
case "batch":
c.ToggleBatch()
case "nobatch":
c.batch = false
case "clear":
c.stack.Backup()
c.stack.Clear()
case "shift":
c.stack.Backup()
c.stack.Shift()
case "reverse":
c.stack.Backup()
c.stack.Reverse()
case "swap":
if c.stack.Len() < 2 {
fmt.Println("stack too small, can't swap")
} else {
c.stack.Backup()
c.stack.Swap()
}
case "undo":
c.stack.Restore()
case "history":
for _, entry := range c.history {
fmt.Println(entry)
}
case "showstack":
fallthrough
case "show":
c.ToggleShow()
case "noshowstack":
c.showstack = false
case "exit":
fallthrough
case "quit":
os.Exit(0)
case "manual":
man()
case "vars":
if len(c.Vars) > 0 {
fmt.Printf("%-20s %s\n", "VARIABLE", "VALUE")
for k, v := range c.Vars {
fmt.Printf("%-20s -> %.2f\n", k, v)
}
} else {
fmt.Println("no vars registered")
}
default: default:
fmt.Println("unknown command or operator!") fmt.Println("unknown command or operator!")

198
command.go Normal file
View File

@@ -0,0 +1,198 @@
/*
Copyright © 2023 Thomas von Dein
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package main
import (
"fmt"
"os"
)
type CommandFunction func(*Calc)
type Command struct {
Help string
Func CommandFunction
}
type Commands map[string]*Command
func NewCommand(help string, function CommandFunction) *Command {
return &Command{
Help: help,
Func: function,
}
}
// define all management (that is: non calculation) commands
func (c *Calc) SetCommands() {
f := Commands{
// Toggles
"debug": NewCommand(
"toggle debugging",
func(c *Calc) {
c.ToggleDebug()
},
),
"nodebug": NewCommand(
"disable debugging",
func(c *Calc) {
c.debug = false
c.stack.debug = false
},
),
"batch": NewCommand(
"toggle batch mode",
func(c *Calc) {
c.ToggleBatch()
},
),
"nobatch": NewCommand(
"disable batch mode",
func(c *Calc) {
c.batch = false
},
),
"showstack": NewCommand(
"toggle show last 5 items of the stack",
func(c *Calc) {
c.ToggleShow()
},
),
"noshowstack": NewCommand(
"disable display of the stack",
func(c *Calc) {
c.showstack = false
},
),
// Display commands
"dump": NewCommand(
"display the stack contents",
func(c *Calc) {
c.stack.Dump()
},
),
"history": NewCommand(
"display calculation history",
func(c *Calc) {
for _, entry := range c.history {
fmt.Println(entry)
}
},
),
"vars": NewCommand(
"show list of variables",
func(c *Calc) {
if len(c.Vars) > 0 {
fmt.Printf("%-20s %s\n", "VARIABLE", "VALUE")
for k, v := range c.Vars {
fmt.Printf("%-20s -> %.2f\n", k, v)
}
} else {
fmt.Println("no vars registered")
}
},
),
// stack manipulation commands
"clear": NewCommand(
"clear the whole stack",
func(c *Calc) {
c.stack.Backup()
c.stack.Clear()
},
),
"shift": NewCommand(
"remove the last element of the stack",
func(c *Calc) {
c.stack.Backup()
c.stack.Shift()
},
),
"reverse": NewCommand(
"reverse the stack elements",
func(c *Calc) {
c.stack.Backup()
c.stack.Reverse()
},
),
"swap": NewCommand(
"exchange the last two elements",
func(c *Calc) {
if c.stack.Len() < 2 {
fmt.Println("stack too small, can't swap")
} else {
c.stack.Backup()
c.stack.Swap()
}
},
),
"undo": NewCommand(
"undo last operation",
func(c *Calc) {
c.stack.Restore()
},
),
"dup": NewCommand(
"duplicate last stack item",
func(c *Calc) {
item := c.stack.Last()
if len(item) == 1 {
c.stack.Backup()
c.stack.Push(item[0])
} else {
fmt.Println("stack empty")
}
},
),
// general commands
"exit": NewCommand(
"exit program",
func(c *Calc) {
os.Exit(0)
},
),
"manual": NewCommand(
"show manual",
func(c *Calc) {
man()
},
),
}
// aliases
f["quit"] = f["exit"]
f["undebug"] = f["nodebug"]
f["show"] = f["showstack"]
c.Commands = f
}