11// src/codemirror.tsx
22import React , { useEffect , useRef } from 'react' ;
3- import { EditorState } from '@codemirror/state' ;
3+ import { EditorState , Compartment , type Extension } from '@codemirror/state' ;
44import {
55 EditorView ,
66 keymap ,
@@ -21,7 +21,13 @@ import {
2121 foldGutter ,
2222 foldKeymap ,
2323} from '@codemirror/language' ;
24- import { defaultKeymap , history , historyKeymap } from '@codemirror/commands' ;
24+
25+ import { javascript } from '@codemirror/lang-javascript' ;
26+ import { python } from '@codemirror/lang-python' ;
27+ import { cpp } from '@codemirror/lang-cpp' ;
28+ import { java } from '@codemirror/lang-java' ;
29+
30+ import { defaultKeymap , history , historyKeymap , indentMore , indentLess } from '@codemirror/commands' ;
2531import { searchKeymap , highlightSelectionMatches } from '@codemirror/search' ;
2632import {
2733 autocompletion ,
@@ -34,18 +40,32 @@ import {yCollab} from 'y-codemirror.next';
3440import * as Y from 'yjs' ;
3541import { Awareness } from 'y-protocols/awareness' ;
3642
43+ const languageCompartment = new Compartment ( ) ;
44+
45+ const languageMap : { [ key : string ] : ( ) => Extension } = {
46+ javascript : ( ) => javascript ( ) ,
47+ python : ( ) => python ( ) ,
48+ cpp : ( ) => cpp ( ) ,
49+ java : ( ) => java ( ) ,
50+ default : ( ) => [ ] , // plain text mode
51+ } ;
52+
3753interface CodeMirrorProps {
3854 ytext : Y . Text ;
3955 awareness : Awareness ;
56+ languageConfig : string ;
4057}
4158
42- export default function CodeMirror ( { ytext, awareness} : CodeMirrorProps ) {
59+ export default function CodeMirror ( { ytext, awareness, languageConfig } : CodeMirrorProps ) {
4360 const editorRef = useRef < HTMLDivElement > ( null ) ;
4461 const viewRef = useRef < EditorView | null > ( null ) ;
4562
4663 useEffect ( ( ) => {
4764 if ( ! editorRef . current || ! ytext || ! awareness ) return ;
4865
66+ const lazyInitialLang = languageMap [ languageConfig . toLowerCase ( ) ] || languageMap . default ;
67+ const initialLanguageExtension = lazyInitialLang ( ) ;
68+
4969 // Create the editor view with yCollab extension
5070 const view = new EditorView ( {
5171 doc : ytext . toString ( ) ,
@@ -68,7 +88,9 @@ export default function CodeMirror({ytext, awareness}: CodeMirrorProps) {
6888 // Re-indent lines when typing specific input
6989 indentOnInput ( ) ,
7090 // Highlight syntax with a default style
71- syntaxHighlighting ( defaultHighlightStyle ) ,
91+ syntaxHighlighting ( defaultHighlightStyle , { fallback : true } ) ,
92+ // Dyanmic configuration for language mode
93+ languageCompartment . of ( initialLanguageExtension ) ,
7294 // Highlight matching brackets near cursor
7395 bracketMatching ( ) ,
7496 // Automatically close brackets
@@ -88,6 +110,17 @@ export default function CodeMirror({ytext, awareness}: CodeMirrorProps) {
88110 // Yjs collaboration extension for CodeMirror 6
89111 yCollab ( ytext , awareness ) ,
90112 keymap . of ( [
113+ {
114+ key : "Tab" ,
115+ preventDefault : true ,
116+ run : indentMore ,
117+ } ,
118+ {
119+ key : "Shift-Tab" ,
120+ preventDefault : true ,
121+ run : indentLess ,
122+ } ,
123+
91124 // Closed-brackets aware backspace
92125 ...closeBracketsKeymap ,
93126 // A large set of basic bindings
@@ -117,6 +150,20 @@ export default function CodeMirror({ytext, awareness}: CodeMirrorProps) {
117150 } ;
118151 } , [ ytext , awareness ] ) ;
119152
153+ // Effect to handle language changes
154+ useEffect ( ( ) => {
155+ const view = viewRef . current ;
156+ if ( ! view ) return ;
157+
158+ const newLazyLangFn = languageMap [ languageConfig . toLowerCase ( ) ] || languageMap . default ;
159+ const newExtension = newLazyLangFn ( ) ;
160+
161+ // Reconfigures compartment with the new language extension
162+ view . dispatch ( {
163+ effects : languageCompartment . reconfigure ( newExtension ) ,
164+ } ) ;
165+ } , [ languageConfig ] ) ;
166+
120167 return (
121168 < div
122169 ref = { editorRef }
0 commit comments