287 lines
6.5 KiB
Go
287 lines
6.5 KiB
Go
// Copyright (c) 2024 Celestino Amoroso (celestino.amoroso@gmail.com).
|
|
// All rights reserved.
|
|
|
|
// text-util.go
|
|
package utils
|
|
|
|
import (
|
|
"bytes"
|
|
"errors"
|
|
"fmt"
|
|
"io"
|
|
"io/ioutil"
|
|
"os"
|
|
"os/user"
|
|
"sort"
|
|
"strings"
|
|
"time"
|
|
)
|
|
|
|
type TextTemplate struct {
|
|
varMap map[string]string
|
|
UserName string
|
|
Uid string
|
|
ProgramDir string
|
|
HomeDir string
|
|
env map[string]string
|
|
}
|
|
|
|
func NewTextTemplate(args ...string) (instance *TextTemplate) {
|
|
instance = &TextTemplate{}
|
|
user, err := user.Current()
|
|
if err == nil {
|
|
instance.UserName = user.Username
|
|
instance.HomeDir = user.HomeDir
|
|
instance.Uid = user.Uid
|
|
}
|
|
|
|
instance.ProgramDir, _ = GetProgramDirPath()
|
|
instance.varMap = make(map[string]string, 5+len(args))
|
|
instance.initVarMap()
|
|
|
|
for _, arg := range args {
|
|
if len(arg) == 0 {
|
|
break
|
|
}
|
|
parts := strings.SplitN(arg, ":", 2)
|
|
if len(parts) == 2 {
|
|
instance.varMap[parts[0]] = parts[1]
|
|
} else {
|
|
instance.varMap[parts[0]] = ""
|
|
}
|
|
}
|
|
|
|
instance.env = make(map[string]string)
|
|
for _, v := range os.Environ() {
|
|
parts := strings.SplitN(v, "=", 2)
|
|
instance.env[parts[0]] = parts[1]
|
|
}
|
|
return
|
|
}
|
|
|
|
func (self *TextTemplate) initVarMap() {
|
|
self.varMap["dt"] = "Current timestamp as YYYY-MM-DD_HH-MM-SS"
|
|
self.varMap["ymd"] = "Current date as YYYY-MM-DD"
|
|
self.varMap["hm"] = "Current time as HH-MM"
|
|
self.varMap["h"] = "Current time as HH"
|
|
self.varMap["hms"] = "Current time as HH-MM-SS"
|
|
self.varMap["month"] = "Month name"
|
|
self.varMap["month-num"] = "Month as number (mm)"
|
|
self.varMap["week-day"] = "Week day name"
|
|
self.varMap["week-day-num"] = "Week day as number"
|
|
self.varMap["yesterday"] = "Yesterday date"
|
|
self.varMap["uid"] = self.Uid
|
|
self.varMap["username"] = self.UserName
|
|
self.varMap["home"] = self.HomeDir
|
|
self.varMap["progdir"] = self.ProgramDir
|
|
self.varMap["hostname"], _ = os.Hostname()
|
|
}
|
|
|
|
func (self *TextTemplate) AddVar(name, value string) {
|
|
self.varMap[name] = value
|
|
}
|
|
|
|
// func MakeVarMap() map[string]string {
|
|
// return map[string]string{
|
|
// "ymd": "Current date as YYYY-MM-DD",
|
|
// "hms": "Current time as HH-MM-SS",
|
|
// // "host": "Hostname",
|
|
// "uid": "UID",
|
|
// "username": "Username",
|
|
// "home": "Home directory",
|
|
// }
|
|
// }
|
|
|
|
func (self *TextTemplate) updateVarMap() {
|
|
var now = time.Now()
|
|
|
|
self.varMap["ymd"] = fmt.Sprintf("%04d-%02d-%02d", now.Year(), now.Month(), now.Day())
|
|
self.varMap["hms"] = fmt.Sprintf("%02d-%02d-%02d", now.Hour(), now.Minute(), now.Second())
|
|
self.varMap["hm"] = fmt.Sprintf("%02d-%02d", now.Hour(), now.Minute())
|
|
self.varMap["h"] = fmt.Sprintf("%02d", now.Hour())
|
|
self.varMap["month"] = now.Format("January")
|
|
self.varMap["month-num"] = fmt.Sprintf("%02d", now.Month())
|
|
self.varMap["week-day-num"] = fmt.Sprintf("%d", 1+now.Weekday())
|
|
self.varMap["week-day"] = now.Format("Monday")
|
|
self.varMap["dt"] = self.varMap["ymd"] + "_" + self.varMap["hms"]
|
|
|
|
yday := now.AddDate(0, 0, -1)
|
|
self.varMap["yesterday"] = fmt.Sprintf("%04d-%02d-%02d", yday.Year(), yday.Month(), yday.Day())
|
|
// self.varMap["uid"] = strconv.Itoa(int(self.Uid))
|
|
// self.varMap["uid"] = self.Uid
|
|
// self.varMap["username"] = self.UserName
|
|
// // self.varMap["host"] = self.Hostname
|
|
// self.varMap["home"] = self.HomeDir
|
|
}
|
|
|
|
func (self *TextTemplate) Expand(template string) string {
|
|
|
|
self.updateVarMap()
|
|
|
|
result := os.Expand(template, func(name string) string {
|
|
value, ok := self.varMap[name]
|
|
if ok {
|
|
return value
|
|
} else {
|
|
return ""
|
|
}
|
|
})
|
|
|
|
return result
|
|
}
|
|
|
|
func (self *TextTemplate) ExpandEnv(template string) (result string) {
|
|
if len(template) > 0 {
|
|
self.updateVarMap()
|
|
result = os.Expand(template, func(name string) string {
|
|
value, ok := self.varMap[name]
|
|
if ok {
|
|
return value
|
|
} else {
|
|
return "${" + name + "}"
|
|
}
|
|
})
|
|
|
|
// for k, v := range self.varMap {
|
|
// self.env[k] = v
|
|
// }
|
|
|
|
result = os.ExpandEnv(result)
|
|
// result = os.Expand(result, func(name string) string {
|
|
// value, ok := self.env[name]
|
|
// if ok {
|
|
// return value
|
|
// } else {
|
|
// return ""
|
|
// }
|
|
// })
|
|
}
|
|
return result
|
|
}
|
|
|
|
func (self *TextTemplate) Value(key string) (value string, ok bool) {
|
|
value, ok = self.varMap[key]
|
|
return
|
|
}
|
|
|
|
func (self *TextTemplate) String() string {
|
|
var sb strings.Builder
|
|
|
|
keys := make([]string, 0, len(self.varMap))
|
|
for k := range self.varMap {
|
|
keys = append(keys, k)
|
|
}
|
|
sort.Strings(keys)
|
|
|
|
for _, k := range keys {
|
|
sb.WriteString(fmt.Sprintf("%s=%#v\n", k, self.varMap[k]))
|
|
}
|
|
// for k, v := range self.varMap {
|
|
// sb.WriteString(fmt.Sprintf("%s=%#v\n", k, v))
|
|
// }
|
|
return sb.String()
|
|
}
|
|
|
|
func ParseParamPairsFile(sourceFile string, separator string, hook func(line int, name, value string) (err error)) (err error) {
|
|
var source io.Reader
|
|
if source, err = os.Open(sourceFile); err == nil {
|
|
err = ParseParamPairs(source, separator, hook)
|
|
}
|
|
return
|
|
}
|
|
|
|
func ParseParamPairs(source io.Reader, separator string, hook func(line int, name, value string) (err error)) (err error) {
|
|
var content, sep, name, value []byte
|
|
var sb strings.Builder
|
|
|
|
if content, err = ioutil.ReadAll(source); err != nil {
|
|
return
|
|
}
|
|
|
|
if len(separator) == 0 {
|
|
sep = []byte{' '}
|
|
} else {
|
|
sep = []byte(separator)
|
|
}
|
|
for lineCount, rawLine := range bytes.Split(content, []byte{'\n'}) {
|
|
rawLine = bytes.TrimSpace(rawLine)
|
|
if len(rawLine) == 0 || rawLine[0] == '#' {
|
|
continue
|
|
}
|
|
parts := bytes.SplitN(rawLine, sep, 2)
|
|
name = bytes.TrimSpace(parts[0])
|
|
if len(parts) > 1 {
|
|
value = bytes.TrimSpace(parts[1])
|
|
} else {
|
|
value = []byte{}
|
|
}
|
|
quoteOn := false
|
|
escMode := false
|
|
sb.Reset()
|
|
for _, c := range value {
|
|
switch c {
|
|
case '"':
|
|
if escMode {
|
|
sb.WriteByte(c)
|
|
escMode = false
|
|
} else {
|
|
quoteOn = !quoteOn
|
|
}
|
|
case '\\':
|
|
if escMode {
|
|
sb.WriteByte(c)
|
|
escMode = false
|
|
} else {
|
|
escMode = true
|
|
}
|
|
case 'n':
|
|
if escMode {
|
|
sb.WriteByte('\n')
|
|
escMode = false
|
|
} else {
|
|
sb.WriteByte(c)
|
|
}
|
|
case 'r':
|
|
if escMode {
|
|
sb.WriteByte('\r')
|
|
escMode = false
|
|
} else {
|
|
sb.WriteByte(c)
|
|
}
|
|
case 't':
|
|
if escMode {
|
|
sb.WriteByte('\t')
|
|
escMode = false
|
|
} else {
|
|
sb.WriteByte(c)
|
|
}
|
|
case '#':
|
|
if quoteOn {
|
|
sb.WriteByte(c)
|
|
} else if escMode {
|
|
sb.WriteByte(c)
|
|
escMode = false
|
|
} else {
|
|
goto endloop
|
|
}
|
|
default:
|
|
if escMode {
|
|
escMode = false
|
|
}
|
|
sb.WriteByte(c)
|
|
}
|
|
}
|
|
endloop:
|
|
if err == nil && quoteOn {
|
|
err = errors.New("unbalanced quotes")
|
|
break
|
|
}
|
|
if err == nil {
|
|
if err = hook(lineCount, string(name), sb.String()); err != nil {
|
|
break
|
|
}
|
|
}
|
|
}
|
|
return
|
|
}
|