Skip to content

Commit

Permalink
added support for pretty print.
Browse files Browse the repository at this point in the history
  • Loading branch information
alvinrdeleon committed May 19, 2015
1 parent 2335f12 commit fc13a4d
Show file tree
Hide file tree
Showing 122 changed files with 4,758 additions and 41,735 deletions.
Expand Up @@ -18,34 +18,74 @@

package org.jspringbot.syntax;

import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang.StringEscapeUtils;
import org.python.core.PySystemState;
import org.python.util.PythonInterpreter;

import org.apache.commons.lang.StringUtils;
import syntaxhighlight.ParseResult;
import syntaxhighlight.Style;
import syntaxhighlight.Theme;
import syntaxhighlighter.SyntaxHighlighterParser;
import syntaxhighlighter.brush.*;
import syntaxhighlighter.theme.*;

import java.awt.*;
import java.io.IOException;
import java.io.StringWriter;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;

/**
* Highlighter utility class
*/
public class HighlighterUtils {

public static final String DEFAULT_THEME = "default";

public static final Map<String, Theme> THEME_MAP = new HashMap<String, Theme>() {{
put(DEFAULT_THEME, new ThemeDefault());
put("django", new ThemeDjango());
put("eclipse", new ThemeEclipse());
put("emacs", new ThemeEmacs());
put("grey", new ThemeFadeToGrey());
put("mdultra", new ThemeMDUltra());
put("midnight", new ThemeMidnight());
put("rdark", new ThemeRDark());
}};


public static final HighlighterUtils INSTANCE = new HighlighterUtils();

public static HighlighterUtils instance() {
return INSTANCE;
}

private PythonInterpreter interpreter;

private boolean enable = false;

private Theme theme;

private Map<String, SyntaxHighlighterParser> parserMap;

private HighlighterUtils() {
PySystemState sys = new PySystemState();
sys.setrecursionlimit(12000);
parserMap = new HashMap<String, SyntaxHighlighterParser>();

parserMap.put("xml", new SyntaxHighlighterParser(new BrushXml()));
parserMap.put("css", new SyntaxHighlighterParser(new BrushCss()));
parserMap.put("json", new SyntaxHighlighterParser(new BrushJScript()));
parserMap.put("javascript", new SyntaxHighlighterParser(new BrushJScript()));
parserMap.put("sql", new SyntaxHighlighterParser(new BrushSql()));
parserMap.put("text", new SyntaxHighlighterParser(new BrushPlain()));
parserMap.put("clojure", new SyntaxHighlighterParser(new BrushJScript()));

theme = THEME_MAP.get(DEFAULT_THEME);
}

public void setTheme(String theme) {
this.theme = THEME_MAP.get(theme);

interpreter = new PythonInterpreter(null, sys);
if(this.theme == null) {
this.theme = THEME_MAP.get(DEFAULT_THEME);
}
}

public void setEnable(boolean enable) {
Expand Down Expand Up @@ -99,15 +139,65 @@ public String highlight(String code, String type, boolean linenumber) {
return "\n" + StringEscapeUtils.escapeHtml(code);
}

interpreter.set("code", code);
interpreter.set("type", type);
SyntaxHighlighterParser parser = parserMap.get(type);
if(parser == null) {
return "\n" + StringEscapeUtils.escapeHtml(code);
}

int i = 0;
StringBuilder buf = new StringBuilder();

for (ParseResult result : parser.parse(code)) {
String before = StringUtils.substring(code, i, result.getOffset());
if (StringUtils.isNotBlank(before)) {
buf.append(StringEscapeUtils.escapeHtml(before));
}

String token = StringUtils.substring(code, result.getOffset(), result.getOffset() + result.getLength());
buf.append("<span");

if(CollectionUtils.isNotEmpty(result.getStyleKeys())) {
buf.append(" style=\"");

for(String styleKey : result.getStyleKeys()) {
Style style = theme.getStyle(styleKey);

if(style.isBold()) {
buf.append("font-weight:bold;");
}
if(style.isItalic()) {
buf.append("font-style:italic;");
}
if(style.isUnderline()) {
buf.append("text-decoration:underline;");
}

Color foreColor = style.getColor();
Color bgColor = style.getBackground();

if(foreColor != null) {
cssColor(buf, "color", foreColor);
}
if(bgColor != null) {
cssColor(buf, "background-color", bgColor);
}
}

buf.append("\"");
}

buf.append(">");
buf.append(token);
buf.append("</span>");
}

return buf.toString();
}

interpreter.exec("from pygments import highlight\n" +
"from pygments.lexers import get_lexer_by_name\n" +
"from pygments.formatters import HtmlFormatter\n" +
"formatter = HtmlFormatter(cssclass=\"syntax\"" + (linenumber ? ",linenos=\"table\"" : "") + ")\n" +
"result = highlight(code, get_lexer_by_name(type), formatter)\n");
private static void cssColor(StringBuilder buf, String style, Color color) {
String rgb = Integer.toHexString(color.getRGB());
rgb = rgb.substring(2, rgb.length());

return String.valueOf(interpreter.get("result")) + "<link rel='stylesheet' href='highlight.css'>";
buf.append(style).append(":#").append(StringUtils.lowerCase(rgb)).append(";");
}
}
@@ -0,0 +1,175 @@
// Copyright (c) 2012 Chan Wai Shing
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
package syntaxhighlight;

