Skip to content

Adding Code Folding for a new Language

Peter Froud edited this page May 24, 2023 · 4 revisions

Overview

The RSyntaxTextArea library includes a FoldParserManager class. The FoldParserManager is a singleton that maps identifiers for syntax styles (e.g. from SyntaxConstants to FoldParsers). To add or modify code folding logic for a language, simply call FoldParserManager.get().addFoldParserMapping() with the appropriate arguments.

Example: Adding Folding for a Language with C-Style Syntax

Let's say you're adding support for a custom language called "Foo". You've already added syntax highlighting for Foo, as described in the previous section. To recap:

AbstractTokenMakerFactory atmf = (AbstractTokenMakerFactory)TokenMakerFactory.getDefaultInstance();
atmf.putMapping("text/foo", "org.mycompany.rsta.FooTokenMaker");
textArea.setSyntaxEditingStyle("text/foo");

Say that the Foo language has the same basic structure as C-like languages - curly braces denote code blocks, and block comments are denoted by /* ... */. In that case, you can simply use the built-in CurlyFoldParser class. It handles code folding for such languages, and provides a few configuration options as well. You would register it with the FoldParserManager to be used whenever an editor is editing Foo code like so:

FoldParserManager.get().addFoldParserMapping("text/foo", new CurlyFoldParser());

After doing this, any instance of RSyntaxTextArea configured to syntax highlight Foo will also provide code folding (assuming code folding is enabled, of course).

There are also built-in fold parsers for HTML, JSON, Latex, Lisp, Python, XML, and YAML. To learn more, check the Javadoc for the folding package.

Creating a Custom Fold Parser

If your language has a unique syntax, you may need to create a custom FoldParser implementation for it. The difficulty of doing this is in proportion to how complex your language's syntax is (actually, how difficult it is to identify "foldable regions" of code).

The FoldParser interface only declares 1 method, getFolds(), which returns all foldable regions in the text area's content. This method is called each time the editor's content is modified (after a small delay, so many quick edits don't cause many re-parsings for folds). In this method, your class should simply scan the RSyntaxTextArea's entire document and return a list of Folds that denotes the top-level foldable regions. RSTA is smart enough to remember the state of folds between parsings, so if you return the same set multiple times, regions that are folded stay folded, and those that are expanded stay expanded. Also, if a collapsed foldable region is removed by an edit, the corresponding content in the editor is expanded automatically. All you care about is returning the list of folds, not determining their state.

There are built-in FoldParser implementations for C-style languages, HTML/JSP/PHP, JSON, XML, and more. You can use any of these as examples for the basis for your custom fold parser.