Skip to content

Instantly share code, notes, and snippets.

@lewis6991
Last active July 4, 2022 15:08
Show Gist options
  • Save lewis6991/dcfe0178813a32e66e603b2b56dd6e40 to your computer and use it in GitHub Desktop.
Save lewis6991/dcfe0178813a32e66e603b2b56dd6e40 to your computer and use it in GitHub Desktop.
New Fold API

Problem

  • Plugins cannot inspect folds
  • Custom folds require foldexpr which is inefficient as it requires evaluating this expression on every buffer line.

Solution

API for plugins to set, inspect folds and get fold events.

Notes

  • Folds are window local and so are most of the folding related options.
  • Fold state (whether a fold is open/closed) is also local to the window.
  • Extmarks are buffer local.
  • Folds can be nested

Proposal

  • Add folding support to extmarks

    • Add a new method to 'foldmethod' named extmark so extmark folds cannot be mixed with other kinds of folds.
    • When folds of calculated, we scan the extmarks for all the folds and store them in win->w_folds.
    • The trigger for updating is the same as other foldmethods.
  • Add nvim_win_add_fold and nvim_win_del_fold. These new API functions are to be used instead of the zf/zd operators.

    • Should these functions work for all fold methods or just manual/marker like zf does?
    nvim_win_add_fold({window}, {start}, {end}, {opts})
        Add a fold to the window from {start} to {end}.
    
        All row arguments are 0-indexed, inclusive.
    
        Only supported for `foldmethod=manåual`
    
        Parameters: ~
            {window}  Window handle, or 0 for current window
            {start}   Start row of fold.
            {end}     End row of fold.
            {opts}    Optional parameters. Reserved for future use.
    
    nvim_win_del_fold({window}, {start}, {end}, {opts})
        Delete a fold from the window from {start} to {end}.
    
        All row arguments are 0-indexed, inclusive.
    
        Only supported for `foldmethod=manual`
    
        Parameters: ~
            {window}  Window handle, or 0 for current window
            {start}   Start row of fold.
            {end}     End row of fold.
            {opts}    Optional parameters. Reserved for future use.
    
    
  • Add nvim_win_get_folds for getting folds for any foldmethod.

    nvim_win_get_folds({window}, {opts})
    
        All row arguments are 0-indexed, inclusive.
    
        Parameters: ~
            {window}  Window handle, or 0 for current window
            {opts}    Optional parameters:
                      - start_row: get folds from this row
                      - end_row: get folds up to this row
        Returns:
    
        Array of dictionaries for each fold. Each elements has the keys:
        - state: string, "open" | "closed"
        - start_row: integer, start row of fold
        - end_row: integer, end row of fold
        - [FUTURE] start_col: integer
        - [FUTURE] end_col: integer
        - children: array of folds ????? SHOULD WE HAVE THIS?
    
    
  • Add nvim_win_toggle_folds change the fold state of all folds in a region.

    nvim_win_toggle_fold({window}, {start}, {end}, {opts})
    
        Parameters: ~
            {window}  Window handle, or 0 for current window
            {opts}    Optional parameters:
                      - action: "toggle", "open", "close"
                        Note: for "toggle", only the first fold state is considered.
                        E.g. if the first fold in the region is open, then all folds
                        in the region will be closed.
    
  • Add nvim_win_attach with an on_fold callback for detecting changes to folds.

    nvim_win_attach({window}, {opts})
        Activates window-update events on a channel, or as Lua
        callbacks.
    
        Parameters: ~
            {window}  Window handle, or 0 for current window
            {opts}    Optional parameters:
                      - on_fold: Lua callback invoked on change.
                        Args:
                        - the string "fold"
                        - window handle
                        - first line where folds where updated
                        - last line where folds where updated
                        - String "add | del | update | open | close"
    
    

Future Enhancements

  • Column-aware folds (aka inline folds)

Questions

  • For nested folds, do we represent them as a flat list of locations or a nested structure?

  • Instead of nvim_win_attach, shall we implement a Fold autocmd instead?

  • Should we assign ID's and namespaces to folds?

Related

  • Fold events: #8538
  • Window events: #8539
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment