From 0212d859364a31928548c820a502038f69c27b4c Mon Sep 17 00:00:00 2001 From: Nick Sabalausky Date: Thu, 1 Aug 2013 23:08:12 -0400 Subject: [PATCH 1/3] highlighter takes optional output range. --- highlighter.d | 57 ++++++++++++++++++++++++++++++++++++--------------- 1 file changed, 41 insertions(+), 16 deletions(-) diff --git a/highlighter.d b/highlighter.d index 9a11096..5182822 100644 --- a/highlighter.d +++ b/highlighter.d @@ -8,24 +8,48 @@ 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 cssClass, string value) + if(isOutputRange!(Sink, string)) { - stdout.write(``, value.replace("&", "&").replace("<", "<"), ``); + sink.put(``); + sink.put(value.replace("&", "&").replace("<", "<")); + sink.put(``); } -// http://ethanschoonover.com/solarized void highlight(R)(TokenRange!R tokens, string fileName) { - stdout.writeln(q"[ + struct StdoutSink + { + void put(string data) + { + stdout.write(data); + } + } + + StdoutSink sink; + highlight(tokens, sink, fileName); +} + +// http://ethanschoonover.com/solarized +void highlight(R, Sink)(TokenRange!R tokens, ref Sink sink, string fileName) + if(isOutputRange!(Sink, string)) +{ + 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, "type", t.value);
 		else if (isKeyword(t.type))
-			writeSpan("kwrd", t.value);
+			writeSpan(sink, "kwrd", t.value);
 		else if (t.type == TokenType.comment)
-			writeSpan("com", t.value);
+			writeSpan(sink, "com", t.value);
 		else if (isStringLiteral(t.type) || t.type == TokenType.characterLiteral)
-			writeSpan("str", t.value);
+			writeSpan(sink, "str", t.value);
 		else if (isNumberLiteral(t.type))
-			writeSpan("num", t.value);
+			writeSpan(sink, "num", t.value);
 		else if (isOperator(t.type))
-			writeSpan("op", t.value);
+			writeSpan(sink, "op", t.value);
 		else
-			stdout.write(t.value.replace("<", "<"));
+			sink.put(t.value.replace("<", "<"));
 	}
-	stdout.writeln("
\n"); + sink.put("
\n\n"); } /+void main(string[] args) From 901c777862dc59b0f6bfbbac964c4518c43f2902 Mon Sep 17 00:00:00 2001 From: Nick Sabalausky Date: Thu, 1 Aug 2013 23:18:44 -0400 Subject: [PATCH 2/3] Add 'highlightBare' function which only outputs the span-highlighted code, without any wrapper HTML. --- highlighter.d | 50 +++++++++++++++++++++++++++++++++++++------------- 1 file changed, 37 insertions(+), 13 deletions(-) diff --git a/highlighter.d b/highlighter.d index 5182822..0b8b60a 100644 --- a/highlighter.d +++ b/highlighter.d @@ -21,26 +21,47 @@ void writeSpan(Sink)(ref Sink sink, string cssClass, string value) sink.put(``); } +private struct StdoutSink +{ + void put(string data) + { + stdout.write(data); + } +} +// http://ethanschoonover.com/solarized void highlight(R)(TokenRange!R tokens, string fileName) { - struct StdoutSink - { - void put(string data) - { - stdout.write(data); - } - } - StdoutSink sink; highlight(tokens, sink, fileName); } -// http://ethanschoonover.com/solarized -void highlight(R, Sink)(TokenRange!R tokens, ref Sink sink, string fileName) - if(isOutputRange!(Sink, string)) +/// Outputs span-highlighted code only, no wrapper HTML +void highlightBare(R)(TokenRange!R tokens) { - sink.put(q"[ + StdoutSink sink; + highlightBare(tokens, sink); +} + +void highlight(R, Sink)(TokenRange!R tokens, ref Sink sink, string fileName) + if (isOutputRange!(Sink, string)) +{ + highlightImpl(tokens, sink, fileName, false); +} + +/// Outputs span-highlighted code only, no wrapper HTML +void highlightBare(R, Sink)(TokenRange!R tokens, ref Sink sink) + if (isOutputRange!(Sink, string)) +{ + highlightImpl(tokens, sink, null, true); +} + +private void highlightImpl(R, Sink)(TokenRange!R tokens, ref Sink sink, string fileName, bool bare) + if (isOutputRange!(Sink, string)) +{ + if (!bare) + { + sink.put(q"[ @@ -63,6 +84,7 @@ html { background-color: #fdf6e3; color: #002b36; }
 ]");
