Files

122 lines
2.7 KiB
Go

package main
import (
"bufio"
"fmt"
"os"
"os/exec"
"sort"
"strings"
)
// readPassword reads a line from stdin with terminal echo disabled, if stdin is a tty.
func readPassword(prompt string) (string, error) {
fmt.Fprint(os.Stderr, prompt)
restore := func() {}
if cmd := exec.Command("stty", "-echo"); true {
cmd.Stdin = os.Stdin
if cmd.Run() == nil {
restore = func() {
r := exec.Command("stty", "echo")
r.Stdin = os.Stdin
r.Run()
}
}
}
defer restore()
reader := bufio.NewReader(os.Stdin)
line, err := reader.ReadString('\n')
fmt.Fprintln(os.Stderr)
if err != nil && line == "" {
return "", err
}
return strings.TrimRight(line, "\r\n"), nil
}
func readLine(prompt string) (string, error) {
fmt.Fprint(os.Stderr, prompt)
reader := bufio.NewReader(os.Stdin)
line, err := reader.ReadString('\n')
if err != nil && line == "" {
return "", err
}
return strings.TrimSpace(line), nil
}
// parseKV parses ["f_name=foo", "l_dep=1"] into {"f_name":"foo","l_dep":"1"}.
func parseKV(args []string) (map[string]interface{}, error) {
out := map[string]interface{}{}
for _, a := range args {
i := strings.IndexByte(a, '=')
if i < 0 {
return nil, fmt.Errorf("expected key=value, got %q", a)
}
out[a[:i]] = a[i+1:]
}
return out, nil
}
func sortedKeys(m map[string]interface{}) []string {
keys := make([]string, 0, len(m))
for k := range m {
keys = append(keys, k)
}
sort.Strings(keys)
return keys
}
func toStr(v interface{}) string {
if v == nil {
return ""
}
return fmt.Sprintf("%v", v)
}
// printIDs prints a []interface{} of numeric ids, one per line.
func printIDs(ids []interface{}) {
for _, id := range ids {
fmt.Println(toStr(id))
}
}
// printDevice pretty-prints one device record, using field labels when available.
func printDevice(dev map[string]interface{}, labels map[string]interface{}) {
lead := []string{"id", "f_name", "user", "grp", "rm", "ts"}
printed := map[string]bool{}
for _, k := range lead {
if v, ok := dev[k]; ok {
printDeviceField(k, labels, v)
printed[k] = true
}
}
for _, k := range sortedKeys(dev) {
if printed[k] {
continue
}
printDeviceField(k, labels, dev[k])
}
}
func printDeviceField(k string, labels map[string]interface{}, v interface{}) {
label := paint(colorStdout, colBlue, padRight(labelFor(k, labels)+":", 20))
if k == "id" {
fmt.Printf("%s %v\n", label, idText(fmt.Sprintf("%v", v)))
return
}
fmt.Printf("%s %v\n", label, v)
}
func labelFor(col string, labels map[string]interface{}) string {
if labels == nil {
return col
}
if meta, ok := labels[col].(map[string]interface{}); ok {
if name, ok := meta["name"].(string); ok && name != "" {
return name
}
}
return col
}