This commit is contained in:
@@ -0,0 +1,108 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
class Pry
|
||||
class Command
|
||||
class WatchExpression < Pry::ClassCommand
|
||||
match 'watch'
|
||||
group 'Context'
|
||||
description 'Watch the value of an expression and print a notification ' \
|
||||
'whenever it changes.'
|
||||
command_options use_prefix: false, state: %i[watch_expressions]
|
||||
|
||||
banner <<-'BANNER'
|
||||
Usage: watch [EXPRESSION]
|
||||
watch
|
||||
watch --delete [INDEX]
|
||||
|
||||
watch [EXPRESSION] adds an expression to the list of those being watched.
|
||||
It will be re-evaluated every time you hit enter in pry. If its value has
|
||||
changed, the new value will be printed to the console.
|
||||
|
||||
This is useful if you are step-through debugging and want to see how
|
||||
something changes over time. It's also useful if you're trying to write
|
||||
a method inside pry and want to check that it gives the right answers
|
||||
every time you redefine it.
|
||||
|
||||
watch on its own displays all the currently watched expressions and their
|
||||
values, and watch --delete [INDEX] allows you to delete expressions from
|
||||
the list being watched.
|
||||
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
|
||||
if opts.present?(:delete)
|
||||
delete opts[:delete]
|
||||
elsif opts.present?(:list) || args.empty?
|
||||
list
|
||||
else
|
||||
add_hook
|
||||
add_expression
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def expressions
|
||||
state.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_instance.pager.open do |pager|
|
||||
pager.puts "Listing all watched expressions:"
|
||||
pager.puts ""
|
||||
expressions.each_with_index do |expr, index|
|
||||
pager.print 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!
|
||||
output.puts "#{blue 'watch'}: #{expr}" if expr.changed?
|
||||
end
|
||||
end
|
||||
|
||||
def add_expression
|
||||
expressions << Expression.new(pry_instance, target, arg_string)
|
||||
output.puts "Watching #{Code.new(arg_string).highlighted}"
|
||||
end
|
||||
|
||||
def add_hook
|
||||
hook = %i[after_eval watch_expression]
|
||||
return if pry_instance.hooks.hook_exists?(*hook)
|
||||
|
||||
pry_instance.hooks.add_hook(*hook) do |_, pry_instance|
|
||||
eval_and_print_changed pry_instance.output
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
Pry::Commands.add_command(Pry::Command::WatchExpression)
|
||||
end
|
||||
end
|
||||
Reference in New Issue
Block a user