go/ui/ui.go

485 lines
9.5 KiB
Go

package cdmnky.dev/cdmnky/go
import (
"bufio"
"fmt"
"os"
"sort"
"strconv"
"strings"
"time"
)
type UI struct {
appname string
version string
build string
usage string
Params Param
Other []string
debug bool
nocolor bool
}
// Returns a new UI object
func New(appname, version, build string) *UI {
return &UI{
appname: appname,
version: version,
build: build,
usage: "",
Params: Param{
params: map[string]map[string]Arg{
"--debug": {"descr": {"enable debug messages"}, "value": {"false"}, "envvar": {}, "required": {"false"}},
"--help": {"descr": {"show this screen"}, "value": {"false"}, "envvar": {}, "required": {"false"}},
"--nocolor": {"descr": {"disable color output"}, "value": {"false"}, "envvar": {}, "required": {"false"}},
},
},
Other: []string{},
debug: false,
nocolor: false,
}
}
type Arg []string
type Param struct {
params map[string]map[string]Arg
}
// Adds a new parameter to the UI parameter stack
func (x *Param) Add(name, descr, value, envvar, required string) {
wrk1 := Arg{}
if len(value) > 0 {
wrk1 = Arg{value}
}
wrk2 := Arg{}
if len(envvar) > 0 {
wrk2 = Arg{envvar}
}
wrk3 := Arg{"false"}
if len(required) > 0 {
wrk3 = Arg{required}
}
x.params[name] = map[string]Arg{"descr": {descr}, "value": wrk1, "envvar": wrk2, "required": wrk3}
}
// IsNocolor...
func (x *UI) IsNocolor() bool {
return x.nocolor
}
// IsDebug...
func (x *UI) IsDebug() bool {
return x.debug
}
// Usage...
func (x *UI) Usage(msg ...interface{}) {
if len(msg) > 0 {
x.usage = fmt.Sprintf("%v", msg...)
x.usage = strings.Replace(x.usage, "[appname]", x.appname, -1)
} else {
x.Outln(x.usage)
}
}
func (x *UI) Help() {
if len(x.usage) > 0 {
x.Outln("USAGE")
x.Outf(" %s \n", x.usage)
x.Outln()
}
x.Outln("PARAMETERS")
sortedKeys := []string{}
for key := range x.Params.params {
sortedKeys = append(sortedKeys, key)
}
sort.Strings(sortedKeys)
for _, key := range sortedKeys {
p := x.Params.params[key]
if key == "--debug" || key == "--nocolor" || key == "--help" {
continue
}
wrk1 := ""
if len(p["required"]) > 0 {
wrk1 = " required... " + p["required"][0]
}
if len(p["value"]) > 0 {
wrk1 += "\n default.... " + p["value"][0]
}
if len(p["envvar"]) > 0 {
wrk1 += "\n env var.... " + p["envvar"][0]
}
name := key + " ..............................................................................."
x.Outf(" %s %s\n", name[:80-len(p["descr"][0])-3], p["descr"][0])
x.Outln(wrk1)
}
x.Outln()
for key := range x.Params.params {
p := x.Params.params[key]
if key == "--debug" || key == "--nocolor" || key == "--help" {
wrk1 := ""
if len(p["required"]) > 0 {
wrk1 = " required... " + p["required"][0]
}
if len(p["value"]) > 0 {
wrk1 += "\n default.... " + p["value"][0]
}
if len(p["envvar"]) > 0 {
wrk1 += "\n env var.... " + p["envvar"][0]
}
name := key + " ..............................................................................."
x.Outf(" %s %s\n", name[:80-len(p["descr"][0])-3], p["descr"][0])
x.Outln(wrk1)
}
}
x.Outln()
}
func (x *UI) Parse(args []string) (err error) {
// parse default variables
tmp := []string{}
for idx, arg := range args {
if idx == 0 {
continue
}
if arg == "--help" {
x.Help()
os.Exit(0)
}
if arg == "--debug" {
x.debug = true
x.Params.params["--debug"]["value"] = Arg{"true"}
continue
}
if arg == "--nocolor" {
x.nocolor = true
x.Params.params["--nocolor"]["value"] = Arg{"true"}
continue
}
tmp = append(tmp, arg)
}
args = tmp
var required = map[string]bool{}
// determine required
for key := range x.Params.params {
if x.Params.params[key]["required"][0] == "true" {
required[key] = true
}
}
var isBool = map[string]bool{}
// determine if parameter is a bool
for key := range x.Params.params {
wrk := x.Params.params[key]["value"]
if len(wrk) > 0 && (wrk[0] == "true" || wrk[0] == "false") {
isBool[key] = true
}
}
// parse bool parameters
tmp = []string{}
for _, arg := range args {
if isBool[arg] {
x.Params.params[arg]["value"] = Arg{"true"}
continue
}
tmp = append(tmp, arg)
}
args = tmp
// parse environment variables
for key := range x.Params.params {
wrk := x.Params.params[key]["envvar"]
if len(wrk) > 0 {
tmp := os.Getenv(wrk[0])
if len(tmp) > 0 {
x.Params.params[key]["value"] = Arg{tmp}
}
}
}
// parse everything else ...
for idx := 0; idx < len(args); idx++ {
name := args[idx]
if n := x.Params.params[name]; n != nil {
idx++
if len(args) > (idx) {
x.Params.params[name]["value"] = append(x.Params.params[name]["value"], args[idx])
}
} else {
x.Other = append(x.Other, args[idx])
}
}
// make sure requred arguments were supplied
errcnt := 0
errmsg := ""
for key := range required {
param := x.Params.params[key]
if len(param["value"]) == 0 {
if errcnt > 0 {
errmsg += ", "
}
errmsg += key
errcnt++
}
}
if len(errmsg) > 0 {
return fmt.Errorf("missing required arguments: %s", errmsg)
}
return nil
}
func (x *UI) Banner() {
print := NewColor(x.nocolor)
print.Yellowf("%s, version %s, build %s \n", x.appname, x.version, x.build)
}
func (x *UI) String(arg string) (val string) {
val = ""
wrk := x.Params.params[arg]["value"]
if len(wrk) > 0 {
val = wrk[len(wrk)-1]
}
return
}
func (x *UI) Strings(arg string) (val []string) {
val = []string{}
for _, wrk := range x.Params.params[arg]["value"] {
if len(wrk) > 0 {
val = append(val, wrk)
}
}
return
}
func (x *UI) Bool(arg string) (val bool) {
val = false
wrk := x.Params.params[arg]["value"]
if len(wrk) > 0 {
val = wrk[len(wrk)-1] == "true"
}
return
}
// Int ...
func (x *UI) Int(name string) (val int) {
var err error
if wrk := x.Params.params[name]; wrk != nil {
tmp := 0
tmp, err = strconv.Atoi(wrk["value"][0])
if err != nil {
tmp = -999
}
val = tmp
}
return
}
// Int32 ...
func (x *UI) Int32(name string) (val int32) {
var err error
if wrk := x.Params.params[name]; wrk != nil {
tmp := 0
tmp, err = strconv.Atoi(wrk["value"][0])
if err != nil {
tmp = -999
}
val = int32(tmp)
}
return
}
// Int64 ...
func (x *UI) Int64(name string) (val int64) {
var err error
if wrk := x.Params.params[name]; wrk != nil {
tmp := 0
tmp, err = strconv.Atoi(wrk["value"][0])
if err != nil {
tmp = -999
}
val = int64(tmp)
}
return
}
// Ints ...
func (x *UI) Ints(name string) (val []int) {
var err error
if wrk := x.Params.params[name]; wrk != nil {
tmp := 0
for _, wrk1 := range wrk["value"] {
tmp, err = strconv.Atoi(wrk1)
if err != nil {
tmp = -999
}
val = append(val, tmp)
}
}
return
}
// Ints32 ...
func (x *UI) Ints32(name string) (val []int32) {
var err error
if wrk := x.Params.params[name]; wrk != nil {
tmp := 0
for _, wrk1 := range wrk["value"] {
tmp, err = strconv.Atoi(wrk1)
if err != nil {
tmp = -999
}
val = append(val, int32(tmp))
}
}
return
}
// Ints64 ...
func (x *UI) Ints64(name string) (val []int64) {
var err error
if wrk := x.Params.params[name]; wrk != nil {
tmp := 0
for _, wrk1 := range wrk["value"] {
tmp, err = strconv.Atoi(wrk1)
if err != nil {
tmp = -999
}
val = append(val, int64(tmp))
}
}
return
}
// Out ...
func (x *UI) Out(msg ...interface{}) {
fmt.Print(msg...)
}
// Outln ...
func (x *UI) Outln(msg ...interface{}) {
fmt.Println(msg...)
}
// Outf ...
func (x *UI) Outf(format string, i ...interface{}) {
fmt.Printf(format, i...)
}
// Info ...
func (x *UI) Info(msg ...interface{}) {
fmt.Print(NewColor(x.nocolor).Sgreenf("[info] "))
fmt.Print(msg...)
}
// Infoln ...
func (x *UI) Infoln(msg ...interface{}) {
fmt.Print(NewColor(x.nocolor).Sgreenf("[info] "))
fmt.Println(msg...)
}
// Infof ...
func (x *UI) Infof(format string, i ...interface{}) {
fmt.Print(NewColor(x.nocolor).Sgreenf("[info] "))
fmt.Printf(format, i...)
}
// Error ...
func (x *UI) Error(msg ...interface{}) {
fmt.Print(NewColor(x.nocolor).Sredf("[error] "))
fmt.Print(msg...)
}
// Errorln ...
func (x *UI) Errorln(msg ...interface{}) {
fmt.Print(NewColor(x.nocolor).Sredf("[error] "))
fmt.Println(msg...)
}
// Errorf ...
func (x *UI) Errorf(format string, i ...interface{}) {
fmt.Print(NewColor(x.nocolor).Sredf("[error] "))
fmt.Printf(format, i...)
}
// Debug ...
func (x *UI) Debug(msg ...interface{}) {
if x.debug {
fmt.Print(NewColor(x.nocolor).Syellowf("[debug] "))
fmt.Print(msg...)
}
}
// Debugln ...
func (x *UI) Debugln(msg ...interface{}) {
if x.debug {
fmt.Print(NewColor(x.nocolor).Syellowf("[debug] "))
fmt.Println(msg...)
}
}
// Debugf ...
func (x *UI) Debugf(format string, i ...interface{}) {
if x.debug {
fmt.Print(NewColor(x.nocolor).Syellowf("[debug] "))
fmt.Printf(format, i...)
}
}
// Log ...
func (x *UI) Log(msg ...interface{}) {
ts := time.Now().Format("2006.01.02 03:04:05PM")
fmt.Print("[" + ts + "] ")
fmt.Print(msg...)
}
// Logln ...
func (x *UI) Logln(msg ...interface{}) {
ts := time.Now().Format("2006.01.02 03:04:05PM")
fmt.Print("[" + ts + "] ")
fmt.Println(msg...)
}
// Logf ...
func (x *UI) Logf(format string, i ...interface{}) {
ts := time.Now().Format("2006.01.02 03:04:05PM")
fmt.Print("[" + ts + "] ")
fmt.Printf(format, i...)
}
// Prompt ...
func (x *UI) Prompt(msg ...interface{}) string {
r := bufio.NewReader(os.Stdin)
fmt.Print(NewColor(x.nocolor).Sredf("%s", msg...))
//fmt.Print(msg...)
line, _, err := r.ReadLine()
if err != nil {
return err.Error()
}
return string(line)
}
// Clear ...
func (x *UI) Clear() {
fmt.Printf("\033[2J\033[1;1H")
}