implement cat --in (fixes #330)

This commit is contained in:
Ryan Fitzgerald 2011-11-06 00:59:49 -07:00
parent 1d68be6f64
commit fd488dfd01
5 changed files with 114 additions and 15 deletions

View File

@ -31,7 +31,7 @@ class Pry
alias_command "file-mode", "shell-mode"
command "cat", "Show output of file FILE. Type `cat --help` for more information." do |*args|
command "cat", "Show code from a file or Pry's input buffer. Type `cat --help` for more information." do |*args|
start_line = 0
end_line = -1
file_name = nil
@ -68,6 +68,8 @@ class Pry
end
end
opt.on :i, :in, "Show entries from Pry's input expression history. Takes an index or range.", :optional => true, :as => Range, :default => -5..-1
opt.on :l, "line-numbers", "Show line numbers."
opt.on :t, :type, "The specific file type for syntax higlighting (e.g ruby, python)", true, :as => Symbol
opt.on :f, :flood, "Do not use a pager to view text longer than one screen."
@ -86,19 +88,49 @@ class Pry
file_name = args.shift
end
if !file_name
raise CommandError, "Must provide a file name."
end
if opts.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 opts[:i].is_a?(Range)
contents = ""
zipped_items.each do |i, s|
contents << "#{text.bold(i.to_s)}:\n"
code = syntax_highlight_by_file_type_or_specified(s, nil, :ruby)
if opts.l?
contents << text.indent(text.with_line_numbers(code, 1), 2)
else
contents << text.indent(code, 2)
end
end
else
contents = syntax_highlight_by_file_type_or_specified(zipped_items.first.last, nil, :ruby)
end
else
unless file_name
raise CommandError, "Must provide a file name."
end
begin
contents, _, _ = read_between_the_lines(file_name, start_line, end_line)
rescue Errno::ENOENT
raise CommandError, "Could not find file: #{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
raise CommandError, "Could not find file: #{file_name}"
end
if opts.l?
contents = text.with_line_numbers contents, start_line + 1
if opts.l?
contents = text.with_line_numbers contents, start_line + 1
end
end
# add the arrow pointing to line that caused the exception

View File

@ -86,13 +86,16 @@ class Pry
end
def syntax_highlight_by_file_type_or_specified(contents, file_name, file_type)
_, language_detected = file_map.find do |k, v|
Array(k).any? do |matcher|
matcher == File.extname(file_name) || matcher == File.basename(file_name)
if file_type
language_detected = file_type
else
_, language_detected = file_map.find do |k, v|
Array(k).any? do |matcher|
matcher == File.extname(file_name) || matcher == File.basename(file_name)
end
end
end
language_detected = file_type if file_type
if Pry.color
CodeRay.scan(contents, language_detected).term
else
@ -247,6 +250,25 @@ class Pry
text.gsub(/^#{margin}/, '')
end
def absolute_index_number(line_number, array_length)
if line_number >= 0
line_number
else
[array_length + line_number, 0].max
end
end
def absolute_index_range(range_or_number, array_length)
case range_or_number
when Range
a = absolute_index_number(range_or_number.begin, array_length)
b = absolute_index_number(range_or_number.end, array_length)
else
a = b = absolute_index_number(range_or_number, array_length)
end
Range.new(a, b)
end
end
end

View File

@ -81,6 +81,14 @@ class Pry
"#{self.send(color, adjusted_index)}: #{line}"
end.join
end
# Returns _text_ indented by _chars_ spaces.
#
# @param [String] text
# @param [Fixnum] chars
def indent(text, chars)
text.lines.map { |l| "#{' ' * chars}#{l}" }.join
end
end
end

View File

@ -72,6 +72,8 @@ class Pry
def size
@count
end
alias count size
alias length size
def empty?
size == 0

View File

@ -9,6 +9,41 @@ describe "Pry::DefaultCommands::Shell" do
end
end
describe "with --in" do
it 'should display the last few expressions with indices' do
output = mock_pry("10", "20", "cat --in")
output.should =~ /^1:/
output.should =~ /^ 10/
output.should =~ /^2:/
output.should =~ /^ 20/
end
end
describe "with --in 1" do
it 'should display the first expression with no index' do
output = mock_pry("10", "20", "cat --in 1")
output.should.not =~ /^\d+:/
output.should =~ /^10/
end
end
describe "with --in -1" do
it 'should display the last expression with no index' do
output = mock_pry("10", "20", "cat --in -1")
output.should.not =~ /^\d+:/
output.should =~ /^20/
end
end
describe "with --in 1..2" do
it 'should display the given range with indices, omitting nils' do
output = mock_pry("10", "20", "cat --ex", ":hello", "cat --in 1..4")
output.should =~ /^1:/
output.should.not =~ /^3:/
output.should =~ /^ :hello/
end
end
# this doesnt work so well on rbx due to differences in backtrace
# so we currently skip rbx until we figure out a workaround
describe "with --ex" do