Skip to content

Commit 778df93

Browse files
committed
feat: Extend the basicSetup props (#316).
1 parent 29d5840 commit 778df93

File tree

5 files changed

+340
-6
lines changed

5 files changed

+340
-6
lines changed

core/README.md

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -273,7 +273,7 @@ export interface ReactCodeMirrorProps
273273
* Whether to optional basicSetup by default
274274
* @default true
275275
*/
276-
basicSetup?: boolean;
276+
basicSetup?: boolean | BasicSetupOptions;
277277
/**
278278
* This disables editing of the editor content by the user.
279279
* @default true
@@ -315,6 +315,32 @@ declare const ReactCodeMirror: React.ForwardRefExoticComponent<
315315
ReactCodeMirrorProps & React.RefAttributes<ReactCodeMirrorRef>
316316
>;
317317
export default ReactCodeMirror;
318+
export interface BasicSetupOptions {
319+
lineNumbers?: boolean;
320+
highlightActiveLineGutter?: boolean;
321+
highlightSpecialChars?: boolean;
322+
history?: boolean;
323+
foldGutter?: boolean;
324+
drawSelection?: boolean;
325+
dropCursor?: boolean;
326+
allowMultipleSelections?: boolean;
327+
indentOnInput?: boolean;
328+
syntaxHighlighting?: boolean;
329+
bracketMatching?: boolean;
330+
closeBrackets?: boolean;
331+
autocompletion?: boolean;
332+
rectangularSelection?: boolean;
333+
crosshairCursor?: boolean;
334+
highlightActiveLine?: boolean;
335+
highlightSelectionMatches?: boolean;
336+
closeBracketsKeymap?: boolean;
337+
defaultKeymap?: boolean;
338+
searchKeymap?: boolean;
339+
historyKeymap?: boolean;
340+
foldKeymap?: boolean;
341+
completionKeymap?: boolean;
342+
lintKeymap?: boolean;
343+
}
318344
```
319345

320346
### Related

core/src/basicSetup.ts

Lines changed: 136 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,136 @@
1+
import {
2+
KeyBinding,
3+
lineNumbers,
4+
highlightActiveLineGutter,
5+
highlightSpecialChars,
6+
drawSelection,
7+
dropCursor,
8+
rectangularSelection,
9+
crosshairCursor,
10+
highlightActiveLine,
11+
keymap,
12+
} from '@codemirror/view';
13+
import { EditorState, Extension } from '@codemirror/state';
14+
import { history, defaultKeymap, historyKeymap } from '@codemirror/commands';
15+
import { highlightSelectionMatches, searchKeymap } from '@codemirror/search';
16+
import { closeBrackets, autocompletion, closeBracketsKeymap, completionKeymap } from '@codemirror/autocomplete';
17+
import {
18+
foldGutter,
19+
indentOnInput,
20+
syntaxHighlighting,
21+
defaultHighlightStyle,
22+
bracketMatching,
23+
foldKeymap,
24+
} from '@codemirror/language';
25+
import { lintKeymap } from '@codemirror/lint';
26+
27+
export interface BasicSetupOptions {
28+
lineNumbers?: boolean;
29+
highlightActiveLineGutter?: boolean;
30+
highlightSpecialChars?: boolean;
31+
history?: boolean;
32+
foldGutter?: boolean;
33+
drawSelection?: boolean;
34+
dropCursor?: boolean;
35+
allowMultipleSelections?: boolean;
36+
indentOnInput?: boolean;
37+
syntaxHighlighting?: boolean;
38+
bracketMatching?: boolean;
39+
closeBrackets?: boolean;
40+
autocompletion?: boolean;
41+
rectangularSelection?: boolean;
42+
crosshairCursor?: boolean;
43+
highlightActiveLine?: boolean;
44+
highlightSelectionMatches?: boolean;
45+
46+
closeBracketsKeymap?: boolean;
47+
defaultKeymap?: boolean;
48+
searchKeymap?: boolean;
49+
historyKeymap?: boolean;
50+
foldKeymap?: boolean;
51+
completionKeymap?: boolean;
52+
lintKeymap?: boolean;
53+
}
54+
55+
/**
56+
This is an extension value that just pulls together a number of
57+
extensions that you might want in a basic editor. It is meant as a
58+
convenient helper to quickly set up CodeMirror without installing
59+
and importing a lot of separate packages.
60+
61+
Specifically, it includes...
62+
63+
- [the default command bindings](https://codemirror.net/6/docs/ref/#commands.defaultKeymap)
64+
- [line numbers](https://codemirror.net/6/docs/ref/#view.lineNumbers)
65+
- [special character highlighting](https://codemirror.net/6/docs/ref/#view.highlightSpecialChars)
66+
- [the undo history](https://codemirror.net/6/docs/ref/#commands.history)
67+
- [a fold gutter](https://codemirror.net/6/docs/ref/#language.foldGutter)
68+
- [custom selection drawing](https://codemirror.net/6/docs/ref/#view.drawSelection)
69+
- [drop cursor](https://codemirror.net/6/docs/ref/#view.dropCursor)
70+
- [multiple selections](https://codemirror.net/6/docs/ref/#state.EditorState^allowMultipleSelections)
71+
- [reindentation on input](https://codemirror.net/6/docs/ref/#language.indentOnInput)
72+
- [the default highlight style](https://codemirror.net/6/docs/ref/#language.defaultHighlightStyle) (as fallback)
73+
- [bracket matching](https://codemirror.net/6/docs/ref/#language.bracketMatching)
74+
- [bracket closing](https://codemirror.net/6/docs/ref/#autocomplete.closeBrackets)
75+
- [autocompletion](https://codemirror.net/6/docs/ref/#autocomplete.autocompletion)
76+
- [rectangular selection](https://codemirror.net/6/docs/ref/#view.rectangularSelection) and [crosshair cursor](https://codemirror.net/6/docs/ref/#view.crosshairCursor)
77+
- [active line highlighting](https://codemirror.net/6/docs/ref/#view.highlightActiveLine)
78+
- [active line gutter highlighting](https://codemirror.net/6/docs/ref/#view.highlightActiveLineGutter)
79+
- [selection match highlighting](https://codemirror.net/6/docs/ref/#search.highlightSelectionMatches)
80+
- [search](https://codemirror.net/6/docs/ref/#search.searchKeymap)
81+
- [linting](https://codemirror.net/6/docs/ref/#lint.lintKeymap)
82+
83+
(You'll probably want to add some language package to your setup
84+
too.)
85+
86+
This extension does not allow customization. The idea is that,
87+
once you decide you want to configure your editor more precisely,
88+
you take this package's source (which is just a bunch of imports
89+
and an array literal), copy it into your own code, and adjust it
90+
as desired.
91+
*/
92+
export const basicSetup = (options: BasicSetupOptions = {}): Extension[] => {
93+
const keymaps: KeyBinding[][] = [];
94+
if (options.closeBracketsKeymap !== false) {
95+
keymaps.push([...closeBracketsKeymap]);
96+
}
97+
if (options.defaultKeymap !== false) {
98+
keymaps.push([...defaultKeymap]);
99+
}
100+
if (options.searchKeymap !== false) {
101+
keymaps.push([...searchKeymap]);
102+
}
103+
if (options.historyKeymap !== false) {
104+
keymaps.push([...historyKeymap]);
105+
}
106+
if (options.foldKeymap !== false) {
107+
keymaps.push([...foldKeymap]);
108+
}
109+
if (options.completionKeymap !== false) {
110+
keymaps.push([...completionKeymap]);
111+
}
112+
if (options.lintKeymap !== false) {
113+
keymaps.push([...lintKeymap]);
114+
}
115+
const extensions: Extension[] = [];
116+
if (options.lineNumbers !== false) extensions.push(lineNumbers());
117+
if (options.highlightActiveLineGutter !== false) extensions.push(highlightActiveLineGutter());
118+
if (options.highlightSpecialChars !== false) extensions.push(highlightSpecialChars());
119+
if (options.history !== false) extensions.push(history());
120+
if (options.foldGutter !== false) extensions.push(foldGutter());
121+
if (options.drawSelection !== false) extensions.push(drawSelection());
122+
if (options.dropCursor !== false) extensions.push(dropCursor());
123+
if (options.allowMultipleSelections !== false) extensions.push(EditorState.allowMultipleSelections.of(true));
124+
if (options.indentOnInput !== false) extensions.push(indentOnInput());
125+
if (options.syntaxHighlighting !== false)
126+
extensions.push(syntaxHighlighting(defaultHighlightStyle, { fallback: true }));
127+
if (options.bracketMatching !== false) extensions.push(bracketMatching());
128+
if (options.closeBrackets !== false) extensions.push(closeBrackets());
129+
if (options.autocompletion !== false) extensions.push(autocompletion());
130+
if (options.rectangularSelection !== false) extensions.push(rectangularSelection());
131+
if (options.crosshairCursor !== false) extensions.push(crosshairCursor());
132+
if (options.highlightActiveLine !== false) extensions.push(highlightActiveLine());
133+
if (options.highlightSelectionMatches !== false) extensions.push(highlightSelectionMatches());
134+
135+
return [...extensions, keymap.of(keymaps.flat())].filter(Boolean);
136+
};

core/src/index.tsx

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,9 @@ import React, { useEffect, useRef, useImperativeHandle } from 'react';
22
import { EditorState, EditorStateConfig, Extension } from '@codemirror/state';
33
import { EditorView, ViewUpdate } from '@codemirror/view';
44
import { useCodeMirror } from './useCodeMirror';
5+
import { BasicSetupOptions } from './basicSetup';
56

7+
export * from './basicSetup';
68
export * from './useCodeMirror';
79

810
export interface ReactCodeMirrorProps
@@ -29,12 +31,16 @@ export interface ReactCodeMirrorProps
2931
* Whether to optional basicSetup by default
3032
* @default true
3133
*/
32-
basicSetup?: boolean;
34+
basicSetup?: boolean | BasicSetupOptions;
3335
/**
3436
* This disables editing of the editor content by the user.
3537
* @default true
3638
*/
3739
editable?: boolean;
40+
/**
41+
* This disables editing of the editor content by the user.
42+
* @default false
43+
*/
3844
readOnly?: boolean;
3945
/**
4046
* Whether to optional basicSetup by default

core/src/useCodeMirror.ts

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
import { useEffect, useState } from 'react';
2-
import { basicSetup } from 'codemirror';
32
import { EditorState, StateEffect } from '@codemirror/state';
43
import { indentWithTab } from '@codemirror/commands';
54
import { EditorView, keymap, ViewUpdate, placeholder } from '@codemirror/view';
65
import { oneDark } from '@codemirror/theme-one-dark';
6+
import { basicSetup } from './basicSetup';
77
import { ReactCodeMirrorProps } from '.';
88

99
export interface UseCodeMirror extends ReactCodeMirrorProps {
@@ -62,12 +62,17 @@ export function useCodeMirror(props: UseCodeMirror) {
6262
onChange(value, vu);
6363
}
6464
});
65+
6566
let getExtensions = [updateListener, defaultThemeOption];
6667
if (defaultIndentWithTab) {
6768
getExtensions.unshift(keymap.of([indentWithTab]));
6869
}
6970
if (defaultBasicSetup) {
70-
getExtensions.unshift(basicSetup);
71+
if (typeof defaultBasicSetup === 'boolean') {
72+
getExtensions.unshift(basicSetup());
73+
} else {
74+
getExtensions.unshift(basicSetup(defaultBasicSetup));
75+
}
7176
}
7277

7378
if (placeholderStr) {

0 commit comments

Comments
 (0)