mirror of
https://github.com/pry/pry.git
synced 2022-11-09 12:35:05 -05:00
use exceptions to handle command errors
This commit is contained in:
parent
10bf1bcd95
commit
a53fe2c5d1
14 changed files with 117 additions and 68 deletions
|
@ -144,6 +144,10 @@ class Pry
|
|||
end
|
||||
end
|
||||
|
||||
# CommandErrors are caught by the REPL loop and displayed to the user. They
|
||||
# indicate an exceptional condition that's fatal to the current command.
|
||||
class CommandError < StandardError
|
||||
end
|
||||
end
|
||||
|
||||
require "method_source"
|
||||
|
|
|
@ -21,20 +21,19 @@ class Pry
|
|||
end
|
||||
|
||||
command "import-set", "Import a command set" do |command_set_name|
|
||||
next output.puts "Provide a command set name" if command_set.nil?
|
||||
raise CommandError, "Provide a command set name" if command_set.nil?
|
||||
|
||||
set = target.eval(arg_string)
|
||||
_pry_.commands.import set
|
||||
end
|
||||
|
||||
command "reload-method", "Reload the source file that contains the specified method" do |meth_name|
|
||||
meth = get_method_or_print_error(meth_name, target, {}, :omit_help)
|
||||
next unless meth
|
||||
meth = get_method_or_raise(meth_name, target, {}, :omit_help)
|
||||
|
||||
if meth.source_type == :c
|
||||
output.puts "Error: Can't reload a C method."
|
||||
raise CommandError, "Can't reload a C method."
|
||||
elsif meth.dynamically_defined?
|
||||
output.puts "Error: Can't reload an eval method."
|
||||
raise CommandError, "Can't reload an eval method."
|
||||
else
|
||||
file_name = meth.source_file
|
||||
load file_name
|
||||
|
|
|
@ -49,7 +49,7 @@ class Pry
|
|||
selection = selection.to_i
|
||||
|
||||
if selection < 0 || selection > _pry_.binding_stack.size - 1
|
||||
output.puts "Invalid binding index #{selection} - use `nesting` command to view valid indices."
|
||||
raise CommandError, "Invalid binding index #{selection} - use `nesting` command to view valid indices."
|
||||
else
|
||||
Pry.start(_pry_.binding_stack[selection])
|
||||
end
|
||||
|
@ -143,16 +143,14 @@ class Pry
|
|||
end
|
||||
|
||||
if file =~ /(\(.*\))|<.*>/ || file == "" || file == "-e"
|
||||
output.puts "Cannot find local context. Did you use `binding.pry` ?"
|
||||
next
|
||||
raise CommandError, "Cannot find local context. Did you use `binding.pry`?"
|
||||
end
|
||||
|
||||
set_file_and_dir_locals(file)
|
||||
output.puts "\n#{text.bold('From:')} #{file} @ line #{line_num} in #{klass}##{meth_name}:\n\n"
|
||||
|
||||
unless File.readable?(file)
|
||||
output.puts "Cannot open #{file.inspect} for reading."
|
||||
next
|
||||
raise CommandError, "Cannot open #{file.inspect} for reading."
|
||||
end
|
||||
|
||||
# This method inspired by http://rubygems.org/gems/ir_b
|
||||
|
|
|
@ -32,8 +32,12 @@ class Pry
|
|||
|
||||
args = [nil] if args.empty?
|
||||
args.each do |method_name|
|
||||
meth = get_method_or_print_error(method_name, target, opts.to_hash(true))
|
||||
next unless meth
|
||||
begin
|
||||
meth = get_method_or_raise(method_name, target, opts.to_hash(true))
|
||||
rescue CommandError => e
|
||||
puts "\nError: #{e.message}"
|
||||
next
|
||||
end
|
||||
|
||||
next output.puts("No documentation found.") if meth.doc.nil? || meth.doc.empty?
|
||||
|
||||
|
@ -71,8 +75,7 @@ class Pry
|
|||
|
||||
next if opts.help?
|
||||
|
||||
meth = get_method_or_print_error(args.shift, target, opts.to_hash(true))
|
||||
next unless meth
|
||||
meth = get_method_or_raise(args.shift, target, opts.to_hash(true))
|
||||
|
||||
output.puts unindent <<-EOS
|
||||
Method Information:
|
||||
|
@ -111,8 +114,7 @@ class Pry
|
|||
|
||||
next if opts.help?
|
||||
|
||||
meth = get_method_or_print_error(args.shift, target, opts.to_hash(true))
|
||||
next unless meth
|
||||
meth = get_method_or_raise(args.shift, target, opts.to_hash(true))
|
||||
|
||||
type_map = { :ruby => "rb", :c => "c", :plain => "plain" }
|
||||
if !opts.doc?
|
||||
|
|
|
@ -9,9 +9,9 @@ class Pry
|
|||
installer = Gem::DependencyInstaller.new :install_dir => destination
|
||||
installer.install gem
|
||||
rescue Errno::EACCES
|
||||
output.puts "Insufficient permissions to install `#{text.green gem}`"
|
||||
raise CommandError, "Insufficient permissions to install `#{text.green gem}`."
|
||||
rescue Gem::GemNotFoundException
|
||||
output.puts "Gem `#{text.green gem}` not found."
|
||||
raise CommandError, "Gem `#{text.green gem}` not found."
|
||||
else
|
||||
Gem.refresh
|
||||
output.puts "Gem `#{text.green gem}` installed."
|
||||
|
@ -21,7 +21,11 @@ class Pry
|
|||
command "gem-cd", "Change working directory to specified gem's directory.", :argument_required => true do |gem|
|
||||
specs = Gem::Specification.respond_to?(:each) ? Gem::Specification.find_all_by_name(gem) : Gem.source_index.find_name(gem)
|
||||
spec = specs.sort { |a,b| Gem::Version.new(b.version) <=> Gem::Version.new(a.version) }.first
|
||||
spec ? Dir.chdir(spec.full_gem_path) : output.puts("Gem `#{gem}` not found.")
|
||||
if spec
|
||||
Dir.chdir(spec.full_gem_path)
|
||||
else
|
||||
raise CommandError, "Gem `#{gem}` not found."
|
||||
end
|
||||
end
|
||||
|
||||
command "gem-list", "List/search installed gems. (Optional parameter: a regexp to limit the search)" do |pattern|
|
||||
|
|
|
@ -33,7 +33,10 @@ class Pry
|
|||
end
|
||||
|
||||
next if opts.h?
|
||||
next output.puts "No input to amend." if eval_string.empty?
|
||||
|
||||
if eval_string.empty?
|
||||
raise CommandError, "No input to amend."
|
||||
end
|
||||
|
||||
replacement_line = "" if !replacement_line
|
||||
input_array = eval_string.each_line.to_a
|
||||
|
@ -77,8 +80,8 @@ class Pry
|
|||
|
||||
if opts.m?
|
||||
meth_name = opts[:m]
|
||||
meth = get_method_or_print_error(meth_name, target, {}, :omit_help)
|
||||
next unless meth and meth.source
|
||||
meth = get_method_or_raise(meth_name, target, {}, :omit_help)
|
||||
next unless meth.source
|
||||
|
||||
range = opts.l? ? one_index_range_or_number(opts[:l]) : (0..-1)
|
||||
range = (0..-2) if opts.o?
|
||||
|
@ -86,7 +89,11 @@ class Pry
|
|||
eval_string << Array(meth.source.each_line.to_a[range]).join
|
||||
elsif opts.f?
|
||||
file_name = File.expand_path(opts[:f])
|
||||
next output.puts "No such file: #{opts[:f]}" if !File.exists?(file_name)
|
||||
|
||||
if !File.exists?(file_name)
|
||||
raise CommandError, "No such file: #{opts[:f]}"
|
||||
end
|
||||
|
||||
text_array = File.readlines(file_name)
|
||||
range = opts.l? ? one_index_range_or_number(opts[:l]) : (0..-1)
|
||||
range = (0..-2) if opts.o?
|
||||
|
@ -94,7 +101,10 @@ class Pry
|
|||
_pry_.input_stack << _pry_.input
|
||||
_pry_.input = StringIO.new(Array(text_array[range]).join)
|
||||
else
|
||||
next output.puts "Error: no input to play command" if !args.first
|
||||
if !args.first
|
||||
raise CommandError, "No input to play command."
|
||||
end
|
||||
|
||||
code = target.eval(args.first)
|
||||
|
||||
range = opts.l? ? one_index_range_or_number(opts[:l]) : (0..-1)
|
||||
|
@ -238,7 +248,11 @@ class Pry
|
|||
case opts["save"]
|
||||
when Range
|
||||
hist_array = Array(history[opts["save"]])
|
||||
next output.puts "Must provide a file name." if !args.first
|
||||
|
||||
if !args.first
|
||||
raise CommandError, "Must provide a file name."
|
||||
end
|
||||
|
||||
file_name = File.expand_path(args.first)
|
||||
when String
|
||||
hist_array = history
|
||||
|
|
|
@ -33,8 +33,13 @@ class Pry
|
|||
|
||||
args = [nil] if args.empty?
|
||||
args.each do |method_name|
|
||||
meth = get_method_or_print_error(method_name, target, opts.to_hash(true))
|
||||
next unless meth and meth.source
|
||||
begin
|
||||
meth = get_method_or_raise(method_name, target, opts.to_hash(true))
|
||||
rescue CommandError => e
|
||||
puts "\nError: #{e.message}"
|
||||
next
|
||||
end
|
||||
next unless meth.source
|
||||
|
||||
output.puts make_header(meth)
|
||||
if Pry.color
|
||||
|
@ -79,8 +84,7 @@ class Pry
|
|||
|
||||
command_name = args.shift
|
||||
if !command_name
|
||||
output.puts "You must provide a command name."
|
||||
next
|
||||
raise CommandError, "You must provide a command name."
|
||||
end
|
||||
|
||||
if find_command(command_name)
|
||||
|
@ -105,7 +109,7 @@ class Pry
|
|||
render_output(opts.flood?, opts.l? ? block.source_line : false, code)
|
||||
code
|
||||
else
|
||||
output.puts "No such command: #{command_name}."
|
||||
raise CommandError, "No such command: #{command_name}."
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -131,7 +135,7 @@ class Pry
|
|||
next if opts.h?
|
||||
|
||||
if [opts.ex? || nil, opts.t? || nil, !args.empty? || nil].compact.size > 1
|
||||
next output.puts "Only one of --ex, --temp, and FILE may be specified"
|
||||
raise CommandError, "Only one of --ex, --temp, and FILE may be specified."
|
||||
end
|
||||
|
||||
# edit of local code, eval'd within pry.
|
||||
|
@ -163,7 +167,10 @@ class Pry
|
|||
# edit of remote code, eval'd at top-level
|
||||
else
|
||||
if opts.ex?
|
||||
next output.puts "No Exception found." if _pry_.last_exception.nil?
|
||||
if _pry_.last_exception.nil?
|
||||
raise CommandError, "No exception found."
|
||||
end
|
||||
|
||||
ex = _pry_.last_exception
|
||||
bt_index = opts[:ex].to_i
|
||||
|
||||
|
@ -175,9 +182,14 @@ class Pry
|
|||
end
|
||||
|
||||
line = ex_line
|
||||
next output.puts "Exception has no associated file." if file_name.nil?
|
||||
next output.puts "Cannot edit exceptions raised in REPL." if Pry.eval_path == file_name
|
||||
|
||||
if file_name.nil?
|
||||
raise CommandError, "Exception has no associated file."
|
||||
end
|
||||
|
||||
if Pry.eval_path == file_name
|
||||
raise CommandError, "Cannot edit exceptions raised in REPL."
|
||||
end
|
||||
else
|
||||
# break up into file:line
|
||||
file_name = File.expand_path(args.first)
|
||||
|
@ -224,13 +236,10 @@ class Pry
|
|||
next if opts.help?
|
||||
|
||||
if !Pry.config.editor
|
||||
output.puts "Error: No editor set!"
|
||||
output.puts "Ensure that #{text.bold("Pry.config.editor")} is set to your editor of choice."
|
||||
next
|
||||
raise CommandError, "No editor set!\nEnsure that #{text.bold("Pry.config.editor")} is set to your editor of choice."
|
||||
end
|
||||
|
||||
meth = get_method_or_print_error(args.shift, target, opts.to_hash(true))
|
||||
next unless meth
|
||||
meth = get_method_or_raise(args.shift, target, opts.to_hash(true))
|
||||
|
||||
if opts.p? || meth.dynamically_defined?
|
||||
lines = meth.source.lines.to_a
|
||||
|
@ -238,7 +247,7 @@ class Pry
|
|||
if lines[0] =~ /^def [^( \n]+/
|
||||
lines[0] = "def #{meth.name}#{$'}"
|
||||
else
|
||||
next output.puts "Error: Pry can only patch methods created with the `def` keyword."
|
||||
raise CommandError, "Pry can only patch methods created with the `def` keyword."
|
||||
end
|
||||
|
||||
temp_file do |f|
|
||||
|
@ -251,7 +260,7 @@ class Pry
|
|||
end
|
||||
|
||||
if meth.source_type == :c
|
||||
output.puts "Error: Can't edit a C method."
|
||||
raise CommandError, "Can't edit a C method."
|
||||
else
|
||||
file, line = meth.source_file, meth.source_line
|
||||
|
||||
|
|
|
@ -45,11 +45,14 @@ class Pry
|
|||
target = target()
|
||||
|
||||
OptionParser.new do |opts|
|
||||
opts.banner = %{Usage: ls [OPTIONS] [VAR]\n\
|
||||
List information about VAR (the current context by default).
|
||||
Shows local and instance variables by default.
|
||||
--
|
||||
}
|
||||
opts.banner = unindent <<-EOS
|
||||
Usage: ls [OPTIONS] [VAR]
|
||||
|
||||
List information about VAR (the current context by default).
|
||||
Shows local and instance variables by default.
|
||||
--
|
||||
EOS
|
||||
|
||||
opts.on("-g", "--globals", "Display global variables.") do
|
||||
options[:g] = true
|
||||
end
|
||||
|
|
|
@ -9,7 +9,7 @@ class Pry
|
|||
begin
|
||||
Dir.chdir File.expand_path(dest)
|
||||
rescue Errno::ENOENT
|
||||
output.puts "No such directory: #{dest}"
|
||||
raise CommandError, "No such directory: #{dest}"
|
||||
end
|
||||
else
|
||||
Pry.config.system.call(output, cmd, _pry_)
|
||||
|
@ -79,22 +79,22 @@ class Pry
|
|||
next if opts.help?
|
||||
|
||||
if opts.ex?
|
||||
next output.puts "No Exception or Exception has no associated file." if file_name.nil?
|
||||
if file_name.nil?
|
||||
raise CommandError, "No Exception or Exception has no associated file."
|
||||
end
|
||||
else
|
||||
file_name = args.shift
|
||||
end
|
||||
|
||||
if !file_name
|
||||
output.puts "Must provide a file name."
|
||||
next
|
||||
raise CommandError, "Must provide a file name."
|
||||
end
|
||||
|
||||
begin
|
||||
contents, _, _ = read_between_the_lines(file_name, start_line, end_line)
|
||||
contents = syntax_highlight_by_file_type_or_specified(contents, file_name, opts[:type])
|
||||
rescue Errno::ENOENT
|
||||
output.puts "Could not find file: #{file_name}"
|
||||
next
|
||||
raise CommandError, "Could not find file: #{file_name}"
|
||||
end
|
||||
|
||||
if opts.l?
|
||||
|
|
|
@ -4,8 +4,8 @@ class Pry
|
|||
Experimental = Pry::CommandSet.new do
|
||||
|
||||
command "reload-method", "Reload the source specifically for a method", :requires_gem => "method_reload" do |meth_name|
|
||||
meth = get_method_or_print_error(meth_name, target, {}, :no_cmd)
|
||||
meth.reload if meth
|
||||
meth = get_method_or_raise(meth_name, target, {}, :omit_help)
|
||||
meth.reload
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -4,7 +4,9 @@ class Pry
|
|||
UserCommandAPI = Pry::CommandSet.new do
|
||||
|
||||
command "define-command", "Define a command in the session, use same syntax as `command` method for command API" do |arg|
|
||||
next output.puts("Provide an arg!") if arg.nil?
|
||||
if arg.nil?
|
||||
raise CommandError, "Provide an arg!"
|
||||
end
|
||||
|
||||
prime_string = "command #{arg_string}\n"
|
||||
command_string = _pry_.r(target, prime_string)
|
||||
|
@ -18,8 +20,13 @@ class Pry
|
|||
end
|
||||
|
||||
command "reload-command", "Reload a command. reload-command CMD_NAME CMD_SET" do |command_name, set_name|
|
||||
next output.puts "Must provide command name" if command_name.nil?
|
||||
next output.puts "Must provide command set name" if set_name.nil?
|
||||
if command_name.nil?
|
||||
raise CommandError, "Must provide command name"
|
||||
end
|
||||
|
||||
if set_name.nil?
|
||||
raise CommandError, "Must provide command set name"
|
||||
end
|
||||
|
||||
cmd = Pry.config.commands.commands[command_name]
|
||||
file_name = cmd.block.source_location.first
|
||||
|
@ -33,8 +40,13 @@ class Pry
|
|||
end
|
||||
|
||||
command "edit-command", "Edit a command. edit-command CMD_NAME CMD_SET" do |command_name, set_name|
|
||||
next output.puts "Must provide command name" if command_name.nil?
|
||||
next output.puts "Must provide a command set name" if set_name.nil?
|
||||
if command_name.nil?
|
||||
raise CommandError, "Must provide command name"
|
||||
end
|
||||
|
||||
if set_name.nil?
|
||||
raise CommandError, "Must provide command set name"
|
||||
end
|
||||
|
||||
cmd = Pry.config.commands.commands[command_name]
|
||||
file_name = cmd.block.source_location.first
|
||||
|
|
|
@ -27,15 +27,15 @@ class Pry
|
|||
file.close
|
||||
end
|
||||
|
||||
def get_method_or_print_error(name, target, opts={}, omit_cmd=false)
|
||||
def get_method_or_raise(name, target, opts={}, omit_help=false)
|
||||
if (meth = Pry::Method.from_str(name, target, opts))
|
||||
set_file_and_dir_locals(meth.source_file)
|
||||
meth
|
||||
else
|
||||
# FIXME: better/more accurate error handling
|
||||
output.print "Invalid method name: #{name}."
|
||||
output.print " Type `#{command_name} --help` for help." unless omit_cmd
|
||||
output.puts
|
||||
message = "Invalid method name: #{name}."
|
||||
message << " Type `#{command_name} --help` for help." unless omit_help
|
||||
raise CommandError, message
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -17,8 +17,9 @@ class Pry
|
|||
elsif options[:methods]
|
||||
new(target.eval("method(:#{str})")) rescue nil
|
||||
else
|
||||
from_str(str, target, :instance => true) ||
|
||||
from_str(str, target, :methods => true)
|
||||
from_str(str, target, :instance => true) or
|
||||
from_str(str, target, :methods => true) or
|
||||
raise CommandError, "Method #{str} could not be found."
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -73,7 +74,7 @@ class Pry
|
|||
strip_leading_hash_and_whitespace_from_ruby_comments(core_doc)
|
||||
when :ruby
|
||||
if pry_method?
|
||||
raise "Error: Can't view doc for a REPL-defined method."
|
||||
raise CommandError, "Can't view doc for a REPL-defined method."
|
||||
else
|
||||
strip_leading_hash_and_whitespace_from_ruby_comments(@method.comment)
|
||||
end
|
||||
|
@ -160,9 +161,9 @@ class Pry
|
|||
private
|
||||
def pry_doc_info
|
||||
if Pry.config.has_pry_doc
|
||||
Pry::MethodInfo.info_for(@method) or puts "Cannot find C method: #{name}."
|
||||
Pry::MethodInfo.info_for(@method) or raise CommandError, "Cannot find C method: #{name}."
|
||||
else
|
||||
puts "Cannot locate this method: #{name}. Try `gem install pry-doc` to get access to Ruby Core documentation."
|
||||
raise CommandError, "Cannot locate this method: #{name}. Try `gem install pry-doc` to get access to Ruby Core documentation."
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -219,6 +219,9 @@ class Pry
|
|||
|
||||
result = set_last_result(target.eval(code, Pry.eval_path, Pry.current_line), target)
|
||||
result
|
||||
rescue CommandError => e
|
||||
output.puts "Error: #{e.message}"
|
||||
@suppress_output = true
|
||||
rescue RescuableException => e
|
||||
set_last_exception(e, target)
|
||||
ensure
|
||||
|
|
Loading…
Reference in a new issue