Kim
Kim

Reputation: 3494

Send stdin keystrokes to channel without newline required

I'd like to send the user's keystrokes to a channel directly after each individual keystroke is made to stdin.

I've attempted the code below, but this doesn't give the desired result because the reader.ReadByte() method blocks until newline is entered.

func chars() <-chan byte {
    ch := make(chan byte)
    reader := bufio.NewReader(os.Stdin)
    go func() {
        for {           
            char, err := reader.ReadByte()
            if err != nil {
                log.Fatal(err)
            }
            ch <- char
        }
    }()
    return ch
}

Thank you for any advice on how might I get each user input character to go immediately to the channel without the need for a newline character.

Upvotes: 9

Views: 1614

Answers (2)

jimt
jimt

Reputation: 26370

Stdin is line-buffered by default. This means it will not yield any input to you, until a newline is encountered. This is not a Go specific thing.

Having it behave in a non-buffered way is highly platform specific. As Rami suggested, ncurses is a way to do it. Another option is the much lighter go-termbox package.

If you want to do it all manually (on Linux at least), you can look at writing C bindings for termios or do syscalls directly in Go.

How platforms like Windows handle this, I do not know. You can dig into the source code for ncurses or termbox to see how they did it.

Upvotes: 11

Rami Jarrar
Rami Jarrar

Reputation: 4643

If you are on Linux, You might want to look at Goncurses package

http://code.google.com/p/goncurses/

It has the function: GetChar() which is what you want.

Upvotes: 5

Related Questions