<s> import sublime , threading <EOL> from . import events , utils <EOL> class ProjectIndex ( ) : <EOL> def __init__ ( self , folder_key , default_data_dict ) : <EOL> self . lock = threading . Lock ( ) <EOL> self . projects = { } <EOL> self . listeners = [ ] <EOL> self . folder_key = folder_key <EOL> self . default_data_dict = default_data_dict <EOL> events . subscribe ( '<STR_LIT>' , lambda view : self . sync_projects ( ) ) <EOL> events . subscribe ( '<STR_LIT>' , lambda view : self . sync_projects ( ) ) <EOL> events . subscribe ( '<STR_LIT>' , self . on_post_save_async ) <EOL> events . subscribe ( '<STR_LIT>' , self . on_post_window_command ) <EOL> def subscribe ( self , listener ) : <EOL> self . listeners . append ( listener ) <EOL> def notify_listeners ( self , project_name ) : <EOL> for listener in self . listeners : <EOL> listener ( project_name ) <EOL> def sync_projects ( self ) : <EOL> project_list = utils . get_project_list ( ) <EOL> with self . lock : <EOL> current_project_names = set ( self . projects . keys ( ) ) <EOL> updated_project_names = { project_name for project_name , project_data in project_list } <EOL> new_project_names = list ( updated_project_names . difference ( current_project_names ) ) <EOL> stale_project_names = list ( current_project_names . difference ( updated_project_names ) ) <EOL> for project_name in stale_project_names : <EOL> del self . projects [ project_name ] <EOL> for project_name , project_data in project_list : <EOL> if project_name in new_project_names : <EOL> self . projects [ project_name ] = { "<STR_LIT>" : project_data , "<STR_LIT:data>" : dict ( self . default_data_dict ) } <EOL> for project_name , project_data in project_list : <EOL> if project_name in new_project_names : <EOL> self . new_project ( project_name , project_data ) <EOL> def on_post_save_async ( self , view ) : <EOL> file_name = view . file_name ( ) . replace ( "<STR_LIT:\\>" , "<STR_LIT:/>" ) <EOL> if file_name . lower ( ) . endswith ( "<STR_LIT>" ) : <EOL> project_name = utils . extract_project_name ( file_name ) <EOL> project_data = sublime . decode_value ( view . substr ( sublime . Region ( <NUM_LIT:0> , view . size ( ) ) ) ) <EOL> self . project_updated ( project_name , project_data ) <EOL> else : <EOL> project_name = utils . get_project_name ( view ) <EOL> if project_name : <EOL> self . project_file_updated ( project_name , file_name ) <EOL> def on_post_window_command ( self , window , command , args ) : <EOL> if command == "<STR_LIT>" : <EOL> window_project_name = utils . get_project_name_from_window ( window ) <EOL> if window_project_name : <EOL> for file_name in args [ "<STR_LIT>" ] : <EOL> if not file_name . lower ( ) . endswith ( "<STR_LIT>" ) : <EOL> self . remove_project_file ( window_project_name , file_name . replace ( "<STR_LIT:\\>" , "<STR_LIT:/>" ) ) <EOL> for file_name in args [ "<STR_LIT>" ] : <EOL> if file_name . lower ( ) . endswith ( "<STR_LIT>" ) : <EOL> project_name = utils . extract_project_name ( file_name ) <EOL> if project_name in self . projects : <EOL> with self . lock : <EOL> if project_name in self . projects : <EOL> del self . projects [ project_name ] <EOL> self . project_deleted ( project_name ) <EOL> def project_updated ( self , project_name , updated_project_data ) : <EOL> if project_name not in self . projects : <EOL> self . sync_projects ( ) <EOL> return <EOL> new_paths = [ utils . normalize_path ( folder [ "<STR_LIT:path>" ] ) for folder in updated_project_data . get ( self . folder_key , [ ] ) ] <EOL> current_paths = [ utils . normalize_path ( folder [ "<STR_LIT:path>" ] ) for folder in self . projects [ project_name ] [ "<STR_LIT>" ] . get ( self . folder_key , [ ] ) ] <EOL> if set ( new_paths ) != set ( current_paths ) : <EOL> with self . lock : <EOL> if project_name in self . projects : <EOL> del self . projects [ project_name ] <EOL> self . sync_projects ( ) <EOL> else : <EOL> self . update_project ( project_name , updated_project_data ) <EOL> def project_file_updated ( self , project_name , file_path ) : <EOL> if project_name not in self . projects : <EOL> return <EOL> project_data = self . projects [ project_name ] [ "<STR_LIT>" ] <EOL> tracked_folders = project_data . get ( self . folder_key , [ ] ) <EOL> for tracked_folder in tracked_folders : <EOL> root_path = utils . normalize_path ( tracked_folder [ "<STR_LIT:path>" ] ) <EOL> if file_path . startswith ( root_path ) : <EOL> break <EOL> else : <EOL> return <EOL> self . update_project_file ( project_name , file_path ) <EOL> def new_project ( self , project_name , project_data ) : <EOL> pass <EOL> def update_project ( self , project_name , updated_project_data ) : <EOL> pass <EOL> def update_project_file ( self , project_name , file_path ) : <EOL> pass <EOL> def remove_project_file ( self , project_name , file_path ) : <EOL> pass <EOL> def project_deleted ( self , project_name ) : <EOL> pass </s>
