Pry не останавливается при вызове из Ruby script, который читается из stdin

Я создал консоль Ruby script, которая использует ARGF для загрузки данных из файла или stdin, который затем вызывает Pry.

Это отлично работает, когда я передаю файл в (Pry pauses), но не удается (Pry не останавливается и просто выходит из Ruby), когда я передаю свои данные с помощью stdin.

Это странно, кто-нибудь знает почему? Я хотел бы передать данные через stdin и приостановить Pry.

Вот пример script:

require 'rubygems'
require 'pry'


def pry_it(str)
    binding.pry
end

pry_it(ARGF.read)

Когда я вызываю это приложение с файлом в ARGV, я получаю свой правильный ответ - pry pauseing

% 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)>

Отлично! Я могу выполнить команды Pry, которые я хочу

Когда я пытаюсь использовать STDIN для отправки данных в свой инструмент:

% 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)>
% 

Посмотрите внимательно: заметьте, что я вернулся в приглашение оболочки, но не останавливается в IRB. Weird! Я не понимаю, почему я получаю такое поведение....

Ответ 1

Попробуйте ARGF с простым:

require 'rubygems'
require 'pry'
binding.pry

Теперь операции IO не охватываются внутренне ARGF.read, и стало очевидно, что здесь не так. ARGF "приклеен" к STDIN, поэтому все, что передается в STDIN, напрямую поступает на вход pry.

Я не знаю точно, какая инструкция в вашем file.txt заставляет pry выйти, но она есть.


UPDATE

Похоже, что скрипт Ruby выдаст что-нибудь на stdin (например, через канал), и $stdin, и STDIN настроены на этот канал, что испортит pry "откуда я бегу" из обнаружения.

Я придумал это не очень элегантное решение:

# 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

Это решение имеет некоторые глюки (например, запрос pry отображается только после ввода).