Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix support for Pry 0.13 #958

Merged
merged 1 commit into from Mar 25, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
61 changes: 43 additions & 18 deletions lib/guard/jobs/pry_wrapper.rb
Expand Up @@ -101,6 +101,14 @@ def handle_interrupt

attr_reader :thread

def _pry_config
rymai marked this conversation as resolved.
Show resolved Hide resolved
Pry.config
end

def _pry_commands
rymai marked this conversation as resolved.
Show resolved Hide resolved
Pry.commands
end

def _switch_to_pry
th = nil
@mutex.synchronize do
Expand Down Expand Up @@ -131,11 +139,10 @@ def _kill_pry
end

def _setup(options)
Pry.config.should_load_rc = false
Pry.config.should_load_local_rc = false
history_file_path = options[:history_file] || HISTORY_FILE
Pry.config.history.file = File.expand_path(history_file_path)
_pry_config.should_load_rc = false
_pry_config.should_load_local_rc = false

_configure_history_file(options[:history_file] || HISTORY_FILE)
_add_hooks(options)

Commands::All.import
Expand All @@ -150,6 +157,17 @@ def _setup(options)
_configure_prompt
end

def _configure_history_file(history_file)
history_file_path = File.expand_path(history_file)

# Pry >= 0.13
if _pry_config.respond_to?(:history_file=)
rymai marked this conversation as resolved.
Show resolved Hide resolved
_pry_config.history_file = history_file_path
else
_pry_config.history.file = history_file_path
end
end

# Add Pry hooks:
#
# * Load `~/.guardrc` within each new Pry session.
Expand All @@ -165,23 +183,23 @@ def _add_hooks(options)
# Add a `when_started` hook that loads a global .guardrc if it exists.
#
def _add_load_guard_rc_hook(guard_rc)
Pry.config.hooks.add_hook :when_started, :load_guard_rc do
_pry_config.hooks.add_hook :when_started, :load_guard_rc do
guard_rc.expand_path.tap { |p| load p if p.exist? }
end
end

# Add a `when_started` hook that loads a project .guardrc if it exists.
#
def _add_load_project_guard_rc_hook(guard_rc)
Pry.config.hooks.add_hook :when_started, :load_project_guard_rc do
_pry_config.hooks.add_hook :when_started, :load_project_guard_rc do
load guard_rc if guard_rc.exist?
end
end

# Add a `after_eval` hook that restores visibility after a command is
# eval.
def _add_restore_visibility_hook
Pry.config.hooks.add_hook :after_eval, :restore_visibility do
_pry_config.hooks.add_hook :after_eval, :restore_visibility do
@terminal_settings.echo
end
end
Expand All @@ -198,7 +216,7 @@ def _setup_commands
# instead restarts guard.
#
def _replace_reset_command
Pry.commands.command "reset", "Reset the Guard to a clean state." do
_pry_commands.command "reset", "Reset the Guard to a clean state." do
output.puts "Guard reset."
exec "guard"
end
Expand All @@ -209,7 +227,7 @@ def _replace_reset_command
# beginning of a line).
#
def _create_run_all_command
Pry.commands.block_command(/^$/, "Hit enter to run all") do
_pry_commands.block_command(/^$/, "Hit enter to run all") do
Pry.run_command "all"
end
end
Expand All @@ -220,7 +238,7 @@ def _create_run_all_command
#
def _create_command_aliases
SHORTCUTS.each do |command, shortcut|
Pry.commands.alias_command shortcut, command.to_s
_pry_commands.alias_command shortcut, command.to_s
end
end

Expand All @@ -232,7 +250,7 @@ def _create_command_aliases
def _create_guard_commands
Guard.state.session.plugins.all.each do |guard_plugin|
cmd = "Run all #{guard_plugin.title}"
Pry.commands.create_command guard_plugin.name, cmd do
_pry_commands.create_command guard_plugin.name, cmd do
group "Guard"

def process # rubocop:disable Lint/NestedMethodDefinition
Expand All @@ -252,7 +270,7 @@ def _create_group_commands
next if group.name == :default

cmd = "Run all #{group.title}"
Pry.commands.create_command group.name.to_s, cmd do
_pry_commands.create_command group.name.to_s, cmd do
group "Guard"

def process # rubocop:disable Lint/NestedMethodDefinition
Expand All @@ -266,7 +284,15 @@ def process # rubocop:disable Lint/NestedMethodDefinition
# `pry`.
#
def _configure_prompt
Pry.config.prompt = [_prompt(">"), _prompt("*")]
prompt_procs = [_prompt(">"), _prompt("*")]
prompt =
if Pry::Prompt.is_a?(Class)
Pry::Prompt.new("Guard", "Guard Pry prompt", prompt_procs)
else
prompt_procs
end

_pry_config.prompt = prompt
end

# Returns the plugins scope, or the groups scope ready for display in the
Expand Down Expand Up @@ -295,12 +321,11 @@ def _clip_name(target)
end

def _history(pry)
# https://github.com/pry/pry/blob/5bf2585d0a49a4a3666a9eae80ee31153e3ffcf4/CHANGELOG.md#v0120-november-5-2018
if Gem::Version.new(Pry::VERSION) < Gem::Version.new("0.12.0")
return pry.input_array.size
if pry.respond_to?(:input_ring)
rymai marked this conversation as resolved.
Show resolved Hide resolved
pry.input_ring.size
else
pry.input_array.size
end

pry.input_ring.size
end
end
end
Expand Down
137 changes: 84 additions & 53 deletions spec/lib/guard/jobs/pry_wrapper_spec.rb
Expand Up @@ -5,10 +5,15 @@
RSpec.describe Guard::Jobs::PryWrapper do
subject { described_class.new({}) }
let(:listener) { instance_double("Listen::Listener") }
let(:pry_config) { double("pry_config") }
let(:pry_hooks) { double("pry_hooks", add_hook: true) }
let(:pry_config) do
double("pry_config", "history_file=" => true, command_prefix: true, "prompt=" => true, "should_load_rc=" => true,
"should_load_local_rc=" => true, hooks: pry_hooks)
end
let(:pry_history) { double("pry_history") }
let(:pry_commands) { double("pry_commands") }
let(:pry_hooks) { double("pry_hooks") }
let(:pry_commands) do
double("pry_commands", alias_command: true, create_command: true, command: true, block_command: true)
end
let(:terminal_settings) { instance_double("Guard::Jobs::TerminalSettings") }

let(:session) { instance_double("Guard::Internals::Session") }
Expand All @@ -18,22 +23,9 @@
let(:scope) { instance_double("Guard::Internals::Scope") }

before do
# TODO: this are here to mock out Pry completely
allow(pry_config).to receive(:prompt=)
allow(pry_config).to receive(:should_load_rc=)
allow(pry_config).to receive(:should_load_local_rc=)
allow(pry_config).to receive(:hooks).and_return(pry_hooks)
allow(pry_config).to receive(:history).and_return(pry_history)
allow(pry_config).to receive(:commands).and_return(pry_commands)
allow(pry_history).to receive(:file=)
allow(pry_commands).to receive(:alias_command)
allow(pry_commands).to receive(:create_command)
allow(pry_commands).to receive(:command)
allow(pry_commands).to receive(:block_command)
allow(pry_hooks).to receive(:add_hook)

allow(Guard).to receive(:listener).and_return(listener)
allow(Pry).to receive(:config).and_return(pry_config)
allow(Pry).to receive(:commands).and_return(pry_commands)
allow(Shellany::Sheller).to receive(:run).with("hash", "stty") { false }

allow(groups).to receive(:all).and_return([])
Expand Down Expand Up @@ -61,6 +53,30 @@
allow(terminal_settings).to receive(:restore)
end

describe "#_setup" do
context "Guard is using Pry >= 0.13" do
it "calls Pry.config.history_file=" do
expect(pry_config).to receive(:history_file=)

