text/dict-set-context.go

141 lines
3.2 KiB
Go

// Copyright (c) 2024 Celestino Amoroso (celestino.amoroso@gmail.com).
// All rights reserved.
// dict-set-context.go
package text
import (
"fmt"
"strings"
"git.portale-stac.it/go-pkg/utils"
sq "github.com/kballard/go-shellquote"
)
type DictSetFlag uint16
const (
KeepVar = DictSetFlag(1 << iota)
)
const (
pipeValueKey = "."
pipeNameKey = "_"
)
type DictSetContext struct {
BaseExpander
flags DictSetFlag
varStores []map[string]string
localStore map[string]string
}
func NewDictSetContext(flags DictSetFlag, varStores ...map[string]string) *DictSetContext {
return NewDictSetContextV(flags, varStores)
}
func NewDictSetContextV(flags DictSetFlag, varStores []map[string]string) *DictSetContext {
ctx := &DictSetContext{
flags: flags,
varStores: varStores,
localStore: make(map[string]string, 10),
}
(&ctx.BaseExpander).Init()
return ctx
}
func (self *DictSetContext) GetVar(name string) (value string, exists bool) {
if value, exists = self.localStore[name]; !exists {
value, exists = findInStores(name, self.varStores)
}
return
}
func (self *DictSetContext) SetVar(name string, value string) (repeatedValue string) {
self.localStore[name] = value
return value
}
func findInStores(key string, stores []map[string]string) (value string, found bool) {
for _, vars := range stores {
if vars != nil {
if value, found = vars[key]; found {
break
}
}
}
return
}
func (self *DictSetContext) Handle(spec string, scanFlags ScannerFlag) (value string, err error) {
var found bool
var rawValue string
if len(spec) > 0 {
//parts := utils.SplitByRune(spec, '|', -1)
parts := utils.ScopedSplitByRune(spec, '|', `'"{`, `'"}`, -1)
name := parts[0]
parts = parts[1:]
if len(name) > 0 {
if scanFlags&DirectValue != 0 {
rawValue = name
found = true
} else {
rawValue, found = findInStores(name, self.varStores)
}
}
self.SetVar(pipeNameKey, name) // NOTE Maybe this line can be deleted
origVarFound := found
for _, part := range parts {
var expandedPart string
self.varStores[0][pipeValueKey] = rawValue
self.SetVar(pipeValueKey, rawValue)
if expandedPart, err = Scan(self, part); err != nil {
break
}
self.SetVar(pipeNameKey, name)
if rawValue, err = self.evalContent(origVarFound, rawValue, expandedPart); err != nil {
break
}
origVarFound = true
}
if err == nil {
if len(rawValue) == 0 && (self.flags&KeepVar) != 0 {
value = Var(name)
} else {
value, err = Scan(self, rawValue)
//value = rawValue
}
}
}
if err == nil && len(value) == 0 && (scanFlags&ValueRequired) != 0 {
err = fmt.Errorf("the variable specification %q requires a value", spec)
}
return
}
func (self *DictSetContext) evalContent(varFound bool, rawValue string, alternateValue string) (value string, err error) {
var args []string
if args, err = sq.Split(alternateValue); err != nil {
return
}
if len(args) == 0 {
value = rawValue
} else {
op := args[0]
if strings.HasPrefix(op, "__") {
var f ExpanderFunc
if f, err = self.GetFunc(op); err == nil {
value, err = f(self, rawValue, args[1:])
}
} else if varFound {
value = rawValue
} else {
value = alternateValue
}
}
return
}