11import { MergeView } from '@codemirror/merge' ;
22import { basicSetup } from 'codemirror' ;
3- import { EditorView } from '@codemirror/view' ;
3+ import { EditorView , ViewUpdate } from '@codemirror/view' ;
4+ import { Compartment } from '@codemirror/state' ;
45import { jupyterTheme } from '@jupyterlab/codemirror' ;
56import { Widget } from '@lumino/widgets' ;
67import type { IDocumentWidget } from '@jupyterlab/docregistry' ;
@@ -43,21 +44,23 @@ export interface ISplitFileDiffOptions {
4344
4445/**
4546 * A Lumino widget that contains a CodeMirror MergeView (side-by-side)
46- * for file diffs. This is view- only (both editors are non- editable) .
47+ * for file diffs. This left pane is view only and right pane in editable.
4748 */
4849export class CodeMirrorSplitFileWidget extends Widget {
4950 private _originalCode : string ;
5051 private _modifiedCode : string ;
5152 private _mergeView : MergeView | null = null ;
5253 private _openDiff : boolean ;
5354 private _scrollWrapper : HTMLElement ;
55+ private _fileEditorWidget ?: IDocumentWidget < FileEditor > ;
5456
5557 constructor ( options : ISplitFileDiffOptions ) {
5658 super ( ) ;
5759 this . addClass ( 'jp-SplitFileDiffView' ) ;
5860 this . _originalCode = options . originalSource ;
5961 this . _modifiedCode = options . newSource ;
6062 this . _openDiff = options . openDiff ?? true ;
63+ this . _fileEditorWidget = options . fileEditorWidget ;
6164
6265 this . node . style . display = 'flex' ;
6366 this . node . style . flexDirection = 'column' ;
@@ -83,7 +86,6 @@ export class CodeMirrorSplitFileWidget extends Widget {
8386 }
8487
8588 // MergeView options: left (a) = original, right (b) = modified
86- //TODO: Currently Both panes are non-editable, but have to make right pane editable.
8789 this . _mergeView = new MergeView ( {
8890 a : {
8991 doc : this . _originalCode ,
@@ -96,21 +98,42 @@ export class CodeMirrorSplitFileWidget extends Widget {
9698 } ,
9799 b : {
98100 doc : this . _modifiedCode ,
99- extensions : [
100- basicSetup ,
101- EditorView . editable . of ( false ) ,
102- EditorView . lineWrapping ,
103- jupyterTheme
104- ]
101+ extensions : [ basicSetup , EditorView . lineWrapping , jupyterTheme ]
105102 } ,
106103 parent : this . _scrollWrapper
107104 } ) ;
108105
106+ this . _enableRightPaneSync ( ) ;
107+
109108 if ( ! this . _openDiff ) {
110109 this . hide ( ) ;
111110 }
112111 }
113112
113+ private _enableRightPaneSync ( ) : void {
114+ if ( ! this . _fileEditorWidget || ! this . _mergeView ?. b ) {
115+ return ;
116+ }
117+
118+ const fileEditor = this . _fileEditorWidget . content ;
119+ const rightEditor = this . _mergeView . b ;
120+
121+ const listenerCompartment = new Compartment ( ) ;
122+
123+ const updateListener = EditorView . updateListener . of (
124+ ( update : ViewUpdate ) => {
125+ if ( update . docChanged ) {
126+ const newText = update . state . doc . toString ( ) ;
127+
128+ fileEditor . model . sharedModel . setSource ( newText ) ;
129+ }
130+ }
131+ ) ;
132+
133+ rightEditor . dispatch ( {
134+ effects : listenerCompartment . reconfigure ( updateListener )
135+ } ) ;
136+ }
114137 private _destroySplitView ( ) : void {
115138 if ( this . _mergeView ) {
116139 try {
0 commit comments