Prev: Execute ruby file from a ruby file
Next: unsubscribe
From: Ryan Mohr on 15 Jun 2010 17:45 I've written a simple console app (type command. get results. repeat.) and I'm looking for a way to send it simulated keystrokes (hoping to remotely send commands through a socket connection and have them "typed" in the main console). I thought the solution would be easy but I'm finding it much harder than anticipated. The solution needs to generate a keystroke programmatically such that the console has no idea whether it was physically typed by the user or not. Tried writing to a modified stdin, directly editing /dev/tty, redirected echos... no luck yet. Any ideas? -- Posted via http://www.ruby-forum.com/.
From: Joel VanderWerf on 15 Jun 2010 18:39 Ryan Mohr wrote: > I've written a simple console app (type command. get results. repeat.) > and I'm looking for a way to send it simulated keystrokes (hoping to > remotely send commands through a socket connection and have them "typed" > in the main console). I thought the solution would be easy but I'm > finding it much harder than anticipated. > > The solution needs to generate a keystroke programmatically such that > the console has no idea whether it was physically typed by the user or > not. > > Tried writing to a modified stdin, directly editing /dev/tty, redirected > echos... no luck yet. What about ruby's PTY lib? PTY.spawn 'your-app' do |r,w,cid| ... end
From: Brian Candler on 16 Jun 2010 04:18 Ryan Mohr wrote: > The solution needs to generate a keystroke programmatically such that > the console has no idea whether it was physically typed by the user or > not. > > Tried writing to a modified stdin, directly editing /dev/tty, redirected > echos... no luck yet. > > Any ideas? Spawn a pty. There's pty.so in the standard library, which is a C extension and unfortunately not well documented, but google for "PTY.spawn" to find some examples, e.g. http://www.ruby-forum.com/topic/133560 http://svn.ruby-lang.org/cgi-bin/viewvc.cgi/branches/ruby_1_8/ext/pty/expect_sample.rb?view=markup -- Posted via http://www.ruby-forum.com/.
From: Ryan Mohr on 16 Jun 2010 16:02 Brian Candler wrote: > Spawn a pty. There's pty.so in the standard library, which is a C > extension and unfortunately not well documented, but google for > "PTY.spawn" to find some examples, e.g. Thanks for the suggestion Brian but I don't think that will work for my case. I need to send keystrokes to stdin of the current process itself. Maybe there's a way to do that with PTY but I couldn't get it to work. Here's a quick example that demonstrates the issue: [code] # prompt is already up and waiting t = Thread.new { print "Enter command: " $stdout.flush # get the next command to run from the user command = gets puts "Executing command #{command}" } # want this to enter the desired command as though it # was typed by the user himself (show up in stdout but # also be picked up by any open 'gets' requests) # ... ? (send "foo" to stdin of the current process) t.join puts "Done." [/code] -- Posted via http://www.ruby-forum.com/.
From: Brian Candler on 16 Jun 2010 16:15
Ryan Mohr wrote: > Brian Candler wrote: >> Spawn a pty. There's pty.so in the standard library, which is a C >> extension and unfortunately not well documented, but google for >> "PTY.spawn" to find some examples, e.g. > > Thanks for the suggestion Brian but I don't think that will work for my > case. I need to send keystrokes to stdin of the current process itself. Then I think you're stuck. When your ruby process was started, its stdin file descriptor was connected to something (e.g. a terminal or a pipe). Only that thing can generate data for your app to read; e.g. you can't write to the read end of a pipe. You could connect forcibly reopen stdin on a different fd: rd, wr = IO.pipe STDIN.reopen(rd) Thread.new do wr.puts "hello" end line = gets puts line.inspect That's really horrible though. It would be better to fork your program entirely: IO.popen("-","rb+") do |pipe| if pipe # parent pipe.puts "hello" res = pipe.gets puts "got: #{res}" else # child line = gets puts line.inspect end end If what you're trying to accomplish is unit testing of a CLI-driven program, then I'd suggest either running the program under test as a child (e.g. using IO.popen or PTY.spawn), or factor out your objects so that they can read and write to arbitrary IO objects that you pass in, so that you can pass them a StringIO or one end of a pipe. Otherwise, perhaps you can explain what you are trying to achieve? Regards, Brian. -- Posted via http://www.ruby-forum.com/. |