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