1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
|
package argvpb
import (
"fmt"
"os"
"time"
"go.wit.com/lib/cobol"
"golang.org/x/term"
)
// since we know when the command starts (duh, this parses os.Args)
// this is a convienent way to provide a standard exit format back
// to the shell that also has built in timing!
// also, it supports a custom Exit() back to your application
func GoodExit(msg string) {
PB.goodExit(msg)
}
func BadExit(msg string, err error) {
PB.badExit(msg, err)
}
func isInteractive() {
// For os.Stdin, this is typically 0.
stdinFd := int(os.Stdin.Fd())
// IsTerminal() returns true if the given file descriptor is connected to a terminal.
if term.IsTerminal(stdinFd) {
fmt.Println("Running in an INTERACTIVE terminal.")
} else {
fmt.Println("Running in a NON-INTERACTIVE environment (pipe, script, etc.).")
}
}
func (pb *Argv) goodExit(msg string) {
go ExitWatchdog()
if me.appExit != nil {
me.appExit()
}
dur := time.Since(pb.Ctime.AsTime())
var appname string
if pb.AppInfo == nil {
appname = os.Args[0]
} else {
appname = pb.AppInfo.APPNAME
}
isInteractive()
fmt.Printf("%s: %s (%s)\n", appname, msg, cobol.FormatDuration(dur))
os.Exit(0)
}
func (pb *Argv) badExit(msg string, err error) {
go ExitWatchdog()
if me.appExit != nil {
me.appExit()
}
isInteractive()
// print out errors. this handles wrapped errors which is a useful
if err != nil {
if u, ok := err.(interface{ Unwrap() []error }); ok {
// If it does, call the method to get the slice of errors.
allerr := u.Unwrap()
for _, e := range allerr {
fmt.Printf("Error: (%v)\n", e)
}
} else {
// If it's not a joined error, you can fall back to the single-unwrap loop.
fmt.Printf("Error: (%v)\n", err)
}
}
dur := time.Since(pb.Ctime.AsTime())
var appname string
if pb.AppInfo == nil {
appname = os.Args[0]
} else {
appname = pb.AppInfo.APPNAME
}
fmt.Printf("%s error: %s (%s)\n", appname, msg, cobol.FormatDuration(dur))
os.Exit(int(ExitPB))
}
// this code doesn't need to be this complicated. I put it here as reference code for myself so I could remember where it is.
func ExitWatchdog() {
dog := time.NewTicker(5 * time.Second)
defer dog.Stop()
dogchan := make(chan bool)
/*
// this example would exit/destroy the ticker in 10 seconds
go func() {
time.Sleep(10 * time.Second)
done <- true
}()
*/
for {
select {
case <-dogchan:
fmt.Println("Done!")
return
case t := <-dog.C:
_ = t
fmt.Println("argv.Exit() watchdog: stalled in", PB.AppInfo.APPNAME+".Exit()")
// h.Scan()
}
}
}
func Defer(dur time.Duration, f func()) {
dog := time.NewTicker(5 * time.Second)
defer dog.Stop()
dogchan := make(chan bool)
/*
// this example would exit/destroy the ticker in 10 seconds
go func() {
time.Sleep(10 * time.Second)
done <- true
}()
*/
for {
select {
case <-dogchan:
fmt.Println("Done!")
return
case t := <-dog.C:
_ = t
fmt.Println("argv.Exit() watchdog: stalled in", PB.AppInfo.APPNAME+".Exit()")
// h.Scan()
}
}
}
|