1 Star 1 Fork 0

bon-ami / eztools

加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
克隆/下载
ui.go 9.12 KB
一键复制 编辑 原始数据 按行查看 历史
package eztools
import (
"bufio"
"errors"
"fmt"
"log"
"os"
"strconv"
"syscall"
"time"
"golang.org/x/crypto/ssh/terminal"
)
const formatComp, formatMinus = "20060102", "2006-01-02"
var (
// Debugging marks debugging mode
Debugging bool // whether more debug procedures
// Verbose marse debugging output level
Verbose = 0
// ChoiceNotification is printed when user needs to choose from choices
ChoiceNotification = "Your choice is: "
defaults bool // whether no more confirmations asked
logger *log.Logger
logFile *os.File
)
// InitLogger opens log file
func InitLogger(out *os.File /*io.Writer*/) error {
if out == nil {
return ErrInvalidInput
}
logger = log.New(out, "", log.LstdFlags)
if logger == nil {
return errors.New("no logger created")
}
logFile = out
// no timestamps
logger.SetFlags(0)
return nil
}
// logOrPrint logs it
// Parameter print2 = also shown on screen
func logOrPrint(print2 bool, out ...interface{}) {
if print2 {
fmt.Println(out...)
if logger == nil {
return
}
}
if logger != nil {
logger.Println(out...)
_ = logFile.Sync()
}
}
// Log logs it
func Log(out ...interface{}) {
logOrPrint(false, out...)
}
// LogPrint logs and prints it
func LogPrint(out ...interface{}) {
logOrPrint(true, out...)
}
// LogWtTime logs a string with time
func LogWtTime(out ...interface{}) {
Log(time.Now().String(), out)
}
// LogPrintWtTime logs and prints a string with time
func LogPrintWtTime(out ...interface{}) {
LogPrint(time.Now().String(), out)
}
// LogErrPrint logs and prints error
func LogErrPrint(err error) {
if err != nil {
LogPrint(err.Error())
}
}
// LogErrPrintWtInfo logs and prints error with information string
func LogErrPrintWtInfo(info string, err error) {
if err != nil {
LogPrint(info + ": " + err.Error())
}
}
// LogErr logs error
func LogErr(err error) {
if err != nil {
Log(err.Error())
}
}
// LogErrWtInfo logs error with information string
func LogErrWtInfo(info string, err error) {
if err != nil {
Log(info + ": " + err.Error())
}
}
// LogFatal logs and prints it and exits
func LogFatal(out ...interface{}) {
if logger != nil {
fmt.Println(out...)
logger.Fatalln(out...)
} else {
log.Fatalln(out...)
}
}
// LogErrFatal logs and prints error and exits
func LogErrFatal(err error) {
LogFatal(err.Error())
}
// ShowStrln prints anything with a line break
func ShowStrln(ps ...interface{}) {
fmt.Println(ps...)
}
// ShowStr prints anything with no line breaks
func ShowStr(ps ...interface{}) {
fmt.Print(ps...)
}
// ShowArrln prints a slice in one line with a line break
func ShowArrln(arr []string) {
for _, i := range arr {
fmt.Print("\"")
fmt.Print(i)
fmt.Print("\", ")
}
fmt.Print("\n")
}
// ShowByteln prints byte slice as string with a line break
func ShowByteln(ps []byte) {
os.Stdout.Write(ps)
fmt.Print("\n")
}
// ShowSthln prints anything with struct names and a line break
func ShowSthln(sth interface{}) {
fmt.Printf("%#v\n", sth)
}
// ShowWtFmt prints with format string like printf
func ShowWtFmt(fs string, sth ...interface{}) {
fmt.Printf(fs, sth...)
}
// PromptStr prompts user and get input
func PromptStr(ps string) string {
fmt.Print(ps + ":")
in := bufio.NewScanner(os.Stdin)
in.Scan()
return in.Text()
}
// PromptPwd prompts user and get password
func PromptPwd(ps string) string {
fmt.Print(ps + ":")
pwd, err := terminal.ReadPassword(int(syscall.Stdin))
fmt.Print("\n")
if err != nil {
return ""
}
return string(pwd)
}
// PromptIntStr prompts user and gets two inputs
// Return values. zero values are default
func PromptIntStr(pi string, ps string) (i int, s string) {
fmt.Printf("%s %s:", pi, ps)
fmt.Scanf("%d %s", &i, &s)
//to exhaust the buffer
bufio.NewScanner(os.Stdin).Scan()
return
}
// PromptInt prompts user and gets input
// Return values. zero values are default
func PromptInt(pi string) (res int, err error) {
res, err = strconv.Atoi(PromptStr(pi))
return
}
// ChkCfmNPrompt checks defaults and return false only when user replied exception
// program exits when user replied 'q' or 'e'
// no more confirmations when user replied 'a' or 'c'
// verbose set when user replied a number, in which case the prompt will show again
func ChkCfmNPrompt(noti, exception string) bool {
if defaults {
return true
}
quitCode := "q"
confCode := "a"
switch exception {
case "q":
quitCode = "e"
case "a":
confCode = "e"
}
val := PromptStr(noti + "?(any number=reset verbose level and ask again/" +
quitCode + "=quit program/" + confCode +
"=defaults to all confirmations/" + exception + "/...)")
switch val {
case quitCode:
LogFatal("Quiting")
case confCode:
defaults = true
case exception:
return false
default:
if v, err := strconv.Atoi(val); err == nil {
Verbose = v
return ChkCfmNPrompt(noti, exception)
}
}
return true
}
// ChooseStringsWtIDs is for general usage to
// ask user to choose from a slice or anything
// parameters.
// fL=quantity of elements
// fI=get index to match user's input
// fV=get message to show for each index
// notif=notification string for user
func ChooseStringsWtIDs(fL func() int, fI func(int) int,
fV func(int) string, notif string) (res int) {
len := fL()
if len < 1 {
return InvalidID
}
for i := 0; i < len; i++ {
fmt.Printf("%d: %s\n", fI(i), fV(i))
}
res, err := PromptInt(notif)
if err == nil {
//check for invalid input
for i := 0; i < len; i++ {
if fI(i) == res {
return
}
}
}
return InvalidID
}
// ChooseInts asks user to choose from a slice
// Parameters. arr[][0]=id. arr[][1]=string
func ChooseInts(arr [][]string, notif string) (id int) {
return ChooseStringsWtIDs(
func() int {
return len(arr)
},
func(i int) int {
ret, err := strconv.Atoi(arr[i][0])
if err != nil {
return InvalidID
}
return ret
},
func(i int) string {
return arr[i][1]
},
notif)
}
// Return values. zero value is default
func choosePairs(choices []pairs, notif string) (res int) {
return ChooseStringsWtIDs(
func() int {
return len(choices)
},
func(i int) int {
return choices[i].id
},
func(i int) string {
return choices[i].str
},
notif)
}
// ChooseMaps asks user to choose from a slice of map of string to string
// parameters: slice.
// separator between two piece of information.
// index(-es) into the map (to be contacted) to be information of each item,
// or separators between two indexes.
// example: (c, ";", "a", "c") with
// c index name value
// 0 a A
// 0 c C
// 1 a B
// 1 c D
// will print
// 0: A;C
// 1: B;D
func ChooseMaps(choices []map[string]string, sep string, indI ...string) int {
if len(choices) < 1 || len(indI) < 1 {
return InvalidID
}
for n, v := range choices {
fmt.Printf("%d: ", n)
for i, j := range indI {
if len(indI) == (i - 1) {
sep = "\n"
}
fmt.Printf("%s%s", v[j], sep)
}
}
fmt.Print(ChoiceNotification)
var str string
fmt.Scanln(&str)
if len(str) < 1 {
return InvalidID
}
res, err := strconv.Atoi(str)
if err != nil {
return InvalidID
}
return res
}
// ChooseStrings asks user to choose from a slice
// return values: index (InvalidID if not a valid one) and string
func ChooseStrings(choices []string) (int, string) {
if choices != nil && len(choices) > 0 {
for i, v := range choices {
fmt.Printf("%d: %s\n", i, v)
}
}
fmt.Print(ChoiceNotification)
var str string
fmt.Scanln(&str)
if len(str) < 1 {
return InvalidID, ""
}
res, err := strconv.Atoi(str)
if err != nil {
return InvalidID, str
}
//check for invalid input
if choices != nil {
for i := range choices {
if i == res {
return res, str
}
}
}
return InvalidID, str
}
// GetDate asks user to input a date string
func GetDate(info string) string {
fmt.Print(info + "date such as " + formatComp + ": ")
var res string
fmt.Scanln(&res)
t, err := time.Parse(formatComp, res)
if err == nil {
return t.Format(formatComp)
}
return "NULL"
}
// TranDate removes minuses from date string
// return current date if empty string as param
func TranDate(date string) string {
if len(date) < 1 {
return time.Now().Format(formatComp)
}
t, err := time.Parse(formatMinus, date)
if err == nil {
return t.Format(formatComp)
}
return ""
}
// DiffDate = dateN - dateO
// return values: difference in days, whether calculated
func DiffDate(dateO, dateN string) (diff int, ok bool) {
timeO, err := time.Parse(formatMinus, dateO)
if err == nil {
return
}
timeN, err := time.Parse(formatMinus, dateN)
if err == nil {
return
}
d := timeN.Sub(timeO)
return int(d.Hours()) / 24, true
}
// TranSize shows the number as file size format
// input params: b=number; precision=how many number to keep lower than point;
// space=whether a space is put between number and unit
// copied from https://programming.guide/go/formatting-byte-size-to-human-readable-format.html
func TranSize(b int64, precision int, space bool) string {
const unit = 1000
var spaceChar string
if space {
spaceChar = " "
}
if b < unit {
return fmt.Sprintf("%d"+spaceChar+"B", b)
}
div, exp := int64(unit), 0
for n := b / unit; n >= unit; n /= unit {
div *= unit
exp++
}
return fmt.Sprintf("%."+strconv.Itoa(precision)+"f"+spaceChar+"%cB",
float64(b)/float64(div), "kMGTPE"[exp])
}
Go
1
https://gitee.com/bon-ami/eztools.git
git@gitee.com:bon-ami/eztools.git
bon-ami
eztools
eztools
main

搜索帮助