mirror of
https://github.com/pry/pry.git
synced 2022-11-09 12:35:05 -05:00
Merge branch 'master' into wip-config
Conflicts: Gemfile
This commit is contained in:
commit
283b85c9a1
8 changed files with 262 additions and 14 deletions
|
@ -40,6 +40,7 @@
|
||||||
being inferred from context (#877)
|
being inferred from context (#877)
|
||||||
* Rename `--installed-plugins` flag to `--plugins`
|
* Rename `--installed-plugins` flag to `--plugins`
|
||||||
* Strip ANSI codes from prompt before measuring length for indentation (#493)
|
* Strip ANSI codes from prompt before measuring length for indentation (#493)
|
||||||
|
* Fix bug in `edit` regarding recognition of file names without suffix.
|
||||||
|
|
||||||
#### Dev-facing changes
|
#### Dev-facing changes
|
||||||
* `rake pry` now accepts switches prefixed with `_` (e.g., `rake pry _v`)
|
* `rake pry` now accepts switches prefixed with `_` (e.g., `rake pry _v`)
|
||||||
|
|
4
Gemfile
4
Gemfile
|
@ -8,9 +8,7 @@ group :development do
|
||||||
gem 'rb-fsevent', :require => 'false'
|
gem 'rb-fsevent', :require => 'false'
|
||||||
end
|
end
|
||||||
|
|
||||||
gem 'binding.repl'
|
platform :rbx do
|
||||||
|
|
||||||
if RbConfig::CONFIG['ruby_install_name'] == 'rbx'
|
|
||||||
gem 'rubysl-singleton'
|
gem 'rubysl-singleton'
|
||||||
gem 'rubysl-prettyprint'
|
gem 'rubysl-prettyprint'
|
||||||
gem 'rb-readline'
|
gem 'rb-readline'
|
||||||
|
|
|
@ -186,7 +186,7 @@ class Pry
|
||||||
end
|
end
|
||||||
|
|
||||||
def probably_a_file?(str)
|
def probably_a_file?(str)
|
||||||
[".rb", ".c", ".py", ".yml", ".gemspec"].include? File.extname(str) ||
|
[".rb", ".c", ".py", ".yml", ".gemspec"].include?(File.extname(str)) ||
|
||||||
str =~ /\/|\\/
|
str =~ /\/|\\/
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -29,34 +29,32 @@ class Pry
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
def greppable
|
def grep(entity)
|
||||||
proc do |entity|
|
|
||||||
entity.tap { |o| o.grep = @grep }
|
entity.tap { |o| o.grep = @grep }
|
||||||
end
|
end
|
||||||
end
|
|
||||||
|
|
||||||
def globals
|
def globals
|
||||||
greppable.call(Globals.new(@target, @opts))
|
grep(Globals.new(@target, @opts))
|
||||||
end
|
end
|
||||||
|
|
||||||
def constants
|
def constants
|
||||||
greppable.call(Constants.new(@interrogatee, @target, @no_user_opts, @opts))
|
grep(Constants.new(@interrogatee, @target, @no_user_opts, @opts))
|
||||||
end
|
end
|
||||||
|
|
||||||
def methods
|
def methods
|
||||||
greppable.call(Methods.new(@interrogatee, @no_user_opts, @opts))
|
grep(Methods.new(@interrogatee, @no_user_opts, @opts))
|
||||||
end
|
end
|
||||||
|
|
||||||
def self_methods
|
def self_methods
|
||||||
greppable.call(SelfMethods.new(@interrogatee, @no_user_opts, @opts))
|
grep(SelfMethods.new(@interrogatee, @no_user_opts, @opts))
|
||||||
end
|
end
|
||||||
|
|
||||||
def instance_vars
|
def instance_vars
|
||||||
greppable.call(InstanceVars.new(@interrogatee, @no_user_opts, @opts))
|
grep(InstanceVars.new(@interrogatee, @no_user_opts, @opts))
|
||||||
end
|
end
|
||||||
|
|
||||||
def local_names
|
def local_names
|
||||||
greppable.call(LocalNames.new(@target, @no_user_opts, @sticky_locals, @args))
|
grep(LocalNames.new(@target, @no_user_opts, @sticky_locals, @args))
|
||||||
end
|
end
|
||||||
|
|
||||||
def local_vars
|
def local_vars
|
||||||
|
|
94
lib/pry/commands/watch_expression.rb
Normal file
94
lib/pry/commands/watch_expression.rb
Normal file
|
@ -0,0 +1,94 @@
|
||||||
|
class Pry
|
||||||
|
class Command::WatchExpression < Pry::ClassCommand
|
||||||
|
require 'pry/commands/watch_expression/expression.rb'
|
||||||
|
|
||||||
|
match 'watch'
|
||||||
|
group 'Context'
|
||||||
|
description 'Evaluate an expression after every command and display it when its value changes.'
|
||||||
|
command_options :use_prefix => false
|
||||||
|
|
||||||
|
banner <<-'BANNER'
|
||||||
|
Usage: watch [EXPRESSION]
|
||||||
|
watch
|
||||||
|
watch --delete [INDEX]
|
||||||
|
|
||||||
|
Evaluate an expression after every command and display it when its value changes.
|
||||||
|
BANNER
|
||||||
|
|
||||||
|
def options(opt)
|
||||||
|
opt.on :d, :delete,
|
||||||
|
"Delete the watch expression with the given index. If no index is given; clear all watch expressions.",
|
||||||
|
:optional_argument => true, :as => Integer
|
||||||
|
opt.on :l, :list,
|
||||||
|
"Show all current watch expressions and their values. Calling watch with no expressions or options will also show the watch expressions."
|
||||||
|
end
|
||||||
|
|
||||||
|
def process
|
||||||
|
case
|
||||||
|
when opts.present?(:delete)
|
||||||
|
delete opts[:delete]
|
||||||
|
when opts.present?(:list) || args.empty?
|
||||||
|
list
|
||||||
|
else
|
||||||
|
add_hook
|
||||||
|
add_expression(args)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
def expressions
|
||||||
|
Pry.config.watch_expressions ||= []
|
||||||
|
end
|
||||||
|
|
||||||
|
def delete(index)
|
||||||
|
if index
|
||||||
|
output.puts "Deleting watch expression ##{index}: #{expressions[index-1]}"
|
||||||
|
expressions.delete_at(index-1)
|
||||||
|
else
|
||||||
|
output.puts "Deleting all watched expressions"
|
||||||
|
expressions.clear
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def list
|
||||||
|
if expressions.empty?
|
||||||
|
output.puts "No watched expressions"
|
||||||
|
else
|
||||||
|
Pry::Pager.with_pager(output) do |pager|
|
||||||
|
pager.puts "Listing all watched expressions:"
|
||||||
|
pager.puts ""
|
||||||
|
expressions.each_with_index do |expr, index|
|
||||||
|
pager.print text.with_line_numbers(expr.to_s, index+1)
|
||||||
|
end
|
||||||
|
pager.puts ""
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def eval_and_print_changed(output)
|
||||||
|
expressions.each do |expr|
|
||||||
|
expr.eval!
|
||||||
|
if expr.changed?
|
||||||
|
output.puts "#{text.blue "watch"}: #{expr.to_s}"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def add_expression(arguments)
|
||||||
|
expressions << Expression.new(target, arg_string)
|
||||||
|
output.puts "Watching #{Code.new(arg_string)}"
|
||||||
|
end
|
||||||
|
|
||||||
|
def add_hook
|
||||||
|
hook = [:after_eval, :watch_expression]
|
||||||
|
unless Pry.hooks.hook_exists?(*hook)
|
||||||
|
Pry.hooks.add_hook(*hook) do |_, _pry_|
|
||||||
|
eval_and_print_changed _pry_.output
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
Pry::Commands.add_command(Pry::Command::WatchExpression)
|
||||||
|
end
|
41
lib/pry/commands/watch_expression/expression.rb
Normal file
41
lib/pry/commands/watch_expression/expression.rb
Normal file
|
@ -0,0 +1,41 @@
|
||||||
|
class Pry
|
||||||
|
class Command::WatchExpression
|
||||||
|
class Expression
|
||||||
|
attr_reader :target, :source, :value, :previous_value
|
||||||
|
|
||||||
|
def initialize(target, source)
|
||||||
|
@target = target
|
||||||
|
@source = source
|
||||||
|
end
|
||||||
|
|
||||||
|
def eval!
|
||||||
|
@previous_value = value
|
||||||
|
@value = target_eval(target, source)
|
||||||
|
end
|
||||||
|
|
||||||
|
def to_s
|
||||||
|
"#{print_source} => #{print_value}"
|
||||||
|
end
|
||||||
|
|
||||||
|
def changed?
|
||||||
|
(value != previous_value)
|
||||||
|
end
|
||||||
|
|
||||||
|
def print_value
|
||||||
|
Pry::ColorPrinter.pp(value, "")
|
||||||
|
end
|
||||||
|
|
||||||
|
def print_source
|
||||||
|
Code.new(source).strip
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
def target_eval(target, source)
|
||||||
|
target.eval(source)
|
||||||
|
rescue => e
|
||||||
|
e
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
|
@ -35,6 +35,16 @@ describe "edit" do
|
||||||
FileUtils.rm(@tf_path) if File.exists?(@tf_path)
|
FileUtils.rm(@tf_path) if File.exists?(@tf_path)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
it "should not allow patching any known kind of file" do
|
||||||
|
["file.rb", "file.c", "file.py", "file.yml", "file.gemspec",
|
||||||
|
"/tmp/file", "\\\\Temp\\\\file"].each do |file|
|
||||||
|
proc {
|
||||||
|
pry_eval "edit -p #{file}"
|
||||||
|
}.should.raise(NotImplementedError).
|
||||||
|
message.should =~ /Cannot yet patch false objects!/
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
it "should invoke Pry.config.editor with absolutified filenames" do
|
it "should invoke Pry.config.editor with absolutified filenames" do
|
||||||
pry_eval 'edit lib/pry.rb'
|
pry_eval 'edit lib/pry.rb'
|
||||||
@file.should == File.expand_path('lib/pry.rb')
|
@file.should == File.expand_path('lib/pry.rb')
|
||||||
|
|
106
spec/commands/watch_expression_spec.rb
Normal file
106
spec/commands/watch_expression_spec.rb
Normal file
|
@ -0,0 +1,106 @@
|
||||||
|
require 'helper'
|
||||||
|
|
||||||
|
describe "watch expression" do
|
||||||
|
|
||||||
|
# Custom eval that will:
|
||||||
|
# 1) Create an instance of pry that can use for multiple calls
|
||||||
|
# 2) Exercise the after_eval hook
|
||||||
|
# 3) Return the output
|
||||||
|
def eval(expr)
|
||||||
|
output = @tester.eval expr
|
||||||
|
@tester.pry.hooks.exec_hook :after_eval, nil, @tester.pry
|
||||||
|
output
|
||||||
|
end
|
||||||
|
|
||||||
|
before do
|
||||||
|
@tester = pry_tester
|
||||||
|
@tester.pry.hooks.clear :after_eval
|
||||||
|
eval "watch --delete"
|
||||||
|
end
|
||||||
|
|
||||||
|
it "registers the after_eval hook" do
|
||||||
|
eval 'watch 1+1'
|
||||||
|
@tester.pry.hooks.hook_exists?(:after_eval, :watch_expression).should == true
|
||||||
|
end
|
||||||
|
|
||||||
|
it "prints no watched expressions" do
|
||||||
|
eval('watch').should =~ /No watched expressions/
|
||||||
|
end
|
||||||
|
|
||||||
|
it "watches an expression" do
|
||||||
|
eval "watch 1+1"
|
||||||
|
eval('watch').should =~ /=> 2/
|
||||||
|
end
|
||||||
|
|
||||||
|
it "watches a local variable" do
|
||||||
|
eval 'foo = :bar'
|
||||||
|
eval 'watch foo'
|
||||||
|
eval('watch').should =~ /=> :bar/
|
||||||
|
end
|
||||||
|
|
||||||
|
it "prints when an expression changes" do
|
||||||
|
ReplTester.start do
|
||||||
|
input 'a = 1'
|
||||||
|
output '=> 1'
|
||||||
|
|
||||||
|
input 'watch a'
|
||||||
|
output "Watching a\nwatch: a => 1"
|
||||||
|
|
||||||
|
input "a = 2"
|
||||||
|
output "watch: a => 2\n=> 2"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
it "doesn't print when an expresison remains the same" do
|
||||||
|
ReplTester.start do
|
||||||
|
input 'a = 1'
|
||||||
|
output '=> 1'
|
||||||
|
|
||||||
|
input 'watch a'
|
||||||
|
output "Watching a\nwatch: a => 1"
|
||||||
|
|
||||||
|
input "a = 1"
|
||||||
|
output "=> 1"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
it "continues to work if you start a second pry instance" do
|
||||||
|
ReplTester.start do
|
||||||
|
input 'a = 1'
|
||||||
|
output '=> 1'
|
||||||
|
|
||||||
|
input 'watch a'
|
||||||
|
output "Watching a\nwatch: a => 1"
|
||||||
|
|
||||||
|
input "a = 2"
|
||||||
|
output "watch: a => 2\n=> 2"
|
||||||
|
end
|
||||||
|
|
||||||
|
ReplTester.start do
|
||||||
|
input 'b = 1'
|
||||||
|
output '=> 1'
|
||||||
|
|
||||||
|
input 'watch b'
|
||||||
|
output "Watching b\nwatch: b => 1"
|
||||||
|
|
||||||
|
input "b = 2"
|
||||||
|
output "watch: b => 2\n=> 2"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe "deleting expressions" do
|
||||||
|
before do
|
||||||
|
eval 'watch :keeper'
|
||||||
|
eval 'watch :delete'
|
||||||
|
eval 'watch -d 2'
|
||||||
|
end
|
||||||
|
|
||||||
|
it "keeps keeper" do
|
||||||
|
eval('watch').should =~ /keeper/
|
||||||
|
end
|
||||||
|
|
||||||
|
it "deletes delete" do
|
||||||
|
eval('watch').should.not =~ /delete/
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
Loading…
Reference in a new issue