@@ -112,6 +112,7 @@ export class Workspace {
112112 #readonly = false ; // TODO do we need workspaces for readonly stuff?
113113 #files = $state . raw < Item [ ] > ( [ ] ) ;
114114 #current = $state . raw ( ) as File ;
115+ #vim = $state ( false ) ;
115116
116117 #handlers = {
117118 hover : new Set < ( pos : number | null ) => void > ( ) ,
@@ -279,23 +280,10 @@ export class Workspace {
279280 if ( this . #view) throw new Error ( 'view is already linked' ) ;
280281 this . #view = view ;
281282
282- view . setState ( this . #get_state( untrack ( ( ) => this . #current) ) ) ;
283-
284- let should_install_vim = localStorage . getItem ( 'vim' ) === 'true' ;
285-
286- const q = new URLSearchParams ( location . search ) ;
287- if ( q . has ( 'vim' ) ) {
288- should_install_vim = q . get ( 'vim' ) === 'true' ;
289- localStorage . setItem ( 'vim' , should_install_vim . toString ( ) ) ;
290- }
291-
292- if ( should_install_vim ) {
293- const { vim } = await import ( '@replit/codemirror-vim' ) ;
294-
295- this . #view?. dispatch ( {
296- effects : vim_mode . reconfigure ( vim ( ) )
297- } ) ;
298- }
283+ untrack ( ( ) => {
284+ view . setState ( this . #get_state( untrack ( ( ) => this . #current) ) ) ;
285+ this . vim = localStorage . getItem ( 'vim' ) === 'true' ;
286+ } ) ;
299287 }
300288
301289 move ( from : Item , to : Item ) {
@@ -476,6 +464,44 @@ export class Workspace {
476464 }
477465 }
478466
467+ get vim ( ) {
468+ return this . #vim;
469+ }
470+
471+ set vim ( value ) {
472+ this . #toggle_vim( value ) ;
473+ }
474+
475+ async #toggle_vim( value : boolean ) {
476+ this . #vim = value ;
477+
478+ localStorage . setItem ( 'vim' , String ( value ) ) ;
479+
480+ // @ts -expect-error jfc CodeMirror is a struggle
481+ let vim_extension_index = default_extensions . findIndex ( ( ext ) => ext . compartment === vim_mode ) ;
482+
483+ let extension : any = [ ] ;
484+
485+ if ( value ) {
486+ const { vim } = await import ( '@replit/codemirror-vim' ) ;
487+ extension = vim ( ) ;
488+ }
489+
490+ default_extensions [ vim_extension_index ] = vim_mode . of ( extension ) ;
491+
492+ this . #view?. dispatch ( {
493+ effects : vim_mode . reconfigure ( extension )
494+ } ) ;
495+
496+ // update all the other states
497+ for ( const file of this . #files) {
498+ if ( file . type !== 'file' ) continue ;
499+ if ( file === this . #current) continue ;
500+
501+ this . states . set ( file . name , this . #create_state( file ) ) ;
502+ }
503+ }
504+
479505 #create_directories( item : Item ) {
480506 // create intermediate directories as necessary
481507 const parts = item . name . split ( '/' ) ;
@@ -497,9 +523,10 @@ export class Workspace {
497523 }
498524
499525 #get_state( file : File ) {
500- let state = this . states . get ( file . name ) ;
501- if ( state ) return state ;
526+ return this . states . get ( file . name ) ?? this . #create_state ( file ) ;
527+ }
502528
529+ #create_state( file : File ) {
503530 const extensions = [
504531 ...default_extensions ,
505532 EditorState . readOnly . of ( this . #readonly) ,
@@ -573,7 +600,7 @@ export class Workspace {
573600 break ;
574601 }
575602
576- state = EditorState . create ( {
603+ const state = EditorState . create ( {
577604 doc : file . contents ,
578605 extensions
579606 } ) ;
0 commit comments