aboutsummaryrefslogtreecommitdiffstats
path: root/subprojects/frontend/src/editor/createEditorState.ts
blob: 7b0f3c07d54d12a3d21627b893106ea401f61e0b (plain) (blame)
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
import {
  closeBrackets,
  closeBracketsKeymap,
  autocompletion,
  completionKeymap,
} from '@codemirror/autocomplete';
import {
  defaultKeymap,
  history,
  historyKeymap,
  indentWithTab,
} from '@codemirror/commands';
import {
  bracketMatching,
  codeFolding,
  foldGutter,
  foldKeymap,
  indentOnInput,
  syntaxHighlighting,
} from '@codemirror/language';
import { lintKeymap, lintGutter } from '@codemirror/lint';
import { search, searchKeymap } from '@codemirror/search';
import { EditorState } from '@codemirror/state';
import {
  drawSelection,
  highlightActiveLine,
  highlightActiveLineGutter,
  highlightSpecialChars,
  keymap,
  lineNumbers,
  rectangularSelection,
} from '@codemirror/view';
import { classHighlighter } from '@lezer/highlight';

import problemLanguageSupport from '../language/problemLanguageSupport';

import type EditorStore from './EditorStore';
import SearchPanel from './SearchPanel';
import editorClassNames from './editorClassNames';
import findOccurrences from './findOccurrences';
import semanticHighlighting from './semanticHighlighting';

export default function createEditorState(
  initialValue: string,
  store: EditorStore,
): EditorState {
  return EditorState.create({
    doc: initialValue,
    extensions: [
      autocompletion({
        activateOnTyping: true,
        override: [(context) => store.contentAssist(context)],
      }),
      closeBrackets(),
      bracketMatching(),
      drawSelection(),
      EditorState.allowMultipleSelections.of(true),
      findOccurrences,
      highlightActiveLine(),
      highlightActiveLineGutter(),
      highlightSpecialChars(),
      history(),
      indentOnInput(),
      rectangularSelection(),
      search({
        createPanel(view) {
          return new SearchPanel(view, store.searchPanel);
        },
      }),
      syntaxHighlighting(classHighlighter),
      semanticHighlighting,
      // We add the gutters to `extensions` in the order we want them to appear.
      lintGutter(),
      lineNumbers(),
      codeFolding({
        placeholderDOM(_view, onClick) {
          const button = document.createElement('button');
          button.className = editorClassNames.foldPlaceholder;
          button.ariaLabel = 'Unfold lines';
          const span = document.createElement('span');
          span.innerText = '...';
          button.appendChild(span);
          button.addEventListener('click', onClick);
          return button;
        },
      }),
      foldGutter({
        markerDOM(open) {
          const div = document.createElement('div');
          div.className = [
            editorClassNames.foldMarker,
            open
              ? editorClassNames.foldMarkerOpen
              : editorClassNames.foldMarkerClosed,
          ].join(' ');
          return div;
        },
      }),
      keymap.of([
        { key: 'Mod-Shift-f', run: () => store.formatText() },
        ...closeBracketsKeymap,
        ...completionKeymap,
        ...foldKeymap,
        ...historyKeymap,
        indentWithTab,
        // Override keys in `lintKeymap` to go through the `EditorStore`.
        { key: 'Mod-Shift-m', run: () => store.lintPanel.open() },
        ...lintKeymap,
        // Override keys in `searchKeymap` to go through the `EditorStore`.
        {
          key: 'Mod-f',
          run: () => store.searchPanel.open(),
          scope: 'editor search-panel',
        },
        {
          key: 'Escape',
          run: () => store.searchPanel.close(),
          scope: 'editor search-panel',
        },
        ...searchKeymap,
        ...defaultKeymap,
      ]),
      problemLanguageSupport(),
    ],
  });
}