diff options
author | Ryan Fitzgerald <rwfitzge@gmail.com> | 2012-08-11 17:39:25 -0700 |
---|---|---|
committer | Ryan Fitzgerald <rwfitzge@gmail.com> | 2012-08-11 17:39:25 -0700 |
commit | 8ce49ee081139791b41fee22e33fe313fa5590aa (patch) | |
tree | 68a32acc865e76f708b52b0789492c3f567e064d /lib/pry/commands/cat.rb | |
parent | 25cbe4313729d53cd8254dca8e3ce0022ab499eb (diff) | |
download | pry-8ce49ee081139791b41fee22e33fe313fa5590aa.tar.gz |
Remove extended_commands, default_commands -> commands
Diffstat (limited to 'lib/pry/commands/cat.rb')
-rw-r--r-- | lib/pry/commands/cat.rb | 170 |
1 files changed, 170 insertions, 0 deletions
diff --git a/lib/pry/commands/cat.rb b/lib/pry/commands/cat.rb new file mode 100644 index 00000000..c4e9b8f7 --- /dev/null +++ b/lib/pry/commands/cat.rb @@ -0,0 +1,170 @@ +class Pry + Pry::Commands.create_command "cat", "Show code from a file, Pry's input buffer, or the last exception." do + banner <<-USAGE + Usage: cat FILE + cat --ex [STACK_INDEX] + cat --in [INPUT_INDEX_OR_RANGE] + + cat is capable of showing part or all of a source file, the context of the + last exception, or an expression from Pry's input history. + + cat --ex defaults to showing the lines surrounding the location of the last + exception. Invoking it more than once travels up the exception's backtrace, + and providing a number shows the context of the given index of the backtrace. + USAGE + + def options(opt) + opt.on :ex, "Show the context of the last exception.", :optional_argument => true, :as => Integer + opt.on :i, :in, "Show one or more entries from Pry's expression history.", :optional_argument => true, :as => Range, :default => -5..-1 + + opt.on :s, :start, "Starting line (defaults to the first line).", :optional_argument => true, :as => Integer + opt.on :e, :end, "Ending line (defaults to the last line).", :optional_argument => true, :as => Integer + opt.on :l, :'line-numbers', "Show line numbers." + opt.on :t, :type, "The file type for syntax highlighting (e.g., 'ruby' or 'python').", :argument => true, :as => Symbol + + opt.on :f, :flood, "Do not use a pager to view text longer than one screen." + end + + def process + handler = case + when opts.present?(:ex) + method :process_ex + when opts.present?(:in) + method :process_in + else + method :process_file + end + + output = handler.call do |code| + code.code_type = opts[:type] || :ruby + + code.between(opts[:start] || 1, opts[:end] || -1). + with_line_numbers(opts.present?(:'line-numbers') || opts.present?(:ex)) + end + + render_output(output, opts) + end + + def process_ex + window_size = Pry.config.default_window_size || 5 + ex = _pry_.last_exception + + raise CommandError, "No exception found." unless ex + + if opts[:ex].nil? + bt_index = ex.bt_index + ex.inc_bt_index + else + bt_index = opts[:ex] + ex.bt_index = bt_index + ex.inc_bt_index + end + + ex_file, ex_line = ex.bt_source_location_for(bt_index) + + raise CommandError, "The given backtrace level is out of bounds." unless ex_file + + if RbxPath.is_core_path?(ex_file) + ex_file = RbxPath.convert_path_to_full(ex_file) + end + + set_file_and_dir_locals(ex_file) + + start_line = ex_line - window_size + start_line = 1 if start_line < 1 + end_line = ex_line + window_size + + header = unindent <<-HEADER + #{text.bold 'Exception:'} #{ex.class}: #{ex.message} + -- + #{text.bold('From:')} #{ex_file} @ line #{ex_line} @ #{text.bold("level: #{bt_index}")} of backtrace (of #{ex.backtrace.size - 1}). + + HEADER + + code = yield(Pry::Code.from_file(ex_file). + between(start_line, end_line). + with_marker(ex_line)) + + "#{header}#{code}" + end + + def process_in + normalized_range = absolute_index_range(opts[:i], _pry_.input_array.length) + input_items = _pry_.input_array[normalized_range] || [] + + zipped_items = normalized_range.zip(input_items).reject { |_, s| s.nil? || s == "" } + + unless zipped_items.length > 0 + raise CommandError, "No expressions found." + end + + if zipped_items.length > 1 + contents = "" + zipped_items.each do |i, s| + contents << "#{text.bold(i.to_s)}:\n" + contents << yield(Pry::Code(s).with_indentation(2)).to_s + end + else + contents = yield(Pry::Code(zipped_items.first.last)) + end + + contents + end + + def process_file + file_name = args.shift + + unless file_name + raise CommandError, "Must provide a filename, --in, or --ex." + end + + file_name, line_num = file_name.split(':') + file_name = File.expand_path(file_name) + set_file_and_dir_locals(file_name) + + code = yield(Pry::Code.from_file(file_name)) + + code.code_type = opts[:type] || detect_code_type_from_file(file_name) + if line_num + code = code.around(line_num.to_i, + Pry.config.default_window_size || 7) + end + + code + end + + def detect_code_type_from_file(file_name) + name, ext = File.basename(file_name).split('.', 2) + + if ext + case ext + when "py" + :python + when "rb", "gemspec", "rakefile", "ru" + :ruby + when "js" + return :javascript + when "yml", "prytheme" + :yaml + when "groovy" + :groovy + when "c" + :c + when "cpp" + :cpp + when "java" + :java + else + :text + end + else + case name + when "Rakefile", "Gemfile" + :ruby + else + :text + end + end + end + end +end |