Code Folding

Problem

A number of users have requested support for Code Folding to reduce the height of the editor. Implementing this feature impacts a number of layers.

GtkTextView and GtkSourceView have rudimentary support for "invisible text". However, we will need to take into account keyboard navigation and auto-expanding some sections given the requested operation.

Additionally, where to find folds will need to be provided by plugins because it can be done a number of ways. For example, Vim has it's own mark syntax for fold points: /* Foo {{{1 */. Additionally, some programming languages will want to use the symbol tree or other heuristics for possible fold points. Some other, more simplified fallback options can be provided based on matching {}.

Some effort should probably be taken to see if we can integrate tree-sitter as part of the API.

Goals

  1. Add support for visualizing and toggling code-folding from Builder's OmniGutter.

  2. Allow plugins to provide the location of fold points and keep them updated while the buffer changes.

Anti-Goals

Affected Modules

  1. OmniGutter (src/plugins/omni-gutter) for drawing

  2. libide-code
    1. new interface (IdeFoldProvider)

    2. get_folds()/set_folds() for IdeBuffer

Interfaces

  1. IdeFoldProvider — should provide the mechanism for plugins to scan a buffer and return a series of folds

  2. IdeFold — contains a fold range and optionally a description of the range (which may come from text extracted from the editor)

Risks

  1. Having invisible text in the buffer may affect some improperly programmed plugins
  2. It also may effect scroll performance
  3. Keeping the folds up to date in the presence of editing may be tricky, especially if the new fold positions are returned from the provider after new text has been entered.

Implementation Details

I would suggest adding ide_buffer_set_folds() and ide_buffer_get_folds() to the buffer so that plugins can update them in their own time. However this may be problematic when dealing with incremental editing of the buffer. In that case, we may want to avoid making set_folds() public.

The gutter renderer will want to pre-fetch the folds before rendering to reduce the overhead in the per-line callback case. The storage container for these folds may want to be implemented with a non-overlapping interval tree for fast range lookups.

Apps/Builder/ThreePointThirtyfive/CodeFolding (last edited 2019-09-19 01:39:44 by ChristianHergert)