text/expander-context.go

143 lines
3.2 KiB
Go
Raw Normal View History

2024-02-16 15:56:50 +01:00
// expander-context.go
package text
import (
"errors"
"fmt"
"strconv"
"strings"
"portale-stac.it/packages/golang"
)
const varIntro = '$'
type ExpanderFunc func(ctx ExpanderContext, varValue string, args []string) (result string, err error)
type ExpanderFuncBlock struct {
name string
expFunc ExpanderFunc
minArgs int
maxArgs int
description string
}
func (self *ExpanderFuncBlock) CheckNumArgs(n int) (ok bool) {
ok = (self.minArgs < 0 || n >= self.minArgs) && (self.maxArgs < 0 || n <= self.maxArgs)
return
}
func (self *ExpanderFuncBlock) synopsys(sb *strings.Builder) {
if self.minArgs < 0 && self.maxArgs < 0 {
sb.WriteString("[...]")
} else {
var i int
for i = 0; i < self.minArgs; i++ {
if i > 0 {
sb.WriteByte(' ')
}
sb.WriteString("arg")
sb.WriteString(strconv.Itoa(i + 1))
}
if self.maxArgs < 0 {
sb.WriteString("...")
} else if i < self.maxArgs {
for j := i; j < self.maxArgs; j++ {
if j > 0 {
sb.WriteByte(' ')
}
sb.WriteString("[arg")
sb.WriteString(strconv.Itoa(j + 1))
}
for j := i; j < self.maxArgs; j++ {
sb.WriteByte(']')
}
}
}
}
func (self *ExpanderFuncBlock) String() string {
var sb strings.Builder
sb.WriteString(self.name)
sb.WriteByte(' ')
self.synopsys(&sb)
if len(self.description) > 0 {
sb.WriteString(" -- ")
if len(self.description) > 80 {
sb.WriteString(self.description[0:80])
sb.WriteString("...")
} else {
sb.WriteString(self.description)
}
}
return sb.String()
}
type ExpanderContext interface {
VariableHandler
GetFunc(name string) (f ExpanderFunc, err error)
AddFunc(name string, f ExpanderFunc, minArgs, maxArgs int, description string)
GetVar(name string) (value string, exists bool)
SetVar(name string, value string) (repeatedValue string)
}
type BaseExpander struct {
functions map[string]*ExpanderFuncBlock
}
func (self *BaseExpander) GetVar(name string) (value string, exists bool) {
return
}
func (self *BaseExpander) SetVar(name string, value string) (repeatedValue string) {
return value
}
func NewExpander() *BaseExpander {
return &BaseExpander{
functions: make(map[string]*ExpanderFuncBlock),
}
}
func (self *BaseExpander) Init() {
if self.functions == nil {
self.functions = make(map[string]*ExpanderFuncBlock)
}
}
func (self *BaseExpander) GetFunc(name string) (f ExpanderFunc, err error) {
var ok bool
var info *ExpanderFuncBlock
if info, ok = self.functions[name]; !ok {
err = fmt.Errorf("unknown function %q", name)
} else {
f = info.expFunc
}
return
}
func (self *BaseExpander) AddFunc(name string, f ExpanderFunc, minArgs, maxArgs int, description string) {
self.functions[name] = &ExpanderFuncBlock{
name: name,
expFunc: f,
minArgs: minArgs,
maxArgs: maxArgs,
description: description,
}
}
func (self *BaseExpander) Handle(varSpec string, flags ScannerFlag) (value string, err error) {
err = errors.New("maybe you did somwthing wrong")
return
}
func (self *BaseExpander) IterateFunc(op func(funcInfo *ExpanderFuncBlock) (err error)) (err error) {
if op != nil {
err = golang.IterateSortedMap(self.functions, func(key string, info *ExpanderFuncBlock) error {
return op(info)
})
}
return
}