1
0
Fork 0
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:
Ryan Fitzgerald 2011-10-01 16:57:39 -07:00
parent 10bf1bcd95
commit a53fe2c5d1
14 changed files with 117 additions and 68 deletions

View file

@ -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"

View file

@ -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

View file

@ -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

View file

@ -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?

View file

@ -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|

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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?

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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