]> Cypherpunks.ru repositories - goredo.git/blobdiff - status.go
Simple real-time status messages
[goredo.git] / status.go
diff --git a/status.go b/status.go
new file mode 100644 (file)
index 0000000..f203b74
--- /dev/null
+++ b/status.go
@@ -0,0 +1,111 @@
+/*
+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()
+               }
+       }()
+}