add module config, sys, util & style
This commit is contained in:
parent
7bd37463ca
commit
c719e245b9
5
config/go.mod
Normal file
5
config/go.mod
Normal file
|
@ -0,0 +1,5 @@
|
|||
module gitea.meta-tech.academy/go/core/config
|
||||
|
||||
go 1.20
|
||||
|
||||
require gopkg.in/yaml.v3 v3.0.1
|
4
config/go.sum
Normal file
4
config/go.sum
Normal file
|
@ -0,0 +1,4 @@
|
|||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
110
config/loader.go
Normal file
110
config/loader.go
Normal file
|
@ -0,0 +1,110 @@
|
|||
package config
|
||||
|
||||
import (
|
||||
"os"
|
||||
"reflect"
|
||||
"regexp"
|
||||
"strings"
|
||||
|
||||
"gopkg.in/yaml.v3"
|
||||
)
|
||||
|
||||
type Cfg interface {
|
||||
GetVar() []VarConfig
|
||||
}
|
||||
|
||||
type VarConfig struct {
|
||||
Name string `yaml:"name"`
|
||||
Value string `yaml:"value"`
|
||||
}
|
||||
|
||||
type ConfigLoader struct {
|
||||
Var []VarConfig
|
||||
Config interface{}
|
||||
varDef *VarPattern
|
||||
refstr []*reflect.Value
|
||||
}
|
||||
|
||||
func LoadConfig(path string, out Cfg, varPattern *VarPattern) {
|
||||
cl := &ConfigLoader{varDef: varPattern, refstr: []*reflect.Value{}}
|
||||
data, err := os.ReadFile(path)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
if err = yaml.Unmarshal(data, out); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
cl.Var = out.GetVar()
|
||||
cl.Config = out
|
||||
cl.parse()
|
||||
cl.refstr = []*reflect.Value{}
|
||||
// cl.setConfigPtr(outi)
|
||||
}
|
||||
|
||||
func (cl *ConfigLoader) findVarName(match string) string {
|
||||
re := regexp.MustCompile(cl.varDef.getPatternCaptureName())
|
||||
parts := re.FindStringSubmatch(match)
|
||||
if len(parts) > 0 {
|
||||
match = parts[1]
|
||||
}
|
||||
return match
|
||||
}
|
||||
|
||||
func (cl *ConfigLoader) findVarValue(v string) string {
|
||||
names := strings.SplitN(v, ".", 2)
|
||||
if names[0] == "var" {
|
||||
for _, varConfig := range cl.Var {
|
||||
if varConfig.Name == names[1] {
|
||||
v = varConfig.Value
|
||||
}
|
||||
}
|
||||
}
|
||||
return v
|
||||
}
|
||||
|
||||
func (cl *ConfigLoader) findStringRef(ref reflect.Value) {
|
||||
switch ref.Kind() {
|
||||
case reflect.Ptr, reflect.Interface:
|
||||
cl.findStringRef(ref.Elem())
|
||||
case reflect.Struct:
|
||||
for i := 0; i < ref.NumField(); i++ {
|
||||
refc := ref.Field(i)
|
||||
cl.findStringRef(refc)
|
||||
}
|
||||
case reflect.Slice:
|
||||
if !ref.IsNil() {
|
||||
for i := 0; i < ref.Len(); i++ {
|
||||
refc := ref.Index(i)
|
||||
cl.findStringRef(refc)
|
||||
}
|
||||
}
|
||||
case reflect.String:
|
||||
if ref.Len() > 0 {
|
||||
cl.refstr = append(cl.refstr, &ref)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (cl *ConfigLoader) parse() {
|
||||
var name string
|
||||
var tmp string
|
||||
var parts []string
|
||||
var re2 *regexp.Regexp
|
||||
|
||||
cl.findStringRef(reflect.ValueOf(&cl))
|
||||
|
||||
re := regexp.MustCompile(cl.varDef.getPatternVar())
|
||||
for _, ref := range cl.refstr {
|
||||
tmp = ref.String()
|
||||
parts = re.FindStringSubmatch(tmp)
|
||||
if len(parts) > 0 {
|
||||
s := strings.SplitAfter(parts[1], cl.varDef.Close)
|
||||
for _, part := range s {
|
||||
name = cl.findVarName(part)
|
||||
re2 = regexp.MustCompile(cl.varDef.getPatternVarName(name))
|
||||
tmp = re2.ReplaceAllString(tmp, cl.findVarValue(name))
|
||||
}
|
||||
ref.SetString(tmp)
|
||||
}
|
||||
}
|
||||
}
|
31
config/varpattern.go
Normal file
31
config/varpattern.go
Normal file
|
@ -0,0 +1,31 @@
|
|||
package config
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"regexp"
|
||||
)
|
||||
|
||||
type VarPattern struct {
|
||||
Open string
|
||||
Close string
|
||||
}
|
||||
|
||||
func (vp *VarPattern) getPatternCaptureName() string {
|
||||
return fmt.Sprintf("%s([^%s]+)%s", regexp.QuoteMeta(vp.Open), regexp.QuoteMeta(string(vp.Close[:1])), regexp.QuoteMeta((vp.Close)))
|
||||
}
|
||||
|
||||
func (vp *VarPattern) getPatternVar() string {
|
||||
return fmt.Sprintf("(%s.+%s)", regexp.QuoteMeta(vp.Open), regexp.QuoteMeta(vp.Close))
|
||||
}
|
||||
|
||||
func (vp *VarPattern) getPatternVarName(name string) string {
|
||||
return fmt.Sprintf("%s%s%s", regexp.QuoteMeta(vp.Open), name, regexp.QuoteMeta(vp.Close))
|
||||
}
|
||||
|
||||
func NewVarPattern(open string, close string) *VarPattern {
|
||||
return &VarPattern{open, close}
|
||||
}
|
||||
|
||||
func DefaultVarPattern() *VarPattern {
|
||||
return NewVarPattern("{%", "%}")
|
||||
}
|
2
go.work.sum
Normal file
2
go.work.sum
Normal file
|
@ -0,0 +1,2 @@
|
|||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
10
style/go.mod
Normal file
10
style/go.mod
Normal file
|
@ -0,0 +1,10 @@
|
|||
module gitea.meta-tech.academy/go/core/style
|
||||
|
||||
go 1.20
|
||||
|
||||
require github.com/gookit/color v1.5.4
|
||||
|
||||
require (
|
||||
github.com/xo/terminfo v0.0.0-20210125001918-ca9a967f8778 // indirect
|
||||
golang.org/x/sys v0.10.0 // indirect
|
||||
)
|
10
style/go.sum
Normal file
10
style/go.sum
Normal file
|
@ -0,0 +1,10 @@
|
|||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||
github.com/gookit/color v1.5.4 h1:FZmqs7XOyGgCAxmWyPslpiok1k05wmY3SJTytgvYFs0=
|
||||
github.com/gookit/color v1.5.4/go.mod h1:pZJOeOS8DM43rXbp4AZo1n9zCU2qjpcRko0b6/QJi9w=
|
||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||
github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
|
||||
github.com/xo/terminfo v0.0.0-20210125001918-ca9a967f8778 h1:QldyIu/L63oPpyvQmHgvgickp1Yw510KJOqX7H24mg8=
|
||||
github.com/xo/terminfo v0.0.0-20210125001918-ca9a967f8778/go.mod h1:2MuV+tbUrU1zIOPMxZ5EncGwgmMJsa+9ucAQZXxsObs=
|
||||
golang.org/x/sys v0.10.0 h1:SqMFp9UcQJZa+pmYuAKjd9xq1f0j5rLcDIk0mj4qAsA=
|
||||
golang.org/x/sys v0.10.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
114
style/style.go
Normal file
114
style/style.go
Normal file
|
@ -0,0 +1,114 @@
|
|||
package style
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
"gitea.meta-tech.academy/go/core/util"
|
||||
"github.com/gookit/color"
|
||||
)
|
||||
|
||||
// Hello returns a greeting for the named person.
|
||||
func Hello(name string) string {
|
||||
// Return a greeting that embeds the name in a message.
|
||||
message := fmt.Sprintf("Hi, %v. Welcome!", name)
|
||||
return message
|
||||
}
|
||||
|
||||
const KEY_STYLE_NAME = 0
|
||||
const KEY_STYLE_COLOR = 1
|
||||
const KEY_STYLE_OPTION = 2
|
||||
|
||||
type Style struct {
|
||||
color *color.RGBStyle
|
||||
Name string
|
||||
}
|
||||
|
||||
type Styles struct {
|
||||
List map[string]*Style
|
||||
DefaultKeyStyle string
|
||||
DefaultValStyle string
|
||||
DefaultKeyPadding string
|
||||
DefaultIndent string
|
||||
}
|
||||
|
||||
func (s *Style) Printf(format string, a ...any) {
|
||||
s.color.Printf(format, a...)
|
||||
}
|
||||
|
||||
func (s *Style) Sprintf(format string, a ...any) string {
|
||||
return s.color.Sprintf(format, a...)
|
||||
}
|
||||
|
||||
func (s *Style) Echo(data string, format ...string) {
|
||||
fmt := "%s"
|
||||
if len(format) > 1 {
|
||||
fmt = format[0]
|
||||
}
|
||||
s.Printf(fmt, data)
|
||||
}
|
||||
|
||||
func (s *Style) Apply(data string, format ...string) string {
|
||||
if len(format) > 1 {
|
||||
return s.Sprintf(format[0], data)
|
||||
} else {
|
||||
return s.Sprintf(data)
|
||||
}
|
||||
}
|
||||
|
||||
func NewStyleByDef(def string) *Style {
|
||||
var o []string = []string{}
|
||||
d := strings.Fields(def)
|
||||
c := strings.Split(d[KEY_STYLE_COLOR], ",")
|
||||
if len(d) > KEY_STYLE_OPTION {
|
||||
o = strings.Split(d[KEY_STYLE_OPTION], ",")
|
||||
}
|
||||
util.prependToSliceStr(&c, "#")
|
||||
var s *color.RGBStyle
|
||||
switch len(c) {
|
||||
case 1:
|
||||
s = color.HEXStyle(c[0])
|
||||
case 2:
|
||||
s = color.HEXStyle(c[0], c[1])
|
||||
}
|
||||
for _, elm := range o {
|
||||
s.AddOpts(color.Color(util.str2int(elm, 10, 0)))
|
||||
}
|
||||
// s.Printf(" %-20s\n", d[KEY_STYLE_NAME])
|
||||
return &Style{s, d[KEY_STYLE_NAME]}
|
||||
}
|
||||
|
||||
func NewStyles() *Styles {
|
||||
l := &Styles{
|
||||
List: make(map[string]*Style),
|
||||
DefaultKeyStyle: "key",
|
||||
DefaultValStyle: "val",
|
||||
DefaultKeyPadding: "18",
|
||||
DefaultIndent: "4",
|
||||
}
|
||||
return l
|
||||
}
|
||||
|
||||
func (s *Styles) Apply(name string, data string) string {
|
||||
return s.List[name].Apply(data)
|
||||
}
|
||||
|
||||
func (s *Styles) Echo(name string, data string) {
|
||||
s.List[name].Echo(data)
|
||||
}
|
||||
|
||||
func (s *Styles) Keyval(key string, val string, names ...string) {
|
||||
sk := s.List[s.DefaultKeyStyle]
|
||||
sv := s.List[s.DefaultValStyle]
|
||||
if len(names) > 1 {
|
||||
sk = s.List[names[0]]
|
||||
if len(names) > 2 {
|
||||
sv = s.List[names[1]]
|
||||
}
|
||||
}
|
||||
fmt.Printf(
|
||||
"%-"+s.DefaultIndent+"s%s : %s\n",
|
||||
" ",
|
||||
sk.Sprintf("%-"+s.DefaultKeyPadding+"s", key),
|
||||
sv.Apply(val),
|
||||
)
|
||||
}
|
5
sys/go.mod
Normal file
5
sys/go.mod
Normal file
|
@ -0,0 +1,5 @@
|
|||
module gitea.meta-tech.academy/go/core/sys
|
||||
|
||||
go 1.20
|
||||
|
||||
require golang.org/x/sys v0.13.0
|
2
sys/go.sum
Normal file
2
sys/go.sum
Normal file
|
@ -0,0 +1,2 @@
|
|||
golang.org/x/sys v0.13.0 h1:Af8nKPmuFypiUBjVoU9V20FiaFXOcuZI21p0ycVYYGE=
|
||||
golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
125
sys/sys.go
Normal file
125
sys/sys.go
Normal file
|
@ -0,0 +1,125 @@
|
|||
package sys
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
"os/exec"
|
||||
"os/signal"
|
||||
"syscall"
|
||||
|
||||
"golang.org/x/sys/unix"
|
||||
)
|
||||
|
||||
var TERM_WIDTH = 0
|
||||
|
||||
func RunCmd(cmd *exec.Cmd) int {
|
||||
cmd.Stdin = os.Stdin
|
||||
cmd.Stdout = os.Stdout
|
||||
cmd.Stderr = os.Stderr
|
||||
return ManageStatusCmd(cmd, cmd.Run())
|
||||
}
|
||||
|
||||
func RunShellCmd(call string) int {
|
||||
cmd := exec.Command("sh", "-c", call)
|
||||
cmd.Stdin = os.Stdin
|
||||
cmd.Stdout = os.Stdout
|
||||
cmd.Stderr = os.Stderr
|
||||
return ManageStatusCmd(cmd, cmd.Run())
|
||||
}
|
||||
|
||||
func ManageStatusCmd(cmd *exec.Cmd, err error) int {
|
||||
if err == nil {
|
||||
return 0
|
||||
}
|
||||
// Figure out the exit code
|
||||
if ws, ok := cmd.ProcessState.Sys().(syscall.WaitStatus); ok {
|
||||
if ws.Exited() {
|
||||
return ws.ExitStatus()
|
||||
}
|
||||
if ws.Signaled() {
|
||||
return -int(ws.Signal())
|
||||
}
|
||||
}
|
||||
return -1
|
||||
}
|
||||
|
||||
func RunInteractiveCmd(cmd string, withStderr bool) int {
|
||||
fmt.Printf(" == go before command : %s\n", cmd)
|
||||
icmd := exec.Command("bash", "-c", cmd)
|
||||
icmd.Stdin = os.Stdin
|
||||
icmd.Stdout = os.Stdout
|
||||
if withStderr {
|
||||
icmd.Stderr = os.Stderr
|
||||
}
|
||||
return ManageStatusCmd(icmd, icmd.Run())
|
||||
}
|
||||
|
||||
func PipeCmd(cmd1 *exec.Cmd, cmd2 *exec.Cmd, buffers ...io.Writer) {
|
||||
fmt.Println("> Pipe Commands")
|
||||
if len(buffers) > 0 {
|
||||
pr, pw := io.Pipe()
|
||||
cmd1.Stdout = pw
|
||||
cmd2.Stdin = pr
|
||||
cmd2.Stdout = buffers[0]
|
||||
if len(buffers) > 1 {
|
||||
cmd2.Stderr = buffers[1]
|
||||
}
|
||||
|
||||
cmd1.Start()
|
||||
cmd2.Start()
|
||||
|
||||
go func() {
|
||||
defer pw.Close()
|
||||
err1 := cmd1.Wait()
|
||||
if err1 != nil {
|
||||
fmt.Printf("error1 : %v\n", err1)
|
||||
}
|
||||
}()
|
||||
|
||||
err2 := cmd2.Wait()
|
||||
if err2 != nil {
|
||||
fmt.Printf("error2 : %v\n", err2)
|
||||
}
|
||||
fmt.Println("< Pipe Commands")
|
||||
}
|
||||
}
|
||||
|
||||
func UpdateTermSize() error {
|
||||
ws, err := unix.IoctlGetWinsize(syscall.Stdout, unix.TIOCGWINSZ)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
TERM_WIDTH = int(ws.Col)
|
||||
return nil
|
||||
}
|
||||
|
||||
func HandleTermChange() {
|
||||
// set signal handler
|
||||
sigwinch := make(chan os.Signal, 1)
|
||||
defer close(sigwinch)
|
||||
signal.Notify(sigwinch, syscall.SIGWINCH)
|
||||
go func() {
|
||||
for {
|
||||
if _, ok := <-sigwinch; !ok {
|
||||
return
|
||||
}
|
||||
_ = UpdateTermSize()
|
||||
fmt.Printf("TERM WIDTH : %d\n", TERM_WIDTH)
|
||||
}
|
||||
}()
|
||||
}
|
||||
|
||||
func HandleSigKill() {
|
||||
done := make(chan os.Signal, 1)
|
||||
defer close(done)
|
||||
signal.Notify(done, syscall.SIGINT, syscall.SIGTERM)
|
||||
go func() {
|
||||
<-done // Will block here until user hits ctrl+c
|
||||
cmd := exec.Command("tput", "cnorm")
|
||||
RunCmd(cmd)
|
||||
cmd = exec.Command("tput", "-x", "clear")
|
||||
RunCmd(cmd)
|
||||
os.Exit(0)
|
||||
}()
|
||||
}
|
3
util/go.mod
Normal file
3
util/go.mod
Normal file
|
@ -0,0 +1,3 @@
|
|||
module gitea.meta-tech.academy/go/core/util
|
||||
|
||||
go 1.20
|
40
util/util.go
Normal file
40
util/util.go
Normal file
|
@ -0,0 +1,40 @@
|
|||
package util
|
||||
|
||||
import (
|
||||
"strconv"
|
||||
"strings"
|
||||
)
|
||||
|
||||
func prependToSliceStr(strs *[]string, prefix string) {
|
||||
for i, elm := range *strs {
|
||||
(*strs)[i] = prefix + elm
|
||||
}
|
||||
}
|
||||
|
||||
func appendToSliceStr(strs *[]string, suffix string) {
|
||||
for i, elm := range *strs {
|
||||
(*strs)[i] = elm + suffix
|
||||
}
|
||||
}
|
||||
|
||||
func str2int64(str string, base int, fallback int64) int64 {
|
||||
str = strings.TrimSuffix(str, "\n")
|
||||
num, err := strconv.ParseInt(str, base, 64)
|
||||
if err != nil {
|
||||
num = fallback
|
||||
}
|
||||
return num
|
||||
}
|
||||
|
||||
func str2int(str string, base int, fallback int) int {
|
||||
return int(str2int64(str, base, int64(fallback)))
|
||||
}
|
||||
|
||||
func castStrings2ints(strs *[]string) []int {
|
||||
a := make([]int, len(*strs))
|
||||
for i, elm := range *strs {
|
||||
var f int = str2int(elm, 10, 0)
|
||||
a[i] = f
|
||||
}
|
||||
return a
|
||||
}
|
Loading…
Reference in New Issue
Block a user