-
Notifications
You must be signed in to change notification settings - Fork 9
/
main.go
111 lines (95 loc) · 2.52 KB
/
main.go
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
package main // import "github.com/tianon/gosleep"
import (
"fmt"
"os"
"time"
"github.com/jessevdk/go-flags"
jinzhuNow "github.com/jinzhu/now"
"go.tianon.xyz/progress"
)
type sleepFlags struct {
For bool `long:"for"`
Until bool `long:"until"`
}
func main() {
// TODO consider making "start" an optional flag
start := time.Now()
opts := sleepFlags{}
flagParser := flags.NewParser(&opts, flags.Default)
flagParser.Usage = "--for <duration> OR --until <time>"
args, err := flagParser.Parse()
if err != nil {
if flagsErr, ok := err.(*flags.Error); ok {
if flagsErr.Type == flags.ErrHelp {
return
}
}
os.Exit(1)
}
if len(args) != 1 {
fmt.Fprintf(os.Stderr, "error: argument expected\n\n")
flagParser.WriteHelp(os.Stderr)
os.Exit(1)
}
if opts.For == opts.Until {
fmt.Fprintf(os.Stderr, "error: exactly one of --for or --until expected\n\n")
flagParser.WriteHelp(os.Stderr)
os.Exit(1)
}
var until time.Time
if opts.For {
d, err := time.ParseDuration(args[0])
if err != nil {
fmt.Fprintf(os.Stderr, "error: failed to parse duration %q: %v\n", args[0], err)
os.Exit(1)
}
until = start.Add(d)
} else { // opts.Until
until, err = jinzhuNow.New(start).Parse(args[0])
if err != nil {
fmt.Fprintf(os.Stderr, "error: failed to parse time %q: %v\n", args[0], err)
os.Exit(1)
}
}
// TODO consider making these optional flags
interval := 100 * time.Millisecond
round := time.Second
if until.Before(start) {
fmt.Fprintf(os.Stderr, "error: requested sleep time in the past: %s\n", until.Sub(start))
os.Exit(1)
}
bar := progress.NewBar(os.Stdout)
bar.Min = start.UnixNano()
bar.Max = until.UnixNano()
now := start
bar.Val = now.UnixNano()
bar.Prefix = func(b *progress.Bar) string {
if b.TickWidth() < 50 {
// if we're really tight, keep it simple
return " ["
}
rNow := now.Round(round)
rStart := start.Round(round)
rUntil := until.Round(round)
return fmt.Sprintf(" %s / %s [", rNow.Sub(rStart).String(), rUntil.Sub(rStart).String())
}
bar.Suffix = func(b *progress.Bar) string {
rNow := now.Round(round)
//rStart := start.Round(round)
rUntil := until.Round(round)
str := fmt.Sprintf("] %5.01f%% ", b.Progress()*100)
if b.TickWidth() > 100 {
// if we're extra wide, let's add a little extra detail
str += fmt.Sprintf("(%s rem) ", rUntil.Sub(rNow).String())
}
return str
}
bar.Start()
for now = start; now.Before(until); now = time.Now() {
bar.Val = now.UnixNano()
bar.Tick()
time.Sleep(interval)
}
bar.Val = now.UnixNano()
bar.Finish()
}