12

I've created a console Ruby script that uses ARGF to load data from a file or stdin, that then calls Pry.

This works great when I pass a file in (Pry pauses) but fails (Pry doesn't stop and just exits Ruby) when I pass my data using stdin.

This is weird, anyone know why? I would like to pass data in via stdin and have Pry pause.

Behold, an example script:

require 'rubygems'
require 'pry'


def pry_it(str)
    binding.pry
end

pry_it(ARGF.read)

When I call this app with a file in ARGV I get my proper response - pry pausing

% bundle exec ruby pry_test.rb file.txt

From: /Users/wilcoxr/Development/json_pry/pry_test.rb @ line 8 Object#pry_it:

    6: def pry_it(str)
    7:
 => 8:  binding.pry
    9: end

[1] pry(main)>

Great! I can execute Pry commands all I want

When I try to use STDIN to send data into my tool:

% cat file.txt | bundle exec ruby pry_test.rb

From: /Users/wilcoxr/Development/json_pry/pry_test.rb @ line 8 Object#pry_it:

    6: def pry_it(str)
    7:
 => 8:  binding.pry
    9: end

[1] pry(main)>
% 

Look closely: note I'm back at my shell prompt, not pauses in IRB. Weird! I don't understand why I'm getting this behavior....

RyanWilcox
  • 13,890
  • 1
  • 36
  • 60

1 Answers1

8

Try ARGF with simple:

require 'rubygems'
require 'pry'
binding.pry

Now IO operations are not covered internally by ARGF.read and it became evident what’s wrong here. ARGF is “glued” to STDIN, therefore whatever is being passed to STDIN goes directly to pry’s input.

I do not know exactly, what instruction in your file.txt forces pry to quit, but there is one.


UPDATE

It looks like if a Ruby script yields anything on stdin (e. g. through a pipe,) both $stdin and STDIN are set to this pipe, messing up pry’s “where am I run from” detection.

I came up with this not-so-elegant solution:

# read input from ARGF
text = ARGF.read

# prepare new stdin to satisfy pry
pry_fd_stdin = IO.sysopen("/dev/tty")
pry_stdin = IO.new(pry_fd_stdin, "r")

# load pry and cheat it with our stdio
require 'pry'
Pry.config.input = pry_stdin

binding.pry

This solution has some glitches (e.g. pry prompt is shown only after input).

user664833
  • 18,397
  • 19
  • 91
  • 140
Aleksei Matiushkin
  • 119,336
  • 10
  • 100
  • 160
  • I suspect you're on to something. I don't think it's the contents of my input file that causes Pry to do things... but I agree with you that STDIN may be interacting with PRY in fun ways Because here's another example of what's up: `echo "hi" | bundle exec ruby pry_test.rb`. This gives the same result as above: a quick exit – RyanWilcox Sep 01 '15 at 15:03
  • Try to run the code above with `ruby pry_test.rb < file.txt`, you’ll see what’s happening in details. It appears that `pry` throws an error and [likely] continues it’s execution, leading your script to exit. – Aleksei Matiushkin Sep 01 '15 at 15:04
  • Ok, yes I agree. I also checked the TTY status of stdin (with `puts IO.pipe.map(&:tty?)`), and it returns false. So I guess Pry reads from STDIN, either reading commands from stdin OR seeing that we're at the end of STDIN - because we read it all, like my example does - AND that we're not an interactive terminal, and exits. So ummm... how do I get around that I wonder... – RyanWilcox Sep 01 '15 at 15:23
  • Thank you - this works to some extent, as you mentioned - but a painful glitch I am experiencing is the total absence of the command-line capabilities typically provided by the `readline` library: **moving on the `pry` command-line** (e.g. moving back a character is not possible), and **reverse-searching `pry` history** (i.e. hitting `control-r` to search the history of previously entered `pry` commands is not possible). Might you know of any workaround for this issue? – user664833 Aug 14 '19 at 21:43