REPL
REPL в мире наколенной разработки расшифровывается как Read → Evaluate → Print Loop. Зачитали, выполнили, напечатали, и так много раз.
Ruby, как и многие другие языки, поставляется с собственной реализацией REPL под названием irb. Который, хотя и справляется с примитивными задачами, все-таки полностью удовлетворить запросы взыскательного разработчика не может. Но существует и гораздо более развитая альтернатива: pry.

Вот рекламный отрывок с официального сайта pry:
Pry — это мощная альтернатива стандартной IRB-оболочке для Ruby. С подсветкой синтаксиса, гибкой архитектурой плагинов, вызовами времени исполнения и просмотром исходников и документации.
И это не просто рекламное бла-бла-бла. Это правда. Я собираюсь показать, как установить и настроить pry со всеми свистелками и кричалками, чтобы удовлетворить самого искушенного разработчика. Предполагается, что актуальная работающая версия Руби установлена и работает на целевой машине.
Подготовка
Перейдите в консоль и выполните команду:
$ gem install pry pry-theme awesome_print coderay
Все, мы полностью готовы. Давайте запустим pry… и убедимся, что никакой разницы в сравнении с irb нет. Внезапно не очень-то приятно.
Ну что ж, давайте научим pry быть чуточку поумнее.
Конфигурационный файл
Это .pryrc. В домашнем каталоге уже есть конфигурационный файл, который рассказывает pry, как выглядеть, и как вести себя в приличном обществе. Если его нет, его можно создать командой cd && touch .pryrc.
Деликатное наполнение .pryrc инструкциями
Я собираюсь продемонстрировать различные возможности pry шаг за шагом. Для нетерпеливых: gist с моим .pryrc.
-
pryруководства: здесь собраны килотонны полезной информации для опытных приистов, -
pryтемы оформления: вопросы, ответы, и т. п.
Редактор по умолчанию
Pry.editor = 'vi' # 'code', 'subl'
Настраивает редактор, который будет использоваться для редактирования текущего контекста (команда edit).
Приглашение командной строки
Pry.config.prompt =
[
->(_obj, _nest_level, _) { "✎ " },
->(*) { " " }
]
.pryrc — это просто руби-файл, поэтому этот процесс может выполнить любой код, который вы хотите, или даже майнить биткойны, пока вы ждете появления следующего приглашения.
Первый уровень и вложенные уровни (внутри блоков) могут отрисовываться по-разному. Раньше я использовал черный закрашенный треугольник, который вырезает тупой парсер хабра для первого уровня и ▷ для вложенных, но постепенно пришел к выводу, что отсутствие каких бы то ни было посторонних символов внутри сниппета существенно облегчает копирование фрагмента куда угодно. Поэтому так.
Цвета
Для поддержки тем оформления используется pry-theme gem. Я использую раскраску синтаксиса (а когда надоедает, запускаю PRY_BW=true pry). Для папок под управлением Rails (содержащих проекты Rails) цвета могут быть настроены еще причудливее, но я ненавижу Rails, и поэтому что там происходит, точно сказать не могу.
unless ENV['PRY_BW']
Pry.color = true
Pry.config.theme = "railscasts"
Pry.config.prompt = PryRails::RAILS_PROMPT if defined?(PryRails::RAILS_PROMPT)
Pry.config.prompt ||= Pry.prompt
end
История
Это просто находка. Находясь в режиме отладчика, или если команда была выполнена непосредственно перед этим, просто нажмите ⏎, и она будет повторена. Чрезвычайно полезно для перехода в код в отладчике (если вы, конечно, вообще пользуетесь отладчиком, а не фиксируете все ошибки пристальным взглядом, не запуская дебаггер никогда, как, например, я).
Pry.config.history.should_save = true
Pry::Commands.command /^$/, "repeat last command" do
_pry_.run_command Pry.history.to_a.last
end
Команды
Отладчик. Велосипед не мой, я просто позаимствовал эти пять строчек у своего товарища по команде, который проводит всю свою жизнь в отладке, но, говорят, работает.
Pry.commands.alias_command 'c', 'continue' rescue nil
Pry.commands.alias_command 's', 'step' rescue nil
Pry.commands.alias_command 'n', 'next' rescue nil
Pry.commands.alias_command 'f', 'finish' rescue nil
Pry.commands.alias_command 'l', 'whereami' rescue nil
Конфигурация описания модуля / класса
Pry.config.ls.separator = "\n" # new lines between methods
Pry.config.ls.heading_color = :magenta
Pry.config.ls.public_method_color = :green
Pry.config.ls.protected_method_color = :yellow
Pry.config.ls.private_method_color = :bright_black
Тут, вроде, и комментировать нечего.
Вызов системных утилит
Pry поддерживает вызов системных утилит (просто добавьте точку перед именем команды без пробела, .ls, или .ps axu).
Плагины
Ниже приведен простейший пример настройки плагина. Никто не любит раздутые конфигурации, мы их отполировываем и таскаем за собой по разным машинами десятилетиями. Приведенный ниже фрагмент — лишь пример (для плагина awesome). Комментарии в коде говорят сами за себя.
# `awesome_print` gem is a great syntax colorized printing
# look at `~/.aprc` for more settings for awesome_print
begin
require 'awesome_print'
# The following line enables awesome_print for all pry output,
# and it also enables paging
Pry.config.print = proc {|output, value| Pry::Helpers::BaseHelpers.stagger_output("=> #{value.ai}", output)}
# If you want awesome_print without automatic pagination, use the line below
module AwesomePrint
Formatter.prepend(Module.new do
def awesome_self(object, type)
return super(object, type) unless type == :string
return super(object, type) unless @options[:string_limit]
return super(object, type) unless object.inspect.to_s.length > @options[:string_limit]
colorize(object.inspect.to_s[0..@options[:string_limit]] + "...", type)
end
end)
end
AwesomePrint.defaults = {
:string_limit => 80,
:indent => 2,
:multiline => true
}
AwesomePrint.pry!
rescue LoadError => err
puts "gem install awesome_print # <-- highly recommended"
end
Пользовательские команды
Я уже говорил, что pry очень крутой REPL? Мы даже можем определить свой собственный набор команд, которые будут использоваться внутри pry. В приведенном ниже примере показано, как создать sql-команду для выполнения чистого SQL из консоли (при условии, что у нас есть рабочее соединение AR) — с минимальным количеством нажатий клавиш.
default_command_set = Pry::CommandSet.new do
command "sql", "Send sql over AR." do |query|
if ENV['RAILS_ENV'] || defined?(Rails)
pp ActiveRecord::Base.connection.select_all(query)
else
pp "No rails env defined"
end
end
end
Pry.config.commands.import default_command_set
Monkeypatches и Globals
Да, мы можем настроить и выполнить любой код Ruby с помощью своих собственных monkeypatches, которые будут доступны только в сеансах pry. Я, например, нахожу вот такой код весьма удобным для тестирования кода, оперирующего массивами и хэшами.
class Array
def self.sample(count = 10, &block)
Array.new(count, &(block || :succ))
end
end
Hash.singleton_class.prepend(Module.new
def sample(count = 10)
(?a...count.times.reduce(?a) { |o| o.succ }).
map(&:to_sym).zip(0...count).to_h
end
end)
Примечание: если вы думаете, что приведенный выше фрагмент переусложнен вот этим вот Integer#succ, вы наверняка никогда не имели дело с длинными хэшами, имеющими более 26 ключей :)
Настройка цвета
Все, что ниже, предназначено для настройки цветов, используя coderay gem. Результат того стоит. Символы красные, а цифры синие, и все такое прочее.
CodeRay.scan("example", :ruby).term # just to load necessary files
$LOAD_PATH << File.dirname(File.realpath(__FILE__))
require "escaped_colors"
module CodeRay
module Encoders
class Terminal < Encoder
TERM_TOKEN_COLORS.each_pair do |key, value|
TOKEN_COLORS[key] = value
end
end
end
end
В заключение
Я надеюсь, что эта заметка дает первое впечатление о том, что такое pry, и почему оно лучше, чем irb. Я не особо заострял внимание на процессе отладки, в основном потому, что я не отлаживаюсь, а пишу правильный код с нуля. Но я надеюсь, что смог заинтересовать тех, кто видит это сочетание букв — pry — впервые — хотя бы попробовать. Поверьте, оно того сто́ит.
Удачных реплик!