1 Star 1 Fork 0

bon-ami / eztools

加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
克隆/下载
ui.go 9.86 KB
一键复制 编辑 原始数据 按行查看 历史
Allen Tse 提交于 2022-11-21 14:22 . DiffDate() supports both formats
package eztools
import (
"bufio"
"fmt"
"io"
"log"
"os"
"runtime"
"strconv"
"strings"
"syscall"
"time"
"golang.org/x/crypto/ssh/terminal"
)
const (
formatComp, formatMinus = "20060102", "2006-01-02"
LogFlagDate = log.Ldate
LogFlagTime = log.Ltime
LogFlagDateNTime = log.LstdFlags
LogFlagFile = log.Lshortfile
LogFlagDateTimeNFile = LogFlagDateNTime | LogFlagFile
)
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
loggingTime bool
logFunc func(...any)
)
// InitLogger opens log file
func InitLogger(out io.Writer) error {
if out == nil {
return ErrInvalidInput
}
loggingTime = false
logger = log.New(out, "", 0)
if logger == nil {
return ErrNoValidResults
}
return nil
}
func SetLogFlags(f int) {
if logger != nil {
if f&LogFlagDateNTime != 0 {
loggingTime = true
} else {
loggingTime = false
}
logger.SetFlags(f)
}
}
// SetLogFunc sets function for all Log*()
func SetLogFunc(f func(...any)) {
logFunc = f
}
func GetCallerLog() string {
ptr, _, _, ok := runtime.Caller(4)
if !ok {
return ""
}
frames := runtime.CallersFrames([]uintptr{ptr})
frame, more := frames.Next()
var str string
if more {
frame, _ := frames.Next()
str = frame.Function + ":" + strconv.Itoa(frame.Line) + "\n"
}
return str + frame.Function + ":" + strconv.Itoa(frame.Line)
}
// GetCaller returns caller function:line
// Parameter: 1 for immediate caller
func GetCaller(skip int) string {
ptr, _, _, ok := runtime.Caller(skip)
if !ok {
return ""
}
frames := runtime.CallersFrames([]uintptr{ptr})
frame, _ := frames.Next()
return frame.Function + ":" + strconv.Itoa(frame.Line)
}
// logOrPrint logs it
// Parameter print2 = also shown on screen
func logOrPrint(print2 bool, out ...any) {
//log.Print(logFunc, logger, "::", out)
if logFunc != nil {
logFunc(out)
return
}
if logger != nil {
logger.Println(out...)
} else {
log.Println(out...)
}
if print2 {
fmt.Println(out...)
}
}
// Log logs it
func Log(out ...any) {
logOrPrint(false, out...)
}
// LogPrint logs and prints it
func LogPrint(out ...any) {
logOrPrint(true, out...)
}
// LogWtTime logs a string with time
func LogWtTime(out ...any) {
if logger != nil && loggingTime {
Log(out...)
} else {
logOrPrint(false, time.Now().String(), out)
}
}
// LogPrintWtTime logs and prints a string with time
func LogPrintWtTime(out ...any) {
if logger != nil && loggingTime {
LogPrint(out...)
} else {
logOrPrint(true, time.Now().String(), out)
}
}
// LogFatal logs and prints it and exits
func LogFatal(out ...any) {
if logFunc != nil {
logFunc(out)
os.Exit(1)
return
}
if logger != nil {
fmt.Println(out...)
logger.Fatalln(out...)
} else {
log.Fatalln(out...)
}
}
// ShowStrln prints anything with a line break
func ShowStrln(ps ...any) {
if logFunc != nil {
logFunc(ps...)
return
}
fmt.Println(ps...)
}
// ShowStr prints anything with no line breaks
func ShowStr(ps ...any) {
if logFunc != nil {
logFunc(ps...)
return
}
fmt.Print(ps...)
}
// ShowArrln prints a slice in one line with a line break
func ShowArrln(arr []string) {
if logFunc != nil {
logFunc(arr)
return
}
for _, i := range arr {
fmt.Print("\"", i, "\", ")
}
fmt.Print("\n")
}
// ShowByteln prints byte slice as string with a line break
func ShowByteln(ps []byte) {
ShowStrln(string(ps[:]))
}
// ShowSthln prints anything with struct names and a line break
func ShowSthln(sth any) {
if logFunc != nil {
logFunc(sth)
return
}
fmt.Printf("%#v\n", sth)
}
// ShowWtFmt prints with format string like printf
func ShowWtFmt(fs string, sth ...any) {
if logFunc != nil {
logFunc(sth...)
return
}
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
//
// All answers taken as lowercase
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 strings.ToLower(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)
}
// 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 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, str
}
res, err := strconv.Atoi(str)
if err != nil {
return InvalidID, str
}
//check for invalid input
if res >= 0 && res < len(choices) {
return res, choices[res]
}
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
func DiffDate(dateO, dateN string) (diff int, err error) {
timeO, err := time.Parse(formatMinus, dateO)
if err != nil {
timeO, err = time.Parse(formatComp, dateO)
if err != nil {
return
}
}
timeN, err := time.Parse(formatMinus, dateN)
if err != nil {
timeN, err = time.Parse(formatComp, dateN)
if err != nil {
return
}
}
d := timeN.Sub(timeO)
return int(d.Hours()) / 24, nil
}
// 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
v4.11.0

搜索帮助