【发布时间】:2020-11-08 15:13:23
【问题描述】:
我要做什么
我正在开发一个突出显示 html 中 java 代码的语法高亮器(示例如下)。
示例输出
我已经使用以下 java-code (caesar-encryption) 测试了代码:
//Encryption
public static String encrypt(String text, int n) {
int x = 0;
int y = 0;
String out = ""; //Empty string for result.
while (x < text.length()) {
if (text.charAt(x) > 64 && text.charAt(x) < 91) {
if (text.charAt(x) + n > 90) {
y = 26;
}
out = out + (char) (text.charAt(x) + n - y);
} else {
out = out + text.charAt(x);
}
x++;
y = 0;
}
return out;
}
输出如下所示:
<!-- Code begins here -->
<div style = "background: LightGray; font: monospace; width: fit-content; height: min-height;"><pre><code>
<span style='color:green; font-weight:bold; '>//Encryption
</span><span style='color:#7f0055; font-weight:bold; '>public</span> <span style='color:#7f0055; font-weight:bold; '>static</span> <span style='color:#7f0055; font-weight:bold; '>String</span> encrypt(<span style='color:#7f0055; font-weight:bold; '>String</span> text, <span style='color:#7f0055; font-weight:bold; '>int</span> n) {
<span style='color:#7f0055; font-weight:bold; '>int</span> x = 0;
<span style='color:#7f0055; font-weight:bold; '>int</span> y = 0;
<span style='color:#7f0055; font-weight:bold; '>String</span> out = <span style='color:blue; font-weight:bold; '>""</span>; <span style='color:green; font-weight:bold; '>//Empty string <span style='color:#7f0055; font-weight:bold; '>for</span> result.
</span> <span style='color:#7f0055; font-weight:bold; '>while</span> (x < text.length()) {
<span style='color:#7f0055; font-weight:bold; '>if</span> (text.charAt(x) > 64 && text.charAt(x) < 91) {
<span style='color:#7f0055; font-weight:bold; '>if</span> (text.charAt(x) + n > 90) {
y = 26;
}
out = out + (<span style='color:#7f0055; font-weight:bold; '>char</span>) (text.charAt(x) + n - y);
} <span style='color:#7f0055; font-weight:bold; '>else</span> {
out = out + text.charAt(x);
}
x++;
y = 0;
}
<span style='color:#7f0055; font-weight:bold; '>return</span> out;
}
</pre></code></div>
<!-- Code ends here -->
如果你用浏览器打开这段代码,它看起来像这样:
代码
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.Font;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.ScrollPaneConstants;
public class Gui {
private JTextArea inputArea;
private JTextArea outputArea;
private boolean inputAreaClicked = false;
public Gui() {
//JFrame
JFrame frame = new JFrame("Syntax-Highlighter");
frame.setSize(700, 700);
frame.setMinimumSize(new Dimension(700, 700));
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
//JPanel
JPanel panel = new JPanel(new GridBagLayout());
//Creating textArea for input
inputArea = new JTextArea("Enter text here...");
inputArea.setLineWrap(true);
inputArea.setTabSize(1);
inputArea.setFont(new Font("monospaced", Font.ITALIC, 12));
inputArea.addMouseListener(new MouseAdapter() { //Set text to "" the first time the inputArea is clicked
@Override
public void mouseClicked(MouseEvent e){
if(!inputAreaClicked) {
inputArea.setText("");
inputArea.setFont(new Font("monospaced", Font.PLAIN, 12));
inputAreaClicked = true;
}
}
});
JScrollPane input = new JScrollPane(inputArea);
input.setPreferredSize(new Dimension(600, 110));
input.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS);
input.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_ALWAYS);
//Creating buttons
JPanel buttonPanel = new JPanel(new FlowLayout(0, 50, 10)); //FlowLayout(align, hgap, vgap)
JButton button = new JButton("Highlight");
button.setFont(new Font("Arial", Font.PLAIN, 20));
button.addActionListener(e -> hightlight(inputArea.getText()));
button.setPreferredSize(new Dimension(140,30));
//Creating textArea for output
outputArea = new JTextArea();
outputArea.setEditable(false);
outputArea.setTabSize(1);
outputArea.setLineWrap(false);
outputArea.setFont(new Font("monospaced", Font.PLAIN, 12));
JScrollPane output = new JScrollPane(outputArea);
output.setPreferredSize(new Dimension(600, 400));
output.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS);
output.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_ALWAYS);
//Layout
GridBagConstraints gbc = new GridBagConstraints();
gbc.weighty = 5;
gbc.gridwidth = GridBagConstraints.REMAINDER;
//Add everything to panel
buttonPanel.add(button);
panel.add(input, gbc);
panel.add(buttonPanel, gbc);
panel.add(output, gbc);
//Add everything to frame
frame.add(panel, BorderLayout.CENTER);
frame.setVisible(true);
}
private void hightlight(String text) {
//Keywords
String[] array = {
"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", "instanceof", "int",
"interface", "long", "native", "new", "null", "package", "private", "protected",
"public", "return", "short", "static", "String", "strictfp", "super", "switch", "synchronized",
"System", "this", "throw", "throws", "transient", "true", "try", "void", "volatile", "while"
};
//Highlight every keyword with color:#7f0055
for(int i = 0; i < array.length; i++) {
text = text.replaceAll(array[i] + "(?![a-zA-Z])", "<span style='color:#7f0055; font-weight:bold; '>" + array[i] + "</span>");
}
//Highlight Strings
text = text.replaceAll("\"(?<render>.*?)\"", "<span style='color:blue; font-weight:bold; '>" + "\"${render}\"" + "</span>");
//Highlight import-statements
text = text.replaceAll("import(?<render>.*?);", "<span style='color:#7f0055; font-weight:bold; '>" + "import${render};" + "</span>");
//Highlight multiline-comments
Pattern p = Pattern.compile("/\\*(?<render>.*?)\\*/", Pattern.DOTALL);
Matcher m = p.matcher(text);
text = m.replaceAll("<span style='color:green; font-weight:bold; '>" + "/\\*${render}\\*/" + "</span>");
//Highlight single-line-comments
text = text.replaceAll("//(?<render>.*?)\n", "<span style='color:green; font-weight:bold; '>" + "//${render}\n" + "</span>");
text = "<!-- Code begins here -->\n<div style = \"background: LightGray; font: monospace; width: fit-content; height: min-height;\"><pre><code>\n"
+ text + "\n</pre></code></div>\n<!-- Code ends here -->\n";
outputArea.setText(text);
}
}
问题
如上图所示,cmets中的关键字仍然以关键字高亮显示。
您知道如何解决这个问题吗?
我的尝试
我尝试使用以下代码(在反向引用中替换),但没有成功:
// Highlight single-line-comments
text = text.replaceAll("//(?<render>.*?)\n", "<span style='color:green; font-weight:bold; '>"
+ "//" + "${render}".replaceAll("color: #7f0055", "color: green") + "\\n</span>");
很遗憾,这不起作用?如何纠正?
【问题讨论】:
-
一个相当老套的解决方案:
<span style='color:green !important; font-weight:bold; '>. -
@Sweeper 不幸的是,这没有帮助。你有别的想法吗?
-
要正确突出 Java 代码,您需要正确解析它,没有任何 hacky 解决方案可以解决所有问题(想想多行 cmets ... Java 字符串文字 ...)。