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
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
|
import { Editor, EditorConfiguration } from 'codemirror';
import {
createAtom,
makeAutoObservable,
observable,
} from 'mobx';
import 'mode-problem';
import {
IXtextOptions,
IXtextServices,
createServices,
removeServices,
} from 'xtext/xtext-codemirror';
const xtextLang = 'problem';
const xtextOptions: IXtextOptions = {
xtextLang,
enableFormattingAction: true,
};
const codeMirrorGlobalOptions: EditorConfiguration = {
mode: `xtext/${xtextLang}`,
indentUnit: 2,
theme: 'material-darker',
};
export default class EditorStore {
_atom;
editor?: Editor;
xtextServices?: IXtextServices;
value = '';
showLineNumbers = false;
constructor() {
this._atom = createAtom('EditorStore');
makeAutoObservable(this, {
_atom: false,
editor: observable.ref,
xtextServices: observable.ref,
});
}
/**
* Attaches a new CodeMirror instance and creates Xtext services.
*
* The store will not subscribe to any CodeMirror events. Instead,
* the editor component should subscribe to them and relay them to the store.
*
* @param newEditor The new CodeMirror instance
*/
editorDidMount(newEditor: Editor) {
if (this.editor) {
throw new Error('CoreMirror editor mounted before unmounting');
}
this.editor = newEditor;
this.xtextServices = createServices(newEditor, xtextOptions);
}
editorWillUnmount() {
if (this.editor) {
removeServices(this.editor);
}
this.editor = undefined;
this.xtextServices = undefined;
}
/**
* Updates the contents of the editor.
*
* @param newValue The new contents of the editor
*/
updateValue(newValue: string) {
this.value = newValue;
}
reportChanged() {
this._atom.reportChanged();
}
_observeEditorChanges() {
this._atom.reportObserved();
}
get codeMirrorOptions(): EditorConfiguration {
return {
...codeMirrorGlobalOptions,
lineNumbers: this.showLineNumbers,
};
}
/**
* @returns `true` if there is history to undo
*/
get canUndo() {
this._observeEditorChanges();
if (!this.editor) {
return false;
}
const { undo: undoSize } = this.editor.historySize();
return undoSize > 0;
}
undo() {
this.editor?.undo();
}
/**
* @returns `true` if there is history to redo
*/
get canRedo() {
this._observeEditorChanges();
if (!this.editor) {
return false;
}
const { redo: redoSize } = this.editor.historySize();
return redoSize > 0;
}
redo() {
this.editor?.redo();
}
toggleLineNumbers() {
this.showLineNumbers = !this.showLineNumbers;
}
}
|