Last active
August 15, 2024 18:16
-
-
Save andy0130tw/d5b18efc53bf3af1fddcc8db12198734 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { foldService } from '@codemirror/language' | |
/** @param {string} text */ | |
function indentLevel(text) { | |
const mat = /** @type {RegExpMatchArray} */ ( | |
text.match(/^( *)([^ ]?)/)) | |
return mat[2] ? mat[1].length : -1 | |
} | |
export const foldByIndentation = foldService.of(({ doc }, from, _to) => { | |
const line = doc.lineAt(from) | |
if (line.number == doc.lines) return null | |
// do not make an empty line foldable | |
const indThis = indentLevel(line.text) | |
if (indThis < 0) return null | |
// find the next non-empty line, recording the level | |
// if it is indented more than the current line | |
let indMin | |
let extent = line.number | |
for (let i = line.number + 1; i <= doc.lines; i++) { | |
const ind = indentLevel(doc.line(i).text) | |
if (ind < 0) continue | |
if (ind <= indThis) return null | |
indMin = ind | |
extent = i | |
break | |
} | |
// there might be no such line | |
if (indMin == null) return null | |
// skip until another non-empty line with less indentation level | |
for (let i = extent + 1; i <= doc.lines; i++) { | |
const ind = indentLevel(doc.line(i).text) | |
if (ind < 0) continue | |
if (ind < indMin) break | |
extent = i | |
} | |
return extent == line.number ? null : { | |
from: doc.line(line.number).to, | |
to: doc.line(extent).to, | |
} | |
}) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment