47 lines
1009 B
Go
47 lines
1009 B
Go
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()
|
|
}
|