Swallowing user input while running a sub-command

2019-05-11 20:47发布

I'm writing a simple REPL (a command line wrapper for adb) in Ruby where I support two kinds of commands:

  1. interactive commands
  2. non-interactive commands

As for 2, I simply want to invoke a system command from the REPL, capture its output while it's outputting text, and allow the user to exit back into the REPL from that command. Example:

>> logcat
... // log output here
! user hits CTRL-D
>> // back at the prompt

This is to happen within my program, not the system shell.

Now the problem is: while logcat is running, the parent process (the REPL) keeps capturing keystrokes and then replays (?) them as soon as the command exits. That means, if for instance hit return a few times, then CTRL-C, it will exit out of the sub command back into the REPL but replay all the keystrokes again, which the REPL doesn't understand (if one of those keystrokes happened to be CTRL-D, it will even unintentionally exit my program... this is obviously not what I want.)

Now I have tried multiple different ways of executing the sub command (via backtick, system, exec), I tried to flush and rewind $stdin before entering back into the loop, I tried trapping the CTRL-C interrupt, but nothing works.

I'm sure there must be a way in Ruby to:

  1. start a sub process
  2. route all user input to that process and only that process (i.e. not the parent process)
  3. return to parent process on CTRL-C

Any idea how to accomplish that?

1条回答
爱情/是我丢掉的垃圾
2楼-- · 2019-05-11 21:47

You can try something like the following:

Signal.trap("INT") {}         # ignore sigint in the parent
IO.popen "sort" do |io|       # run sort in a sub process
  puts io.read                # output stdout
end
Signal.trap("INT") { exit }   # restore sigint 

while true do
  puts "looping"
  sleep 1
end

If you run the program you can type in:

$ ruby test.rb
c
d
b
^D
b
c
d
looping
looping
^C
$

or

$ ruby test.rb
c
d
b
^C
looping
looping
^C
$

It works because popen runs the command in a sub process, which has its own signal handling.

查看更多
登录 后发表回答