From: Ryan Mohr on
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
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
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
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
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/.

 |  Next  |  Last
Pages: 1 2
Prev: Execute ruby file from a ruby file
Next: unsubscribe