Custom Script Editor
As a general direction for improvement, your technique for finding those keywords uses startsWith, which will effectively compare any given character once per potential keyword or operator. If you switch to regular expressions, by compiling a Pattern that matches any keyword or any operator, you build (what amounts to) a lookup table that typically allows one comparison per character, reducing the total number of comparisons significantly.

You can even use Pattern.quote to make building the String easier.

public Pattern fromList(List&lt;String&gt; strings) {
  StringBuilder builder = new StringBuilder();
  boolean isFirst = true;
  for (String string : strings) {
    if (!isFirst) {
      builder.append('|');
    }
    builder.append(Pattern.quote(string));
    isFirst = false;
  }
  return Pattern.compile(builder.toString());
}


After that, search for every occurrence of the String using either Pattern.matcher() (or Scanner.next()), which will save you those repeated comparisons. At that point you can use the start and end methods on Matcher (or the same on Scanner.match()).

I do notice that your algorithm will tend to highlight the first half of terms like publicValue even if the compiler does not detect it as a keyword. For this, you may want to customize the patterns you generate to match word boundaries.