diff --git a/Guardfile b/Guardfile index dc386d72..8afa438e 100644 --- a/Guardfile +++ b/Guardfile @@ -12,9 +12,11 @@ module ::Guard paths.delete('some_lib') puts "Running: #{paths.join ' '}" if paths.size.zero? + warn 'Running all tests' system 'rake recspec' else paths.each do |path| + warn "Running #{path}" system "rake spec run=#{path}" or return warn "\e[32;1mNice!!\e[0m Now running all specs, just to be sure." run_all diff --git a/lib/pry/commands/ls.rb b/lib/pry/commands/ls.rb index 92df203d..4df20c64 100644 --- a/lib/pry/commands/ls.rb +++ b/lib/pry/commands/ls.rb @@ -1,19 +1,91 @@ class Pry module Helpers module Formatting - def self.tablify(things, screen_width) - maximum_width = things.map{|t| Pry::Helpers::Text.strip_color(t).length}.max + Pry.config.ls.separator.length - maximum_width = screen_width if maximum_width > screen_width - columns = screen_width / maximum_width - - things.each_slice(columns).map do |slice| - slice.map do |s| - padding_width = maximum_width - Pry::Helpers::Text.strip_color(s).length - padding = Pry.config.ls.separator.ljust(padding_width, Pry.config.ls.separator) - s + padding - end.join("") - end.join("\n") + def self.tablify(things, line_length) + table = Table.new(things, :column_count => things.size) + table.column_count -= 1 until 0 == table.column_count or + table.fits_on_line?(line_length) + table.to_s end + + class Table + attr_reader :items, :column_count + def initialize items, args = {} + @column_count = args[:column_count] + self.items = items + end + + def to_s + rows_to_s.join("\n") + end + + def rows_to_s style = :color_on + widths = columns.map{|e| _max_width(e)} + @rows_without_colors.map do |r| + padded = [] + r.each_with_index do |e,i| + next unless e + item = e.ljust(widths[i]) + item.sub! e, recall_color_for(e) if :color_on == style + padded << item + end + padded.join(Pry.config.ls.separator) + end + end + + def items= items + @items = items + _rebuild_colorless_cache + _recolumn + items + end + + def column_count= n + @column_count = n + _recolumn + end + + def fits_on_line? line_length + _max_width(rows_to_s :no_color) <= line_length + end + + def columns + @rows_without_colors.transpose + end + + def ==(other); items == other.to_a end + def to_a; items.to_a end + + private + def _max_width(things) + things.compact.map(&:size).max || 0 + end + + def _rebuild_colorless_cache + @colorless_cache = {} + @plain_items = [] + items.map do |e| + plain = Pry::Helpers::Text.strip_color(e) + @colorless_cache[plain] = e + @plain_items << plain + end + end + + def _recolumn + @rows_without_colors = [] + return if items.size.zero? + row_count = (items.size.to_f/column_count).ceil + row_count.times do |i| + row_indices = (0...column_count).map{|e| row_count*e+i} + @rows_without_colors << row_indices.map{|e| @plain_items[e]} + end + end + + def recall_color_for thing + @colorless_cache[thing] + end + end + end end @@ -21,10 +93,6 @@ class Pry match 'ls' group 'Context' description 'Show the list of vars and methods in the current scope.' - - Pry::Commands.create_command "ls" do - group "Context" - description "Show the list of vars and methods in the current scope." command_options :shellwords => false, :interpolate => false def options(opt) diff --git a/spec/commands/ls_spec.rb b/spec/commands/ls_spec.rb index b3318302..e03176d2 100644 --- a/spec/commands/ls_spec.rb +++ b/spec/commands/ls_spec.rb @@ -28,24 +28,56 @@ describe "ls" do end end + describe 'Formatting Table' do + it 'knows about colorized fitting' do + t = Pry::Helpers::Formatting::Table.new %w(hihi), :column_count => 1 + t.fits_on_line?(4).should == true + t.items = [] + t.fits_on_line?(4).should == true + + t.items = %w(hi hi) + t.fits_on_line?(4).should == true + t.column_count = 2 + t.fits_on_line?(4).should == false + + t.items = %w( + a ccc + bb dddd + ).sort + t.fits_on_line?(8).should == true + t.fits_on_line?(7).should == false + end + end + describe 'formatting - should order downward and wrap to columns' do FAKE_COLUMNS = 62 - def try_round_trip(text) - text.strip! - things = text.split(/\s+/) - actual = Pry::Helpers::Formatting.tablify(things, FAKE_COLUMNS) - if actual != text - actual.strip.should == text - puts text, 'vs.', actual + def try_round_trip(expected) + things = expected.split(/\s+/).sort + actual = Pry::Helpers::Formatting.tablify(things, FAKE_COLUMNS).strip + [expected, actual].each{|e| e.gsub! /\s+$/, ''} + if actual != expected + bar = '-'*25 + puts \ + bar+'expected'+bar, + expected, + bar+'actual'+bar, + actual end + actual.should == expected + end + + it 'should handle a tiny case' do + try_round_trip(<<-eot) +asdf asfddd fdass + eot end it 'should handle the basic case' do - try_round_trip(<<-EOT) + try_round_trip(<<-eot) aadd ddasffssdad sdsaadaasd ssfasaafssd adassdfffaasds f sdsfasddasfds ssssdaa assfsafsfsds fsasa ssdsssafsdasdf - EOT + eot end it 'should handle... another basic case' do @@ -61,6 +93,13 @@ asfadsssaaad fasfaafdssd s EOT end + it 'should handle colors' do + try_round_trip(<<-EOT) +\e[31maaaaaaaaaa\e[0m \e[31mccccccccccccccccccccccccccccc\e[0m +\e[31mbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb\e[0m \e[31mddddddddddddd\e[0m + EOT + end + it 'should handle empty input' do try_round_trip('') end