How to synchronize input with output on a terminal?
I'm writing a linux shell for a custom scripting language, and I want to print a "... " before each follow-up line a user enters for a single statement, with the first line having a ">>> " printed, then waiting for input. Following is an example:
>>> void f() {
... "this is a test"
... }
>>>
I'm reading the line with fgets
, an开发者_如何学JAVAd after I read it completely, I print the "... ", and repeat using another call to fgets
. This works fine for moderately fast interactive input. But if I paste code containing newlines into the terminal, what I get is the following
>>> void f() {
"this is a test"
}
... ... >>>
The "... "'es are printed too late, even though I emit a fflush
call after I print them to stdout
. Does anyone know whether there is anything special to do to make this work?
If you turn off echo (see stty(1)
-echo
) for the terminal, then you are in complete control over when the input is printed to the screen.
My assumption is the paste is causing all lines to be written to the terminal at once, and your program will never get an opportunity to send output to the terminal when necessary. So, if you turn off echo and print the user's input as they enter it, you can perform your special handling when you see the newline chars.
You can see that the irb
program does something very similar by running strace
on it:
ioctl(0, SNDCTL_TMR_TIMEBASE or TCGETS, {B38400 opost isig icanon echo ...}) = 0
...
ioctl(0, SNDCTL_TMR_STOP or TCSETSW, {B38400 opost isig -icanon -echo ...}) = 0
There's not really a simple way to do it using stdio -- you'll need to use something like ncurses to control the terminal. The issue is that when you copy and paste multiple lines like that, they all get pulled into stdin's read buffer in a single call to read(2)
, so stdout has no chance to intervene and print the intervening prompts.
精彩评论