manifoldco / promptui

Interactive prompt for command-line applications
https://www.manifold.co
BSD 3-Clause "New" or "Revised" License
6.03k stars 333 forks source link

Hi, do we support read multiple lines until ctrl+d to generate an io.EOF #167

Closed hitzhangjie closed 3 years ago

hitzhangjie commented 3 years ago

I use promptui to let user input the issue title and body, the body part contains multiple lines.

So I think it would be better to support multiple lines in our utility.

I don't know whether prompui has supported this feature or not.

hitzhangjie commented 3 years ago

the readline repo only reads a single line.

I found another repo, like https://github.com/chzyer/readline/blob/master/example/readline-multiline/readline-multiline.go, which supports read multiple lines. It looks like easy to support it.

If this feature meets the design of promptui?


  1. add a config option to prompt.Prmopt{} like ReadMultiLine bool
  2. if this option is true, then keep readling lines until an io.EOF is found
hitzhangjie commented 3 years ago

Now I don't think read multiple lines is a good idea, considering the use cases is limited and not convenient to modify the input.

Maybe launch an editor then read the content is better and easier.

hitzhangjie commented 3 years ago

I'll close this.

StevenACoffman commented 3 years ago

I wondered how to do this as well:

// GetMultiLineInput - an empty line terminated with a ctrl-D or ASCII Group Separator Ctrl-] and newline
func GetMultiLineInput(scn *bufio.Scanner) string {
    var lines []string
    terminator := false

    for scn.Scan() {
        line := scn.Text()
        if len(line) == 1 {
            // ASCII Group Separator (GS ^]): ctrl-]
            if strings.HasSuffix(line, "\x1D") || strings.HasSuffix(line, "\x04") {
                trimLine := strings.TrimSuffix(line, "\x1D")
                if !(trimLine == "") {
                    lines = append(lines, trimLine)
                }
                terminator = true
                break
            }
        }
        lines = append(lines, line)
    }

    if err := scn.Err(); err != nil {
        _, _ = fmt.Fprintln(os.Stderr, err)
        return strings.Join(lines, "\n")
    }
    // If we didn't break out of the scan loop
    // due to a Group Separator input character on an empty line
    // then we need to append the last line that had the EOF (Ctrl-D) character
    if !terminator {
        lines = append(lines, scn.Text())
    }

    return strings.Join(lines, "\n")
}

If you drop the ASCII Group Separator Ctrl-] requirement, you can simplify the code.