-
Notifications
You must be signed in to change notification settings - Fork 0
/
main.go
170 lines (145 loc) · 4.2 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
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
package main
import (
"fmt"
"os"
"github.com/andres-lowrie/human/cmds"
"github.com/andres-lowrie/human/format"
"github.com/andres-lowrie/human/io"
"github.com/davecgh/go-spew/spew"
)
// @todo move this?
type ErrUnknownFmt struct{ s string }
func (e ErrUnknownFmt) Error() string {
return e.s
}
type Direction struct {
From bool
Into bool
// @todo fix this hack by passing in the Direction type to the other functions
toStr func() string
}
func getDirection(args io.CliArgs) Direction {
d := Direction{From: true}
if args.Flags["i"] || len(args.Options["--input"]) > 0 {
d.From = false
d.Into = true
}
d.toStr = func() string {
if d.Into {
return "into"
}
return "from"
}
return d
}
// centralize all the writing to stdout here
func doOutput(a interface{}) {
log := io.NewLogger(io.OFF, false)
log.Debug("Output:")
log.Debug(spew.Sdump(a))
if err, ok := a.(error); ok {
fmt.Println(err.Error())
os.Exit(1)
}
fmt.Println(a)
}
func run(log io.Ourlog, args io.CliArgs) {
log.Debug("Program start")
log.Debug(spew.Sdump(args))
// The idea here is that human will print out all parseable values for each
// known parser (the below map); ie: arguments are used to make it more
// specific similar to `dig`, where `dig` with no args gives all the
// information it has, and then something like `dig +short` gives you a whole
// lot less
// @TODO see if we can use GetParsers instead of instantiating directly
handlers := map[string]format.Format{"number": format.NewNumber(), "size": format.NewSize()}
// If user is asking for help, then all other input gathering logic is
// avoided since this would not be a normal run.
// Note there's also a "help" command, we're not considering that here because
// that's a command and so it can follow the normal flow
passedHelp := func() bool {
_, shortOpt := args.Flags["h"]
_, longOpt := args.Options["help"]
if shortOpt || longOpt {
return true
}
return false
}()
// @TODO read stdin
if len(args.Positionals) < 1 && passedHelp == false {
fmt.Println("@notimplementedyet read arguments from stdin")
// if stdio is empty, then we need to show usage
// r := bufio.NewReader(os.Stdin)
// _, err := r.Peek(10)
// // spew.Dump(got)
// spew.Dump(err)
return
}
if passedHelp {
helpCmd := cmds.NewGlobalHelp()
output, _ := helpCmd.Run("", "", args)
doOutput(output)
return
}
// Are we processing a command or a format?
//
// Commands don't require parsers or the like so for those we just need to
// execute them.
//
// If we are processing a format, then we need to figure out direction and
// which format. We'll default to the `--from` direction since it might be
// the most common usecase i.e. we want to go "from" machine into human
// format
input := args.Positionals[0]
direction := getDirection(args)
log.Debug("Direction: %s", direction.toStr())
if c, ok := cmds.GetCommand(input); ok {
output, err := c.Run(direction.toStr(), input, args)
if err != nil {
return
}
doOutput(output)
return
}
// The logic here is that if no explicit `into` or `from` flag (ie: `direction`) was given
// then the first positional argument (read left from right) is the format
// and anything after that is the actual input, however if only 1 positional
// argument was given then that must be the input in which case we should run
// all the possible translations (ie: formats)
var format string
if len(args.Positionals) > 1 {
format = args.Positionals[0]
input = args.Positionals[1]
}
log.Debug("Format: %s", format)
var output string
if format == "" {
log.Info("Unknown Format '%s', trying all the handlers", format)
for _, c := range handlers {
output, _ = c.Run(direction.toStr(), input, args)
if output != "" {
doOutput(output)
}
}
return
}
c, ok := handlers[format]
if !ok {
msg := fmt.Sprintf("unknown format '%s', nothing to do", format)
doOutput(ErrUnknownFmt{msg})
return
}
log.Debug("Input: ", input)
// @todo: figure out how to show errors
output, err := c.Run(direction.toStr(), input, args)
doOutput(output)
if err != nil {
log.Debug("There was an error")
os.Exit(1)
}
}
func main() {
args := io.ParseCliArgs(os.Args[1:])
log := io.GetLogger(args)
run(log, args)
}