这篇文章是对 Java 实现语法高亮的局部;我用 Java 的起因是 Android App 开发须要,因为我用的是 Android Studio ,所以着色的格调是参考的 Android Studio 默认色彩;思考到 Java 与 C# 属于同等级别的编译型高级语言,而且它们的语法较相似,所以能够在之前 C# 高亮的根底上履行批改:
//可用的语法着色数据
var Colors = {
//Java 暗
JavaDark: {
"language": "Java",
"theme": "dark",
"classColor": "#FFC66D",
"annotationColor": "#808080",
"annotationsColor": "#808080",
"stringColor": "#71A567",
"constantColor": "#5295CB",
"notesColor": "#BBB529",
"keywordsInfo": [{
"color": "#CB772F",
"keywords": ["abstract", "assert", "boolean", "break", "byte", "case", "catch", "char", "class", "const", "continue", "default", "do", "double", "else", "enum", "extends", "false", "final", "finally", "float", "for", "goto", "if", "implements", "import", "int", "instanceof", "interface", "long", "native", "new", "null", "object", "operator", "out", "override", "package", "private", "protected", "public", "return", " strictfp", "super", "short", "switch", "synchronized", "static", "string", "struct", "switch", "this", "throw", "throws", "true", "try", "transient", "void", "volatile", "while"]
}],
"customClassInfo": [{
"color": "#B8D7A3",
"keywords": ["Calendar", "Color", "ForegroundColorSpan", "InputMethodManager", "Log", "PreferenceManager", "R", "Spanned", "String", "StyleSpan", "Typeface"]
}]
}
};
//应用某一种色彩数据对指定的文本进行语法着色(主入口)
function StainColor(text, colorObj) {
if (colorObj.language == "Java") {
return StainGrammerJava(text, colorObj);
}
}
//Java 语法着色
function StainGrammerJava(text, colorObj) {
text = text.replace(/&/g, "&");
text = text.replace(/\</g, "<").replace(/\>/g, ">");
var t_regex = null;
var strings = new Array();
var tstring = null;
//临时排除一般字符串
while (tstring = text.match(/"(?:(?:\\")|[^"\r\n])*"/)) {
text = text.replace(/"(?:(?:\\")|[^"\r\n])*"/, "###str_{" + strings.length + "}###");
strings.push(tstring[0]);
}
//临时排除多行正文
var comments = new Array();
var tcomment = null;
while (tcomment = text.match(/\/\*(?:.|\s)*?\*\//)) {
text = text.replace(/\/\*(?:.|\s)*?\*\//, "###comment_{" + comments.length + "}###");
comments.push(tcomment[0]);
}
//临时排除单行正文
var annotations = new Array();
var tannotation = null;
while (tannotation = text.match(/\/\/.*/)) {
text = text.replace(/\/\/.*/, "###annotation_{" + annotations.length + "}###");
annotations.push(tannotation[0]);
}
//临时排除单字符
var chars = new Array();
var tchar = null;
while (tchar = text.match(/(?:'\\?[^\\]')|''/)) {
text = text.replace(/(?:'\\?[^\\]')|''/, "###char_{" + chars.length + "}###");
chars.push(tchar[0]);
}
//临时排除@注解
var notes = new Array();
var tnote = null;
while (tnote = text.match(/@ *\w+/)) {
text = text.replace(/@ *\w+/, "###note_{" + notes.length + "}###");
notes.push(tnote[0]);
}
//临时排除常数
var constants = new Array();
var tconstant = null;
while (tconstant = text.match(/\b\d+(?!\}#)\b/)) {
text = text.replace(/\b\d+(?!\}#)\b/, "###constant_{" + constants.length + "}###");
constants.push(tconstant[0]);
}
//临时排除16进制常数
while (tconstant = text.match(/\b0x(?:[0-9]|[a-f]|[A-F])+\b/)) {
text = text.replace(/\b0x(?:[0-9]|[a-f]|[A-F])+\b/, "###constant_{" + constants.length + "}###");
constants.push(tconstant[0]);
}
//临时排除类申明与定义局部
var classes = new Array();
var tclass = null;
while (tclass = text.match(/class +\w+/)) {
text = text.replace(/class +\w+/, "###class_{" + classes.length + "}###");
classes.push(tclass[0]);
}
//临时排除接口申明与定义局部
var interfaces = new Array();
var tinterface = null;
while (tinterface = text.match(/interface +\w+/)) {
text = text.replace(/interface +\w+/, "###interface_{" + interfaces.length + "}###");
interfaces.push(tinterface[0]);
}
//临时排除异样捕捉的类型
var exceptions = new Array();
var texception = null;
while (texception = text.match(/catch *\([ *\w\.]+(?=(?: +\w+))/)) {
text = text.replace(/catch *\([ *\w\.]+(?=(?: +\w+))/, "###exception_{" + exceptions.length + "}###");
exceptions.push(texception[0]);
}
//临时排除类型申明与初始化
var types = new Array();
var ttype = null;
while (ttype = text.match(/\w+(?= *\?? *(?:\[\])? +\w+ *[;=,\)])/)) {
text = text.replace(/\w+(?= *\?? *(?:\[\])? +\w+ *[;=,\)])/, "###type_{" + types.length + "}###");
types.push(ttype[0]);
}
//临时排除 new 关键字的类型实例化
var newes = new Array();
var tnew = null;
while (tnew = text.match(/new +[\w\. ]+ *[\(\[]/)) {
text = text.replace(/new +[\w\. ]+ *[\(\[]/, "###new_{" + newes.length + "}###");
newes.push(tnew[0]);
}
//临时排除泛型申明与一般办法的泛型返回类型
var genericsl = new Array();
var tgenericl = null;
while (tgenericl = text.match(/\w+(?= *(?:<) *(?:\w+|\?)(?:(?:<)|(?:>)|,|\w| |\.)* *(?:>)(?: *\[ *\])? +\w+ *[;=,\(\)])/)) {
text = text.replace(/\w+(?= *(?:<) *(?:\w+|\?)(?:(?:<)|(?:>)|,|\w| |\.)* *(?:>)(?: *\[ *\])? +\w+ *[;=,\(\)])/, "###genericl_{" + genericsl.length + "}###");
genericsl.push(tgenericl[0]);
}
//临时排除 new 关键字的泛型实例化
var newgenerics = new Array();
var tnewgeneric = null;
while (tnewgeneric = text.match(/new +[\w]+ *(?:<) *\w*(?:(?:<)|(?:>)|,|\w| |\.)* *(?:>) *\(/)) {
text = text.replace(/new +[\w]+ *(?:<) *\w*(?:(?:<)|(?:>)|,|\w| |\.)* *(?:>) *\(/, "###newgeneric_{" + newgenerics.length + "}###");
newgenerics.push(tnewgeneric[0]);
}
//临时排除显式类型转换中的一般类型
var converts = new Array();
var tconvert = null;
while (tconvert = text.match(/\( *\w+ *\) *\w+/)) {
text = text.replace(/\( *\w+ *\) *\w+/, "###convert_{" + converts.length + "}###");
converts.push(tconvert[0]);
}
//临时排除办法的返回类型
var methods = new Array();
var tmethod = null;
while (tmethod = text.match(/\w+(?=(?: *\[ *\])? +\w+ *\()/)) {
text = text.replace(/\w+(?=(?: *\[ *\])? +\w+ *\()/, "###method_{" + methods.length + "}###");
methods.push(tmethod[0]);
}
//临时排除泛型办法的返回类型
var gmethods = new Array();
var tgmethod = null;
while (tgmethod = text.match(/\w+(?= +\w+(?:<)\w+(?:>) *\()/)) {
text = text.replace(/\w+(?= +\w+(?:<)\w+(?:>) *\()/, "###gmethod_{" + gmethods.length + "}###");
gmethods.push(tgmethod[0]);
}
//还原并着色@注解
for (var i = 0; i < notes.length; i++) {
var coloredText = "<strong style=\"color:" + colorObj.notesColor + ";\">" + notes[i] + "</strong>";
t_regex = new RegExp("###note_\\{" + i + "\\}###");
text = text.replace(t_regex, coloredText);
}
//还原并着色常数
for (var i = 0; i < constants.length; i++) {
var coloredText = "<strong style=\"color:" + colorObj.constantColor + ";\">" + constants[i] + "</strong>";
t_regex = new RegExp("###constant_\\{" + i + "\\}###");
text = text.replace(t_regex, coloredText);
}
//还原并着色类申明与定义局部
for (var i = 0; i < classes.length; i++) {
var leftText = classes[i].substr(0, classes[i].match(/class\s+/)[0].length);
var keyword = classes[i].substr(leftText.length);
var coloredText = leftText + "<strong style=\"color:" + colorObj.classColor + ";\">" + keyword + "</strong>";
t_regex = new RegExp("###class_\\{" + i + "\\}###");
text = text.replace(t_regex, coloredText);
}
//还原并着色接口申明与定义局部
for (var i = 0; i < interfaces.length; i++) {
var leftText = interfaces[i].substr(0, interfaces[i].match(/interface\s+/)[0].length);
var keyword = interfaces[i].substr(leftText.length);
var coloredText = leftText + "<strong style=\"color:" + colorObj.classColor + ";\">" + keyword + "</strong>";
t_regex = new RegExp("###interface_\\{" + i + "\\}###");
text = text.replace(t_regex, coloredText);
}
//还原并着色异样捕捉的类型
for (var i = 0; i < exceptions.length; i++) {
var leftText = "";
if (exceptions[i].indexOf(".") >= 0) {
leftText = exceptions[i].substring(0, exceptions[i].lastIndexOf(".") + 1);
} else {
leftText = exceptions[i].substr(0, exceptions[i].match(/catch\s*\(\s*/)[0].length);
}
var keyword = exceptions[i].substr(leftText.length);
var coloredText = leftText + "<strong style=\"color:" + colorObj.classColor + ";\">" + keyword + "</strong>";
t_regex = new RegExp("###exception_\\{" + i + "\\}###");
text = text.replace(t_regex, coloredText);
}
//还原并着色类型申明与初始化
for (var i = 0; i < types.length; i++) {
var skip = false;
for (var j = 0; j < colorObj.keywordsInfo.length; j++) {
if (colorObj.keywordsInfo[j].keywords.indexOf(types[i]) >= 0) {
skip = true;
break;
}
}
//对关键字进行排除
if (skip) {
var originText = types[i];
t_regex = new RegExp("###type_\\{" + i + "\\}###");
text = text.replace(t_regex, originText);
} else {
var coloredText = "<strong style=\"color:" + colorObj.classColor + ";\">" + types[i] + "</strong>";
t_regex = new RegExp("###type_\\{" + i + "\\}###");
text = text.replace(t_regex, coloredText);
}
}
//还原并着色 new 关键字的类型实例化
for (var i = 0; i < newes.length; i++) {
var skip = false;
for (var j = 0; j < colorObj.keywordsInfo.length; j++) {
t_regex = new RegExp("new +");
var keyword = newes[i].replace(t_regex, "");
if (keyword.indexOf(".") >= 0) {
keyword = keyword.substr(keyword.indexOf(".") + 1);
}
keyword = keyword.substr(0, keyword.search(/[\(\[]/));
if (colorObj.keywordsInfo[j].keywords.indexOf(keyword) >= 0) {
skip = true;
break;
}
}
//对关键字进行排除
if (skip) {
var originText = newes[i];
t_regex = new RegExp("###new_\\{" + i + "\\}###");
text = text.replace(t_regex, originText);
} else {
var leftText = "", keyword = "";
if (newes[i].indexOf(".") >= 0) {
leftText = newes[i].substring(0, newes[i].lastIndexOf(".") + 1);
keyword = newes[i].substring(newes[i].lastIndexOf(".") + 1, newes[i].search(/[\(\[]/));
} else {
leftText = newes[i].substring(0, newes[i].match(/new\s+/)[0].length);
keyword = newes[i].substring(leftText.length + newes[i].lastIndexOf(".") + 1, newes[i].search(/[\(\[]/));
}
var rightText = newes[i].substring(newes[i].lastIndexOf(keyword) + keyword.length);
var coloredText = leftText + "<strong style=\"color:" + colorObj.classColor + ";\">" + keyword + "</strong>" + rightText;
t_regex = new RegExp("###new_\\{" + i + "\\}###");
text = text.replace(t_regex, coloredText);
}
}
//还原并着色泛型申明
for (var i = 0; i < genericsl.length; i++) {
var coloredText = "<strong style=\"color:" + colorObj.classColor + ";\">" + genericsl[i] + "</strong>";
t_regex = new RegExp("###genericl_\\{" + i + "\\}###");
text = text.replace(t_regex, coloredText);
}
//还原并着色 new 关键字的泛型实例化
for (var i = 0; i < newgenerics.length; i++) {
var originText = newgenerics[i];
var coloredText = "";
var tnewgeneric = null;
while (tnewgeneric = originText.match(/\w+(?=(?: *<))/)) {
coloredText = "<strong style=\"color:" + colorObj.classColor + ";\">" + tnewgeneric[0] + "</strong>";
originText = originText.replace(/\w+(?=(?: *<))/, coloredText);
}
t_regex = new RegExp("###newgeneric_\\{" + i + "\\}###");
text = text.replace(t_regex, originText);
}
//临时排除单对泛型括号中的类型
var agbrackets = new Array();
var tagbrackets = null;
while (tagbrackets = text.match(/< *[\.,\w ]+ *>/)) {
text = text.replace(/< *[\.,\w ]+ *>/, "###agbrackets_{" + agbrackets.length + "}###");
agbrackets.push(tagbrackets[0]);
}
//还原并着色单对泛型括号中的类型
for (var i = 0; i < agbrackets.length; i++) {
var leftText = agbrackets[i].substr(0, agbrackets[i].match(/<\s*/)[0].length);
var rightText = agbrackets[i].substr(agbrackets[i].search(/>\s*/));
agbrackets[i] = agbrackets[i].replace(leftText, "").replace(rightText, "");
var gtypes = agbrackets[i].split(",");
var coloredText = "";
for (var x = 0; x < gtypes.length; x++) {
var skip = false;
for (var j = 0; j < colorObj.keywordsInfo.length; j++) {
if (colorObj.keywordsInfo[j].keywords.indexOf(gtypes[x].trim()) >= 0) {
skip = true;
break;
}
}
//对关键字进行排除
if (skip) {
coloredText += gtypes[x] + ",";
} else {
var keyword = "";
if (gtypes[x].lastIndexOf(".") >= 0) {
var namespace = gtypes[x].substring(0, gtypes[x].lastIndexOf(".") + 1);
coloredText += namespace;
keyword = gtypes[x].substr(gtypes[x].lastIndexOf(".") + 1);
} else {
keyword = gtypes[x];
}
coloredText += "<strong style=\"color:" + colorObj.classColor + ";\">" + keyword + "</strong>,";
}
}
coloredText = coloredText.substr(0, coloredText.length - 1);
coloredText = leftText + coloredText + rightText;
t_regex = new RegExp("###agbrackets_\\{" + i + "\\}###");
text = text.replace(t_regex, coloredText);
}
//还原并着色显式类型转换中的一般类型
for (var i = 0; i < converts.length; i++) {
var keyword = "", leftText = "", rightText = "";
var skip = false;
for (var j = 0; j < colorObj.keywordsInfo.length; j++) {
leftText = converts[i].substr(0, converts[i].match(/\(/)[0].length);
keyword = converts[i].substring(leftText.length, converts[i].lastIndexOf(")"));
rightText = converts[i].substr(converts[i].lastIndexOf(")"));
if (colorObj.keywordsInfo[j].keywords.indexOf(keyword.replace(/\s/g, "")) >= 0) {
skip = true;
break;
}
}
//对关键字进行排除
if (skip) {
var originText = converts[i];
t_regex = new RegExp("###convert_\\{" + i + "\\}###");
text = text.replace(t_regex, originText);
} else {
var coloredText = leftText + "<strong style=\"color:" + colorObj.classColor + ";\">" + keyword + "</strong>" + rightText;
t_regex = new RegExp("###convert_\\{" + i + "\\}###");
text = text.replace(t_regex, coloredText);
}
}
//还原并着色办法的返回类型
for (var i = 0; i < methods.length; i++) {
var skip = false;
for (var j = 0; j < colorObj.keywordsInfo.length; j++) {
if (colorObj.keywordsInfo[j].keywords.indexOf(methods[i]) >= 0) {
skip = true;
break;
}
}
//对关键字进行排除
if (skip) {
var originText = methods[i];
t_regex = new RegExp("###method_\\{" + i + "\\}###");
text = text.replace(t_regex, originText);
} else {
var coloredText = "<strong style=\"color:" + colorObj.classColor + ";\">" + methods[i] + "</strong>";
t_regex = new RegExp("###method_\\{" + i + "\\}###");
text = text.replace(t_regex, coloredText);
}
}
//还原并着色泛型办法的返回类型
for (var i = 0; i < gmethods.length; i++) {
var skip = false;
for (var j = 0; j < colorObj.keywordsInfo.length; j++) {
if (colorObj.keywordsInfo[j].keywords.indexOf(gmethods[i]) >= 0) {
skip = true;
break;
}
}
//对关键字进行排除
if (skip) {
var originText = gmethods[i];
t_regex = new RegExp("###gmethod_\\{" + i + "\\}###");
text = text.replace(t_regex, originText);
} else {
var coloredText = "<strong style=\"color:" + colorObj.classColor + ";\">" + gmethods[i] + "</strong>";
t_regex = new RegExp("###gmethod_\\{" + i + "\\}###");
text = text.replace(t_regex, coloredText);
}
}
//自定义额定类型着色(动态类、枚举等间接成员拜访)
for (var i = 0; i < colorObj.customClassInfo.length; i++) {
for (var j = 0; j < colorObj.customClassInfo[i].keywords.length; j++) {
var tcustomClassInfo = null;
var t_regex = new RegExp("(\\b" + colorObj.customClassInfo[i].keywords[j] + ")(?= *\\. *\\w+)", "g");
var coloredText = "<strong style=\"color:" + colorObj.customClassInfo[i].color + ";\">" + colorObj.customClassInfo[i].keywords[j] + "</strong>";
text = text.replace(t_regex, coloredText);
}
}
//关键字着色
for (var i = 0; i < colorObj.keywordsInfo.length; i++) {
for (var j = 0; j < colorObj.keywordsInfo[i].keywords.length; j++) {
t_regex = new RegExp("\\b" + colorObj.keywordsInfo[i].keywords[j] + "\\b", "g");
var coloredText = "<strong style=\"color:" + colorObj.keywordsInfo[i].color + ";\">" + colorObj.keywordsInfo[i].keywords[j] + "</strong>";
text = text.replace(t_regex, coloredText);
}
}
//还原并着色非空字符串
for (var i = 0; i < strings.length; i++) {
var coloredText = "<strong style=\"color:" + colorObj.stringColor + ";\">" + strings[i] + "</strong>";
t_regex = new RegExp("###str_\\{" + i + "\\}###");
text = text.replace(t_regex, coloredText);
}
//还原并着色非空字符
for (var i = 0; i < chars.length; i++) {
var coloredText = "<strong style=\"color:" + colorObj.stringColor + ";\">" + chars[i] + "</strong>";
t_regex = new RegExp("###char_\\{" + i + "\\}###");
text = text.replace(t_regex, coloredText);
}
//还原并着色单行正文
for (var i = 0; i < annotations.length; i++) {
//还原单行正文中的字符串
var t_string = null;
while (t_string = annotations[i].match(/###str_\{(\d+)\}###/)) {
annotations[i] = annotations[i].replace(/###str_\{(\d+)\}###/, strings[t_string[1]]);
}
//还原单行正文中的多行正文
var t_comment = null;
while (t_comment = annotations[i].match(/###comment_\{(\d+)\}###/)) {
annotations[i] = annotations[i].replace(/###comment_\{(\d+)\}###/, comments[t_comment[1]]);
}
var coloredText = "<strong style=\"color:" + colorObj.annotationColor + ";\">" + annotations[i] + "</strong>";
t_regex = new RegExp("###annotation_\\{" + i + "\\}###");
text = text.replace(t_regex, coloredText);
}
//还原并着色多行正文
for (var i = 0; i < comments.length; i++) {
//还原多行正文中的字符串
var t_string = null;
while (t_string = comments[i].match(/###str_\{(\d+)\}###/)) {
comments[i] = comments[i].replace(/###str_\{(\d+)\}###/, strings[t_string[1]]);
}
var coloredText = "<strong style=\"color:" + colorObj.annotationsColor + ";\">" + comments[i] + "</strong>";
t_regex = new RegExp("###comment_\\{" + i + "\\}###");
text = text.replace(t_regex, coloredText);
}
return text;
}
总的来看,Java 仿佛不容许成员名以 @ 字符结尾,所以成员名相干的正则中能够去掉对 @ 前缀的解决,同样运算符重载和预编译指令局部也如此;去掉很多局部后发现高亮的中央较少,所以就独自再加了 16 进制常数和 @ 注解的高亮,这样看上去就不至于太枯燥,大略成果如下:
发表回复