Skip to content

Commit

Permalink
Merge pull request #87 from d-m-u/removing_color_from_tableize
Browse files Browse the repository at this point in the history
remove color from length count
  • Loading branch information
bdunne authored Jul 16, 2020
2 parents 057042e + 4df5c3e commit 7467dfc
Show file tree
Hide file tree
Showing 2 changed files with 168 additions and 2 deletions.
38 changes: 36 additions & 2 deletions lib/more_core_extensions/core_ext/array/tableize.rb
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,9 @@ def tableize

private

ANSI_ESCAPE_SEQUENCE = /\e\[[^m]+m/.freeze
ANSI_RESET = "\e[0m".freeze

def tableize_hashes
# Convert the target to an Array of Arrays
keys = options[:columns] || columns_from_hash_keys
Expand Down Expand Up @@ -102,7 +105,7 @@ def widths_and_justifications
end

def apply_width!(widths, field, field_i)
widths[field_i] = [widths[field_i].to_i, field.to_s.length].max
widths[field_i] = [widths[field_i].to_i, ansi_strip(field.to_s).length].max
widths[field_i] = [options[:max_width], widths[field_i].to_i].min if options[:max_width]
end

Expand All @@ -118,10 +121,41 @@ def format_row(row, widths, justifications)
end

def format_field(field, width, justification)
field = field.to_s.gsub(/\n|\r/, '').slice(0, width)
field = field.to_s.gsub(/\n|\r/, '')
field = ansi_truncate(field, width)
"%0#{justification}#{width}s" % field
end

def ansi_escapes?(field)
!!field.match(ANSI_ESCAPE_SEQUENCE)
end

def ansi_escapes(field)
field.to_enum(:scan, ANSI_ESCAPE_SEQUENCE).map { Regexp.last_match }
end

def ansi_strip(field)
field.gsub(ANSI_ESCAPE_SEQUENCE, '')
end

def ansi_truncate(field, width)
escapes = ansi_escapes(field)
if escapes.none?
field.slice(0, width)
else
escape_widths = 0
escapes.each do |e|
break if e.offset(0).first - escape_widths >= width

escape_widths += e[0].size
end

field = field.slice(0, width + escape_widths)
field << ANSI_RESET if ansi_escapes?(field) && !field.end_with?(ANSI_RESET)
field
end
end

def format_table(table, widths)
if options[:header] && table.size > 1
header_separator = widths.collect { |w| "-" * (w + 2) }.join("|")
Expand Down
132 changes: 132 additions & 0 deletions spec/core_ext/array/tableize_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,28 @@
expect(test.tableize).to eq(expected)
end

it 'with color' do
test = [["Col1", "Col2"], ["Val1", "Val2"], ["\033[31mValue3\e[0m", "Value4"]]
expected = <<-EOF
Col1 | Col2
--------|--------
Val1 | Val2
\e[31mValue3\e[0m | Value4
EOF
expect(test.tableize).to eq(expected)
end

it 'with unterminated color' do
test = [["Col1", "Col2"], ["Val1", "Val2"], ["\033[31mValue3", "Value4"]]
expected = <<-EOF
Col1 | Col2
--------|--------
Val1 | Val2
\e[31mValue3\e[0m | Value4
EOF
expect(test.tableize).to eq(expected)
end

it 'with numeric column values right justified' do
test = [["Col1", "Col2"], ["Val1", 200], ["Value3", 30]]
expected = <<-EOF
Expand All @@ -34,6 +56,17 @@
expect(test.tableize).to eq(expected)
end

it 'with really long column value and color' do
test = [["Col1", "Col2"], ["Val1", "Val2"], ["\033[31mReally Really Long Value3\e[0m", "Value4"]]
expected = <<-EOF
Col1 | Col2
---------------------------|--------
Val1 | Val2
\e[31mReally Really Long Value3\e[0m | Value4
EOF
expect(test.tableize).to eq(expected)
end

it 'with really long column value and :max_width option' do
test = [["Col1", "Col2"], ["Val1", "Val2"], ["Really Really Long Value3", "Value4"]]
expected = <<-EOF
Expand All @@ -45,6 +78,61 @@
expect(test.tableize(:max_width => 10)).to eq(expected)
end

it 'with really long column value and color and :max_width option' do
test = [["Col1", "Col2"], ["Val1", "Val2"], ["\033[31mReally Really Long Value3\e[0m", "Value4"]]
expected = <<-EOF
Col1 | Col2
------------|--------
Val1 | Val2
\e[31mReally Rea\e[0m | Value4
EOF
expect(test.tableize(:max_width => 10)).to eq(expected)
end

it 'with really long column value and color and :max_width option that chops off the color' do
test = [["Col1", "Col2"], ["Val1", "Val2"], ["Really Really Long \033[31mValue3\e[0m", "Value4"]]
expected = <<-EOF
Col1 | Col2
------------|--------
Val1 | Val2
Really Rea | Value4
EOF
expect(test.tableize(:max_width => 10)).to eq(expected)
end

it 'with really long column value and color and :max_width option within an escape sequence' do
test = [["Col1", "Col2"], ["Val1", "Val2"], ["\033[31mReally Really Long Value3\e[0m", "Value4"]]
expected = <<-EOF
Co | Co
----|----
Va | Va
\e[31mRe\e[0m | Va
EOF
expect(test.tableize(:max_width => 2)).to eq(expected)
end

it 'with oversized :max_width option' do
test = [["Col1", "Col2"], ["Val1", "Val2"], ["Really Really Long Value3", "Value4"]]
expected = <<-EOF
Col1 | Col2
---------------------------|--------
Val1 | Val2
Really Really Long Value3 | Value4
EOF
expect(test.tableize(:max_width => 100)).to eq(expected)
end

it 'with color and oversized :max_width option' do
test = [["Col1", "Col2"], ["Val1", "Val2"], ["\033[31mReally Really Long Value3\e[0m", "Value4"]]
expected = <<-EOF
Col1 | Col2
---------------------------|--------
Val1 | Val2
\e[31mReally Really Long Value3\e[0m | Value4
EOF
expect(test.tableize(:max_width => 100)).to eq(expected)
end

it 'with :header => false option' do
test = [["Col1", "Col2"], ["Val1", "Val2"], ["Value3", "Value4"]]
expected = <<-EOF
Expand Down Expand Up @@ -154,3 +242,47 @@
end
end
end

describe MoreCoreExtensions::ArrayTableize::Tableizer do
describe "#ansi_truncate (private)" do
subject { described_class.new(nil, nil) }

it "with color" do
s = "foo\e[31mbar\e[32mbaz\e[0mqux"

expect(subject.send(:ansi_truncate, s, 0)).to eq ""
expect(subject.send(:ansi_truncate, s, 1)).to eq "f"
expect(subject.send(:ansi_truncate, s, 2)).to eq "fo"
expect(subject.send(:ansi_truncate, s, 3)).to eq "foo"
expect(subject.send(:ansi_truncate, s, 4)).to eq "foo\e[31mb\e[0m"
expect(subject.send(:ansi_truncate, s, 5)).to eq "foo\e[31mba\e[0m"
expect(subject.send(:ansi_truncate, s, 6)).to eq "foo\e[31mbar\e[0m"
expect(subject.send(:ansi_truncate, s, 7)).to eq "foo\e[31mbar\e[32mb\e[0m"
expect(subject.send(:ansi_truncate, s, 8)).to eq "foo\e[31mbar\e[32mba\e[0m"
expect(subject.send(:ansi_truncate, s, 9)).to eq "foo\e[31mbar\e[32mbaz\e[0m"
expect(subject.send(:ansi_truncate, s, 10)).to eq "foo\e[31mbar\e[32mbaz\e[0mq\e[0m"
expect(subject.send(:ansi_truncate, s, 11)).to eq "foo\e[31mbar\e[32mbaz\e[0mqu\e[0m"
expect(subject.send(:ansi_truncate, s, 12)).to eq "foo\e[31mbar\e[32mbaz\e[0mqux\e[0m"
expect(subject.send(:ansi_truncate, s, 13)).to eq "foo\e[31mbar\e[32mbaz\e[0mqux\e[0m"
end

it "without color" do
s = "foobarbazqux"

expect(subject.send(:ansi_truncate, s, 0)).to eq ""
expect(subject.send(:ansi_truncate, s, 1)).to eq "f"
expect(subject.send(:ansi_truncate, s, 2)).to eq "fo"
expect(subject.send(:ansi_truncate, s, 3)).to eq "foo"
expect(subject.send(:ansi_truncate, s, 4)).to eq "foob"
expect(subject.send(:ansi_truncate, s, 5)).to eq "fooba"
expect(subject.send(:ansi_truncate, s, 6)).to eq "foobar"
expect(subject.send(:ansi_truncate, s, 7)).to eq "foobarb"
expect(subject.send(:ansi_truncate, s, 8)).to eq "foobarba"
expect(subject.send(:ansi_truncate, s, 9)).to eq "foobarbaz"
expect(subject.send(:ansi_truncate, s, 10)).to eq "foobarbazq"
expect(subject.send(:ansi_truncate, s, 11)).to eq "foobarbazqu"
expect(subject.send(:ansi_truncate, s, 12)).to eq "foobarbazqux"
expect(subject.send(:ansi_truncate, s, 13)).to eq "foobarbazqux"
end
end
end

0 comments on commit 7467dfc

Please sign in to comment.