import { JupyterFrontEnd } from '@jupyterlab/application' ; import { Settings } from '@jupyterlab/settingregistry' ; import { JSONArray , JSONExt , PartialJSONValue } from '@lumino/coreutils' ; import { CodeSnippetWidget } from './CodeSnippetWidget' ; export interface ICodeSnippet { name : string ; description : string ; language : string ; code : string [ ] ; id : number ; tags ? : string [ ] ; } export class CodeSnippetService { private settingManager : Settings ; private static codeSnippetService : CodeSnippetService ; private codeSnippetList : ICodeSnippet [ ] ; private constructor ( settings , app ) { this . settingManager = settings ; this . settingManager . changed . connect ( async ( plugin ) => { const newCodeSnippetList = plugin . get ( 'snippets' ) . user ; if ( ! JSONExt . deepEqual ( newCodeSnippetList , this . codeSnippetList as unknown as PartialJSONValue ) ) { this . codeSnippetList = this . convertToICodeSnippetList ( newCodeSnippetList as JSONArray ) ; const leftWidgets = app . shell . widgets ( 'left' ) . iter ( ) ; let current = leftWidgets . next ( ) ; while ( current ) { if ( current instanceof CodeSnippetWidget ) { current . updateCodeSnippetWidget ( ) ; break ; } current = leftWidgets . next ( ) ; } } } ) ; const defaultSnippets = this . convertToICodeSnippetList ( this . settingManager . default ( 'snippets' ) as JSONArray ) ; if ( this . settingManager . get ( 'snippets' ) . user === undefined ) { this . settingManager . set ( 'snippets' , defaultSnippets as unknown as PartialJSONValue ) . then ( ( ) => { const userSnippets = this . convertToICodeSnippetList ( this . settingManager . get ( 'snippets' ) . user as JSONArray ) ; this . codeSnippetList = userSnippets ; } ) ; } else { const userSnippets = this . convertToICodeSnippetList ( this . settingManager . get ( 'snippets' ) . user as JSONArray ) ; this . codeSnippetList = userSnippets ; } if ( this . settingManager . get ( 'snippetPreviewFontSize' ) . user === undefined ) { this . settingManager . set ( 'snippetPreviewFontSize' , this . settingManager . default ( 'snippetPreviewFontSize' ) ) ; } } private convertToICodeSnippetList ( snippets ) { const snippetList = [ ] ; snippets . forEach ( ( snippet ) => { snippetList . push ( snippet as unknown as ICodeSnippet ) ; } ) ; return snippetList ; } static init ( settings , app ) { if ( ! this . codeSnippetService ) { this . codeSnippetService = new CodeSnippetService ( settings , app ) ; } } static getCodeSnippetService ( ) { return this . codeSnippetService ; } get settings ( ) : Settings { return this . settingManager ; } get snippets ( ) : ICodeSnippet [ ] { return this . codeSnippetList ; } getSnippet ( snippetName ) { return this . codeSnippetList . filter ( ( snippet ) => snippet . name . toLowerCase ( ) === snippetName . toLowerCase ( ) ) ; } async addSnippet ( snippet ) { const id = snippet . id ; this . codeSnippetList . splice ( id , 0 , snippet ) ; const numSnippets = this . codeSnippetList . length ; let i = id + 1 ; for ( ; i < numSnippets ; i ++ ) { this . codeSnippetList [ i ] . id += 1 ; } await this . settingManager . set ( 'snippets' , this . codeSnippetList as unknown as PartialJSONValue ) . catch ( ( _ ) => { return false ; } ) ; return true ; } async deleteSnippet ( id ) { let numSnippets = this . codeSnippetList . length ; if ( id >= numSnippets ) { console . log ( 'error in codeSnippetService' ) ; } if ( id === numSnippets - 1 ) { this . codeSnippetList . pop ( ) ; } else { this . codeSnippetList . splice ( id , 1 ) ; numSnippets = this . codeSnippetList . length ; let i = id ; for ( ; i < numSnippets ; i ++ ) { this . codeSnippetList [ i ] . id -= 1 ; } } await this . settingManager . set ( 'snippets' , this . codeSnippetList as unknown as PartialJSONValue ) . catch ( ( _ ) => { return false ; } ) ; return true ; } async renameSnippet ( oldName , newName ) { for ( const snippet of this . codeSnippetList ) { if ( snippet . name === oldName ) { snippet . name = newName ; break ; } } await this . settingManager . set ( 'snippets' , this . codeSnippetList as unknown as PartialJSONValue ) . catch ( ( _ ) => { return false ; } ) ; return true ; } duplicateNameExists ( newName ) { for ( const snippet of this . codeSnippetList ) { if ( snippet . name . toLowerCase ( ) === newName . toLowerCase ( ) ) { return true ; } } return false ; } async modifyExistingSnippet ( oldName , newSnippet ) { for ( const snippet of this . codeSnippetList ) { if ( snippet . name . toLowerCase ( ) === oldName . toLowerCase ( ) ) { this . codeSnippetList . splice ( snippet . id , 1 , newSnippet ) ; break ; } } await this . settingManager . set ( 'snippets' , this . codeSnippetList as unknown as PartialJSONValue ) . catch ( ( _ ) => { return false ; } ) ; return true ; } async moveSnippet ( fromIdx , toIdx ) { if ( toIdx > fromIdx ) { toIdx = toIdx - 1 ; } if ( toIdx === fromIdx ) { return ; } const snippetToMove = this . codeSnippetList [ fromIdx ] ; this . deleteSnippet ( fromIdx ) . then ( ( res ) => { if ( ! res ) { console . log ( 'Error in moving snippet(delete)' ) ; return false ; } } ) ; snippetToMove . id = toIdx ; this . addSnippet ( snippetToMove ) . then ( ( res ) => { if ( ! res ) { console . log ( 'Error in moving snippet(add)' ) ; return false ; } } ) ; await this . settingManager . set ( 'snippets' , this . codeSnippetList as unknown as PartialJSONValue ) . catch ( ( _ ) => { return false ; } ) ; return true ; } private sortSnippets ( ) { this . codeSnippetList . sort ( ( a , b ) => a . id - b . id ) ; } async orderSnippets ( ) { this . sortSnippets ( ) ; this . codeSnippetList . forEach ( ( snippet , i ) => ( snippet . id = i ) ) ; await this . settingManager . set ( 'snippets' , this . codeSnippetList as unknown as PartialJSONValue ) . catch ( ( _ ) => { return false ; } ) ; return true ; } }