Added existing files
This commit is contained in:
parent
1ce95fbbab
commit
4e04fa6472
116
file-util.go
Normal file
116
file-util.go
Normal file
@ -0,0 +1,116 @@
|
|||||||
|
// file_util.go
|
||||||
|
package utils
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
|
"os"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
func FileSize(filePath string) (size int64) {
|
||||||
|
info, err := os.Stat(filePath)
|
||||||
|
if err == nil {
|
||||||
|
size = info.Size()
|
||||||
|
} else {
|
||||||
|
size = -1
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func IsRegularFile(filePath string) bool {
|
||||||
|
if filePath != "" {
|
||||||
|
info, err := os.Stat(filePath)
|
||||||
|
// return (err == nil || os.IsExist(err)) && info.Mode().IsRegular()
|
||||||
|
return (err == nil || errors.Is(err, os.ErrExist)) && info.Mode().IsRegular()
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func IsDirectory(filePath string) bool {
|
||||||
|
if filePath != "" {
|
||||||
|
info, err := os.Stat(filePath)
|
||||||
|
return (err == nil || errors.Is(err, os.ErrExist)) && info.Mode().IsDir()
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func IsSymLink(filePath string) bool {
|
||||||
|
if filePath != "" {
|
||||||
|
info, err := os.Stat(filePath)
|
||||||
|
return (err == nil || errors.Is(err, os.ErrExist)) && (info.Mode()&os.ModeSymlink != 0)
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func IsSymLinkByDirEntry(e os.DirEntry) bool {
|
||||||
|
info, _ := e.Info()
|
||||||
|
return info.Mode()&os.ModeSymlink != 0
|
||||||
|
}
|
||||||
|
|
||||||
|
func StreamIsTerminal(fh *os.File) bool {
|
||||||
|
var isTerminal bool = false
|
||||||
|
if fh != nil {
|
||||||
|
fi, _ := fh.Stat()
|
||||||
|
isTerminal = (fi.Mode() & os.ModeCharDevice) != 0
|
||||||
|
}
|
||||||
|
return isTerminal
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Ispirata a https://stackoverflow.com/a/50741908
|
||||||
|
*/
|
||||||
|
func MoveFile(sourcePath, destPath string) (int64, error) {
|
||||||
|
var size int64 = 0
|
||||||
|
|
||||||
|
err := os.Rename(sourcePath, destPath)
|
||||||
|
if err != nil {
|
||||||
|
inputFile, err := os.Open(sourcePath)
|
||||||
|
if err != nil {
|
||||||
|
return 0, fmt.Errorf("Couldn't open source file: %s", err)
|
||||||
|
}
|
||||||
|
outputFile, err := os.Create(destPath)
|
||||||
|
if err != nil {
|
||||||
|
inputFile.Close()
|
||||||
|
return 0, fmt.Errorf("Couldn't open dest file: %s", err)
|
||||||
|
}
|
||||||
|
defer outputFile.Close()
|
||||||
|
size, err = io.Copy(outputFile, inputFile)
|
||||||
|
inputFile.Close()
|
||||||
|
if err != nil {
|
||||||
|
return 0, fmt.Errorf("Writing to output file failed: %s", err)
|
||||||
|
}
|
||||||
|
// The copy was successful, so now delete the original file
|
||||||
|
err = os.Remove(sourcePath)
|
||||||
|
if err != nil {
|
||||||
|
return 0, fmt.Errorf("Failed removing original file: %s", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return size, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func ParseMemSize(s string) (size int64, err error) {
|
||||||
|
const MULTIPLES = "BKMGTP"
|
||||||
|
// s = strings.TrimSpace(s)
|
||||||
|
if len(s) != 0 {
|
||||||
|
s = strings.ToUpper(s)
|
||||||
|
s = strings.ReplaceAll(s, ".", "")
|
||||||
|
s = strings.ReplaceAll(s, ",", "")
|
||||||
|
s = strings.ReplaceAll(s, " ", "")
|
||||||
|
pos := strings.IndexAny(s, MULTIPLES)
|
||||||
|
if pos >= 0 {
|
||||||
|
size, err = strconv.ParseInt(s[0:pos], 10, 64)
|
||||||
|
mul := strings.IndexByte(MULTIPLES, s[pos])
|
||||||
|
for ; mul > 0; mul-- {
|
||||||
|
size = size * 1_000
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
size, err = strconv.ParseInt(s, 10, 64)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
err = errors.New("Empty string")
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
6
go.mod
Normal file
6
go.mod
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
module portale-stac.it/packages/utils
|
||||||
|
|
||||||
|
go 1.21
|
||||||
|
|
||||||
|
require golang.org/x/text v0.3.7
|
||||||
|
|
2
go.sum
Normal file
2
go.sum
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
golang.org/x/text v0.3.7 h1:olpwvP2KacW1ZWvsR7uQhoyTYvKAupfQrRGBFM352Gk=
|
||||||
|
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
|
36
gzip-util.go
Normal file
36
gzip-util.go
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
// gzip-util.go
|
||||||
|
package utils
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bufio"
|
||||||
|
"compress/gzip"
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
const GZIP_SUFFIX = ".gz"
|
||||||
|
|
||||||
|
func CreateGzipReader(in io.Reader) (reader *bufio.Reader, err error) {
|
||||||
|
inflate, err := gzip.NewReader(in)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Errorf("Can't inflate gzipped input stream: %v", err)
|
||||||
|
} else {
|
||||||
|
reader = bufio.NewReader(inflate)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func CreateGzipFile(in io.Reader, fileName string) (reader *bufio.Reader, err error) {
|
||||||
|
if len(fileName) > 0 && strings.HasSuffix(fileName, GZIP_SUFFIX) {
|
||||||
|
inflate, err := gzip.NewReader(in)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Errorf("Can't inflate gzipped input stream %#v: %v", fileName, err)
|
||||||
|
} else {
|
||||||
|
reader = bufio.NewReader(inflate)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
reader = bufio.NewReader(in)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
154
misc-util.go
Normal file
154
misc-util.go
Normal file
@ -0,0 +1,154 @@
|
|||||||
|
package utils
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"math/rand"
|
||||||
|
|
||||||
|
"os"
|
||||||
|
"strconv"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"golang.org/x/text/language"
|
||||||
|
"golang.org/x/text/message"
|
||||||
|
)
|
||||||
|
|
||||||
|
func NewEnglishPrinter() *message.Printer {
|
||||||
|
return message.NewPrinter(language.English)
|
||||||
|
}
|
||||||
|
|
||||||
|
func ExitErrorf(rc int, format string, args ...interface{}) {
|
||||||
|
fmt.Fprintf(os.Stderr, format+"\n", args...)
|
||||||
|
os.Exit(rc)
|
||||||
|
}
|
||||||
|
|
||||||
|
func ExitMessagef(rc int, format string, args ...interface{}) {
|
||||||
|
fmt.Printf(format+"\n", args...)
|
||||||
|
os.Exit(rc)
|
||||||
|
}
|
||||||
|
|
||||||
|
func OnStringIndex(index uint, values ...string) (value string) {
|
||||||
|
if index >= 0 && index < uint(len(values)) {
|
||||||
|
value = values[index]
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func OnEmpty(s string, altValues ...string) (value string) {
|
||||||
|
if len(s) == 0 {
|
||||||
|
for _, altValue := range altValues {
|
||||||
|
if len(altValue) > 0 {
|
||||||
|
value = altValue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
value = s
|
||||||
|
}
|
||||||
|
return s
|
||||||
|
}
|
||||||
|
|
||||||
|
func OnCond(cond bool, trueValue, falseValue string) string {
|
||||||
|
if cond {
|
||||||
|
return trueValue
|
||||||
|
} else {
|
||||||
|
return falseValue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func OnCondIface(cond bool, trueValue, falseValue interface{}) interface{} {
|
||||||
|
if cond {
|
||||||
|
return trueValue
|
||||||
|
} else {
|
||||||
|
return falseValue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func OnCondInt(cond bool, trueValue, falseValue int) int {
|
||||||
|
if cond {
|
||||||
|
return trueValue
|
||||||
|
} else {
|
||||||
|
return falseValue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func OnCondInt64(cond bool, trueValue, falseValue int64) int64 {
|
||||||
|
if cond {
|
||||||
|
return trueValue
|
||||||
|
} else {
|
||||||
|
return falseValue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func OnSuccess(cond bool) string {
|
||||||
|
return OnCond(cond, "SUCCEEDED", "FAILED")
|
||||||
|
}
|
||||||
|
|
||||||
|
func OnOk(cond bool) string {
|
||||||
|
return OnCond(cond, "OK", "KO")
|
||||||
|
}
|
||||||
|
|
||||||
|
func RandBool() bool {
|
||||||
|
rand.Seed(time.Now().UnixNano())
|
||||||
|
return rand.Intn(2) > 0
|
||||||
|
}
|
||||||
|
|
||||||
|
func S2Uint32(s string, defaultValue uint32) uint32 {
|
||||||
|
var res uint32
|
||||||
|
v, err := strconv.ParseUint(s, 10, 32)
|
||||||
|
if err == nil {
|
||||||
|
res = uint32(v)
|
||||||
|
} else {
|
||||||
|
res = defaultValue
|
||||||
|
}
|
||||||
|
return res
|
||||||
|
}
|
||||||
|
|
||||||
|
func S2Int32(s string, defaultValue int32) int32 {
|
||||||
|
var res int32
|
||||||
|
v, err := strconv.ParseUint(s, 10, 32)
|
||||||
|
if err == nil {
|
||||||
|
res = int32(v)
|
||||||
|
} else {
|
||||||
|
res = defaultValue
|
||||||
|
}
|
||||||
|
return res
|
||||||
|
}
|
||||||
|
|
||||||
|
func RemoveQuotes(s string) string {
|
||||||
|
l := len(s)
|
||||||
|
if l >= 2 {
|
||||||
|
if (s[0] == '"' && s[l-1] == '"') || (s[0] == '\'' && s[l-1] == '\'') {
|
||||||
|
s = s[1 : l-1]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return s
|
||||||
|
}
|
||||||
|
|
||||||
|
// Credits: https://yourbasic.org/golang/formatting-byte-size-to-human-readable-format/
|
||||||
|
func ByteCountSI(b int64) string {
|
||||||
|
const unit = 1000
|
||||||
|
if b < unit {
|
||||||
|
return fmt.Sprintf("%d B", b)
|
||||||
|
}
|
||||||
|
div, exp := int64(unit), 0
|
||||||
|
for n := b / unit; n >= unit; n /= unit {
|
||||||
|
div *= unit
|
||||||
|
exp++
|
||||||
|
}
|
||||||
|
return fmt.Sprintf("%.1f %cB",
|
||||||
|
float64(b)/float64(div), "kMGTPE"[exp])
|
||||||
|
}
|
||||||
|
|
||||||
|
// Credits: https://yourbasic.org/golang/formatting-byte-size-to-human-readable-format/
|
||||||
|
func ByteCountIEC(b int64) string {
|
||||||
|
const unit = 1024
|
||||||
|
if b < unit {
|
||||||
|
return fmt.Sprintf("%d B", b)
|
||||||
|
}
|
||||||
|
div, exp := int64(unit), 0
|
||||||
|
for n := b / unit; n >= unit; n /= unit {
|
||||||
|
div *= unit
|
||||||
|
exp++
|
||||||
|
}
|
||||||
|
return fmt.Sprintf("%.1f %ciB",
|
||||||
|
float64(b)/float64(div), "KMGTPE"[exp])
|
||||||
|
}
|
169
os-util.go
Normal file
169
os-util.go
Normal file
@ -0,0 +1,169 @@
|
|||||||
|
// os-util.go
|
||||||
|
package utils
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"os"
|
||||||
|
"os/user"
|
||||||
|
"path"
|
||||||
|
"path/filepath"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
func ExpandPath(sourcePath string) (expandedPath string, err error) {
|
||||||
|
if strings.HasPrefix(sourcePath, "~") {
|
||||||
|
var home, userName, remainder string
|
||||||
|
|
||||||
|
slashPos := strings.IndexRune(sourcePath, '/')
|
||||||
|
if slashPos > 0 {
|
||||||
|
userName = sourcePath[1:slashPos]
|
||||||
|
remainder = sourcePath[slashPos:]
|
||||||
|
} else {
|
||||||
|
userName = sourcePath[1:]
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(userName) == 0 {
|
||||||
|
home, err = os.UserHomeDir()
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
var userInfo *user.User
|
||||||
|
userInfo, err = user.Lookup(userName)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
home = userInfo.HomeDir
|
||||||
|
}
|
||||||
|
expandedPath = os.ExpandEnv(path.Join(home, remainder))
|
||||||
|
} else {
|
||||||
|
expandedPath = os.ExpandEnv(sourcePath)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func ExpandPathV(sourcePath string, maps ...map[string]string) (expandedPath string, err error) {
|
||||||
|
var normalizedPath string
|
||||||
|
if strings.HasPrefix(sourcePath, "~") {
|
||||||
|
var home, userName, remainder string
|
||||||
|
|
||||||
|
slashPos := strings.IndexRune(sourcePath, '/')
|
||||||
|
if slashPos > 0 {
|
||||||
|
userName = sourcePath[1:slashPos]
|
||||||
|
remainder = sourcePath[slashPos:]
|
||||||
|
} else {
|
||||||
|
userName = sourcePath[1:]
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(userName) == 0 {
|
||||||
|
home, err = os.UserHomeDir()
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
var userInfo *user.User
|
||||||
|
userInfo, err = user.Lookup(userName)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
home = userInfo.HomeDir
|
||||||
|
}
|
||||||
|
normalizedPath = path.Join(home, remainder)
|
||||||
|
} else {
|
||||||
|
normalizedPath = sourcePath
|
||||||
|
}
|
||||||
|
|
||||||
|
expandedPath = os.Expand(normalizedPath, func(name string) (value string) {
|
||||||
|
var ok bool
|
||||||
|
for _, vars := range maps {
|
||||||
|
if value, ok = vars[name]; ok {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if !ok {
|
||||||
|
value = os.Getenv(name)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func ExpandRealPath(sourcePath string) (expandedRealPath string, err error) {
|
||||||
|
var expandedPath string
|
||||||
|
if expandedPath, err = ExpandPath(sourcePath); err == nil {
|
||||||
|
if expandedPath, err = filepath.Abs(expandedPath); err == nil {
|
||||||
|
expandedRealPath, err = filepath.EvalSymlinks(expandedPath)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetProgramDirPath() (dir string, err error) {
|
||||||
|
var exe string
|
||||||
|
exe, err = os.Executable()
|
||||||
|
if err == nil {
|
||||||
|
exe, err = filepath.EvalSymlinks(exe)
|
||||||
|
if err == nil {
|
||||||
|
exe, err = filepath.Abs(exe)
|
||||||
|
if err == nil {
|
||||||
|
dir = filepath.Dir(exe)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetProgramPath() (exec string, err error) {
|
||||||
|
var tmpExec string
|
||||||
|
tmpExec, err = os.Executable()
|
||||||
|
if err == nil {
|
||||||
|
tmpExec, err = filepath.EvalSymlinks(tmpExec)
|
||||||
|
if err == nil {
|
||||||
|
exec, err = filepath.Abs(tmpExec)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func MakeParentDir(filePath string) (dir string, err error) {
|
||||||
|
dir = filepath.Dir(filePath)
|
||||||
|
if !IsDirectory(dir) {
|
||||||
|
if err1 := os.MkdirAll(dir, 0755); err1 != nil {
|
||||||
|
err = fmt.Errorf("Can't make parent path of %#v: %v", filePath, err1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func ExpandFilePathAndMakeParent(specPath string) (expandedPath, expandedParent string, err error) {
|
||||||
|
expandedPath, err = ExpandPath(specPath)
|
||||||
|
if err == nil {
|
||||||
|
expandedParent, err = MakeParentDir(expandedPath)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func ExpandFilePathAndMakeParentV(specPath string, maps ...map[string]string) (expandedPath, expandedParent string, err error) {
|
||||||
|
expandedPath, err = ExpandPathV(specPath, maps...)
|
||||||
|
if err == nil {
|
||||||
|
expandedParent, err = MakeParentDir(expandedPath)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func MakeDir(dirPath string) (err error) {
|
||||||
|
if !IsDirectory(dirPath) {
|
||||||
|
if err1 := os.MkdirAll(dirPath, 0755); err1 != nil {
|
||||||
|
err = fmt.Errorf("Can't make directory path %#v: %v", dirPath, err1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func ExpandDirPathAndMakeParent(specPath string) (expandedPath string, err error) {
|
||||||
|
expandedPath, err = ExpandPath(specPath)
|
||||||
|
if err == nil {
|
||||||
|
err = MakeDir(expandedPath)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
222
string.go
Normal file
222
string.go
Normal file
@ -0,0 +1,222 @@
|
|||||||
|
// string
|
||||||
|
package utils
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
func PadStringRight(s string, pad string, size int, suffix string) (paddedString string) {
|
||||||
|
if len(pad) == 0 {
|
||||||
|
pad = " "
|
||||||
|
}
|
||||||
|
space := size - len(s)
|
||||||
|
if space > 0 {
|
||||||
|
paddedString = s + strings.Repeat(pad, space)
|
||||||
|
} else {
|
||||||
|
paddedString = s
|
||||||
|
}
|
||||||
|
paddedString += ": %v"
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func UnescapeSpecialChars(source string, charSet, specialChars string) string {
|
||||||
|
var buf strings.Builder
|
||||||
|
var escape bool
|
||||||
|
for _, c := range source {
|
||||||
|
if c == '\\' {
|
||||||
|
if escape {
|
||||||
|
buf.WriteByte('\\')
|
||||||
|
escape = false
|
||||||
|
} else {
|
||||||
|
escape = true
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if escape {
|
||||||
|
if index := strings.IndexRune(charSet, c); index >= 0 {
|
||||||
|
if index < len(specialChars) {
|
||||||
|
buf.WriteByte(specialChars[index])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
escape = false
|
||||||
|
} else {
|
||||||
|
buf.WriteRune(c)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return buf.String()
|
||||||
|
}
|
||||||
|
|
||||||
|
func UnescapeBlanks(source string) string {
|
||||||
|
return UnescapeSpecialChars(source, "nrt", "\n\r\t")
|
||||||
|
}
|
||||||
|
|
||||||
|
func EscapeSpecialChars(source string, charSet string) string {
|
||||||
|
var buf strings.Builder
|
||||||
|
for _, c := range source {
|
||||||
|
if strings.IndexRune(charSet, c) >= 0 {
|
||||||
|
buf.WriteByte(92) // 92 = backslash
|
||||||
|
}
|
||||||
|
buf.WriteRune(c)
|
||||||
|
}
|
||||||
|
return buf.String()
|
||||||
|
}
|
||||||
|
|
||||||
|
func EscapeShellSpecialChars(source string) string {
|
||||||
|
return EscapeSpecialChars(source, "!`$\\()#~&*;")
|
||||||
|
}
|
||||||
|
|
||||||
|
func SplitPair(source, sep string) (left, right string) {
|
||||||
|
parts := strings.SplitN(source, sep, 2)
|
||||||
|
left = strings.TrimSpace(parts[0])
|
||||||
|
if len(parts) > 1 {
|
||||||
|
right = strings.TrimSpace(parts[1])
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func StartsWith(s string, aliases ...string) bool {
|
||||||
|
startsWith := false
|
||||||
|
for _, alias := range aliases {
|
||||||
|
if startsWith = strings.HasPrefix(alias, s); startsWith {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return startsWith
|
||||||
|
}
|
||||||
|
|
||||||
|
func JoinStringMap(m map[string]string, kvSep, itemSep string) string {
|
||||||
|
var sb strings.Builder
|
||||||
|
for key, value := range m {
|
||||||
|
if sb.Len() > 0 {
|
||||||
|
sb.WriteString(itemSep)
|
||||||
|
}
|
||||||
|
sb.WriteString(key)
|
||||||
|
sb.WriteString(kvSep)
|
||||||
|
sb.WriteString(value)
|
||||||
|
}
|
||||||
|
return sb.String()
|
||||||
|
}
|
||||||
|
|
||||||
|
func JoinMap(m map[string]any, kvSep, itemSep string) string {
|
||||||
|
var sb strings.Builder
|
||||||
|
for key, value := range m {
|
||||||
|
if sb.Len() > 0 {
|
||||||
|
sb.WriteString(itemSep)
|
||||||
|
}
|
||||||
|
sb.WriteString(key)
|
||||||
|
sb.WriteString(kvSep)
|
||||||
|
if s, ok := value.(fmt.Stringer); ok {
|
||||||
|
sb.WriteString(s.String())
|
||||||
|
} else {
|
||||||
|
sb.WriteString(fmt.Sprintf("%v", value))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return sb.String()
|
||||||
|
}
|
||||||
|
|
||||||
|
func SplitByRune(s string, sep rune, maxParts int) (parts []string) {
|
||||||
|
return ScopedSplitByRune(s, sep, `'"`, `'"`, maxParts)
|
||||||
|
// var capacity int = 0
|
||||||
|
// var sb strings.Builder
|
||||||
|
// if maxParts < 0 {
|
||||||
|
// for _, b := range s {
|
||||||
|
// if b == sep {
|
||||||
|
// capacity++
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// capacity++
|
||||||
|
// } else {
|
||||||
|
// capacity = max(1, maxParts)
|
||||||
|
// }
|
||||||
|
// parts = make([]string, 0, capacity)
|
||||||
|
|
||||||
|
// count := 0
|
||||||
|
// quote := rune(0)
|
||||||
|
// for i, r := range s {
|
||||||
|
// if r == sep && quote == rune(0) {
|
||||||
|
// if len(parts) < capacity {
|
||||||
|
// count++
|
||||||
|
// if count == maxParts {
|
||||||
|
// sb.WriteString(s[i:])
|
||||||
|
// }
|
||||||
|
// parts = append(parts, sb.String())
|
||||||
|
// sb.Reset()
|
||||||
|
// if count == maxParts {
|
||||||
|
// break
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// } else if r == '\'' || r == '"' {
|
||||||
|
// if quote == r {
|
||||||
|
// quote = rune(0)
|
||||||
|
// } else {
|
||||||
|
// quote = r
|
||||||
|
// }
|
||||||
|
// sb.WriteRune(r)
|
||||||
|
// } else {
|
||||||
|
// sb.WriteRune(r)
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// if maxParts < 0 {
|
||||||
|
// parts = append(parts, sb.String())
|
||||||
|
// } else {
|
||||||
|
// for ; count < maxParts; count++ {
|
||||||
|
// parts = append(parts, sb.String())
|
||||||
|
// sb.Reset()
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// return parts
|
||||||
|
}
|
||||||
|
|
||||||
|
func ScopedSplitByRune(s string, sep rune, scopeOpeners, scopeClosers string, maxParts int) (parts []string) {
|
||||||
|
var capacity int = 0
|
||||||
|
var sb strings.Builder
|
||||||
|
|
||||||
|
if len(scopeClosers) != len(scopeOpeners) {
|
||||||
|
panic("scope openers and closers must have the same length")
|
||||||
|
}
|
||||||
|
|
||||||
|
if maxParts < 0 {
|
||||||
|
capacity = strings.Count(s, string(sep)) + 1
|
||||||
|
} else {
|
||||||
|
capacity = max(1, maxParts)
|
||||||
|
}
|
||||||
|
|
||||||
|
parts = make([]string, 0, capacity)
|
||||||
|
|
||||||
|
count := 0
|
||||||
|
scopeIndex := -1
|
||||||
|
for i, r := range s {
|
||||||
|
if r == sep && scopeIndex < 0 {
|
||||||
|
if len(parts) < capacity {
|
||||||
|
count++
|
||||||
|
if count == maxParts {
|
||||||
|
sb.WriteString(s[i:])
|
||||||
|
}
|
||||||
|
parts = append(parts, sb.String())
|
||||||
|
sb.Reset()
|
||||||
|
if count == maxParts {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if scopeIndex < 0 {
|
||||||
|
if quoteIndex := strings.IndexRune(scopeOpeners, r); quoteIndex >= 0 {
|
||||||
|
scopeIndex = quoteIndex
|
||||||
|
}
|
||||||
|
} else if quoteIndex := strings.IndexRune(scopeClosers, r); quoteIndex >= 0 {
|
||||||
|
scopeIndex = -1
|
||||||
|
}
|
||||||
|
sb.WriteRune(r)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if maxParts < 0 {
|
||||||
|
parts = append(parts, sb.String())
|
||||||
|
} else {
|
||||||
|
for ; count < maxParts; count++ {
|
||||||
|
parts = append(parts, sb.String())
|
||||||
|
sb.Reset()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return parts
|
||||||
|
}
|
283
text-util.go
Normal file
283
text-util.go
Normal file
@ -0,0 +1,283 @@
|
|||||||
|
// 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
|
||||||
|
}
|
69
time.go
Normal file
69
time.go
Normal file
@ -0,0 +1,69 @@
|
|||||||
|
package utils
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
func StringTimestamp2GoTime(s string) (ts time.Time) {
|
||||||
|
secs, err := strconv.ParseInt(s, 10, 64)
|
||||||
|
if err == nil {
|
||||||
|
ts = time.Unix(secs, 0)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func StringSeconds2GoDuration(s string) (secs time.Duration) {
|
||||||
|
if len(s) > 0 {
|
||||||
|
if s[len(s)-1] != 's' {
|
||||||
|
s += "s"
|
||||||
|
}
|
||||||
|
secs, _ = time.ParseDuration(s)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Convert the spec string to a number of seconds.
|
||||||
|
// spec is a number, optionally followed by a time unit among 's'(seconds),
|
||||||
|
// 'm'(minutes), 'h'(hours), and 'd'(days)
|
||||||
|
// If the time unit is omitted, defaultUnit is used.
|
||||||
|
// Empty spec returns 0 seconds.
|
||||||
|
func ParseTimeInterval(spec string, defaultUnit byte) (interval int64, err error) {
|
||||||
|
var u byte
|
||||||
|
var intVal int
|
||||||
|
|
||||||
|
spec = strings.TrimSpace(spec)
|
||||||
|
if len(spec) == 0 {
|
||||||
|
//err = errors.New(iface.ErrEmptyValue)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
spec = strings.ToLower(spec)
|
||||||
|
u = spec[len(spec)-1]
|
||||||
|
if u >= '0' && u <= '9' {
|
||||||
|
u = 'm'
|
||||||
|
} else {
|
||||||
|
spec = spec[0 : len(spec)-1]
|
||||||
|
}
|
||||||
|
if intVal, err = strconv.Atoi(spec); err != nil {
|
||||||
|
return
|
||||||
|
// } else if intVal <= 0 {
|
||||||
|
// err = errors.New(iface.ErrMustBePositive)
|
||||||
|
// return
|
||||||
|
}
|
||||||
|
|
||||||
|
switch u {
|
||||||
|
case 's':
|
||||||
|
interval = int64(intVal)
|
||||||
|
case 'm':
|
||||||
|
interval = int64(intVal) * 60
|
||||||
|
case 'h':
|
||||||
|
interval = int64(intVal) * 3600
|
||||||
|
case 'd':
|
||||||
|
interval = int64(intVal) * 86400
|
||||||
|
default:
|
||||||
|
err = fmt.Errorf("invalid time unit %c", u)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
204
tty-util.go
Normal file
204
tty-util.go
Normal file
@ -0,0 +1,204 @@
|
|||||||
|
package utils
|
||||||
|
|
||||||
|
import (
|
||||||
|
"os"
|
||||||
|
)
|
||||||
|
|
||||||
|
const STDIN uint = 0
|
||||||
|
const STDOUT uint = 1
|
||||||
|
const STDERR uint = 2
|
||||||
|
|
||||||
|
const (
|
||||||
|
NONE = iota
|
||||||
|
BLACK
|
||||||
|
RED
|
||||||
|
GREEN
|
||||||
|
BLUE
|
||||||
|
BROWN
|
||||||
|
// YELLOW
|
||||||
|
CYAN
|
||||||
|
MAGENTA
|
||||||
|
WHITE
|
||||||
|
)
|
||||||
|
|
||||||
|
type TTYContext struct {
|
||||||
|
isTTY [3]bool
|
||||||
|
}
|
||||||
|
|
||||||
|
func (self *TTYContext) Init() {
|
||||||
|
for i, _ := range self.isTTY {
|
||||||
|
self.isTTY[i] = StreamIsTerminal(getStream(uint(i)))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (self *TTYContext) IsTTY(fd uint) bool {
|
||||||
|
if fd == STDERR || fd == STDOUT {
|
||||||
|
return self.isTTY[fd]
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func (self *TTYContext) Clean() {
|
||||||
|
for i, _ := range self.isTTY {
|
||||||
|
self.isTTY[i] = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (self *TTYContext) Bold(fd uint) string {
|
||||||
|
if self.isTTY[fd] {
|
||||||
|
return "\x1b[1m"
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
func (self *TTYContext) BoldOff(fd uint) string {
|
||||||
|
if self.isTTY[fd] {
|
||||||
|
return "\x1b[22m"
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
func (self *TTYContext) Underline(fd uint) string {
|
||||||
|
if self.isTTY[fd] {
|
||||||
|
return "\x1b[4m"
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
func (self *TTYContext) UnderlineOff(fd uint) string {
|
||||||
|
if self.isTTY[fd] {
|
||||||
|
return "\x1b[24m"
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
func (self *TTYContext) Italic(fd uint) string {
|
||||||
|
if self.isTTY[fd] {
|
||||||
|
return "\x1b[3m"
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
func (self *TTYContext) ItalicOff(fd uint) string {
|
||||||
|
if self.isTTY[fd] {
|
||||||
|
return "\x1b[23m"
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
func (self *TTYContext) BlackFg(fd uint) string {
|
||||||
|
if self.isTTY[fd] {
|
||||||
|
return "\x1b[30m"
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
func (self *TTYContext) RedFg(fd uint) string {
|
||||||
|
if self.isTTY[fd] {
|
||||||
|
return "\x1b[31m"
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
func (self *TTYContext) GreenFg(fd uint) string {
|
||||||
|
if self.isTTY[fd] {
|
||||||
|
return "\x1b[32m"
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
func (self *TTYContext) BrownFg(fd uint) string {
|
||||||
|
if self.isTTY[fd] {
|
||||||
|
return "\x1b[33m"
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
func (self *TTYContext) BlueFg(fd uint) string {
|
||||||
|
if self.isTTY[fd] {
|
||||||
|
return "\x1b[34m"
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
func (self *TTYContext) MagentaFg(fd uint) string {
|
||||||
|
if self.isTTY[fd] {
|
||||||
|
return "\x1b[35m"
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
func (self *TTYContext) CyanFg(fd uint) string {
|
||||||
|
if self.isTTY[fd] {
|
||||||
|
return "\x1b[36m"
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
func (self *TTYContext) WhiteFg(fd uint) string {
|
||||||
|
if self.isTTY[fd] {
|
||||||
|
return "\x1b[37m"
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
func (self *TTYContext) FgColor(fd uint, n uint) string {
|
||||||
|
var color string
|
||||||
|
switch n {
|
||||||
|
case BLACK:
|
||||||
|
color = self.BlackFg(fd)
|
||||||
|
case WHITE:
|
||||||
|
color = self.WhiteFg(fd)
|
||||||
|
case RED:
|
||||||
|
color = self.RedFg(fd)
|
||||||
|
case GREEN:
|
||||||
|
color = self.GreenFg(fd)
|
||||||
|
case BLUE:
|
||||||
|
color = self.BlueFg(fd)
|
||||||
|
case BROWN:
|
||||||
|
color = self.BrownFg(fd)
|
||||||
|
case CYAN:
|
||||||
|
color = self.CyanFg(fd)
|
||||||
|
case MAGENTA:
|
||||||
|
color = self.MagentaFg(fd)
|
||||||
|
}
|
||||||
|
return color
|
||||||
|
}
|
||||||
|
|
||||||
|
// func (self *TTYContext) BgColor(fd uint, n int) string {
|
||||||
|
// var color string
|
||||||
|
// switch n {
|
||||||
|
// case BLACK:
|
||||||
|
// color = self.BlackBg(fd)
|
||||||
|
// case WHITE:
|
||||||
|
// color = self.WhiteBg(fd)
|
||||||
|
// case RED:
|
||||||
|
// color = self.RedBg(fd)
|
||||||
|
// case GREEN:
|
||||||
|
// color = self.GreenBg(fd)
|
||||||
|
// case CYAN:
|
||||||
|
// color = self.CyanBg(fd)
|
||||||
|
// case MAGENTA:
|
||||||
|
// color = self.MagentaBg(fd)
|
||||||
|
// }
|
||||||
|
// return color
|
||||||
|
// }
|
||||||
|
|
||||||
|
func (self *TTYContext) Reset(fd uint) string {
|
||||||
|
if StreamIsTerminal(getStream(fd)) {
|
||||||
|
return "\x1b[0m"
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
func getStream(fd uint) *os.File {
|
||||||
|
var s *os.File = nil
|
||||||
|
|
||||||
|
switch fd {
|
||||||
|
case STDOUT:
|
||||||
|
s = os.Stdout
|
||||||
|
case STDERR:
|
||||||
|
s = os.Stderr
|
||||||
|
}
|
||||||
|
return s
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user