Search code examples
juliapolling

How can I test whether stdin has input available in julia?


I would like to detect whether there is input on stdin in a short time window, and continue execution either way, with the outcome stored in a Bool. (My real goal is to implement a pause button on a simulation that runs in the terminal. A second keypress should unpause the program, and it should continue executing.) I have tried to use poll_fd but it does not work on stdin:

julia> FileWatching.poll_fd(stdin, readable=true)
ERROR: MethodError: no method matching poll_fd(::Base.TTY; readable=true)

Is there a way that will work on julia? I have found a solution that works in python, and I have considered using this via PyCall, but I am looking for

  1. a cleaner, pure-julia way; and
  2. a way that does not fight or potentially interfere with julia's use of libuv.

Solution

  • bytesavailable(stdin)
    

    Here is a sample usage. Note that if you capture the keyboard you also need to handle Ctrl+C yourself (in this example only the first byte of chunk is checked).

    If you want to run it fully asynchronously put @async in front of the while loop. However if there will be no more code in this case this program will just exit.

    import REPL
    term = REPL.Terminals.TTYTerminal("xterm",stdin,stdout,stderr)
    REPL.Terminals.raw!(term,true)
    Base.start_reading(stdin)
    
    while (true)
        sleep(1)
        bb = bytesavailable(stdin)
        if bb > 0
            data = read(stdin, bb)
            if data[1] == UInt(3)
                println("Ctrl+C - exiting")
                exit()
            end
            println("Got $bb bytes: $(string(data))")
        end
    end