Search code examples
ace-editor

Ace Editor custom mode – adding highlight rules to existing set


I have a JavaScript editor (Ace Editor) related to GraalVM scripting, where I added some custom JavaScript rules. I'd like them to be reflected in the editor, using custom highlight rules. However, it seems that I am unable to add new rules no matter what I try. I have a custom mode that's correctly included, the problem is in the rules.

My starting point looked like this (mode code not included):

ace.define('ace/mode/custom_highlight_rules', ['require', 'exports', 'ace/lib/oop', 'ace/mode/text_highlight_rules'], (acequire, exports) => {
    const oop = acequire('ace/lib/oop');
    const JavaScriptHighlightRules = acequire("./javascript_highlight_rules").JavaScriptHighlightRules;

    const CustomHighlightRules = function CustomHighlightRules() {
        this.$rules = new JavaScriptHighlightRules().getRules();
    };

    oop.inherits(CustomHighlightRules, JavaScriptHighlightRules);

    exports.CustomHighlightRules = CustomHighlightRules;
});

Now, I have tried using addRules() from the documentation, like this:

this.addRules({
    start: [ {
        token: "keyword",
        regex: "my_keyword",
    } ]
}, 'custom-');

However, my_keyword is not highlighted.

It is important to note that replacing it with:

this.$rules = {
    start: [ {
        token: "keyword",
        regex: "my_keyword",
    } ]
};

Does highlight this keyword, but nothing else because there are no other rules – that's how I know that the code is doing anything at all.

I have also tried something like this:

this.$rules.start.push({
    token: "keyword",
    regex: "my_keyword",
    next: "start",
});

So that the rule is in the built-in start object, but it doesn't appear to work. Also tried variations on the regex (e.g. using native RegEx code like /my_keyword/).

I have noticed that when using addRules(), my custom object does not have processed: true in it, which indicates that maybe I added the rules too late? It seems like this is the correct place though.

What am I doing wrong?


Solution

  • I didn't go into why this works, but it looks like the assignment to this.$rules needs to be done at the end—so first the object needs to be built, and then assigned. A working example on how to do this can be found here: https://ace.c9.io/tool/mode_creator.html under TypeScript, which inherits JavaScript, exactly as I wanted.

    My function therefore looks like this now:

    const CustomHighlightRules = function CustomHighlightRules(options) {
        let customRules = [
            {
                token: "keyword",
                regex: "my_keyword"
            }
        ];
    
        let JSRules = new JavaScriptHighlightRules({jsx: (options && options.jsx)}).getRules();
    
        JSRules.no_regex = customRules.concat(JSRules.no_regex);
        this.$rules = JSRules;
    }