/* goredo -- djb's redo implementation on pure Go Copyright (C) 2020-2021 Sergey Matveev This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 3 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ package main import ( "flag" "fmt" "log" "os" ) const ( EnvStatusFd = "REDO_STATUS_FD" EnvNoStatus = "REDO_NO_STATUS" StatusRun = iota StatusDone StatusWait StatusWaited ) var ( FdStatus *os.File flagNoStatus *bool ) func init() { cmdName := CmdName() if !(cmdName == CmdNameRedo || cmdName == CmdNameRedoIfchange) { return } flagNoStatus = flag.Bool("no-status", false, "disable statusline (REDO_NO_STATUS=1)") } func statusInit() { if NoProgress || *flagNoStatus { return } if v := os.Getenv(EnvNoStatus); v == "1" { return } if v := os.Getenv(EnvStatusFd); v != "" { if v == "NO" { return } FdStatus = mustParseFd(v, EnvStatusFd) return } var r *os.File var err error r, FdStatus, err = os.Pipe() if err != nil { log.Fatalln(err) } go func() { running := 0 waiting := 0 done := 0 var out string buf := make([]byte, 1) var n int for { n, err = r.Read(buf) if err != nil || n != 1 { break } switch buf[0] { case StatusRun: running++ case StatusDone: running-- done++ case StatusWait: waiting++ case StatusWaited: waiting-- } if NoColor { out = fmt.Sprintf( "\rrun: %d wait: %d done: %d", running, waiting, done, ) } else { out = fmt.Sprintf( "\rrun: %s%d%s wait: %s%d%s done: %s%d%s", CRedo, running, CReset, CWait, waiting, CReset, CJS, done, CReset, ) } out = erasedStatus(out, "\r") LogMutex.Lock() os.Stderr.WriteString(out) LogMutex.Unlock() } }() }