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 Winkler wrote:

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,

<snip long array

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?

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

Elliot Winkler 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

--
Posted via http://www.ruby-forum.com/\.

1)
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

···

--
Posted via http://www.ruby-forum.com/.

#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, Justin Collins <collinsj@seattleu.edu> wrote:

Elliot Winkler wrote:
> 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,
<snip long array
>
> 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?

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

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.

···

On 10/30/06, Elliot Winkler <elliot.winkler@gmail.com> wrote:

#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?