package goutil import ( "bufio" "errors" "flag" "fmt" "io/ioutil" "os" "os/exec" "path" "path/filepath" "runtime" "strings" ) func DecorateError(s string, err error) error { if err != nil { return errors.New(s + ": " + err.Error()) } else { return nil } } func WriteFile(filename string, data string) error { return ioutil.WriteFile(filename, []byte(data), 0644) } func AppendToFile(filename string, data string) error { f, err := os.OpenFile(filename, os.O_APPEND|os.O_WRONLY|os.O_CREATE, 0644) if err != nil { return errors.New("AppendToFile " + filename + ": " + err.Error()) } defer f.Close() _, err = f.WriteString(data) return err } func ReadFile(filename string) (string, error) { data, err := ioutil.ReadFile(filename) return string(data), err } func TrimExt(path string) string { extension := filepath.Ext(path) return path[0 : len(path)-len(extension)] } func ListFilesExt(dir string, ext string) []string { list := make([]string, 0) ext = strings.ToUpper(ext) files, err := ioutil.ReadDir(dir) if err == nil { for _, file := range files { if !file.IsDir() { if strings.ToUpper(filepath.Ext(file.Name())) == ext { list = append(list, path.Join(dir, file.Name())) } } } } return list } func RecListFilesExt(dir string, ext string) []string { list := make([]string, 0) traverse := func(path string, info os.FileInfo, err error) error { if err != nil { return err } if info.IsDir() { list = append(list, ListFilesExt(path, ext)...) } return nil } filepath.Walk(dir, traverse) return list } func PathExists(path string) bool { if _, err := os.Stat(path); os.IsNotExist(err) { return false } else { return true } } func AskFor(question string) (string, error) { fmt.Print(question + ": ") reader := bufio.NewReader(os.Stdin) s, err := reader.ReadString('\n') if err == nil { return strings.TrimSpace(s), nil } else { return "", err } } func IntMin(x, y int) int { if x < y { return x } else { return y } } func IntMax(x, y int) int { if x > y { return x } else { return y } } func StrSliceAt(sl []string, i int) string { if i < len(sl) { return sl[i] } else { return "" } } func StrSlice(sl []string, start int, end int) []string { bound := func(i int) int { return IntMin(IntMax(0, i), len(sl)) } start = bound(start) end = bound(end) return sl[start:end] } func OpenInDefaultApp(filename string, wait bool) error { var cmd *exec.Cmd goos := runtime.GOOS switch goos { case "windows": cmd = exec.Command(filepath.Join(os.Getenv("SYSTEMROOT"), "System32", "rundll32.exe"), "url.dll,FileProtocolHandler", filename) case "darwin": cmd = exec.Command("open", filename) default: cmd = exec.Command("xdg-open", filename) } if wait { err := cmd.Run() if goos == "windows" { AskFor("Press Enter when you're done") } return err } else { return cmd.Start() } } type CommandFunc func(args []string) error type CommandFlagsInit func(s *flag.FlagSet) type CommandInitExecFunc func() (CommandFlagsInit, CommandFunc) type Command struct { cmd string exec CommandFunc desc string flags *flag.FlagSet } func NewCommandWithFlags(cmd string, f CommandInitExecFunc, desc string) Command { flagsInit, exec := f() var flags *flag.FlagSet if flagsInit != nil { flags = flag.NewFlagSet(cmd, flag.ExitOnError) flagsInit(flags) } c := Command{cmd, exec, desc, flags} return c } func NewCommand(cmd string, f CommandFunc, desc string) Command { return NewCommandWithFlags(cmd, func() (CommandFlagsInit, CommandFunc) { return nil, f }, desc) } type commandCollection map[string]Command func usageAndExit(cmds []Command) { app := os.Args[0] fmt.Println(app) fmt.Println() fmt.Println("Possible commands:") for _, cmd := range cmds { fmt.Println(" " + cmd.cmd) fmt.Println(" \t" + cmd.desc) } fmt.Println() fmt.Println("for detailed information type '" + app + " help COMMAND'") os.Exit(-1) } func Execute(possibleCommands []Command) error { commands := commandCollection{} for _, c := range possibleCommands { commands[c.cmd] = c } arglen := len(os.Args) if arglen <= 1 { usageAndExit(possibleCommands) } cmdStr := os.Args[1] if cmdStr == "help" { if arglen == 2 { usageAndExit(possibleCommands) } else { cmd, ok := commands[os.Args[2]] if !ok { usageAndExit(possibleCommands) } else { fmt.Println("Description of " + cmd.cmd + ":") fmt.Println(" " + cmd.desc) if cmd.flags != nil { fmt.Println("Possible flags:") cmd.flags.PrintDefaults() } else { fmt.Println("No flags") } return nil } } } cmd, ok := commands[cmdStr] if !ok { usageAndExit(possibleCommands) } if cmd.flags != nil { cmd.flags.Parse(os.Args[2:]) return cmd.exec(cmd.flags.Args()) } else { return cmd.exec(os.Args[2:]) } }