1
0
Fork 0
mirror of https://github.com/pry/pry.git synced 2022-11-09 12:35:05 -05:00

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-19mode
- jruby-head - jruby-head
script:
- rake spec
- bundle exec bacon spec/isolation/readline_spec.rb
matrix: matrix:
allow_failures: allow_failures:
- rvm: ruby-head - rvm: ruby-head

View file

@ -21,7 +21,8 @@
* User can whitelist objects whose inspect output should appear in prompt (#885) * User can whitelist objects whose inspect output should appear in prompt (#885)
* See `Pry.config.prompt_safe_objects` * See `Pry.config.prompt_safe_objects`
* `whereami` is now aliased to `@` * `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. #### Bug fixes, etc.
* `binding.pry` inside `.pryrc` file now works, with some limitations (@richo / #1118) * `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'] if explicit_list = ENV['run']
explicit_list.split(',') explicit_list.split(',')
else else
Dir['spec/**/*_spec.rb'].shuffle! (Dir['spec/**/*_spec.rb'] - Dir["spec/isolation/*_spec.rb"]).shuffle!
end end
run_specs paths run_specs paths
end end

View file

@ -132,19 +132,13 @@ require 'rbconfig'
require 'tempfile' require 'tempfile'
require 'pathname' 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? if Pry::Helpers::BaseHelpers.jruby?
begin begin
require 'ffi' require 'ffi'
rescue LoadError 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
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). # only fail on jruby (where win32console doesn't work).
# Instead we'll recommend ansicon, which does. # Instead we'll recommend ansicon, which does.
rescue LoadError 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
end end

View file

@ -2,7 +2,7 @@ class Pry::Config::Default
include Pry::Config::Behavior include Pry::Config::Behavior
default = { default = {
:input => proc { Readline }, :input => proc { lazy_readline },
:output => proc { $stdout }, :output => proc { $stdout },
:commands => proc { Pry::Commands }, :commands => proc { Pry::Commands },
:prompt_name => proc { Pry::DEFAULT_PROMPT_NAME }, :prompt_name => proc { Pry::DEFAULT_PROMPT_NAME },
@ -35,13 +35,7 @@ class Pry::Config::Default
:extra_sticky_locals => proc { {} }, :extra_sticky_locals => proc { {} },
:command_completer => proc { proc { Pry.commands.commands.keys } }, :command_completer => proc { proc { Pry.commands.commands.keys } },
:file_completer => proc { proc { Dir["."] } }, :file_completer => proc { proc { Dir["."] } },
:completer => proc { :completer => proc { lazy_completer }
if defined?(Bond) && Readline::VERSION !~ /editline/i
Pry::BondCompleter.start
else
Pry::InputCompleter.start
end
}
} }
def initialize def initialize
@ -54,13 +48,14 @@ class Pry::Config::Default
default.each do |key, value| default.each do |key, value|
define_method(key) do define_method(key) do
if default[key].equal?(value) if default[key].equal?(value)
default[key] = value.call default[key] = instance_eval(&value)
end end
default[key] default[key]
end end
end end
private private
# TODO: # TODO:
# all of this configure_* stuff is a relic of old code. # all of this configure_* stuff is a relic of old code.
# we should try move this code to being command-local. # we should try move this code to being command-local.
@ -101,4 +96,28 @@ private
history.should_load = false history.should_load = false
end end
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 end

View file

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

View file

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

View file

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

View file

@ -54,7 +54,7 @@ class Pry::Terminal
end end
def screen_size_according_to_readline 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 = Readline.get_screen_size
size if nonzero_column?(size) size if nonzero_column?(size)
end end

View file

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