diff --git a/highlighter.d b/highlighter.d index 9a11096..869b872 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("]");
+
+]");
+ }
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