java实现代码高亮
1 package JavaSyntaxHighterDemo; 2 3 import java.io.BufferedReader; 4 import java.io.File; 5 import java.io.FileInputStream; 6 import java.io.InputStreamReader; 7 import java.util.Arrays; 8 import java.util.HashSet; 9 import java.util.Set; 10 11 /** 12 * @author Kevin Tse 13 * @version 0.1 14 */ 15 public class JavaSyntaxHighlighter { 16 17 public static int STATE_TEXT = 1; // 普通文本 18 public static int STATE_DOUBLE_QUOTE = 2; // 双引号 19 public static int STATE_SINGLE_QUOTE = 3; // 单引号 20 public static int STATE_MULTI_LINE_COMMENT = 4; // 多行注释 21 public static int STATE_LINE_COMMENT = 5; // 单行注释 22 23 private int lineNumber; // 行号 24 private boolean enableLineNumber = true; // 开启行号标志 25 26 public boolean isEnableLineNumber() { 27 return enableLineNumber; 28 } 29 30 // line numbers are printed by default. 31 // but this behavior can be disabled by invoking this method and setting the 32 // flag to false 33 public void setEnableLineNumber(boolean enableLineNumber) { 34 this.enableLineNumber = enableLineNumber; 35 } 36 37 String[] literalArray = { "null", "true", "false" }; //字面常量 38 String[] keywordArray = { "abstract", "break", "case", "catch", "class", 39 "const", "continue", "default", "do", "else", "extends", "final", 40 "finally", "for", "goto", "if", "implements", "import", 41 "instanceof", "interface", "native", "new", "package", "private", 42 "protected", "public", "return", "static", "strictfp", "super", 43 "switch", "synchronized", "this", "throw", "throws", "transient", 44 "try", "volatile", "while" }; //关键词 45 String[] primitiveTypeArray = { "boolean", "char", "byte", "short", "int", 46 "long", "float", "double", "void" }; //原始数据类型 47 48 SetliteralSet = new HashSet (Arrays.asList(literalArray)); 49 Set keywordSet = new HashSet (Arrays.asList(keywordArray)); 50 Set primitiveTypeSet = new HashSet (Arrays 51 .asList(primitiveTypeArray)); 52 53 public String process(String src) { 54 int currentState = STATE_TEXT; 55 int identifierLength = 0; 56 int currentIndex = -1; 57 char currentChar = 0; 58 String identifier = ""; 59 StringBuffer out = new StringBuffer(); 60 61 while (++currentIndex != src.length() - 1) { 62 currentChar = src.charAt(currentIndex); 63 if (Character.isJavaIdentifierPart(currentChar)) { 64 out.append(currentChar); 65 ++identifierLength; 66 continue; 67 } 68 if (identifierLength > 0) { 69 identifier = out.substring(out.length() - identifierLength); 70 if (currentState == STATE_TEXT) { 71 if (literalSet.contains(identifier)) { // identifier is a 72 // literal 73 out.insert(out.length() - identifierLength, 74 " "); 75 out.append(""); 76 } else if (keywordSet.contains(identifier)) { // identifier 77 // is a 78 // keyword 79 out.insert(out.length() - identifierLength, 80 ""); 81 out.append(""); 82 } else if (primitiveTypeSet.contains(identifier)) { // identifier 83 // is a 84 // primitive 85 // type 86 out.insert(out.length() - identifierLength, 87 ""); 88 out.append(""); 89 } else if (identifier.equals(identifier.toUpperCase()) 90 && !Character.isDigit(identifier.charAt(0))) { // identifier 91 // is 92 // a 93 // constant 94 out.insert(out.length() - identifierLength, 95 ""); 96 out.append(""); 97 } else if (Character.isUpperCase(identifier.charAt(0))) { // identifier 98 // is 99 // non-primitive 100 // type 101 out.insert(out.length() - identifierLength, 102 ""); 103 out.append(""); 104 } 105 } 106 } 107 108 switch (currentChar) { 109 // because I handle the "greater than" and "less than" marks 110 // somewhere else, I comment them out here 111 // case '<': 112 // out.append("<"); 113 // break; 114 // case '>': 115 // out.append(">"); 116 // break; 117 case '\"': 118 out.append('\"'); 119 if (currentState == STATE_TEXT) { 120 currentState = STATE_DOUBLE_QUOTE; 121 out.insert(out.length() - ("\"").length(), 122 ""); 123 } else if (currentState == STATE_DOUBLE_QUOTE) { 124 currentState = STATE_TEXT; 125 out.append(""); 126 } 127 break; 128 case '\'': 129 out.append("\'"); 130 if (currentState == STATE_TEXT) { 131 currentState = STATE_SINGLE_QUOTE; 132 out.insert(out.length() - ("\'").length(), 133 ""); 134 } else if (currentState == STATE_SINGLE_QUOTE) { 135 currentState = STATE_TEXT; 136 out.append(""); 137 } 138 break; 139 case '\\': 140 out.append("\\"); 141 if (currentState == STATE_DOUBLE_QUOTE 142 || currentState == STATE_SINGLE_QUOTE) { 143 // treat as a character escape sequence 144 out.append(src.charAt(++currentIndex)); 145 } 146 break; 147 // if you want to translate tabs into spaces, uncomment the 148 // following lines 149 // case '\t': 150 // // replace tabs with tabsize number of spaces 151 // for (int i = 0; i < tabSize; i++) 152 // out.append(" "); 153 // break; 154 case '*': 155 out.append('*'); 156 if (currentState == STATE_TEXT && currentIndex > 0 157 && src.charAt(currentIndex - 1) == '/') { 158 out.insert(out.length() - ("/*").length(), 159 ""); 160 currentState = STATE_MULTI_LINE_COMMENT; 161 } 162 break; 163 case '/': 164 out.append("/"); 165 if (currentState == STATE_TEXT && currentIndex > 0 166 && src.charAt(currentIndex - 1) == '/') { 167 out.insert(out.length() - ("//").length(), 168 ""); 180 currentState = STATE_TEXT; 181 } 182 if (currentChar == '\r' && currentIndex < src.length() - 1) { 183 out.append("\r\n"); 184 ++currentIndex; 185 } else 186 out.append('\n'); 187 188 if (enableLineNumber) 189 out.append(""); 169 currentState = STATE_LINE_COMMENT; 170 } else if (currentState == STATE_MULTI_LINE_COMMENT) { 171 out.append(""); 172 currentState = STATE_TEXT; 173 } 174 break; 175 case '\r': 176 case '\n': 177 // end single line comments 178 if (currentState == STATE_LINE_COMMENT) { 179 out.insert(out.length() - 1, "" 190 + (++lineNumber) + "."); 191 break; 192 case 0: 193 if (currentState == STATE_LINE_COMMENT 194 && currentIndex == (src.length() - 1)) 195 out.append("