繁体   English   中英

Java JEditorPane中的语法突出显示

[英]Syntax highlighting in JEditorPane in java

我想在jEditorPane中执行语法突出显示。 它允许我执行单行语法高亮显示,但是如果XML标记被分为两行或更多行,则它不起作用。 以下是我用于语法突出显示的代码。 帮我解决这个问题。 谢谢.....

public class XmlView extends PlainView {

    private static HashMap<Pattern, Color> patternColors;
    private static String TAG_PATTERN = "(</?[A-Za-z\\-_0-9]*)\\s?>?";
    private static String TAG_END_PATTERN = "(/>)";
    private static String TAG_ATTRIBUTE_PATTERN = "\\s(\\w*)\\=";
    private static String TAG_ATTRIBUTE_VALUE = "[a-z\\-]*\\=(\"[^\"]*\")";
    private static String TAG_COMMENT = "(<\\!--[\\w * \\S]*-->)";
    private static String TAG_CDATA = "(<\\!\\[CDATA\\[.*\\]\\]>)";

    static {
        // NOTE: the order is important!
        patternColors = new LinkedHashMap<Pattern, Color>();
        patternColors.put(Pattern.compile(TAG_PATTERN), new Color(163, 21, 21));
        patternColors.put(Pattern.compile(TAG_CDATA), Color.GRAY);
        patternColors.put(Pattern.compile(TAG_ATTRIBUTE_PATTERN), new Color(127, 0, 127));
        patternColors.put(Pattern.compile(TAG_END_PATTERN), new Color(63, 127, 127));
        patternColors.put(Pattern.compile(TAG_ATTRIBUTE_VALUE), new Color(42, 0, 255));
        patternColors.put(Pattern.compile(TAG_COMMENT), new Color(0, 128, 0));
    }

    public XmlView(Element element) {

        super(element);

        // Set tabsize to 4 (instead of the default 8)
        getDocument().putProperty(PlainDocument.tabSizeAttribute, 4);
    }

    @Override
    protected int drawUnselectedText(Graphics graphics, int x, int y, int p0,
            int p1) throws BadLocationException {

        Document doc = getDocument();
        String text = doc.getText(p0, p1 - p0);

        Segment segment = getLineBuffer();

        SortedMap<Integer, Integer> startMap = new TreeMap<Integer, Integer>();
        SortedMap<Integer, Color> colorMap = new TreeMap<Integer, Color>();

        // Match all regexes on this snippet, store positions
        for (Map.Entry<Pattern, Color> entry : patternColors.entrySet()) {

            Matcher matcher = entry.getKey().matcher(text);

            while (matcher.find()) {
                startMap.put(matcher.start(1), matcher.end());
                colorMap.put(matcher.start(1), entry.getValue());
            }
        }

        // TODO: check the map for overlapping parts

        int i = 0;

        // Colour the parts
        for (Map.Entry<Integer, Integer> entry : startMap.entrySet()) {
            int start = entry.getKey();
            int end = entry.getValue();

            if (i < start) {
                graphics.setColor(Color.black);
                doc.getText(p0 + i, start - i, segment);
                x = Utilities.drawTabbedText(segment, x, y, graphics, this, i);
            }

            graphics.setColor(colorMap.get(start));
            i = end;
            doc.getText(p0 + start, i - start, segment);
            x = Utilities.drawTabbedText(segment, x, y, graphics, this, start);
        }

        // Paint possible remaining text black
        if (i < text.length()) {
            graphics.setColor(Color.black);
            doc.getText(p0 + i, text.length() - i, segment);
            x = Utilities.drawTabbedText(segment, x, y, graphics, this, i);
        }

        return x;
    }

}

标签,注释和CDATA部分的正则表达式需要分为两部分:

Pattern TAG_START     = Pattern.compile("</?[\\w-]+");
Pattern TAG_END       = Pattern.compile("/?>");
Pattern COMMENT_START = Pattern.compile("<!--");
Pattern COMMENT_END   = Pattern.compile("-->");
Pattern CDATA_START   = Pattern.compile("<\\[CDATA\\[");
Pattern CDATA_END     = Pattern.compile("\\]\\]>");

只要您在*_START模式之一上找到匹配*_START ,就会设置一个标志,指示您处于其他模式。 例如,在TAG_START上进行的匹配会使您进入TAG模式,这意味着您位于标签内。 每种模式都有其自己的模式集,某些模式与其他模式共享,某些模式特定。

例如,在默认模式下,您将寻找上面列出的*_START模式以及其他合适的模式。 在TAG模式下,您会寻找属性/值对和TAG_END模式,而这些在标签之外是没有意义的。 而你总是认准TAG_END模式首先 ,确保你真的是仍处于标签。 (或者*_END模式适用于您所处的模式。)

由于模式可以跨行边界持续存在,因此这意味着您必须在绘制一条线和绘制下一条线(复杂)之间保存某种状态,或者每次绘制一条线时(慢速)扫描整个文档。 无论采用哪种方法,性能都在很大程度上取决于正则表达式的质量。 例如,您的正则表达式:

"(<\\!--[\\w * \\S]*-->)"

...最初将消耗<!--到文档末尾的所有内容,而仅需回溯很长一段路。 另外,如果有两个或多个注释,则它将从第一个注释的开头到最后一个注释的结尾匹配。 由于这两个原因,我会这样写:

"<!--[^-]*+(?>-(?!->))*+-->"

注意使用所有格修饰符( *+ )和原子组( (?>...) )。 从正确性的角度来看,它们不是必需的,但是它们使正则表达式更加有效,这在该项目中将尤其重要。

还有一件事:如果要为此使用find() ,还应该在每个正则表达式的开头添加\\G (最后匹配的结尾锚),就像Friedl在他的正则表达式中所做的那样。

您可能需要使用Pattern.MULTILINE标志吗?

例如

Pattern.compile(TAG_PATTERN, Pattern.MULTILINE)

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM