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)
|
||||
* Rename `--installed-plugins` flag to `--plugins`
|
||||
* 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
|
||||
* `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'
|
||||
end
|
||||
|
||||
gem 'binding.repl'
|
||||
|
||||
if RbConfig::CONFIG['ruby_install_name'] == 'rbx'
|
||||
platform :rbx do
|
||||
gem 'rubysl-singleton'
|
||||
gem 'rubysl-prettyprint'
|
||||
gem 'rb-readline'
|
||||
|
|
|
@ -186,7 +186,7 @@ class Pry
|
|||
end
|
||||
|
||||
def probably_a_file?(str)
|
||||
[".rb", ".c", ".py", ".yml", ".gemspec"].include? File.extname(str) ||
|
||||
[".rb", ".c", ".py", ".yml", ".gemspec"].include?(File.extname(str)) ||
|
||||
str =~ /\/|\\/
|
||||
end
|
||||
|
||||
|
|
|
@ -29,34 +29,32 @@ class Pry
|
|||
|
||||
private
|
||||
|
||||
def greppable
|
||||
proc do |entity|
|
||||
entity.tap { |o| o.grep = @grep }
|
||||
end
|
||||
def grep(entity)
|
||||
entity.tap { |o| o.grep = @grep }
|
||||
end
|
||||
|
||||
def globals
|
||||
greppable.call(Globals.new(@target, @opts))
|
||||
grep(Globals.new(@target, @opts))
|
||||
end
|
||||
|
||||
def constants
|
||||
greppable.call(Constants.new(@interrogatee, @target, @no_user_opts, @opts))
|
||||
grep(Constants.new(@interrogatee, @target, @no_user_opts, @opts))
|
||||
end
|
||||
|
||||
def methods
|
||||
greppable.call(Methods.new(@interrogatee, @no_user_opts, @opts))
|
||||
grep(Methods.new(@interrogatee, @no_user_opts, @opts))
|
||||
end
|
||||
|
||||
def self_methods
|
||||
greppable.call(SelfMethods.new(@interrogatee, @no_user_opts, @opts))
|
||||
grep(SelfMethods.new(@interrogatee, @no_user_opts, @opts))
|
||||
end
|
||||
|
||||
def instance_vars
|
||||
greppable.call(InstanceVars.new(@interrogatee, @no_user_opts, @opts))
|
||||
grep(InstanceVars.new(@interrogatee, @no_user_opts, @opts))
|
||||
end
|
||||
|
||||
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
|
||||
|
||||
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)
|
||||
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
|
||||
pry_eval 'edit 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