Skip to content

Commit

Permalink
Giant act of yak shaving. We now reorder attributes, so that they are…
Browse files Browse the repository at this point in the history
… printed in the same order they are read in, and we also add some front matter which mimics the common front matter in the repository. We hard code self closing tags to not have a space between the close of the inner matter and the '/>', as this is the usual style; this may still result in ugly diffs for some documents, as it is hard coded.
  • Loading branch information
flaviusb committed Jul 12, 2010
1 parent cf2cc76 commit 9dcd066
Showing 1 changed file with 82 additions and 3 deletions.
85 changes: 82 additions & 3 deletions constantscript.scala
@@ -1,6 +1,8 @@
import java.io.File
import java.io._
import scala.xml._
import scala.xml.transform._
import java.nio.channels.Channels
import scala.util.control.Exception.ultimately

object constantconverter extends RewriteRule {
override def transform(node: Node) = node match {
Expand All @@ -22,14 +24,91 @@ object constantconverter extends RewriteRule {
case _ => n
}
}
case (mde: Elem) => {
// Time for some yak shaving; we must reverse the attribute list, as it is kept reversed at the moment in scala
def reverse(first: MetaData, next: MetaData): MetaData = {
// First time through is null, first
// Last time through is last, null
if (next == null || next == scala.xml.Null)
return first;

val intermediate = next.copy(first)
reverse(intermediate, next.next)
}
mde.copy(attributes=reverse(scala.xml.Null, mde.attributes))
}
case otherwise => otherwise
}
// Epic yak shaving
def isAtomAndNotText(x: Node) = x.isAtom && !x.isInstanceOf[Text]
def toXML(
x: Node,
pscope: NamespaceBinding = TopScope,
sb: StringBuilder = new StringBuilder,
stripComments: Boolean = false,
decodeEntities: Boolean = true,
preserveWhitespace: Boolean = false,
minimizeTags: Boolean = false): StringBuilder =
{
x match {
case c: Comment => if (!stripComments) c buildString sb else sb
case x: SpecialNode => x buildString sb
case g: Group =>
g.nodes foreach {toXML(_, x.scope, sb, stripComments, decodeEntities, preserveWhitespace, minimizeTags)}
sb
case _ =>
// print tag with namespace declarations
sb.append('<')
x.nameToString(sb)
if (x.attributes ne null) x.attributes.buildString(sb)
x.scope.buildString(sb, pscope)
if (x.child.isEmpty && minimizeTags) {
// no children, so use short form: <xyz .../>
sb.append("/>")
} else {
// children, so use long form: <xyz ...>...</xyz>
sb.append('>')
sequenceToXML(x.child, x.scope, sb, stripComments, decodeEntities, preserveWhitespace, minimizeTags)
sb.append("</")
x.nameToString(sb)
sb.append('>')
}
}
}

def sequenceToXML(
children: Seq[Node],
pscope: NamespaceBinding = TopScope,
sb: StringBuilder = new StringBuilder,
stripComments: Boolean = false,
decodeEntities: Boolean = true,
preserveWhitespace: Boolean = false,
minimizeTags: Boolean = false): Unit =
{
if (children.isEmpty) return
else if (children forall isAtomAndNotText) { // add space
val it = children.iterator
val f = it.next
toXML(f, pscope, sb, stripComments, decodeEntities, preserveWhitespace, minimizeTags)
while (it.hasNext) {
val x = it.next
sb.append(' ')
toXML(x, pscope, sb, stripComments, decodeEntities, preserveWhitespace, minimizeTags)
}
}
else children foreach { toXML(_, pscope, sb, stripComments, decodeEntities, preserveWhitespace, minimizeTags) }
}
final def write(w: java.io.Writer, node: Node) {
w.write("<?xml version=\"1.0\" encoding=\"utf-8\"?>\n")
w.write(toXML(node, preserveWhitespace=true, minimizeTags=true).toString)
}
def main(args: Array[String]) = {
for(file <- args) {
var doc = XML.load(file)
val fdoc = new RuleTransformer(constantconverter).transform(doc).head
//println(fdoc)
XML.save(file, fdoc)
val fos = new FileOutputStream(file)
val w = Channels.newWriter(fos.getChannel(), "utf-8")
ultimately(w.close())(write(w, fdoc))
}
}
}

0 comments on commit 9dcd066

Please sign in to comment.