]> Cypherpunks.ru repositories - goredo.git/blob - status.go
Simple real-time status messages
[goredo.git] / status.go
1 /*
2 goredo -- redo implementation on pure Go
3 Copyright (C) 2020 Sergey Matveev <stargrave@stargrave.org>
4
5 This program is free software: you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation, version 3 of the License.
8
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12 GNU General Public License for more details.
13
14 You should have received a copy of the GNU General Public License
15 along with this program.  If not, see <http://www.gnu.org/licenses/>.
16 */
17
18 package main
19
20 import (
21         "flag"
22         "fmt"
23         "os"
24         "strings"
25 )
26
27 const (
28         EnvStatusFd = "REDO_STATUS_FD"
29         EnvNoStatus = "REDO_NO_STATUS"
30
31         StatusRun = iota
32         StatusDone
33         StatusWait
34         StatusWaited
35 )
36
37 var (
38         FdStatus *os.File
39
40         flagNoStatus = flag.Bool("no-status", false, "disable statusline (REDO_NO_STATUS=1)")
41 )
42
43 func statusInit() {
44         if *flagNoStatus {
45                 return
46         }
47         if v := os.Getenv(EnvNoStatus); v == "1" {
48                 return
49         }
50         if v := os.Getenv(EnvStatusFd); v != "" {
51                 if v == "NO" {
52                         return
53                 }
54                 FdStatus = mustParseFd(v, EnvStatusFd)
55                 return
56         }
57         var r *os.File
58         var err error
59         r, FdStatus, err = os.Pipe()
60         if err != nil {
61                 panic(err)
62         }
63         go func() {
64                 running := 0
65                 waiting := 0
66                 done := 0
67                 var out string
68                 outLenPrev := 0
69                 buf := make([]byte, 1)
70                 var n int
71                 for {
72                         n, err = r.Read(buf)
73                         if err != nil || n != 1 {
74                                 break
75                         }
76                         switch buf[0] {
77                         case StatusRun:
78                                 running++
79                         case StatusDone:
80                                 running--
81                                 done++
82                         case StatusWait:
83                                 waiting++
84                         case StatusWaited:
85                                 waiting--
86                         }
87                         if NoColor {
88                                 out = fmt.Sprintf(
89                                         "\rrun: %d wait: %d done: %d\r",
90                                         running, waiting, done,
91                                 )
92                         } else {
93                                 out = fmt.Sprintf(
94                                         "\rrun: %s%d%s wait: %s%d%s done: %s%d%s\r",
95                                         CRedo, running, CReset,
96                                         CWait, waiting, CReset,
97                                         CJS, done, CReset,
98                                 )
99                         }
100                         if len(out) < outLenPrev {
101                                 outLenPrev = len(out)
102                                 out += strings.Repeat(" ", outLenPrev-len(out))
103                         } else {
104                                 outLenPrev = len(out)
105                         }
106                         LogMutex.Lock()
107                         os.Stderr.WriteString(out)
108                         LogMutex.Unlock()
109                 }
110         }()
111 }