summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog4
-rw-r--r--lib/pp.rb61
-rw-r--r--lib/prettyprint.rb177
3 files changed, 188 insertions, 54 deletions
diff --git a/ChangeLog b/ChangeLog
index 3868270e5c..c2f08137c2 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,7 @@
+Fri Feb 22 11:30:01 2002 Tanaka Akira <akr@m17n.org>
+
+ * prettyprint.rb: FillGroup implemented.
+
Thu Feb 21 21:40:18 2002 Usaku Nakamura <usa@ruby-lang.org>
* ext/extmk.rb.in (create_makefile): remove unnecessary -L option from
diff --git a/lib/pp.rb b/lib/pp.rb
index 24503b1919..0a18a6f318 100644
--- a/lib/pp.rb
+++ b/lib/pp.rb
@@ -6,38 +6,46 @@
== Which seems better?
non-pretty-printed output by (({p})) is:
- #<PP:0x806486c @stack=[], @nest=[0], @buf=#<PP::Group:0x8064844 @tail=0, @singleline_length=9, @buf=[#<PP::Group:0x80647cc @tail=0, @singleline_length=9, @buf=[#<PP::Text:0x8064768 @text="[">, #<PP::Group:0x80646c8 @tail=1, @singleline_length=1, @buf=[#<PP::Text:0x8064664 @text="1">]>, #<PP::Text:0x80646b4 @text=",">, #<PP::Breakable:0x8064650 @indent=1, @sep=" ">, #<PP::Group:0x8064614 @tail=1, @singleline_length=1, @buf=[#<PP::Text:0x80645b0 @text="2">]>, #<PP::Text:0x8064600 @text=",">, #<PP::Breakable:0x806459c @indent=1, @sep=" ">, #<PP::Group:0x8064560 @tail=1, @singleline_length=1, @buf=[#<PP::Text:0x80644fc @text="3">]>, #<PP::Text:0x806472c @text="]">]>]>>
+ #<PP:0x81a0d10 @stack=[], @genspace=#<Proc:0x81a0cc0>, @nest=[0], @newline="\n", @buf=#<PrettyPrint::Group:0x81a0c98 @group=0, @tail=0, @buf=[#<PrettyPrint::Group:0x81a0ba8 @group=1, @tail=0, @buf=[#<PrettyPrint::Text:0x81a0b30 @tail=2, @width=1, @text="[">, #<PrettyPrint::Group:0x81a0a68 @group=2, @tail=1, @buf=[#<PrettyPrint::Text:0x81a09f0 @tail=1, @width=1, @text="1">], @singleline_width=1>, #<PrettyPrint::Text:0x81a0a7c @tail=0, @width=1, @text=",">, #<PrettyPrint::Breakable:0x81a0a2c @group=2, @genspace=#<Proc:0x81a0cc0>, @newline="\n", @indent=1, @tail=2, @sep=" ", @width=1>, #<PrettyPrint::Group:0x81a09c8 @group=2, @tail=1, @buf=[#<PrettyPrint::Text:0x81a0950 @tail=1, @width=1, @text="2">], @singleline_width=1>, #<PrettyPrint::Text:0x81a0af4 @tail=0, @width=1, @text="]">], @singleline_width=6>], @singleline_width=6>, @sharing_detection=false>
pretty-printed output by (({pp})) is:
- #<PP:0x403279c
+ #<PP:0x40d0688
@buf=
- #<PP::Group:0x4032666
+ #<PrettyPrint::Group:0x40d064c
@buf=
- [#<PP::Group:0x4032666
- @buf=
- [#<PP::Text:0x40326de @text="[">,
- #<PP::Group:0x4032666
- @buf=[#<PP::Text:0x40326de @text="1">],
- @singleline_length=1,
- @tail=1>,
- #<PP::Text:0x40326de @text=",">,
- #<PP::Breakable:0x40326b6 @indent=1, @sep=" ">,
- #<PP::Group:0x4032666
- @buf=[#<PP::Text:0x40326de @text="2">],
- @singleline_length=1,
- @tail=1>,
- #<PP::Text:0x40326de @text=",">,
- #<PP::Breakable:0x40326b6 @indent=1, @sep=" ">,
- #<PP::Group:0x4032666
- @buf=[#<PP::Text:0x40326de @text="3">],
- @singleline_length=1,
- @tail=1>,
- #<PP::Text:0x40326de @text="]">],
- @singleline_length=9,
- @tail=0>],
- @singleline_length=9,
+ [#<PrettyPrint::Group:0x40d05d4
+ @buf=
+ [#<PrettyPrint::Text:0x40d0598 @tail=2, @text="[", @width=1>,
+ #<PrettyPrint::Group:0x40d0534
+ @buf=[#<PrettyPrint::Text:0x40d04f8 @tail=1, @text="1", @width=1>],
+ @group=2,
+ @singleline_width=1,
+ @tail=1>,
+ #<PrettyPrint::Text:0x40d053e @tail=0, @text=",", @width=1>,
+ #<PrettyPrint::Breakable:0x40d0516
+ @genspace=#<Proc:0x40d0656>,
+ @group=2,
+ @indent=1,
+ @newline="\n",
+ @sep=" ",
+ @tail=2,
+ @width=1>,
+ #<PrettyPrint::Group:0x40d04e4
+ @buf=[#<PrettyPrint::Text:0x40d04a8 @tail=1, @text="2", @width=1>],
+ @group=2,
+ @singleline_width=1,
+ @tail=1>,
+ #<PrettyPrint::Text:0x40d057a @tail=0, @text="]", @width=1>],
+ @group=1,
+ @singleline_width=6,
+ @tail=0>],
+ @group=0,
+ @singleline_width=6,
@tail=0>,
+ @genspace=#<Proc:0x40d0656>,
@nest=[0],
+ @newline="\n",
+ @sharing_detection=false,
@stack=[]>
I like the latter. If you do too, this library is for you.
@@ -110,6 +118,7 @@ class PP < PrettyPrint
pp = PP.new
pp.guard_inspect_key {pp.pp obj}
pp.format(out, width)
+ #$pp = pp
out << "\n"
end
diff --git a/lib/prettyprint.rb b/lib/prettyprint.rb
index 6d4a6f97b5..b05da3f56f 100644
--- a/lib/prettyprint.rb
+++ b/lib/prettyprint.rb
@@ -49,6 +49,11 @@ non-string formatting, etc.
--- group {...}
groups line break hints added in the block.
+ The line break hints are all to be breaked or not.
+
+--- fill_group {...}
+ groups line break hints added in the block.
+ The each line break hints may be breaked or not differently.
--- format(out[, width])
outputs buffered data to ((|out|)).
@@ -65,17 +70,13 @@ non-string formatting, etc.
a result of a given block for (({PrettyPrint.new})).
== Bugs
-* Line breaks in a group is constrained to whether all line break hints are
- to be breaked or not. Maybe, non-constrained version of
- PrettyPrint#group should be provided to filling multi lines.
-
-* Box based formatting?
+* Box based formatting? Other (better) model/algorithm?
== References
-Strictly Pretty, Christian Lindig, March 2000,
+Christian Lindig, Strictly Pretty, March 2000,
((<URL:http://www.gaertner.de/~lindig/papers/strictly-pretty.html>))
-A prettier printer, Philip Wadler, March 1998,
+Philip Wadler, A prettier printer, March 1998,
((<URL:http://cm.bell-labs.com/cm/cs/who/wadler/topics/recent.html#prettier>))
=end
@@ -98,40 +99,36 @@ class PrettyPrint
end
def nest(indent)
- nest_enter(indent)
+ @nest << @nest.last + indent
begin
yield
ensure
- nest_leave
+ @nest.pop
end
end
- def nest_enter(indent)
- @nest << @nest.last + indent
- end
-
- def nest_leave
- @nest.pop
- end
-
def group
- group_enter
+ g = Group.new
+ @buf << g
+ @stack << @buf
+ @buf = g
begin
yield
ensure
- group_leave
+ @buf = @stack.pop
end
end
- def group_enter
- g = Group.new
+ def fill_group
+ g = FillGroup.new
@buf << g
@stack << @buf
@buf = g
- end
-
- def group_leave
- @buf = @stack.pop
+ begin
+ yield
+ ensure
+ @buf = @stack.pop
+ end
end
def format(out, width=79)
@@ -147,8 +144,10 @@ class PrettyPrint
end
def update_tails(tails, group)
+ @tail = tails[-1][1]
tails[-1][1] += @width
end
+ attr_reader :tail
def singleline_width
return @width
@@ -174,6 +173,7 @@ class PrettyPrint
end
def update_tails(tails, group)
+ @tail = tails[-1][1]
if group == tails[-1][0]
tails[-2][1] += @width + tails[-1][1]
tails[-1][1] = 0
@@ -182,6 +182,7 @@ class PrettyPrint
tails << [group, 0]
end
end
+ attr_reader :tail
def singleline_width
return @width
@@ -209,18 +210,19 @@ class PrettyPrint
end
def update_tails(tails, group)
- @tail = tails.empty? ? 0 : tails[-1][1]
+ @tail = tails[-1][1]
len = 0
@buf.reverse_each {|obj|
obj.update_tails(tails, group + 1)
len += obj.singleline_width
}
@singleline_width = len
- while !tails.empty? && group <= tails[-1][0]
+ while group < tails[-1][0]
tails[-2][1] += tails[-1][1]
tails.pop
end
end
+ attr_reader :tail
def singleline_width
return @singleline_width
@@ -233,7 +235,7 @@ class PrettyPrint
def multiline_output(out, group, margin, width)
if margin + singleline_width + @tail <= width
singleline_output(out)
- margin += singleline_width
+ margin += @singleline_width
else
@buf.each {|obj|
margin = obj.multiline_output(out, group + 1, margin, width)
@@ -242,6 +244,20 @@ class PrettyPrint
return margin
end
end
+
+ class FillGroup < Group
+ def multiline_output(out, group, margin, width)
+ @buf.each {|obj|
+ if margin + obj.singleline_width + obj.tail <= width
+ obj.singleline_output(out)
+ margin += obj.singleline_width
+ else
+ margin = obj.multiline_output(out, group + 1, margin, width)
+ end
+ }
+ return margin
+ end
+ end
end
if __FILE__ == $0
@@ -674,8 +690,113 @@ End
end
+ class Fill < RUNIT::TestCase
+ def setup
+ @pp = PrettyPrint.new
+ @pp.fill_group {
+ @pp.text 'abc'
+ @pp.breakable
+ @pp.text 'def'
+ @pp.breakable
+ @pp.text 'ghi'
+ @pp.breakable
+ @pp.text 'jkl'
+ @pp.breakable
+ @pp.text 'mno'
+ @pp.breakable
+ @pp.text 'pqr'
+ @pp.breakable
+ @pp.text 'stu'
+ }
+ end
+
+ def test_0_6
+ expected = <<'End'.chomp
+abc
+def
+ghi
+jkl
+mno
+pqr
+stu
+End
+ @pp.format(out='', 0)
+ assert_equal(expected, out)
+ @pp.format(out='', 6)
+ assert_equal(expected, out)
+ end
+
+ def test_7_10
+ expected = <<'End'.chomp
+abc def
+ghi jkl
+mno pqr
+stu
+End
+ @pp.format(out='', 7)
+ assert_equal(expected, out)
+ @pp.format(out='', 10)
+ assert_equal(expected, out)
+ end
+
+ def test_11_14
+ expected = <<'End'.chomp
+abc def ghi
+jkl mno pqr
+stu
+End
+ @pp.format(out='', 11)
+ assert_equal(expected, out)
+ @pp.format(out='', 14)
+ assert_equal(expected, out)
+ end
+
+ def test_15_18
+ expected = <<'End'.chomp
+abc def ghi jkl
+mno pqr stu
+End
+ @pp.format(out='', 15)
+ assert_equal(expected, out)
+ @pp.format(out='', 18)
+ assert_equal(expected, out)
+ end
+
+ def test_19_22
+ expected = <<'End'.chomp
+abc def ghi jkl mno
+pqr stu
+End
+ @pp.format(out='', 19)
+ assert_equal(expected, out)
+ @pp.format(out='', 22)
+ assert_equal(expected, out)
+ end
+
+ def test_23_26
+ expected = <<'End'.chomp
+abc def ghi jkl mno pqr
+stu
+End
+ @pp.format(out='', 23)
+ assert_equal(expected, out)
+ @pp.format(out='', 26)
+ assert_equal(expected, out)
+ end
+
+ def test_27
+ expected = <<'End'.chomp
+abc def ghi jkl mno pqr stu
+End
+ @pp.format(out='', 27)
+ assert_equal(expected, out)
+ end
+
+ end
+
RUNIT::CUI::TestRunner.run(WadlerExample.suite)
RUNIT::CUI::TestRunner.run(StrictPrettyExample.suite)
RUNIT::CUI::TestRunner.run(TailGroup.suite)
RUNIT::CUI::TestRunner.run(NonString.suite)
+ RUNIT::CUI::TestRunner.run(Fill.suite)
end