package main import ( "fmt" "os" "os/exec" "strings" ) // yesno asks a y/n question with a default. Reads a single keypress. func yesno(prompt string, def bool) bool { suffix := " y/N ? " if def { suffix = " Y/n ? " } ans := strings.ToLower(strings.TrimSpace(getkey(prompt + suffix))) if ans == "" { return def } return ans == "y" || ans == "yes" } // getkey reads a single keypress from the terminal without echo. It reads a // single byte directly from stdin; readline is not reading at this point (we // are inside command execution), so there is no reader to desync with. func getkey(prompt string) string { fmt.Print(prompt) stty("-icanon", "-echo") var buf [1]byte n, err := os.Stdin.Read(buf[:]) stty("icanon", "echo") key := "" if err == nil && n > 0 { key = strings.Trim(string(buf[:n]), "\r\n\t") } fmt.Println(key) return key } func stty(args ...string) { c := exec.Command("stty", args...) c.Stdin = os.Stdin c.Stdout = os.Stdout c.Stderr = os.Stderr c.Run() }