34 def separate(ts: List[XML.Tree]): XML.Body = Library.separate(Separator, ts.map(List(_))).flatten |
33 def separate(ts: List[XML.Tree]): XML.Body = Library.separate(Separator, ts.map(List(_))).flatten |
35 |
34 |
36 |
35 |
37 /* text metric -- standardized to width of space */ |
36 /* text metric -- standardized to width of space */ |
38 |
37 |
39 abstract class Metric |
38 abstract class Metric { |
40 { |
|
41 val unit: Double |
39 val unit: Double |
42 def apply(s: String): Double |
40 def apply(s: String): Double |
43 } |
41 } |
44 |
42 |
45 object Default_Metric extends Metric |
43 object Default_Metric extends Metric { |
46 { |
|
47 val unit = 1.0 |
44 val unit = 1.0 |
48 def apply(s: String): Double = s.length.toDouble |
45 def apply(s: String): Double = s.length.toDouble |
49 } |
46 } |
50 |
47 |
51 |
48 |
55 |
52 |
56 private sealed abstract class Tree { def length: Double } |
53 private sealed abstract class Tree { def length: Double } |
57 private case class Block( |
54 private case class Block( |
58 markup: Option[(Markup, Option[XML.Body])], |
55 markup: Option[(Markup, Option[XML.Body])], |
59 consistent: Boolean, indent: Int, body: List[Tree], length: Double) extends Tree |
56 consistent: Boolean, indent: Int, body: List[Tree], length: Double) extends Tree |
60 private case class Break(force: Boolean, width: Int, indent: Int) extends Tree |
57 private case class Break(force: Boolean, width: Int, indent: Int) extends Tree { |
61 { def length: Double = width.toDouble } |
58 def length: Double = width.toDouble |
|
59 } |
62 private case class Str(string: String, length: Double) extends Tree |
60 private case class Str(string: String, length: Double) extends Tree |
63 |
61 |
64 private val FBreak = Break(true, 1, 0) |
62 private val FBreak = Break(true, 1, 0) |
65 |
63 |
66 private def make_block( |
64 private def make_block( |
67 markup: Option[(Markup, Option[XML.Body])], |
65 markup: Option[(Markup, Option[XML.Body])], |
68 consistent: Boolean, |
66 consistent: Boolean, |
69 indent: Int, |
67 indent: Int, |
70 body: List[Tree]): Tree = |
68 body: List[Tree] |
71 { |
69 ): Tree = { |
72 val indent1 = force_nat(indent) |
70 val indent1 = force_nat(indent) |
73 |
71 |
74 @tailrec def body_length(prts: List[Tree], len: Double): Double = |
72 @tailrec def body_length(prts: List[Tree], len: Double): Double = { |
75 { |
|
76 val (line, rest) = |
73 val (line, rest) = |
77 Library.take_prefix[Tree]({ case Break(true, _, _) => false case _ => true }, prts) |
74 Library.take_prefix[Tree]({ case Break(true, _, _) => false case _ => true }, prts) |
78 val len1 = (line.foldLeft(0.0) { case (l, t) => l + t.length }) max len |
75 val len1 = (line.foldLeft(0.0) { case (l, t) => l + t.length }) max len |
79 (rest: @unchecked) match { |
76 (rest: @unchecked) match { |
80 case Break(true, _, ind) :: rest1 => |
77 case Break(true, _, ind) :: rest1 => |
86 } |
83 } |
87 |
84 |
88 |
85 |
89 /* formatted output */ |
86 /* formatted output */ |
90 |
87 |
91 private sealed case class Text(tx: XML.Body = Nil, pos: Double = 0.0, nl: Int = 0) |
88 private sealed case class Text(tx: XML.Body = Nil, pos: Double = 0.0, nl: Int = 0) { |
92 { |
|
93 def newline: Text = copy(tx = fbrk :: tx, pos = 0.0, nl = nl + 1) |
89 def newline: Text = copy(tx = fbrk :: tx, pos = 0.0, nl = nl + 1) |
94 def string(s: String, len: Double): Text = |
90 def string(s: String, len: Double): Text = |
95 copy(tx = if (s == "") tx else XML.Text(s) :: tx, pos = pos + len) |
91 copy(tx = if (s == "") tx else XML.Text(s) :: tx, pos = pos + len) |
96 def blanks(wd: Int): Text = string(Symbol.spaces(wd), wd.toDouble) |
92 def blanks(wd: Int): Text = string(Symbol.spaces(wd), wd.toDouble) |
97 def content: XML.Body = tx.reverse |
93 def content: XML.Body = tx.reverse |
119 val default_breakgain: Double = default_margin / 20 |
115 val default_breakgain: Double = default_margin / 20 |
120 |
116 |
121 def formatted(input: XML.Body, |
117 def formatted(input: XML.Body, |
122 margin: Double = default_margin, |
118 margin: Double = default_margin, |
123 breakgain: Double = default_breakgain, |
119 breakgain: Double = default_breakgain, |
124 metric: Metric = Default_Metric): XML.Body = |
120 metric: Metric = Default_Metric |
125 { |
121 ): XML.Body = { |
126 val emergencypos = (margin / 2).round.toInt |
122 val emergencypos = (margin / 2).round.toInt |
127 |
123 |
128 def make_tree(inp: XML.Body): List[Tree] = |
124 def make_tree(inp: XML.Body): List[Tree] = |
129 inp flatMap { |
125 inp flatMap { |
130 case XML.Wrapped_Elem(markup, body1, body2) => |
126 case XML.Wrapped_Elem(markup, body1, body2) => |