I'm writing a wizard for a CLI in Go. What I'd like to do is ask the user what he wants to do, prepare the appropriate CLI command, and write it to the console. The user then would submit the command to the CLI by pressing Enter, possibly after editing it first. In other words, I want to write output to stdout that becomes input to stdin when the user presses Enter. Is there a way to do this in Go?
-
Take a look at http://stackoverflow.com/questions/30655143/call-source-from-inside-a-go-program/30657036#30657036 But do not send a "\n" at the end of the command. – Alvivi Jun 24 '15 at 22:26
-
Thanks - this is a good find and is close to what I want. Unfortunately, it's OS dependent (doesn't even compile in Windows). Also, the output is messy in Linux (prints the command twice). It has promise, though, and I'll work with it and post it as a solution to my own question if I can get it going satisfactorily. – David Tootill Jun 25 '15 at 17:11
2 Answers
For getting input directly from user:
var s string
_, err := fmt.Scanf("%s", &s)
For curses-like application, look here: https://github.com/rthornton128/goncurses/blob/master/ncurses.go
It has C bindings.

- 17,361
- 24
- 78
- 126
-
This doesn't do it - I'm looking to provide a way to receive input from the user directly from text written by the application to the console. It's straightforward to collect something the user has typed himself. What I want to do is write something to the console and allow the user to submit it back by pressing Enter. The solution suggested in alvivi's comment above is close, though it has the issues noted. – David Tootill Jun 25 '15 at 17:14
-
You mean curses-like application? Please see if the curses lib in my update is helpful. – NeoWang Jun 26 '15 at 02:10
I've found a Go command line editor package, https://github.com/peterh/liner, that incorporates the capability requested and a good deal more. It allows you to write a CLI with history and command completion, with the command completion feature providing exactly what I asked for in the question: it presents text that the user can edit and submit to the CLI. It supports Windows, Linux, and Mac. Here's a slightly modified version of the example in its README that runs a simple CLI with command completion. For example, the user can type "j" and press Tab to cycle through a list of names, edit one to taste, and press Enter to submit.
package main
import (
"fmt"
"log"
"os"
"strings"
"github.com/peterh/liner"
)
var (
history_fn = ".liner_history"
names = []string{"jack", "john", "james", "mary", "mike", "nancy"}
)
func main() {
line := liner.NewLiner()
defer line.Close()
line.SetCompleter(func(line string) (c []string) {
for _, n := range names {
if strings.HasPrefix(n, strings.ToLower(line)) {
c = append(c, n)
}
}
return
})
if f, err := os.Open(history_fn); err == nil {
line.ReadHistory(f)
f.Close()
}
line.SetCtrlCAborts(true)
for true {
if name, err := line.Prompt("What is your name? "); err != nil {
if err.Error() == "EOF" || err == liner.ErrPromptAborted {
break
}
log.Print("Error reading line: ", err)
} else {
log.Print("Got: ", name)
line.AppendHistory(name)
}
}
fmt.Printf("End of test\n")
if f, err := os.Create(history_fn); err != nil {
log.Print("Error writing history file: ", err)
} else {
line.WriteHistory(f)
f.Close()
}
}

- 541
- 5
- 11