RichTextFX comment and property regex

210 views Asked by At

I am trying to use the RichTextFX library to show a properties file in the CodeArea. I have created some Regex for comments as well as properties to try to style to CodeArea. EDIT: I am able to get them working properly. Except for when I add a comment to a line that has a property. My regex for determining a Property is not able to tell when there's a # at the beginning of the line. I have tried but am unable to get it to negate the rest of it if it sees there is a # at the beginning.

Here's the two patterns that I am using:

Pattern COMMENT = Pattern.compile("(?<SingleLineComment>#+)(?<Comment>.*\n)");

Pattern PROPERTY = Pattern.compile("(\n?(?<PropertyName>.+)(\\h*=\\h*)(?<PropertyValue>\\S+))");

Here's how they are being used in code:

import javafx.application.Application;
import javafx.scene.Scene;
import javafx.stage.Stage;
import org.fxmisc.richtext.CodeArea;
import org.fxmisc.richtext.LineNumberFactory;
import org.fxmisc.richtext.model.StyleSpans;
import org.fxmisc.richtext.model.StyleSpansBuilder;
import java.util.Collection;
import java.util.Collections;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class RegexTest extends Application
{
    public static void main (String[] args) {
        launch(args);
    }



    @Override
    public void start (Stage primaryStage) throws Exception {
        _area = new CodeArea();
        _area.getStylesheets().add(getClass().getResource("/css/settings-design.css").toExternalForm());
        _area.setParagraphGraphicFactory(LineNumberFactory.get(_area));

        _area.textProperty().addListener((obs, oldValue, newValue) -> {
            computeHighlighting(newValue);
        });

        primaryStage.setScene(new Scene(_area, 400, 600));

        primaryStage.show();

        _area.appendText(PROPERTIES);
    }

    private void computeHighlighting(String text) {
        Matcher equalsTest = COMMENT.matcher(text);
        while (equalsTest.find()){
            _area.setStyle( equalsTest.start(), equalsTest.end(), Collections.singleton("comment"));
        }

        Matcher propertyMatcher = PROPERTY.matcher(text);
        while (propertyMatcher.find()){
            _area.setStyle(propertyMatcher.start(1), propertyMatcher.end(3), Collections.singleton("property-name"));
            _area.setStyle(propertyMatcher.start(4), propertyMatcher.end(4), Collections.singleton("property-value"));
        }
    }

    private CodeArea _area;

    private static final Pattern COMMENT = Pattern.compile("(?<SingleLineComment>#+\\h*)(?<Comment>.*)\n?");
    private static final Pattern PROPERTY = Pattern.compile("(?:[#].+|(\n?(?<PropertyName>.+)(\\h*=\\h*)(?<PropertyValue>\\S+)))");

    private static final Pattern EQUALSTEST = Pattern.compile("=");

    public static final String PROPERTIES = "#Tue Nov 06 12:42:33 CST 2018\n" +
            "#prop0=true";

And code-area.css:

.comment {
    -fx-fill: #008e00;
}

.property-name {
    -fx-fill: #ff8e31;
}

.property-value {
    -fx-fill: #58a3ff;
}

Thank you in advance for your help!

1

There are 1 answers

0
Tezra On

Here is a regex for parsing a property file line into it's key-divider-value-comment parts that is Java complaint.

^\s*(?:|(?<PropertyName>\w+(?:\.\w+)*)(?<Divider>\s*[=: ]\s*)(?<PropertyValue>\w(?:.|\\,|\\[\n\r\f\v]+)*))(?<Comment>[#!].*)?$

Note that this regex is still not exhaustive, and the built in Properties class is much more suited to this task than regex. (Use the load function to parse the source, and than it basically works like a Map)