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

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

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

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

Вот пример скрипта:

require 'rubygems'
require 'pry'


def pry_it(str)
    binding.pry
end

pry_it(ARGF.read)

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

% 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. Странный! Я не понимаю, почему у меня такое поведение....


person RyanWilcox    schedule 01.09.2015    source источник


Ответы (1)


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

require 'rubygems'
require 'pry'
binding.pry

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

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


ОБНОВЛЕНИЕ

Похоже, если 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

В этом решении есть некоторые сбои (например, подсказка показывается только после ввода).

person Aleksei Matiushkin    schedule 01.09.2015
comment
Я подозреваю, что ты что-то замышляешь. Я не думаю, что содержимое моего входного файла заставляет Pry что-то делать... но я согласен с вами, что STDIN может интересно взаимодействовать с PRY. Потому что вот еще один пример того, что происходит: echo "hi" | bundle exec ruby pry_test.rb. Это дает тот же результат, что и выше: быстрый выход - person RyanWilcox; 01.09.2015
comment
Попробуйте запустить приведенный выше код с помощью ruby pry_test.rb < file.txt, вы увидите, что происходит в деталях. Похоже, что pry выдает ошибку и [вероятно] продолжает выполнение, что приводит к завершению вашего скрипта. - person Aleksei Matiushkin; 01.09.2015
comment
Хорошо, да, я согласен. Я также проверил статус TTY стандартного ввода (с puts IO.pipe.map(&:tty?)), и он возвращает false. Итак, я предполагаю, что Pry читает из STDIN, либо читает команды из stdin, либо видит, что мы находимся в конце STDIN — потому что мы читаем все, как в моем примере — И что мы не интерактивный терминал, и выходит. Итак, эммм... как мне обойти это, интересно... - person RyanWilcox; 01.09.2015
comment
Спасибо - это работает до некоторой степени, как вы упомянули, но болезненный сбой, с которым я сталкиваюсь, - это полное отсутствие возможностей командной строки, обычно предоставляемых библиотекой readline: переход в командную строку pry (например, возврат на символ невозможен) и обратный поиск в pry истории (т. е. нажатие control-r для поиска в истории ранее введенных pry команд невозможно). Может быть вы знаете какой-нибудь обходной путь для этой проблемы? - person user664833; 15.08.2019