+	}
 
 	foreach (Token t; tokens)
 	{
@@ -81,7 +103,9 @@ html  { background-color: #fdf6e3; color: #002b36; }
 		else
 			sink.put(t.value.replace("<", "<"));
 	}
-	sink.put("
\n\n"); + + if (!bare) + sink.put("\n\n"); } /+void main(string[] args) From f290e057247c3b35e14bcf055dfa55ef7544eadd Mon Sep 17 00:00:00 2001 From: Nick Sabalausky Date: Thu, 1 Aug 2013 23:26:55 -0400 Subject: [PATCH 3/3] highlightBare supports optional CSS class prefix for better CSS hygiene. --- highlighter.d | 27 ++++++++++++++------------- 1 file changed, 14 insertions(+), 13 deletions(-) diff --git a/highlighter.d b/highlighter.d index 0b8b60a..869b872 100644 --- a/highlighter.d +++ b/highlighter.d @@ -11,10 +11,11 @@ import std.array; import std.range; import std.d.lexer; -void writeSpan(Sink)(ref Sink sink, string cssClass, string value) +void writeSpan(Sink)(ref Sink sink, string cssClassPrefix, string cssClass, string value) if(isOutputRange!(Sink, string)) { sink.put(``); sink.put(value.replace("&", "&").replace("<", "<")); @@ -37,26 +38,26 @@ void highlight(R)(TokenRange!R tokens, string fileName) } /// Outputs span-highlighted code only, no wrapper HTML -void highlightBare(R)(TokenRange!R tokens) +void highlightBare(R)(TokenRange!R tokens, string cssClassPrefix=null) { StdoutSink sink; - highlightBare(tokens, 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); + highlightImpl(tokens, sink, fileName, false, null); } /// Outputs span-highlighted code only, no wrapper HTML -void highlightBare(R, Sink)(TokenRange!R tokens, ref Sink sink) +void highlightBare(R, Sink)(TokenRange!R tokens, ref Sink sink, string cssClassPrefix=null) if (isOutputRange!(Sink, string)) { - highlightImpl(tokens, sink, null, true); + highlightImpl(tokens, sink, null, true, cssClassPrefix); } -private void highlightImpl(R, Sink)(TokenRange!R tokens, ref Sink sink, string fileName, bool bare) +private void highlightImpl(R, Sink)(TokenRange!R tokens, ref Sink sink, string fileName, bool bare, string cssClassPrefix) if (isOutputRange!(Sink, string)) { if (!bare) @@ -89,17 +90,17 @@ html { background-color: #fdf6e3; color: #002b36; } foreach (Token t; tokens) { if (isBasicType(t.type)) - writeSpan(sink, "type", t.value); + writeSpan(sink, cssClassPrefix, "type", t.value); else if (isKeyword(t.type)) - writeSpan(sink, "kwrd", t.value); + writeSpan(sink, cssClassPrefix, "kwrd", t.value); else if (t.type == TokenType.comment) - writeSpan(sink, "com", t.value); + writeSpan(sink, cssClassPrefix, "com", t.value); else if (isStringLiteral(t.type) || t.type == TokenType.characterLiteral) - writeSpan(sink, "str", t.value); + writeSpan(sink, cssClassPrefix, "str", t.value); else if (isNumberLiteral(t.type)) - writeSpan(sink, "num", t.value); + writeSpan(sink, cssClassPrefix, "num", t.value); else if (isOperator(t.type)) - writeSpan(sink, "op", t.value); + writeSpan(sink, cssClassPrefix, "op", t.value); else sink.put(t.value.replace("<", "<")); }