* prettyprint.rb: FillGroup implemented.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@2111 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
parent
5024bd594d
commit
9ce7325615
@ -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>
|
Thu Feb 21 21:40:18 2002 Usaku Nakamura <usa@ruby-lang.org>
|
||||||
|
|
||||||
* ext/extmk.rb.in (create_makefile): remove unnecessary -L option from
|
* ext/extmk.rb.in (create_makefile): remove unnecessary -L option from
|
||||||
|
53
lib/pp.rb
53
lib/pp.rb
@ -6,38 +6,46 @@
|
|||||||
== Which seems better?
|
== Which seems better?
|
||||||
|
|
||||||
non-pretty-printed output by (({p})) is:
|
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:
|
pretty-printed output by (({pp})) is:
|
||||||
#<PP:0x403279c
|
#<PP:0x40d0688
|
||||||
@buf=
|
@buf=
|
||||||
#<PP::Group:0x4032666
|
#<PrettyPrint::Group:0x40d064c
|
||||||
@buf=
|
@buf=
|
||||||
[#<PP::Group:0x4032666
|
[#<PrettyPrint::Group:0x40d05d4
|
||||||
@buf=
|
@buf=
|
||||||
[#<PP::Text:0x40326de @text="[">,
|
[#<PrettyPrint::Text:0x40d0598 @tail=2, @text="[", @width=1>,
|
||||||
#<PP::Group:0x4032666
|
#<PrettyPrint::Group:0x40d0534
|
||||||
@buf=[#<PP::Text:0x40326de @text="1">],
|
@buf=[#<PrettyPrint::Text:0x40d04f8 @tail=1, @text="1", @width=1>],
|
||||||
@singleline_length=1,
|
@group=2,
|
||||||
|
@singleline_width=1,
|
||||||
@tail=1>,
|
@tail=1>,
|
||||||
#<PP::Text:0x40326de @text=",">,
|
#<PrettyPrint::Text:0x40d053e @tail=0, @text=",", @width=1>,
|
||||||
#<PP::Breakable:0x40326b6 @indent=1, @sep=" ">,
|
#<PrettyPrint::Breakable:0x40d0516
|
||||||
#<PP::Group:0x4032666
|
@genspace=#<Proc:0x40d0656>,
|
||||||
@buf=[#<PP::Text:0x40326de @text="2">],
|
@group=2,
|
||||||
@singleline_length=1,
|
@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>,
|
@tail=1>,
|
||||||
#<PP::Text:0x40326de @text=",">,
|
#<PrettyPrint::Text:0x40d057a @tail=0, @text="]", @width=1>],
|
||||||
#<PP::Breakable:0x40326b6 @indent=1, @sep=" ">,
|
@group=1,
|
||||||
#<PP::Group:0x4032666
|
@singleline_width=6,
|
||||||
@buf=[#<PP::Text:0x40326de @text="3">],
|
|
||||||
@singleline_length=1,
|
|
||||||
@tail=1>,
|
|
||||||
#<PP::Text:0x40326de @text="]">],
|
|
||||||
@singleline_length=9,
|
|
||||||
@tail=0>],
|
@tail=0>],
|
||||||
@singleline_length=9,
|
@group=0,
|
||||||
|
@singleline_width=6,
|
||||||
@tail=0>,
|
@tail=0>,
|
||||||
|
@genspace=#<Proc:0x40d0656>,
|
||||||
@nest=[0],
|
@nest=[0],
|
||||||
|
@newline="\n",
|
||||||
|
@sharing_detection=false,
|
||||||
@stack=[]>
|
@stack=[]>
|
||||||
|
|
||||||
I like the latter. If you do too, this library is for you.
|
I like the latter. If you do too, this library is for you.
|
||||||
@ -110,6 +118,7 @@ class PP < PrettyPrint
|
|||||||
pp = PP.new
|
pp = PP.new
|
||||||
pp.guard_inspect_key {pp.pp obj}
|
pp.guard_inspect_key {pp.pp obj}
|
||||||
pp.format(out, width)
|
pp.format(out, width)
|
||||||
|
#$pp = pp
|
||||||
out << "\n"
|
out << "\n"
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -49,6 +49,11 @@ non-string formatting, etc.
|
|||||||
|
|
||||||
--- group {...}
|
--- group {...}
|
||||||
groups line break hints added in the block.
|
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])
|
--- format(out[, width])
|
||||||
outputs buffered data to ((|out|)).
|
outputs buffered data to ((|out|)).
|
||||||
@ -65,17 +70,13 @@ non-string formatting, etc.
|
|||||||
a result of a given block for (({PrettyPrint.new})).
|
a result of a given block for (({PrettyPrint.new})).
|
||||||
|
|
||||||
== Bugs
|
== Bugs
|
||||||
* Line breaks in a group is constrained to whether all line break hints are
|
* Box based formatting? Other (better) model/algorithm?
|
||||||
to be breaked or not. Maybe, non-constrained version of
|
|
||||||
PrettyPrint#group should be provided to filling multi lines.
|
|
||||||
|
|
||||||
* Box based formatting?
|
|
||||||
|
|
||||||
== References
|
== References
|
||||||
Strictly Pretty, Christian Lindig, March 2000,
|
Christian Lindig, Strictly Pretty, March 2000,
|
||||||
((<URL:http://www.gaertner.de/~lindig/papers/strictly-pretty.html>))
|
((<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>))
|
((<URL:http://cm.bell-labs.com/cm/cs/who/wadler/topics/recent.html#prettier>))
|
||||||
|
|
||||||
=end
|
=end
|
||||||
@ -98,41 +99,37 @@ class PrettyPrint
|
|||||||
end
|
end
|
||||||
|
|
||||||
def nest(indent)
|
def nest(indent)
|
||||||
nest_enter(indent)
|
@nest << @nest.last + indent
|
||||||
begin
|
begin
|
||||||
yield
|
yield
|
||||||
ensure
|
ensure
|
||||||
nest_leave
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def nest_enter(indent)
|
|
||||||
@nest << @nest.last + indent
|
|
||||||
end
|
|
||||||
|
|
||||||
def nest_leave
|
|
||||||
@nest.pop
|
@nest.pop
|
||||||
end
|
end
|
||||||
|
end
|
||||||
|
|
||||||
def group
|
def group
|
||||||
group_enter
|
|
||||||
begin
|
|
||||||
yield
|
|
||||||
ensure
|
|
||||||
group_leave
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def group_enter
|
|
||||||
g = Group.new
|
g = Group.new
|
||||||
@buf << g
|
@buf << g
|
||||||
@stack << @buf
|
@stack << @buf
|
||||||
@buf = g
|
@buf = g
|
||||||
|
begin
|
||||||
|
yield
|
||||||
|
ensure
|
||||||
|
@buf = @stack.pop
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def group_leave
|
def fill_group
|
||||||
|
g = FillGroup.new
|
||||||
|
@buf << g
|
||||||
|
@stack << @buf
|
||||||
|
@buf = g
|
||||||
|
begin
|
||||||
|
yield
|
||||||
|
ensure
|
||||||
@buf = @stack.pop
|
@buf = @stack.pop
|
||||||
end
|
end
|
||||||
|
end
|
||||||
|
|
||||||
def format(out, width=79)
|
def format(out, width=79)
|
||||||
tails = [[-1, 0]]
|
tails = [[-1, 0]]
|
||||||
@ -147,8 +144,10 @@ class PrettyPrint
|
|||||||
end
|
end
|
||||||
|
|
||||||
def update_tails(tails, group)
|
def update_tails(tails, group)
|
||||||
|
@tail = tails[-1][1]
|
||||||
tails[-1][1] += @width
|
tails[-1][1] += @width
|
||||||
end
|
end
|
||||||
|
attr_reader :tail
|
||||||
|
|
||||||
def singleline_width
|
def singleline_width
|
||||||
return @width
|
return @width
|
||||||
@ -174,6 +173,7 @@ class PrettyPrint
|
|||||||
end
|
end
|
||||||
|
|
||||||
def update_tails(tails, group)
|
def update_tails(tails, group)
|
||||||
|
@tail = tails[-1][1]
|
||||||
if group == tails[-1][0]
|
if group == tails[-1][0]
|
||||||
tails[-2][1] += @width + tails[-1][1]
|
tails[-2][1] += @width + tails[-1][1]
|
||||||
tails[-1][1] = 0
|
tails[-1][1] = 0
|
||||||
@ -182,6 +182,7 @@ class PrettyPrint
|
|||||||
tails << [group, 0]
|
tails << [group, 0]
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
attr_reader :tail
|
||||||
|
|
||||||
def singleline_width
|
def singleline_width
|
||||||
return @width
|
return @width
|
||||||
@ -209,18 +210,19 @@ class PrettyPrint
|
|||||||
end
|
end
|
||||||
|
|
||||||
def update_tails(tails, group)
|
def update_tails(tails, group)
|
||||||
@tail = tails.empty? ? 0 : tails[-1][1]
|
@tail = tails[-1][1]
|
||||||
len = 0
|
len = 0
|
||||||
@buf.reverse_each {|obj|
|
@buf.reverse_each {|obj|
|
||||||
obj.update_tails(tails, group + 1)
|
obj.update_tails(tails, group + 1)
|
||||||
len += obj.singleline_width
|
len += obj.singleline_width
|
||||||
}
|
}
|
||||||
@singleline_width = len
|
@singleline_width = len
|
||||||
while !tails.empty? && group <= tails[-1][0]
|
while group < tails[-1][0]
|
||||||
tails[-2][1] += tails[-1][1]
|
tails[-2][1] += tails[-1][1]
|
||||||
tails.pop
|
tails.pop
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
attr_reader :tail
|
||||||
|
|
||||||
def singleline_width
|
def singleline_width
|
||||||
return @singleline_width
|
return @singleline_width
|
||||||
@ -233,7 +235,7 @@ class PrettyPrint
|
|||||||
def multiline_output(out, group, margin, width)
|
def multiline_output(out, group, margin, width)
|
||||||
if margin + singleline_width + @tail <= width
|
if margin + singleline_width + @tail <= width
|
||||||
singleline_output(out)
|
singleline_output(out)
|
||||||
margin += singleline_width
|
margin += @singleline_width
|
||||||
else
|
else
|
||||||
@buf.each {|obj|
|
@buf.each {|obj|
|
||||||
margin = obj.multiline_output(out, group + 1, margin, width)
|
margin = obj.multiline_output(out, group + 1, margin, width)
|
||||||
@ -242,6 +244,20 @@ class PrettyPrint
|
|||||||
return margin
|
return margin
|
||||||
end
|
end
|
||||||
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
|
end
|
||||||
|
|
||||||
if __FILE__ == $0
|
if __FILE__ == $0
|
||||||
@ -674,8 +690,113 @@ End
|
|||||||
|
|
||||||
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(WadlerExample.suite)
|
||||||
RUNIT::CUI::TestRunner.run(StrictPrettyExample.suite)
|
RUNIT::CUI::TestRunner.run(StrictPrettyExample.suite)
|
||||||
RUNIT::CUI::TestRunner.run(TailGroup.suite)
|
RUNIT::CUI::TestRunner.run(TailGroup.suite)
|
||||||
RUNIT::CUI::TestRunner.run(NonString.suite)
|
RUNIT::CUI::TestRunner.run(NonString.suite)
|
||||||
|
RUNIT::CUI::TestRunner.run(Fill.suite)
|
||||||
end
|
end
|
||||||
|
Loading…
x
Reference in New Issue
Block a user