Hi, I’m using v6 and have been struggling for a while to add a folding feature.
I want to add the possibility to fold on indent level with small buttons on the gutter (like in other editors, exp vs-code).
So my question is, how can I achive an folding on indent levels?
I have already experimented with indentService, foldService, foldNodeProp, but unfortunately can’t get them to work.
My goal would be to be able to add an extension that can be loaded alongside yaml.
Thank you for pointing this out. I have already tried with the service, but I will have a closer look next week.
So the idea behind it is to register a service as an extension, to which I give a function that determines the “from/to” value, correct?
Thanks again for your help. I worked my way through it and found a solution. Who wants a similar behavior can use the following code. With this it is possible to fold on deeper indent level. Since it is still important for our use case, the folding starts with the next line (but can be removed).
foldOnIndent.ts:
import { foldService } from '@codemirror/language'
export default function foldOnIndent() {
return foldService.of((state, from, to) => {
const line = state.doc.lineAt(from) // First line
const lines = state.doc.lines // Number of lines in the document
const indent = line.text.search(/\S|$/) // Indent level of the first line
let foldStart = from // Start of the fold
let foldEnd = to // End of the fold
// Check the next line if it is on a deeper indent level
// If it is, check the next line and so on
// If it is not, go on with the foldEnd
let nextLine = line
while (nextLine.number < lines) {
nextLine = state.doc.line(nextLine.number + 1) // Next line
const nextIndent = nextLine.text.search(/\S|$/) // Indent level of the next line
// If the next line is on a deeper indent level, add it to the fold
if (nextIndent > indent) {
foldEnd = nextLine.to // Set the fold end to the end of the next line
} else {
break // If the next line is not on a deeper indent level, stop
}
}
// If the fold is only one line, don't fold it
if (state.doc.lineAt(foldStart).number === state.doc.lineAt(foldEnd).number) {
return null
}
// Set the fold start to the end of the first line
// With this, the fold will not include the first line
foldStart = line.to
// Return a fold that covers the entire indent level
return { from: foldStart, to: foldEnd }
})
}
codemirror.vue:
import foldOnIndent from '@/.../foldOnIndent'
...
// Create your extension array and register it on codemirror
const extensions = [foldOnIndent()]
...
Oh and as you mentioned, the icons to collapse are automatically displayed in the Gutter.