Add folding at specific levels programmatically

Hi, I would need some help again.
In the past, thanks to you, I wrote my own folding plugin that allows you to fold at new/deeper indent level.
Here is the old thread: Add folding on indent levels for plain text and yaml language
Here is a working example: folding-example

Now I would like to provide the user with some buttons to fold directly at a certain level. I have already folded and unfolded everything with foldAll() and unfoldAll(). New I would like to have single buttons to foldLvl1(), foldLvl2() and so on.

What would be the right way to implement something like this? I thought of two ways, if it works, to get directly all possible foldings from my plugin somehow and loop through and check how deep they are. The second way would be to parse through the entire content again to determine “again” the folding (which would be kind of duplicate).

Through research and also answers from marjin I came across “foldable()” and “foldEffect()”, but I’m stuck on figuring out how to use those and especially how I could use the already determined “foldings” from my plugin for that.

I hope you can help me and thank you very much.

Fold points are identified by line in CodeMirror’s folding system, not by depth, so if you have something like…

{"foo": {"bar": [
  1,
  2
]}}

It won’t let you fold just the inner object, since that is broken at the same line as the outer object, which will take precedence.

If you expect code to be formatted in a way that makes this not a problem, or your fold function makes it a non-issue (as in the indentation-folding example), you could write a function that runs over the entire document, finding lines that start a fold of the level you are interested in, and accumulating fold effects for their foldable ranges. You can then dispatch a transaction with those effects to fold them all at once.

1 Like

Thank you for your really fast reply.
Is there a way to get all the lines that start a folding (at best, from my plugin that already set all the folding ranges) and loop through it?

In my example I already have all the folding ranges (coming from the indent lvl in a yaml structure). Can I get all the folding ranges from the codemirror instance somehow? folding-example

Next step would be to loop over the folding ranges and find (for example “line 6” and fold them by dispatching the foldEffect() ), right?

Edit:
Okay, I found something out. I still need to tweak it, but it works under my lab conditions. When I have it ready, I’ll provide an example.

My way now is to swap out my plugin (from the example above) and run the function that gives me the ranges again specifically when the user clicks the desired button.

So, user clicks the button. It loops over all rows from the doc and all folding ranges are determined. Then I loop over all folding ranges, determine the line from the start position and check the indent level of the line. If the line is larger (deeper) than I want to collapse, the folding range is collapsed.

I don’t know if this is the best way, but here would be a working example. The function foldOnIndentLvl(view, 4) can be triggered by a button with the desired indent level. Thanks again :slight_smile:

working-example