subject
end
end

context "Guard is using Pry < 0.13" do
let(:pry_config) do
double("pry_config", "history" => true, command_prefix: true, "prompt=" => true, "should_load_rc=" => true,
"should_load_local_rc=" => true, hooks: pry_hooks)
end

it "calls Pry.config.history.file=" do
expect(pry_config).to receive(:history).and_return(pry_history)
expect(pry_history).to receive(:file=)

subject
end
end
end

describe "#foreground" do
before do
allow(Pry).to receive(:start) do
Expand Down Expand Up @@ -136,60 +152,75 @@
allow(scope).to receive(:titles).and_return(["all"])

allow(listener).to receive(:paused?).and_return(false)

expect(Pry).to receive(:view_clip).and_return("main")
allow(Pry).to receive(:view_clip).and_return("main")
end

let(:pry) { instance_double(Pry, input_ring: []) }
context "Guard is using Pry >= 0.13" do
let(:pry) { double("Pry", input_ring: []) }
let(:pry_prompt) { double }

context "Guard is not paused" do
it 'displays "guard"' do
expect(prompt.call(double, 0, pry))
.to eq "[0] guard(main)> "
it "calls Pry::Prompt.new" do
expect(Pry::Prompt).to receive(:is_a?).with(Class).and_return(true)
expect(Pry::Prompt).to receive(:new).with("Guard", "Guard Pry prompt", an_instance_of(Array)).and_return(pry_prompt)
expect(pry_config).to receive(:prompt=).with(pry_prompt)

subject
end
end

context "Guard is using a lower version of Pry" do
let(:pry) { instance_double(Pry, input_array: []) }
context "Guard is not paused" do
it "displays 'guard'" do
expect(prompt.call(double, 0, pry))
.to eq "[0] guard(main)> "
end
end

it 'displays "guard"' do
stub_const("Pry::VERSION", "0.11.0")
context "Guard is paused" do
before do
allow(listener).to receive(:paused?).and_return(true)
end

expect(prompt.call(double, 0, pry))
.to eq "[0] guard(main)> "
it "displays 'pause'" do
expect(prompt.call(double, 0, pry))
.to eq "[0] pause(main)> "
end
end
end

context "Guard is paused" do
before do
allow(listener).to receive(:paused?).and_return(true)
end
context "with a groups scope" do
before do
allow(scope).to receive(:titles).and_return(%w[Backend Frontend])
end

it 'displays "pause"' do
expect(prompt.call(double, 0, pry))
.to eq "[0] pause(main)> "
it "displays the group scope title in the prompt" do
expect(prompt.call(double, 0, pry))
.to eq "[0] Backend,Frontend guard(main)> "
end
end
end

context "with a groups scope" do
before do
allow(scope).to receive(:titles).and_return(%w[Backend Frontend])
end
context "with a plugins scope" do
before do
allow(scope).to receive(:titles).and_return(%w[RSpec Ronn])
end

it "displays the group scope title in the prompt" do
expect(prompt.call(double, 0, pry))
.to eq "[0] Backend,Frontend guard(main)> "
it "displays the group scope title in the prompt" do
result = prompt.call(double, 0, pry)
expect(result).to eq "[0] RSpec,Ronn guard(main)> "
end
end
end

context "with a plugins scope" do
before do
allow(scope).to receive(:titles).and_return(%w[RSpec Ronn])
context "Guard is using Pry < 0.13" do
let(:pry) { double("Pry", input_array: []) }

it "does not call Pry::Prompt.new" do
expect(Pry::Prompt).to receive(:is_a?).with(Class).and_return(false)
expect(pry_config).to receive(:prompt=).with(an_instance_of(Array))

subject
end

it "displays the group scope title in the prompt" do
result = prompt.call(double, 0, pry)
expect(result).to eq "[0] RSpec,Ronn guard(main)> "
it "displays 'guard'" do
expect(prompt.call(double, 0, pry))
.to eq "[0] guard(main)> "
end
end
end
Expand Down