public AttributedString highlight()

in gogo/jline/src/main/java/org/apache/felix/gogo/jline/Highlighter.java [52:201]


    public AttributedString highlight(LineReader reader, String buffer) {
        try {
            Program program = null;
            List<Token> tokens = null;
            List<Statement> statements = null;
            String repaired = buffer;
            while (program == null) {
                try {
                    org.apache.felix.gogo.runtime.Parser parser = new org.apache.felix.gogo.runtime.Parser(repaired);
                    program = parser.program();
                    tokens = parser.tokens();
                    statements = parser.statements();
                } catch (EOFError e) {
                    repaired = repaired + " " + e.repair();
                    // Make sure we don't loop forever
                    if (repaired.length() > buffer.length() + 1024) {
                        return new AttributedStringBuilder().append(buffer).toAttributedString();
                    }
                }
            }

            Map<String, String> colors = Posix.getColorMap(session, "HIGHLIGHTER", DEFAULT_HIGHLIGHTER_COLORS);

            int underlineStart = -1;
            int underlineEnd = -1;
            int negativeStart = -1;
            int negativeEnd = -1;
            String search = reader.getSearchTerm();
            if (search != null && search.length() > 0) {
                underlineStart = buffer.indexOf(search);
                if (underlineStart >= 0) {
                    underlineEnd = underlineStart + search.length() - 1;
                }
            }
            if (reader.getRegionActive() != RegionType.NONE) {
                negativeStart = reader.getRegionMark();
                negativeEnd = reader.getBuffer().cursor();
                if (negativeStart > negativeEnd) {
                    int x = negativeEnd;
                    negativeEnd = negativeStart;
                    negativeStart = x;
                }
                if (reader.getRegionActive() == RegionType.LINE) {
                    while (negativeStart > 0 && reader.getBuffer().atChar(negativeStart - 1) != '\n') {
                        negativeStart--;
                    }
                    while (negativeEnd < reader.getBuffer().length() - 1 && reader.getBuffer().atChar(negativeEnd + 1) != '\n') {
                        negativeEnd++;
                    }
                }
            }

            Type[] types = new Type[repaired.length()];

            Arrays.fill(types, Type.Unknown);

            int cur = 0;
            for (Token token : tokens) {
                // We're on the repair side, so exit now
                if (token.start() >= buffer.length()) {
                    break;
                }
                if (token.start() > cur) {
                    cur = token.start();
                }
                // Find corresponding statement
                Statement statement = null;
                for (int i = statements.size() - 1; i >= 0; i--) {
                    Statement s = statements.get(i);
                    if (s.start() <= cur && cur < s.start() + s.length()) {
                        statement = s;
                        break;
                    }
                }

                // Reserved tokens
                Type type = Type.Unknown;
                if (Token.eq(token, "{")
                        || Token.eq(token, "}")
                        || Token.eq(token, "(")
                        || Token.eq(token, ")")
                        || Token.eq(token, "[")
                        || Token.eq(token, "]")
                        || Token.eq(token, "|")
                        || Token.eq(token, ";")
                        || Token.eq(token, "=")) {
                    type = Type.Reserved;
                } else if (token.charAt(0) == '\'' || token.charAt(0) == '"') {
                    type = Type.String;
                } else if (token.toString().matches("^[-+]?[0-9]*\\.?[0-9]+([eE][-+]?[0-9]+)?$")) {
                    type = Type.Number;
                } else if (token.charAt(0) == '$') {
                    type = Type.Variable;
                } else if (((Set<?>) session.get(CommandSessionImpl.CONSTANTS)).contains(token.toString())
                        || Token.eq(token, "null") || Token.eq(token, "false") || Token.eq(token, "true")) {
                    type = Type.Constant;
                } else {
                    boolean isFirst = statement != null && statement.tokens().size() > 0
                            && token == statement.tokens().get(0);
                    boolean isThirdWithNext = statement != null && statement.tokens().size() > 3
                            && token == statement.tokens().get(2);
                    boolean isAssign = statement != null && statement.tokens().size() > 1
                            && Token.eq(statement.tokens().get(1), "=");
                    if (isFirst && isAssign) {
                        type = Type.VariableName;
                    }
                    if (isFirst && !isAssign || isAssign && isThirdWithNext) {
                        Object v = session.get(Shell.resolve(session, token.toString()));
                        type = (v instanceof Function) ? Type.Function : Type.BadFunction;
                    }
                }
                Arrays.fill(types, token.start(), Math.min(token.start() + token.length(), types.length), type);
                cur = Math.min(token.start() + token.length(), buffer.length());
            }

            if (buffer.length() < repaired.length()) {
                Arrays.fill(types, buffer.length(), repaired.length(), Type.Repair);
            }

            AttributedStringBuilder sb = new AttributedStringBuilder();
            for (int i = 0; i < repaired.length(); i++) {
                sb.style(AttributedStyle.DEFAULT);
                applyStyle(sb, colors, types[i]);
                if (i >= underlineStart && i <= underlineEnd) {
                    sb.style(sb.style().underline());
                }
                if (i >= negativeStart && i <= negativeEnd) {
                    sb.style(sb.style().inverse());
                }
                char c = repaired.charAt(i);
                if (c == '\t' || c == '\n') {
                    sb.append(c);
                } else if (c < 32) {
                    sb.style(sb.style().inverseNeg())
                            .append('^')
                            .append((char) (c + '@'))
                            .style(sb.style().inverseNeg());
                } else {
                    int w = WCWidth.wcwidth(c);
                    if (w > 0) {
                        sb.append(c);
                    }
                }
            }

            return sb.toAttributedString();
        } catch (SyntaxError e) {
            return super.highlight(reader, buffer);
        }
    }