PP / PrettyPrint annoyances

Hello all,

PP/PrettyPrint comes in handy when I’m trying to inspect the contents of
large arrays, but what if some elements are short length-wise?

irb(main):001:0> require ‘pp’
=> true
irb(main):002:0> pp (0…20).to_a
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19,
20]
=> nil
irb(main):003:0> pp (0…40).to_a
[0,
1,
2,
3,
4,
5,
6,
7,
8,
9,
10,
11,
12,
13,
14,
15,
16,
17,
18,
19,
20,
21,
22,
23,
24,
25,
26,
27,
28,
29,
30,
31,
32,
33,
34,
35,
36,
37,
38,
39,
40]
=> nil

This behavior is sort of ridiculous in my opinion. I’d rather have
something
more like:

[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19,
20,
21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38,
39, 40]

I’ve looked at the source code and documentation for PrettyPrint and PP
but
I don’t understand how they work, so I’m not really sure how the classes
could be extended so they work how I want them to work. I also tried
numerous Google searches and it seems no one has a problem with the
default
behavior as I do. Can someone give me a hand here or at least point me
in
the right direction?

Elliot W. wrote:

This behavior is sort of ridiculous in my opinion. I’d rather have
something
more like:

[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19,
20,
21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38,
39, 40]

The problem with ‘pp’ in my opinion is the mysterious ‘breakable’. What
you can do is omit the and handle end of line cases in different manner.
Someday I may look at changing ‘breakable’, but for now this works.

<< START OF CODE

require ‘pp’

class PP
def comma
text ‘,’
end

def comma_newline
text “,\n”
end

def seplist_with_limit(list, limit=20, item_sep=nil, line_sep=nil,
iter_method=:each)
item_sep ||= lambda { comma }
line_sep ||= lambda { comma_newline }

count = 0
first = true
list.__send__(iter_method) { |v|
  if count % limit == 0
    if first
      first = false
    else
      line_sep.call
    end
  else
    item_sep.call
  end
  yield(v)
  count += 1
}

end
end

class Array
def pretty_print(q)
q.group(1, ‘[’, ‘]’) {
q.seplist_with_limit(self, 20) { |v|
q.pp v
}
}
end
end

pp (0…20).to_a

pp (0…40).to_a

END OF CODE

Elliot W. wrote:

=> nil
irb(main):003:0> pp (0…40).to_a
[0,
<snip long array

I’ve looked at the source code and documentation for PrettyPrint and
PP but
I don’t understand how they work, so I’m not really sure how the classes
could be extended so they work how I want them to work. I also tried
numerous Google searches and it seems no one has a problem with the
default
behavior as I do. Can someone give me a hand here or at least point me in
the right direction?

You could just use inspect (not sure if that’s what you really want,
though):

irb(main):001:0> (0…100).to_a.inspect
=> “[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18,
19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36,
37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54,
55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72,
73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90,
91, 92, 93, 94, 95, 96, 97, 98, 99, 100]”

-Justin

irb(main):011:0> a=(0…20).to_a
=> [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18,
19, 20]
irb(main):012:0> print a.inspect
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19,
20]
=> nil

2)irb(main):013:0> a=(0…20).to_a
=> [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18,
19, 20]
irb(main):014:0> a.each{|e| print “#{e}\t”}
0 1 2 3 4 5 6 7 8
9 10 11 12 13 14 15 16 17
18 19 20
=> [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18,
19, 20]

Which one do you really want 1) or 2)?

Li

#inspect would work if the array were simple, but the array I want to
pretty
print is not. I would give you the real case but it’s really long, so a
better example is:

#!/usr/bin/ruby
require ‘pp’
array = [
{ :key1 => ‘value1’, :key2 => ‘value2’, :key3 => ‘value3’ },
1, 2, 3,
[
‘foo’, ‘bar’,
[
{ :key1 => ‘value1’, :key2 => ‘value2’ },
‘baz’, ‘quux’
]
]
]
array2 = array.dup
array2[4][2].push(‘a longer string’, ‘an even longer string’)

p array
puts
pp array
puts
p array2
puts
pp array2

==OUTPUT==

[{:key1=>“value1”, :key2=>“value2”, :key3=>“value3”}, 1, 2, 3, [“foo”,
“bar”, [{:key1=>“value1”, :key2=>“value2”}, “baz”, “quux”]]]

[{:key1=>“value1”, :key2=>“value2”, :key3=>“value3”},
1,
2,
3,
[“foo”, “bar”, [{:key1=>“value1”, :key2=>“value2”}, “baz”, “quux”]]]

[{:key1=>“value1”, :key2=>“value2”, :key3=>“value3”}, 1, 2, 3, [“foo”,
“bar”, [{:key1=>“value1”, :key2=>“value2”}, “baz”, “quux”, “longer
string”,
“even longer string”]]]

[{:key1=>“value1”, :key2=>“value2”, :key3=>“value3”},
1,
2,
3,
[“foo”,
“bar”,
[{:key1=>“value1”, :key2=>“value2”},
“baz”,
“quux”,
“longer string”,
“even longer string”]]]

For array2, I want 1, 2, and 3 to be on one line, “foo” and “bar” to be
one
line, and “baz”, “quux” and “longer string” to be one line. PP isn’t
doing
that, obviously.

Perhaps someone knows of another pretty print library?

– Elliot

On 10/30/06, Elliot W. [email protected] wrote:

    'foo', 'bar',

puts

[{:key1=>“value1”, :key2=>“value2”, :key3=>“value3”},

For array2, I want 1, 2, and 3 to be on one line, “foo” and “bar” to be one
line, and “baz”, “quux” and “longer string” to be one line. PP isn’t doing
that, obviously.

Perhaps someone knows of another pretty print library?

I thought that changing Array#pretty_print would be sufficient, after
deeper look it seems that the problem is in the prettyprint module -
somewhere in the breaking routines - if the whole group (=array,
hash,…) is short enough to fit within the desired width (default
=79) then it’s not split into line. Otherwise every line is split.
So it’s a kind of take all or nothing deal.

The solution would be (better, harder) patching prettyprint.rb to
check the individual fields for overflow or (hack, posissibly easier)
to patch Array#pretty_print from pp.rb to add breakable just in the
desired places.