crunchy-cli/cli/commands/logger.go
2022-07-26 12:47:23 +02:00

196 lines
3.8 KiB
Go

package commands
import (
"fmt"
"github.com/crunchy-labs/crunchy-cli/utils"
"io"
"log"
"os"
"runtime"
"strings"
"sync"
"time"
)
var prefix, progressDown, progressDownFinish string
func initPrefixBecauseWindowsSucksBallsHard() {
// dear windows user, please change to a good OS, linux in the best case.
// MICROSHIT DOES NOT GET IT DONE TO SHOW THE SYMBOLS IN THE ELSE CLAUSE
// CORRECTLY. NOT IN THE CMD NOR POWERSHELL. WHY TF, IT IS ONE OF THE MOST
// PROFITABLE COMPANIES ON THIS PLANET AND CANNOT SHOW A PROPER UTF-8 SYMBOL
// IN THEIR OWN PRODUCT WHICH GETS USED MILLION TIMES A DAY
if runtime.GOOS == "windows" {
prefix = "=>"
progressDown = "|"
progressDownFinish = "->"
} else {
prefix = "➞"
progressDown = "↓"
progressDownFinish = "↳"
}
}
type progress struct {
message string
stop bool
}
func NewLogger(debug, info, err bool) *Logger {
initPrefixBecauseWindowsSucksBallsHard()
debugLog, infoLog, errLog := log.New(io.Discard, prefix+" ", 0), log.New(io.Discard, prefix+" ", 0), log.New(io.Discard, prefix+" ", 0)
if debug {
debugLog.SetOutput(os.Stdout)
}
if info {
infoLog.SetOutput(os.Stdout)
}
if err {
errLog.SetOutput(os.Stderr)
}
if debug {
debugLog = log.New(debugLog.Writer(), "[debug] ", 0)
infoLog = log.New(infoLog.Writer(), "[info] ", 0)
errLog = log.New(errLog.Writer(), "[err] ", 0)
}
return &Logger{
DebugLog: debugLog,
InfoLog: infoLog,
ErrLog: errLog,
devView: debug,
}
}
type Logger struct {
utils.Logger
DebugLog *log.Logger
InfoLog *log.Logger
ErrLog *log.Logger
devView bool
progress chan progress
done chan interface{}
lock sync.Mutex
}
func (l *Logger) IsDev() bool {
return l.devView
}
func (l *Logger) IsQuiet() bool {
return l.DebugLog.Writer() == io.Discard && l.InfoLog.Writer() == io.Discard && l.ErrLog.Writer() == io.Discard
}
func (l *Logger) Debug(format string, v ...interface{}) {
l.DebugLog.Printf(format, v...)
}
func (l *Logger) Info(format string, v ...interface{}) {
l.InfoLog.Printf(format, v...)
}
func (l *Logger) Warn(format string, v ...interface{}) {
l.Err(format, v...)
}
func (l *Logger) Err(format string, v ...interface{}) {
l.ErrLog.Printf(format, v...)
}
func (l *Logger) Empty() {
if !l.devView && l.InfoLog.Writer() != io.Discard {
fmt.Println("")
}
}
func (l *Logger) SetProcess(format string, v ...interface{}) {
if l.InfoLog.Writer() == io.Discard {
return
} else if l.devView {
l.Debug(format, v...)
return
}
initialMessage := fmt.Sprintf(format, v...)
p := progress{
message: initialMessage,
}
l.lock.Lock()
if l.done != nil {
l.progress <- p
return
} else {
l.progress = make(chan progress, 1)
l.progress <- p
l.done = make(chan interface{})
}
go func() {
states := []string{"-", "\\", "|", "/"}
var count int
for i := 0; ; i++ {
select {
case p := <-l.progress:
if p.stop {
fmt.Printf("\r" + strings.Repeat(" ", len(prefix)+len(initialMessage)))
if count > 1 {
fmt.Printf("\r%s %s\n", progressDownFinish, p.message)
} else {
fmt.Printf("\r%s %s\n", prefix, p.message)
}
if l.done != nil {
l.done <- nil
}
l.progress = nil
l.lock.Unlock()
return
} else {
if count > 0 {
fmt.Printf("\r%s %s\n", progressDown, p.message)
}
l.progress = make(chan progress, 1)
count++
fmt.Printf("\r%s %s", states[i/10%4], initialMessage)
l.lock.Unlock()
}
default:
if i%10 == 0 {
fmt.Printf("\r%s %s", states[i/10%4], initialMessage)
}
time.Sleep(35 * time.Millisecond)
}
}
}()
}
func (l *Logger) StopProcess(format string, v ...interface{}) {
if l.InfoLog.Writer() == io.Discard {
return
} else if l.devView {
l.Debug(format, v...)
return
}
l.lock.Lock()
l.progress <- progress{
message: fmt.Sprintf(format, v...),
stop: true,
}
<-l.done
l.done = nil
}