package main import ( "bytes" "flag" "fmt" "io" "io/ioutil" "local/pt-todo-server/pttodo" "os" "os/exec" "path" "syscall" "gopkg.in/yaml.v2" ) func main() { if err := _main(); err != nil { panic(err) } } func _main() error { filepath := flag.String("f", "-", "path to yaml file") e := flag.Bool("e", false, "edit file") flag.Parse() if *e { if err := edit(*filepath); err != nil { return err } } return dump(os.Stdout, *filepath) } func edit(filepath string) error { var tempFile string cp := func() error { f, err := ioutil.TempFile(os.TempDir(), path.Base(filepath)) if err != nil { return err } g, err := os.Open(filepath) if err != nil { return err } if _, err := io.Copy(f, g); err != nil { return err } g.Close() f.Close() tempFile = f.Name() return nil } vi := func() error { vibin, err := exec.LookPath("vi") if err != nil { return err } cpid, err := syscall.ForkExec( vibin, []string{vibin, tempFile}, &syscall.ProcAttr{ Dir: "", Env: os.Environ(), Files: []uintptr{os.Stdin.Fd(), os.Stdout.Fd(), os.Stderr.Fd()}, Sys: nil, }, ) if err != nil { return err } proc, err := os.FindProcess(cpid) if err != nil { return err } state, err := proc.Wait() if err != nil { return err } if exitCode := state.ExitCode(); exitCode != 0 { return fmt.Errorf("bad exit code on vim: %d, state: %+v", exitCode, state) } return nil } verify := func() error { return dump(io.Discard, tempFile) } save := func() error { return os.Rename(tempFile, filepath) } for _, foo := range []func() error{cp, vi, verify, save} { if err := foo(); err != nil { if tempFile != "" { os.Remove(tempFile) } return err } } return nil } func dump(writer io.Writer, filepath string) error { var reader io.Reader if filepath == "-" { reader = os.Stdin } else { b, err := ioutil.ReadFile(filepath) if err != nil { return err } reader = bytes.NewReader(b) } b, err := ioutil.ReadAll(reader) if err != nil { return err } var root pttodo.Root if err := yaml.Unmarshal(b, &root); err != nil { return err } root.MoveScheduledToTodo() b2, err := yaml.Marshal(root) if err != nil { return err } fmt.Fprintf(writer, "%s\n", b2) return nil }