CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutSign UpSign In
sagemathinc

Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place.

GitHub Repository: sagemathinc/cocalc
Path: blob/master/src/packages/frontend/codemirror/extensions/fold-code-selection.ts
Views: 687
1
/*
2
* This file is part of CoCalc: Copyright © 2020 Sagemath, Inc.
3
* License: MS-RSL – see LICENSE.md for details
4
*/
5
6
import * as CodeMirror from "codemirror";
7
import { cm_start_end } from "./util";
8
9
/*
10
The variable mode determines whether we are folding or unfolding *everything*
11
selected. If mode='fold', fold everything; if mode='unfold', unfolding everything;
12
and if mode=undefined, not yet decided. If undecided, which is decided on the first
13
thing that we would toggle, e.g., if the first fold point is unfolded, we make sure
14
everything is folded in all ranges, but if the first fold point is not folded, we then
15
make everything unfolded.
16
*/
17
18
CodeMirror.defineExtension(
19
"foldCodeSelectionAware",
20
function (mode: undefined | "fold" | "unfold") {
21
// @ts-ignore
22
const editor: any = this;
23
for (const selection of editor.listSelections()) {
24
const { start_line, end_line } = cm_start_end(selection);
25
for (let n = start_line; n <= end_line; n++) {
26
const pos = CodeMirror.Pos(n);
27
try {
28
if (mode != null) {
29
editor.foldCode(pos, null, mode);
30
} else {
31
// try to toggle and see if anything happens
32
const is_folded = editor.isLineFolded(n);
33
editor.foldCode(pos);
34
if (editor.isLineFolded(n) !== is_folded) {
35
// this is a foldable line, and what did we just do? What it was, keep doing it.
36
mode = editor.isLineFolded(n) ? "fold" : "unfold";
37
}
38
}
39
} catch (err) {
40
// I've observed in production getting
41
// "Inserting collapsed marker partially overlapping an existing one"
42
// raised in production. It's way better to just log this in the console.
43
// In particular, this happens for the file fcs.tsx as of this writing, when
44
// you select all and hit control+Q:
45
// https://github.com/sagemathinc/cocalc/blob/250045ad8af9db9f485d810141f065096c52f11b/src/@cocalc/frontend/project/info/fcs.tsx
46
47
console.warn(`WARNING: ${err}`);
48
}
49
}
50
}
51
}
52
);
53
54
// This isFolded extension that comes with CodeMirror isn't useful for the above, since it
55
// is only at a *point*, not a line.
56
CodeMirror.defineExtension("isLineFolded", function (line: number): boolean {
57
// @ts-ignore
58
const editor: any = this;
59
for (const mark of editor.findMarks(
60
{ line, ch: 0 },
61
{ line: line + 1, ch: 0 }
62
)) {
63
if (mark.__isFold) {
64
return true;
65
}
66
}
67
return false;
68
});
69
70