package cmd import ( "fmt" "github.com/eiannone/keyboard" "sync" "time" ) type Log struct { Level string Message string Time string Source string } type LoggerQueue struct { queue chan Log currentInput string } var Logger = &LoggerQueue{ queue: make(chan Log, 100), } func (l *LoggerQueue) log(level string, message string, source string) { l.queue <- Log{ Level: level, Message: message, Time: time.Now().Format("2006/01/02 15:04:05"), Source: source, } } func (l *LoggerQueue) Info(message string) { l.log("INFO", message, "") } func (l *LoggerQueue) Warning(message string) { l.log("WARNING", message, "") } func (l *LoggerQueue) Error(message string) { l.log("ERROR", message, "") } func (l *LoggerQueue) processLogs(stopChan chan struct{}) { ticker := time.NewTicker(100 * time.Millisecond) defer ticker.Stop() for { select { case logEntry := <-l.queue: displayLog(logEntry) case <-stopChan: fmt.Print("\033[2K\r") println("Stopping") return case <-ticker.C: refreshInputDisplay(l.currentInput) } } } func displayLog(logEntry Log) { fmt.Printf("\033[2K\r%s [%s]: %s\n", logEntry.Time, logEntry.Level, logEntry.Message) fmt.Print("> ") } func refreshInputDisplay(input string) { fmt.Print("\033[2K\r> " + input) } func Start(wg *sync.WaitGroup, stopChan chan struct{}) { defer wg.Done() if err := keyboard.Open(); err != nil { panic(err) } defer func() { go keyboard.Close() }() go Logger.processLogs(stopChan) input := "" for { char, key, err := keyboard.GetKey() if err != nil { Logger.Error(fmt.Sprintf("Keyboard error: %v", err)) break } switch { case key == keyboard.KeyEnter: switch input { case "": // Do nothing case "stop": Logger.Info("Received stop command.") close(stopChan) return default: Logger.Info(fmt.Sprintf("Unknown command: %s", input)) } input = "" case key == keyboard.KeyBackspace || key == keyboard.KeyBackspace2: if len(input) > 0 { input = input[:len(input)-1] } case key == keyboard.KeySpace: input += " " case key == keyboard.KeyCtrlC: Logger.Info("Received stop command.") close(stopChan) return case char != 0: input += string(char) } Logger.currentInput = input // Update stored user input } }