cm-extensions.ts
3.02 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
import CodeMirror from 'codemirror';
// Comment/uncomment the specified range
CodeMirror.defineExtension('commentRange', function (isComment, from, to) {
let cm = this,
curMode = CodeMirror.innerMode(
cm.getMode(),
cm.getTokenAt(from).state,
).mode;
cm.operation(function () {
if (isComment) {
// Comment range
cm.replaceRange(curMode.commentEnd, to);
cm.replaceRange(curMode.commentStart, from);
if (from.line == to.line && from.ch == to.ch)
// An empty comment inserted - put cursor inside
cm.setCursor(from.line, from.ch + curMode.commentStart.length);
} else {
// Uncomment range
let selText = cm.getRange(from, to);
let startIndex = selText.indexOf(curMode.commentStart);
let endIndex = selText.lastIndexOf(curMode.commentEnd);
if (startIndex > -1 && endIndex > -1 && endIndex > startIndex) {
// Take string till comment start
selText =
selText.substr(0, startIndex) +
// From comment start till comment end
selText.substring(
startIndex + curMode.commentStart.length,
endIndex,
) +
// From comment end till string end
selText.substr(endIndex + curMode.commentEnd.length);
}
cm.replaceRange(selText, from, to);
}
});
});
// Applies automatic formatting to the specified range
CodeMirror.defineExtension('autoFormatRange', function (from, to) {
let cm = this;
let outer = cm.getMode(),
text = cm.getRange(from, to).split('\n');
let state = CodeMirror.copyState(outer, cm.getTokenAt(from).state);
let tabSize = cm.getOption('tabSize');
let out = '',
lines = 0,
atSol = from.ch == 0;
function newline() {
out += '\n';
atSol = true;
++lines;
}
for (let i = 0; i < text.length; ++i) {
let stream = new CodeMirror.StringStream(text[i], tabSize);
while (!stream.eol()) {
let inner = CodeMirror.innerMode(outer, state);
let style = outer.token(stream, state),
cur = stream.current();
stream.start = stream.pos;
if (!atSol || /\S/.test(cur)) {
out += cur;
atSol = false;
}
if (
!atSol &&
inner.mode.newlineAfterToken &&
inner.mode.newlineAfterToken(
style,
cur,
stream.string.slice(stream.pos) || text[i + 1] || '',
inner.state,
)
)
newline();
}
if (!stream.pos && outer.blankLine) outer.blankLine(state);
if (!atSol) newline();
}
cm.operation(function () {
cm.replaceRange(out, from, to);
for (let cur = from.line + 1, end = from.line + lines; cur <= end; ++cur)
cm.indentLine(cur, 'smart');
cm.setSelection(from, cm.getCursor(false));
});
});
// Applies automatic mode-aware indentation to the specified range
CodeMirror.defineExtension('autoIndentRange', function (from, to) {
let cmInstance = this;
this.operation(function () {
for (let i = from.line; i <= to.line; i++) {
cmInstance.indentLine(i, 'smart');
}
});
});