def string(s: String): Result_Buffer = if (s.isEmpty) this else {
buffer match { case (text: Text_Buffer) :: ts => copy(buffer = text.add(s) :: ts) case _ => copy(buffer = Text_Buffer(List(s)) :: buffer)
}
}
}
privatetype State = List[Result_Buffer] privateval init_state: State = List(Result_Buffer())
privatesealedcaseclass Text(
main: State = init_state,
pos: Double = 0.0,
nl: Int = 0
) { def add(elem: Elem_Buffer): Text =
(main: @unchecked) match { case res :: rest => copy(main = res.add(elem) :: rest)
}
def push(m: Markup_Body): Text =
copy(main = Result_Buffer(markup = m) :: main)
def pop: Text =
(main: @unchecked) match { case res1 :: res2 :: rest => copy(main = res2.add(res1.result_elem) :: rest)
}
def result: XML.Body =
(main: @unchecked) match { case List(res) if res.markup == no_markup => res.result_body
}
def reset: Text = copy(main = init_state) def restore(other: Text): Text = copy(main = other.main)
def string(s: String, len: Double): Text =
(main: @unchecked) match { case res :: rest => copy(main = res.string(s) :: rest, pos = pos + len)
} def blanks(wd: Int): Text = string(Symbol.spaces(wd), wd.toDouble) def newline: Text = string("\n", 0.0).copy(pos = 0.0, nl = nl + 1)
}
privatedef break_dist(trees: List[Tree], after: Double): Double =
trees match { case (_: Break) :: _ => 0.0 case t :: ts => t.length + break_dist(ts, after) case Nil => after
}
privatedef force_break(tree: Tree): Tree =
tree match { case Break(false, wd, ind) => Break(true, wd, ind) case _ => tree } privatedef force_all(trees: List[Tree]): List[Tree] = trees.map(force_break)
privatedef force_next(trees: List[Tree]): List[Tree] =
trees match { case Nil => Nil case (t: Break) :: ts => force_break(t) :: ts case t :: ts => t :: force_next(ts)
}
val default_margin: Double = 76.0 val default_breakgain: Double = default_margin / 20
def formatted(input: XML.Body,
recode: String => String = identity,
margin: Double = default_margin,
breakgain: Double = default_breakgain,
metric: Metric = Codepoint.Metric
): XML.Body = { val margin_defined = margin > 0 val margin1 = if (margin_defined) margin else default_margin val emergencypos = ((margin1 / 2) max 1).round.toInt
def make_tree(inp: XML.Body): List[Tree] =
inp flatMap { case XML.Wrapped_Elem(markup1, markup2, body) =>
List(make_block(make_tree(body), markup = (markup1, Some(markup2)), open_block = true)) case XML.Elem(markup, body) =>
markup match { case Markup.Block(consistent, indent) =>
List(make_block(make_tree(body), consistent = consistent, indent = indent)) case Markup.Break(width, indent) =>
List(Break(false, force_nat(width), force_nat(indent))) case Markup(Markup.ITEM, _) =>
List(make_block(make_tree(bullet ::: body), markup = item_markup, indent = 2)) case _ =>
List(make_block(make_tree(body), markup = (markup, None), open_block = true))
} case XML.Text(text) =>
Library.separate(FBreak,
split_lines(text).map { s0 => val s = recode(s0); Str(s, metric(s)) })
}
def format(trees: List[Tree], before: Double, after: Double, text: Text): Text =
trees match { case Nil => text case End :: ts => format(ts, before, after, text.pop) case (block: Block) :: ts if block.open_block =>
format(block.body ::: End :: ts, before, after, text.push(block.markup)) case (block: Block) :: ts => val pos1 = text.pos + block.indent val pos2 = (pos1.round.toInt % emergencypos).toDouble val before1 = if (!margin_defined || pos1 < emergencypos) pos1 else pos2 val after1 = break_dist(ts, after) val body1 = if (margin_defined && block.consistent && text.pos + block.length > margin - after1) {
force_all(block.body)
} else block.body val btext1 = if (block.markup == no_markup) format(body1, before1, after1, text) else { val btext = format(body1, before1, after1, text.reset) val elem = Elem_Buffer(block.markup, btext.result)
btext.restore(text.add(elem))
} val ts1 = if (text.nl < btext1.nl) force_next(ts) else ts
format(ts1, before, after, btext1) case Break(force, wd, ind) :: ts => if (!force &&
(!margin_defined ||
text.pos + wd <= ((margin - break_dist(ts, after)) max (before + breakgain)))) {
format(ts, before, after, text.blanks(wd))
} else format(ts, before, after, text.newline.blanks((before + ind).ceil.toInt)) case Str(s, len) :: ts => format(ts, before, after, text.string(s, len))
}
format(make_tree(input), 0.0, 0.0, Text()).result
}
¤ Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.0.7Bemerkung:
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung ist noch experimentell.