+/*
+goredo -- redo implementation on pure Go
+Copyright (C) 2020 Sergey Matveev <stargrave@stargrave.org>
+
+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 <http://www.gnu.org/licenses/>.
+*/
+
+package main
+
+import (
+ "flag"
+ "fmt"
+ "os"
+ "strings"
+)
+
+const (
+ EnvStatusFd = "REDO_STATUS_FD"
+ EnvNoStatus = "REDO_NO_STATUS"
+
+ StatusRun = iota
+ StatusDone
+ StatusWait
+ StatusWaited
+)
+
+var (
+ FdStatus *os.File
+
+ flagNoStatus = flag.Bool("no-status", false, "disable statusline (REDO_NO_STATUS=1)")
+)
+
+func statusInit() {
+ if *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 {
+ panic(err)
+ }
+ go func() {
+ running := 0
+ waiting := 0
+ done := 0
+ var out string
+ outLenPrev := 0
+ 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\r",
+ running, waiting, done,
+ )
+ } else {
+ out = fmt.Sprintf(
+ "\rrun: %s%d%s wait: %s%d%s done: %s%d%s\r",
+ CRedo, running, CReset,
+ CWait, waiting, CReset,
+ CJS, done, CReset,
+ )
+ }
+ if len(out) < outLenPrev {
+ outLenPrev = len(out)
+ out += strings.Repeat(" ", outLenPrev-len(out))
+ } else {
+ outLenPrev = len(out)
+ }
+ LogMutex.Lock()
+ os.Stderr.WriteString(out)
+ LogMutex.Unlock()
+ }
+ }()
+}