Merge pull request #1117 from pry/lazy-readline

lazy load readline through Proc defined on Pry::Config::Default.
This commit is contained in:
Robert 2014-02-03 05:22:27 -08:00
commit e054af7468
11 changed files with 96 additions and 37 deletions

View File

@ -8,6 +8,10 @@ rvm:
- jruby-19mode
- jruby-head
script:
- rake spec
- bundle exec bacon spec/isolation/readline_spec.rb
matrix:
allow_failures:
- rvm: ruby-head

View File

@ -21,7 +21,8 @@
* User can whitelist objects whose inspect output should appear in prompt (#885)
* See `Pry.config.prompt_safe_objects`
* `whereami` is now aliased to `@`
* improve configuration(Pry.config) to lazy-load default configuration values. (#1096)
* default configuration(Pry.config) lazy loads its values. (#1096)
* require of 'readline' is delayed until Pry.start() has been called for the first time. (#1117)
#### Bug fixes, etc.
* `binding.pry` inside `.pryrc` file now works, with some limitations (@richo / #1118)

View File

@ -42,7 +42,7 @@ task :test do
if explicit_list = ENV['run']
explicit_list.split(',')
else
Dir['spec/**/*_spec.rb'].shuffle!
(Dir['spec/**/*_spec.rb'] - Dir["spec/isolation/*_spec.rb"]).shuffle!
end
run_specs paths
end

View File

@ -132,19 +132,13 @@ require 'rbconfig'
require 'tempfile'
require 'pathname'
begin
require 'readline'
rescue LoadError
warn "You're running a version of ruby with no Readline support"
warn "Please `gem install rb-readline` or recompile ruby --with-readline."
exit!
end
if Pry::Helpers::BaseHelpers.jruby?
begin
require 'ffi'
rescue LoadError
warn "Need to `gem install ffi`"
# TODO: Why do we need this?
warn "For a better Pry experience on JRuby, please `gem install ffi`."
end
end
@ -155,7 +149,8 @@ if Pry::Helpers::BaseHelpers.windows? && !Pry::Helpers::BaseHelpers.windows_ansi
# only fail on jruby (where win32console doesn't work).
# Instead we'll recommend ansicon, which does.
rescue LoadError
warn "For a better pry experience, please use ansicon: https://github.com/adoxa/ansicon"
warn "For a better Pry experience on Windows, please use ansicon:"
warn " http://adoxa.3eeweb.com/ansicon/"
end
end

View File

@ -2,7 +2,7 @@ class Pry::Config::Default
include Pry::Config::Behavior
default = {
:input => proc { Readline },
:input => proc { lazy_readline },
:output => proc { $stdout },
:commands => proc { Pry::Commands },
:prompt_name => proc { Pry::DEFAULT_PROMPT_NAME },
@ -35,13 +35,7 @@ class Pry::Config::Default
:extra_sticky_locals => proc { {} },
:command_completer => proc { proc { Pry.commands.commands.keys } },
:file_completer => proc { proc { Dir["."] } },
:completer => proc {
if defined?(Bond) && Readline::VERSION !~ /editline/i
Pry::BondCompleter.start
else
Pry::InputCompleter.start
end
}
:completer => proc { lazy_completer }
}
def initialize
@ -54,13 +48,14 @@ class Pry::Config::Default
default.each do |key, value|
define_method(key) do
if default[key].equal?(value)
default[key] = value.call
default[key] = instance_eval(&value)
end
default[key]
end
end
private
# TODO:
# all of this configure_* stuff is a relic of old code.
# we should try move this code to being command-local.
@ -101,4 +96,28 @@ private
history.should_load = false
end
end
def lazy_readline
require 'readline'
Readline
rescue LoadError
warn "Sorry, you can't use Pry without Readline or a compatible library."
warn "Possible solutions:"
warn " * Rebuild Ruby with Readline support using `--with-readline`"
warn " * Use the rb-readline gem, which is a pure-Ruby port of Readline"
warn " * Use the pry-coolline gem, a pure-ruby alternative to Readline"
raise
end
def lazy_completer
if defined?(Bond) && !is_editline?(input)
Pry::BondCompleter.start
else
Pry::InputCompleter.start
end
end
def is_editline?(input)
defined?(input::VERSION) && input::VERSION =~ /editline/i
end
end

View File

@ -2,7 +2,6 @@ class Pry
# The History class is responsible for maintaining the user's input history,
# both internally and within Readline.
class History
attr_accessor :loader, :saver, :pusher, :clearer
# @return [Fixnum] Number of lines in history when Pry first loaded.
@ -17,10 +16,18 @@ class Pry
# Assign the default methods for loading, saving, pushing, and clearing.
def restore_default_behavior
@loader = method(:read_from_file)
@saver = method(:save_to_file)
@pusher = method(:push_to_readline)
@clearer = method(:clear_readline)
Pry.config.input # force Readline to load if applicable
@loader = method(:read_from_file)
@saver = method(:save_to_file)
if defined?(Readline)
@pusher = method(:push_to_readline)
@clearer = method(:clear_readline)
else
@pusher = proc { }
@clearer = proc { }
end
end
# Load the input history using `History.loader`.

View File

@ -10,11 +10,11 @@ class Pry
attr_accessor :current_line
attr_accessor :line_buffer
attr_accessor :eval_path
attr_accessor :history
attr_accessor :cli
attr_accessor :quiet
attr_accessor :last_internal_error
attr_accessor :config
attr_writer :history
def_delegators :@plugin_manager, :plugins, :load_plugins, :locate_plugins
@ -28,6 +28,10 @@ class Pry
def prompt
config.prompt
end
def history
@history ||= History.new
end
end
def self.main
@ -233,15 +237,22 @@ class Pry
end
def self.auto_resize!
ver = Readline::VERSION
if ver[/edit/i]
Pry.config.input # by default, load Readline
if !defined?(Readline) || Pry.config.input != Readline
warn "Sorry, you must be using Readline for Pry.auto_resize! to work."
return
end
if Readline::VERSION =~ /edit/i
warn <<-EOT
Readline version #{ver} detected - will not auto_resize! correctly.
Readline version #{Readline::VERSION} detected - will not auto_resize! correctly.
For the fix, use GNU Readline instead:
https://github.com/guard/guard/wiki/Add-proper-Readline-support-to-Ruby-on-Mac-OS-X
EOT
return
end
trap :WINCH do
begin
Readline.set_screen_size(*Terminal.size!)
@ -269,7 +280,6 @@ Readline version #{ver} detected - will not auto_resize! correctly.
# Basic initialization.
def self.init
@plugin_manager ||= PluginManager.new
self.history ||= History.new
reset_defaults
locate_plugins
end

View File

@ -179,7 +179,7 @@ class Pry
end
end
if input == Readline
if defined?(Readline) and input == Readline
input_readline(current_prompt, false) # false since we'll add it manually
elsif defined? Coolline and input.is_a? Coolline
input_readline(current_prompt)

View File

@ -54,7 +54,7 @@ class Pry::Terminal
end
def screen_size_according_to_readline
if Readline.respond_to?(:get_screen_size)
if defined?(Readline) && Readline.respond_to?(:get_screen_size)
size = Readline.get_screen_size
size if nonzero_column?(size)
end

View File

@ -6,16 +6,22 @@ def completer_test(bind, pry=nil, assert_flag=true)
return proc {|*symbols| symbols.each(&test) }
end
if defined?(Bond) && Readline::VERSION !~ /editline/i
describe 'bond-based completion' do
it 'should pull in Bond by default' do
Pry.config.completer.should == Pry::BondCompleter
describe 'Bond-based completion' do
before do
@local = Pry::Config.new Pry::Config::Default.new
@local.completer
end
it "should use Bond if it's available" do
if defined?(Bond) && defined?(Readline) && Readline::VERSION !~ /editline/i
@local.completer.should == Pry::BondCompleter
else
@local.completer.should == Pry::InputCompleter
end
end
end
describe Pry::InputCompleter do
before do
# The AMQP gem has some classes like this:
# pry(main)> AMQP::Protocol::Test::ContentOk.name

View File

@ -0,0 +1,17 @@
require "bundler/setup"
require "bacon"
describe "Readline" do
describe "on require of 'pry'" do
it "is not made available" do
require('pry').should.be.true
defined?(Readline).should.be.nil
end
end
describe "on invoke of 'pry'" do
it "is made available" do
Pry.start self, input: StringIO.new("exit-all\n"), output: StringIO.new
defined?(Readline).should == "constant"
end
end
end