package main import ( "log" "os" "os/exec" "path" "strings" "9fans.net/go/acme" ) var win *acme.Win var name string func main() { log.SetFlags(0) log.SetPrefix("Git: ") win, err := acme.New() if err != nil { log.Fatal(err) } pwd, _ := os.Getwd() name = strings.TrimSuffix(pwd, "/") + "/" win.Name(name + "+git") win.Clear() win.Ctl("dumpdir " + pwd) win.Ctl("dump " + os.Args[0]) win.Fprintf("tag", "Add Commit Diff Log Pull Push Status ") run("Status", win) go func() { for cmd := range events(win) { run(cmd, win) } }() r, err := acme.Log() if err != nil { log.Fatal(err) } for { ev, err := r.Read() if err != nil { log.Fatal(err) } if ev.Op == "put" && path.Dir(ev.Name) == pwd { run("Status", win) } } } func run(cmd string, win *acme.Win) { var file string argv := strings.Fields(cmd) argc := len(argv) prog := argv[0] if prog == "Add" { if argc < 2 { file = "." } else { pwd, _ := os.Getwd() pwd = strings.TrimSuffix(pwd, "/") + "/" file = strings.TrimPrefix(strings.TrimSpace(cmd[len(prog):]), pwd) } _, err := gitCommand([]string{"add", file}) if err != nil { win.Errf("%v", err) return } run("Status", win) } if prog == "Commit" { oldEditor := os.Getenv("EDITOR") err := os.Setenv("EDITOR", "editinacme") if err != nil { log.Println(err) return } _, err = gitCommand([]string{"commit"}) if err != nil { win.Errf("%v", err) return } os.Setenv("EDITOR", oldEditor) run("Status", win) } if prog == "Diff" { output, err := gitCommand([]string{"diff"}) if err != nil { win.Errf("%v", err) return } win.Clear() win.Fprintf("body", "%s", output) } if prog == "Log" { output, err := gitCommand([]string{"log", "--oneline"}) if err != nil { win.Errf("%v", err) return } win.Clear() win.Fprintf("body", "%s", output) } if prog == "Pull" { output, err := gitCommand(append([]string{"pull"}, strings.Fields(cmd[len(prog):])...)) if err != nil { win.Errf("%v", err) return } win.Clear() win.Fprintf("body", "%s", output) } if prog == "Push" { output, err := gitCommand(append([]string{"push"}, strings.Fields(cmd[len(prog):])...)) if err != nil { win.Errf("%v", err) return } win.Clear() win.Fprintf("body", "%s", output) } if prog == "Status" { output, err := gitCommand([]string{"status"}) if err != nil { win.Errf("%v", err) return } win.Clear() win.Fprintf("body", "%s", output) } if prog == "Show" { hash := argv[1] output, err := gitCommand([]string{"show", hash}) if err != nil { win.Errf("%v", err) } win.Clear() win.Fprintf("body", "%s", output) } } func isKnownCommand(cmd string) bool { return cmd == "Add" || cmd == "Commit" || cmd == "Diff" || cmd == "Log" || cmd == "Status" || cmd == "Push" || cmd == "Pull" } func events(w *acme.Win) <-chan string { c := make(chan string, 10) go func() { for e := range w.EventChan() { switch e.C2 { case 'x', 'X': if string(e.Text) == "Del" { w.WriteEvent(e) os.Exit(0) } else if isKnownCommand(string(e.Text)) { c <- string(e.Text) + " " + string(e.Arg) } else { w.WriteEvent(e) } case 'l', 'L': // Chech if e.Text is a commit hash cmd := exec.Command("git", "rev-parse", string(e.Text)+"^{commit}") output, err := cmd.Output() if err != nil { w.WriteEvent(e) } else { c <- "Show " + string(output) } default: w.WriteEvent(e) } } w.CloseFiles() close(c) }() return c } func gitCommand(argv []string) ([]byte, error) { git, err := exec.LookPath("git") if err != nil { return nil, err } prog := exec.Command(git, argv...) return prog.Output() }