1 // goredo -- djb's redo implementation on pure Go
2 // Copyright (C) 2020-2024 Sergey Matveev <stargrave@stargrave.org>
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.
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.
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/>.
32 EnvLevel = "REDO_LEVEL"
33 EnvNoProgress = "REDO_NO_PROGRESS"
34 EnvDebug = "REDO_DEBUG"
35 EnvLogWait = "REDO_LOG_WAIT"
36 EnvLogLock = "REDO_LOG_LOCK"
37 EnvLogPid = "REDO_LOG_PID"
38 EnvLogJS = "REDO_LOG_JS"
39 EnvNoColor = "NO_COLOR"
62 flagDebug = flag.Bool("d", false, fmt.Sprintf("enable debug logging (%s=1)", EnvDebug))
76 t := term.NewTerminal(&b, "")
77 CDebug = string(t.Escape.Yellow)
78 CRedo = string(t.Escape.Green)
79 CWait = string(t.Escape.Blue)
80 CLock = string(t.Escape.Cyan)
81 CErr = string(t.Escape.Red)
82 CWarn = string(t.Escape.Magenta)
83 CJS = string(t.Escape.White)
84 CReset = string(t.Escape.Reset)
85 KeyEraseLine = fmt.Sprintf("%s[K", CReset[0:1])
88 if !(cmdName == CmdNameRedo || cmdName == CmdNameRedoIfchange) {
91 flagNoProgress = flag.Bool("no-progress", false,
92 fmt.Sprintf("no progress printing (%s=1), also implies -no-status", EnvNoProgress))
93 flagLogWait = flag.Bool("log-wait", false,
94 fmt.Sprintf("enable wait messages logging (%s=1)", EnvLogWait))
95 flagLogLock = flag.Bool("log-lock", false,
96 fmt.Sprintf("enable lock messages logging (%s=1)", EnvLogLock))
97 flagLogPid = flag.Bool("log-pid", false,
98 fmt.Sprintf("append PIDs (%s=1)", EnvLogPid))
99 flagLogJS = flag.Bool("log-js", false,
100 fmt.Sprintf("enable jobserver messages logging (%s=1)", EnvLogJS))
103 func erasedStatus(s, end string) string {
104 if NoProgress || NoColor {
107 return s + KeyEraseLine + end
110 func withPrependedTgt(s string) {
112 stderrWrite(erasedStatus(s, "\n"))
115 i := strings.IndexByte(s, ']')
120 tgt, s := s[1:i], s[i+1:]
121 if tgt != LastLoggedTgt {
123 tgt = "redo " + tgt + " ..."
125 tgt = fmt.Sprintf("[%d] %s", MyPID, tgt)
127 stderrWrite(erasedStatus(colourize(CDebug, tgt), "\n"))
129 stderrWrite(erasedStatus(s, "\n"))
132 func stderrWrite(s string) {
134 os.Stderr.WriteString(s)
138 func tracef(level, format string, args ...interface{}) {
141 p = fmt.Sprintf("[%d] ", MyPID)
145 p = erasedStatus(StderrPrefix+p+fmt.Sprintf(format, args...), "\n")
154 if !(LogWait || Debug) {
164 if !(LogLock || Debug) {
169 if !(LogJS || Debug) {
178 msg := fmt.Sprintf(format, args...)
179 msg = StderrPrefix + colourize(level, p+strings.Repeat(". ", Level)+msg)
180 msg = erasedStatus(msg, "\n")
184 func colourize(colour, s string) string {
188 return colour + s + CReset