import java.util.ArrayList;
import java.util.List;

/**
* The parser parsed result.
*
* This class include the information needed to highlight the syntax.
* Information includes where the content located in the document (offset and
* length) and what style(s) should be applied on that segment of content.
*
* @author Chan Wai Shing <cws1989@gmail.com>
*/
public class ParseResult {

/**
* The start position of the content.
*/
protected int offset;
/**
* The length of the content.
*/
protected int length;
/**
* The style keys of the content. The style at higher index of the list will
* override the style of the lower index.
*/
protected List<String> styleKeys;

/**
* Constructor.
*
* @param offset the start position of the content
* @param length the length of the content
* @param styleKeys the style keys of the content
*/
public ParseResult(int offset, int length, List<String> styleKeys) {
this.offset = offset;
this.length = length;
this.styleKeys = new ArrayList<String>(styleKeys);
}

/**
* The start position of the content.
* @return the start position of the content
*/
public int getOffset() {
return offset;
}

/**
* The start position of the content.
* @param offset the start position of the content
*/
public void setOffset(int offset) {
this.offset = offset;
}

/**
* The length of the content.
* @return the length of the content
*/
public int getLength() {
return length;
}

/**
* The length of the content.
* @param length the length of the content
*/
public void setLength(int length) {
this.length = length;
}

/**
* Get the style keys represented by one string key, see
* {@link Theme#getStylesAttributeSet(String)}.
* @return the style keys of the content
*/
public String getStyleKeysString() {
StringBuilder sb = new StringBuilder(10);
for (int i = 0, iEnd = styleKeys.size(); i < iEnd; i++) {
if (i != 0) {
sb.append(" ");
}
sb.append(styleKeys.get(i));
}
return sb.toString();
}

/**
* The style keys of the content.
* @param styleKeys the style keys of the content
*/
public void setStyleKeys(List<String> styleKeys) {
this.styleKeys = new ArrayList<String>(styleKeys);
}

/**
* The style keys of the content.
* @param styleKey the style key
* @return see the return value of {@link List#add(Object)}
*/
public boolean addStyleKey(String styleKey) {
return styleKeys.add(styleKey);
}

/**
* The style keys of the content.
* @param styleKey the style key
* @return see the return value of {@link List#remove(Object)}
*/
public boolean removeStyleKey(String styleKey) {
return styleKeys.remove(styleKey);
}

/**
* The style keys of the content.
*/
public void clearStyleKeys() {
styleKeys.clear();
}

/**
* The style keys for this matched result, see {@link syntaxhighlighter.theme}.
* @return the style keys
*/
public List<String> getStyleKeys() {
return new ArrayList<String>(styleKeys);
}

/**
* {@inheritDoc}
*/
@Override
public String toString() {
StringBuilder sb = new StringBuilder();

sb.append("[");
sb.append(offset);
sb.append("; ");
sb.append(length);
sb.append("; ");
for (int i = 0, iEnd = styleKeys.size(); i < iEnd; i++) {
if (i != 0) {
sb.append(", ");
}
sb.append(styleKeys.get(i));
}
sb.append("]");

return sb.toString();
}
}
42 changes: 42 additions & 0 deletions jspringbot-pretty-logger/src/main/java/syntaxhighlight/Parser.java
@@ -0,0 +1,42 @@
// Copyright (c) 2012 Chan Wai Shing
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
package syntaxhighlight;

import java.util.List;

/**
* The parser for syntax highlight.
*
* @author Chan Wai Shing <cws1989@gmail.com>
*/
public interface Parser {

List<ParseResult> parse(String content);

/**
* Parse the {@code content} and return the parsed result.
* @param fileExtension the file extension of the content, null means not
* provided
* @param content the content
* @return the parsed result
*/
List<ParseResult> parse(String fileExtension, String content);
}

0 comments on commit fc13a4d

Please sign in to comment.