diff --git a/highlighter.d b/highlighter.d index 9a110964..869b8726 100644 --- a/highlighter.d +++ b/highlighter.d @@ -8,24 +8,70 @@ module highlighter; import std.stdio; import std.array; +import std.range; import std.d.lexer; -void writeSpan(string cssClass, string value) +void writeSpan(Sink)(ref Sink sink, string cssClassPrefix, string cssClass, string value) + if(isOutputRange!(Sink, string)) { - stdout.write(``, value.replace("&", "&").replace("<", "<"), ``); + sink.put(``); + sink.put(value.replace("&", "&").replace("<", "<")); + sink.put(``); } +private struct StdoutSink +{ + void put(string data) + { + stdout.write(data); + } +} // http://ethanschoonover.com/solarized void highlight(R)(TokenRange!R tokens, string fileName) { - stdout.writeln(q"[ + StdoutSink sink; + highlight(tokens, sink, fileName); +} + +/// Outputs span-highlighted code only, no wrapper HTML +void highlightBare(R)(TokenRange!R tokens, string cssClassPrefix=null) +{ + StdoutSink sink; + highlightBare(tokens, sink, cssClassPrefix); +} + +void highlight(R, Sink)(TokenRange!R tokens, ref Sink sink, string fileName) + if (isOutputRange!(Sink, string)) +{ + highlightImpl(tokens, sink, fileName, false, null); +} + +/// Outputs span-highlighted code only, no wrapper HTML +void highlightBare(R, Sink)(TokenRange!R tokens, ref Sink sink, string cssClassPrefix=null) + if (isOutputRange!(Sink, string)) +{ + highlightImpl(tokens, sink, null, true, cssClassPrefix); +} + +private void highlightImpl(R, Sink)(TokenRange!R tokens, ref Sink sink, string fileName, bool bare, string cssClassPrefix) + if (isOutputRange!(Sink, string)) +{ + if (!bare) + { + sink.put(q"[ -]"); - stdout.writeln("", fileName, ""); - stdout.writeln(q"[ + +]"); + sink.put(""); + sink.put(fileName); + sink.put("\n"); + sink.put(q"[ -
]");
+
+]");
+	}
 
 	foreach (Token t; tokens)
 	{
 		if (isBasicType(t.type))
-			writeSpan("type", t.value);
+			writeSpan(sink, cssClassPrefix, "type", t.value);
 		else if (isKeyword(t.type))
-			writeSpan("kwrd", t.value);
+			writeSpan(sink, cssClassPrefix, "kwrd", t.value);
 		else if (t.type == TokenType.comment)
-			writeSpan("com", t.value);
+			writeSpan(sink, cssClassPrefix, "com", t.value);
 		else if (isStringLiteral(t.type) || t.type == TokenType.characterLiteral)
-			writeSpan("str", t.value);
+			writeSpan(sink, cssClassPrefix, "str", t.value);
 		else if (isNumberLiteral(t.type))
-			writeSpan("num", t.value);
+			writeSpan(sink, cssClassPrefix, "num", t.value);
 		else if (isOperator(t.type))
-			writeSpan("op", t.value);
+			writeSpan(sink, cssClassPrefix, "op", t.value);
 		else
-			stdout.write(t.value.replace("<", "<"));
+			sink.put(t.value.replace("<", "<"));
 	}
-	stdout.writeln("
\n"); + + if (!bare) + sink.put("
\n\n"); } /+void main(string[] args)