@@ -45,6 +45,9 @@ import KeyboardEvent from "utils/keyboardEvent";
4545import Url from "utils/Url" ;
4646import constants from "./constants" ;
4747
48+ const { Fold } = ace . require ( "ace/edit_session/fold" ) ;
49+ const { Range } = ace . require ( "ace/range" ) ;
50+
4851export default class Acode {
4952 #modules = { } ;
5053 #pluginsInit = { } ;
@@ -475,19 +478,28 @@ export default class Acode {
475478
476479 async format ( selectIfNull = true ) {
477480 const file = editorManager . activeFile ;
481+ if ( ! file ?. session ) return ;
482+
478483 const name = ( file . session . getMode ( ) . $id || "" ) . split ( "/" ) . pop ( ) ;
479484 const formatterId = appSettings . value . formatter [ name ] ;
480485 const formatter = this . #formatter. find ( ( { id } ) => id === formatterId ) ;
481486
482- await formatter ?. format ( ) ;
483-
484- if ( ! formatter && selectIfNull ) {
487+ if ( ! formatter ) {
488+ if ( ! selectIfNull ) {
489+ toast ( strings [ "please select a formatter" ] ) ;
490+ return ;
491+ }
485492 formatterSettings ( name ) ;
486493 this . #afterSelectFormatter( name ) ;
487494 return ;
488495 }
489- if ( ! formatter && ! selectIfNull ) {
490- toast ( strings [ "please select a formatter" ] ) ;
496+
497+ const foldsSnapshot = this . #captureFoldState( file . session ) ;
498+
499+ try {
500+ await formatter . format ( ) ;
501+ } finally {
502+ this . #restoreFoldState( file . session , foldsSnapshot ) ;
491503 }
492504 }
493505
@@ -506,6 +518,77 @@ export default class Acode {
506518 return fsOperation ( file ) ;
507519 }
508520
521+ #captureFoldState( session ) {
522+ if ( ! session ?. getAllFolds ) return null ;
523+ return this . #serializeFolds( session . getAllFolds ( ) ) ;
524+ }
525+
526+ #restoreFoldState( session , folds ) {
527+ if ( ! session || ! Array . isArray ( folds ) || ! folds . length ) return ;
528+
529+ try {
530+ const foldObjects = this . #parseSerializableFolds( folds ) ;
531+ if ( ! foldObjects . length ) return ;
532+ session . removeAllFolds ?. ( ) ;
533+ session . addFolds ?. ( foldObjects ) ;
534+ } catch ( error ) {
535+ console . warn ( "Failed to restore folds after formatting:" , error ) ;
536+ }
537+ }
538+
539+ #serializeFolds( folds ) {
540+ if ( ! Array . isArray ( folds ) || ! folds . length ) return null ;
541+
542+ return folds
543+ . map ( ( fold ) => {
544+ if ( ! fold ?. range ) return null ;
545+ const { start, end } = fold . range ;
546+ if ( ! start || ! end ) return null ;
547+
548+ return {
549+ range : {
550+ start : { row : start . row , column : start . column } ,
551+ end : { row : end . row , column : end . column } ,
552+ } ,
553+ placeholder : fold . placeholder ,
554+ ranges : this . #serializeFolds( fold . ranges || [ ] ) ,
555+ } ;
556+ } )
557+ . filter ( Boolean ) ;
558+ }
559+
560+ #parseSerializableFolds( folds ) {
561+ if ( ! Array . isArray ( folds ) || ! folds . length ) return [ ] ;
562+
563+ return folds
564+ . map ( ( fold ) => {
565+ const { range, placeholder, ranges } = fold ;
566+ const { start, end } = range || { } ;
567+ if ( ! start || ! end ) return null ;
568+
569+ try {
570+ const foldInstance = new Fold (
571+ new Range ( start . row , start . column , end . row , end . column ) ,
572+ placeholder ,
573+ ) ;
574+
575+ if ( Array . isArray ( ranges ) && ranges . length ) {
576+ const subFolds = this . #parseSerializableFolds( ranges ) ;
577+ if ( subFolds . length ) {
578+ foldInstance . subFolds = subFolds ;
579+ foldInstance . ranges = subFolds ;
580+ }
581+ }
582+
583+ return foldInstance ;
584+ } catch ( error ) {
585+ console . warn ( "Failed to parse fold:" , error ) ;
586+ return null ;
587+ }
588+ } )
589+ . filter ( Boolean ) ;
590+ }
591+
509592 newEditorFile ( filename , options ) {
510593 new EditorFile ( filename , options ) ;
511594 }
0 commit comments