summaryrefslogtreecommitdiff
path: root/lib/pry/commands/cat.rb
diff options
context:
space:
mode:
authorRyan Fitzgerald <rwfitzge@gmail.com>2012-08-11 17:39:25 -0700
committerRyan Fitzgerald <rwfitzge@gmail.com>2012-08-11 17:39:25 -0700
commit8ce49ee081139791b41fee22e33fe313fa5590aa (patch)
tree68a32acc865e76f708b52b0789492c3f567e064d /lib/pry/commands/cat.rb
parent25cbe4313729d53cd8254dca8e3ce0022ab499eb (diff)
downloadpry-8ce49ee081139791b41fee22e33fe313fa5590aa.tar.gz
Remove extended_commands, default_commands -> commands
Diffstat (limited to 'lib/pry/commands/cat.rb')
-rw-r--r--lib/pry/commands/cat.rb170
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