<s> import sublime <EOL> import sublime_plugin <EOL> import subprocess <EOL> import os <EOL> import codecs <EOL> import platform <EOL> def update_settings ( ) : <EOL> t = sublime . load_settings ( "<STR_LIT>" ) <EOL> projects_path = t . get ( "<STR_LIT>" ) <EOL> if projects_path : <EOL> t . set ( "<STR_LIT>" , projects_path ) <EOL> sublime . save_settings ( "<STR_LIT>" ) <EOL> update_settings ( ) <EOL> class JsonFile : <EOL> def __init__ ( self , fpath , encoding = "<STR_LIT:utf-8>" ) : <EOL> self . encoding = encoding <EOL> self . fpath = fpath <EOL> def load ( self , default = [ ] ) : <EOL> self . fdir = os . path . dirname ( self . fpath ) <EOL> if not os . path . isdir ( self . fdir ) : <EOL> os . makedirs ( self . fdir ) <EOL> if os . path . exists ( self . fpath ) : <EOL> f = codecs . open ( self . fpath , "<STR_LIT>" , encoding = self . encoding ) <EOL> content = f . read ( ) <EOL> try : <EOL> data = sublime . decode_value ( content ) <EOL> except : <EOL> sublime . message_dialog ( "<STR_LIT>" % self . fpath ) <EOL> raise <EOL> if not data : <EOL> data = default <EOL> f . close ( ) <EOL> else : <EOL> f = codecs . open ( self . fpath , "<STR_LIT>" , encoding = self . encoding ) <EOL> data = default <EOL> f . close ( ) <EOL> return data <EOL> def save ( self , data , indent = <NUM_LIT:4> ) : <EOL> self . fdir = os . path . dirname ( self . fpath ) <EOL> if not os . path . isdir ( self . fdir ) : <EOL> os . makedirs ( self . fdir ) <EOL> f = codecs . open ( self . fpath , "<STR_LIT>" , encoding = self . encoding ) <EOL> f . write ( sublime . encode_value ( data , True ) ) <EOL> f . close ( ) <EOL> def remove ( self ) : <EOL> if os . path . exists ( self . fpath ) : <EOL> os . remove ( self . fpath ) <EOL> def subl ( args = [ ] ) : <EOL> executable_path = sublime . executable_path ( ) <EOL> if sublime . platform ( ) == '<STR_LIT>' : <EOL> app_path = executable_path [ : executable_path . rfind ( "<STR_LIT>" ) + <NUM_LIT:5> ] <EOL> executable_path = app_path + "<STR_LIT>" <EOL> subprocess . Popen ( [ executable_path ] + args ) <EOL> if sublime . platform ( ) == "<STR_LIT>" : <EOL> def fix_focus ( ) : <EOL> window = sublime . active_window ( ) <EOL> view = window . active_view ( ) <EOL> window . run_command ( '<STR_LIT>' ) <EOL> window . focus_view ( view ) <EOL> sublime . set_timeout ( fix_focus , <NUM_LIT> ) <EOL> def expand_folder ( folder , project_file ) : <EOL> root = os . path . dirname ( project_file ) <EOL> if not os . path . isabs ( folder ) : <EOL> folder = os . path . abspath ( os . path . join ( root , folder ) ) <EOL> return folder <EOL> def get_node ( ) : <EOL> if sublime . platform ( ) == "<STR_LIT>" : <EOL> node = subprocess . check_output ( [ "<STR_LIT>" , "<STR_LIT>" , "<STR_LIT>" ] ) . decode ( ) . strip ( ) <EOL> else : <EOL> node = platform . node ( ) . split ( "<STR_LIT:.>" ) [ <NUM_LIT:0> ] <EOL> return node <EOL> def dont_close_windows_when_empty ( func ) : <EOL> def f ( * args , ** kwargs ) : <EOL> preferences = sublime . load_settings ( "<STR_LIT>" ) <EOL> close_windows_when_empty = preferences . get ( "<STR_LIT>" ) <EOL> preferences . set ( "<STR_LIT>" , False ) <EOL> func ( * args , ** kwargs ) <EOL> if close_windows_when_empty : <EOL> preferences . set ( "<STR_LIT>" , close_windows_when_empty ) <EOL> return f <EOL> class Manager : <EOL> def __init__ ( self , window ) : <EOL> self . window = window <EOL> settings_file = '<STR_LIT>' <EOL> self . settings = sublime . load_settings ( settings_file ) <EOL> default_projects_dir = os . path . join ( sublime . packages_path ( ) , "<STR_LIT>" , "<STR_LIT>" ) <EOL> self . projects_path = self . settings . get ( <EOL> "<STR_LIT>" , [ self . settings . get ( "<STR_LIT>" , default_projects_dir ) ] ) <EOL> self . projects_path = [ <EOL> os . path . normpath ( os . path . expanduser ( d ) ) for d in self . projects_path ] <EOL> node = get_node ( ) <EOL> if self . settings . get ( "<STR_LIT>" , False ) : <EOL> self . projects_path = [ d + "<STR_LIT>" + node for d in self . projects_path ] + self . projects_path <EOL> self . primary_dir = self . projects_path [ <NUM_LIT:0> ] <EOL> self . projects_info = self . get_all_projects_info ( ) <EOL> def list_project_files ( self , folder ) : <EOL> pfiles = [ ] <EOL> library = os . path . join ( folder , "<STR_LIT>" ) <EOL> if os . path . exists ( library ) : <EOL> j = JsonFile ( library ) <EOL> for f in j . load ( [ ] ) : <EOL> if os . path . exists ( f ) and f not in pfiles : <EOL> pfiles . append ( os . path . normpath ( f ) ) <EOL> pfiles . sort ( ) <EOL> j . save ( pfiles ) <EOL> for path , dirs , files in os . walk ( folder , followlinks = True ) : <EOL> for f in files : <EOL> f = os . path . join ( path , f ) <EOL> if f . endswith ( "<STR_LIT>" ) and f not in pfiles : <EOL> pfiles . append ( os . path . normpath ( f ) ) <EOL> for d in dirs : <EOL> d = os . path . join ( path , d ) <EOL> if len ( os . listdir ( d ) ) == <NUM_LIT:0> : <EOL> os . rmdir ( d ) <EOL> return pfiles <EOL> def get_info_from_project_file ( self , pfile ) : <EOL> pdir = self . which_project_dir ( pfile ) <EOL> if pdir : <EOL> pname = os . path . relpath ( pfile , pdir ) . replace ( "<STR_LIT>" , "<STR_LIT>" ) <EOL> else : <EOL> pname = os . path . basename ( pfile ) . replace ( "<STR_LIT>" , "<STR_LIT>" ) <EOL> pd = JsonFile ( pfile ) . load ( ) <EOL> if pd and "<STR_LIT>" in pd and pd [ "<STR_LIT>" ] : <EOL> folder = pd [ "<STR_LIT>" ] [ <NUM_LIT:0> ] . get ( "<STR_LIT:path>" , "<STR_LIT>" ) <EOL> else : <EOL> folder = "<STR_LIT>" <EOL> star = False <EOL> for w in sublime . windows ( ) : <EOL> if w . project_file_name ( ) == pfile : <EOL> star = True <EOL> break <EOL> return { <EOL> pname : { <EOL> "<STR_LIT>" : expand_folder ( folder , pfile ) , <EOL> "<STR_LIT:file>" : pfile , <EOL> "<STR_LIT>" : star <EOL> } <EOL> } <EOL> def get_all_projects_info ( self ) : <EOL> ret = { } <EOL> for pdir in self . projects_path : <EOL> pfiles = self . list_project_files ( pdir ) <EOL> for f in pfiles : <EOL> ret . update ( self . get_info_from_project_file ( f ) ) <EOL> return ret <EOL> def which_project_dir ( self , pfile ) : <EOL> for pdir in self . projects_path : <EOL> if ( os . path . realpath ( os . path . dirname ( pfile ) ) + os . path . sep ) . startswith ( <EOL> os . path . realpath ( pdir ) + os . path . sep ) : <EOL> return pdir <EOL> return None <EOL> def display_projects ( self ) : <EOL> plist = [ [ key , key + "<STR_LIT:*>" if value [ "<STR_LIT>" ] else key , value [ "<STR_LIT>" ] , value [ "<STR_LIT:file>" ] ] <EOL> for key , value in self . projects_info . items ( ) ] <EOL> plist = sorted ( plist ) <EOL> if self . settings . get ( "<STR_LIT>" , False ) : <EOL> j = JsonFile ( os . path . join ( self . primary_dir , "<STR_LIT>" ) ) <EOL> recent = j . load ( [ ] ) <EOL> plist = sorted ( plist , key = lambda p : recent . index ( p [ <NUM_LIT:3> ] ) if p [ <NUM_LIT:3> ] in recent else - <NUM_LIT:1> , <EOL> reverse = True ) <EOL> count = <NUM_LIT:0> <EOL> for i in range ( len ( plist ) ) : <EOL> if plist [ i ] [ <NUM_LIT:0> ] is not plist [ i ] [ <NUM_LIT:1> ] : <EOL> plist . insert ( count , plist . pop ( i ) ) <EOL> count = count + <NUM_LIT:1> <EOL> return [ item [ <NUM_LIT:0> ] for item in plist ] , [ [ item [ <NUM_LIT:1> ] , item [ <NUM_LIT:2> ] ] for item in plist ] <EOL> def project_file_name ( self , project ) : <EOL> return self . projects_info [ project ] [ "<STR_LIT:file>" ] <EOL> def project_workspace ( self , project ) : <EOL> return self . project_file_name ( project ) . replace ( "<STR_LIT>" , "<STR_LIT>" ) <EOL> def update_recent ( self , project ) : <EOL> j = JsonFile ( os . path . join ( self . primary_dir , "<STR_LIT>" ) ) <EOL> recent = j . load ( [ ] ) <EOL> pname = self . project_file_name ( project ) <EOL> if pname not in recent : <EOL> recent . append ( pname ) <EOL> else : <EOL> recent . append ( recent . pop ( recent . index ( pname ) ) ) <EOL> if len ( recent ) > <NUM_LIT:50> : <EOL> recent = recent [ ( <NUM_LIT:50> - len ( recent ) ) : len ( recent ) ] <EOL> j . save ( recent ) <EOL> def clear_recent_projects ( self ) : <EOL> def clear_callback ( ) : <EOL> ok = sublime . ok_cancel_dialog ( "<STR_LIT>" ) <EOL> if ok : <EOL> j = JsonFile ( os . path . join ( self . primary_dir , "<STR_LIT>" ) ) <EOL> j . remove ( ) <EOL> sublime . set_timeout ( clear_callback , <NUM_LIT:100> ) <EOL> def get_project_data ( self , project ) : <EOL> return JsonFile ( self . project_file_name ( project ) ) . load ( ) <EOL> def check_project ( self , project ) : <EOL> wsfile = self . project_workspace ( project ) <EOL> j = JsonFile ( wsfile ) <EOL> if not os . path . exists ( wsfile ) : <EOL> j . save ( { } ) <EOL> else : <EOL> show_open_files = self . settings . get ( "<STR_LIT>" , False ) <EOL> data = j . load ( { } ) <EOL> data [ "<STR_LIT>" ] = show_open_files <EOL> df = data . get ( "<STR_LIT>" , { } ) <EOL> df [ "<STR_LIT>" ] = show_open_files <EOL> data [ "<STR_LIT>" ] = df <EOL> j . save ( data ) <EOL> @ dont_close_windows_when_empty <EOL> def close_project_by_window ( self , window ) : <EOL> window . run_command ( "<STR_LIT>" ) <EOL> def close_project_by_name ( self , project ) : <EOL> for w in sublime . windows ( ) : <EOL> if w . project_file_name ( ) == self . project_file_name ( project ) : <EOL> self . close_project_by_window ( w ) <EOL> if w . id ( ) != sublime . active_window ( ) . id ( ) : <EOL> w . run_command ( "<STR_LIT>" ) <EOL> return True <EOL> return False <EOL> def add_project ( self ) : <EOL> @ dont_close_windows_when_empty <EOL> def close_all_files ( ) : <EOL> self . window . run_command ( "<STR_LIT>" ) <EOL> def add_callback ( project ) : <EOL> pd = self . window . project_data ( ) <EOL> f = os . path . join ( self . primary_dir , "<STR_LIT>" % project ) <EOL> if pd : <EOL> JsonFile ( f ) . save ( pd ) <EOL> else : <EOL> JsonFile ( f ) . save ( { } ) <EOL> JsonFile ( f . replace ( "<STR_LIT>" , "<STR_LIT>" ) ) . save ( { } ) <EOL> self . close_project_by_window ( self . window ) <EOL> self . window . run_command ( "<STR_LIT>" ) <EOL> close_all_files ( ) <EOL> self . __init__ ( self . window ) <EOL> self . switch_project ( project ) <EOL> def show_input_panel ( ) : <EOL> project = "<STR_LIT>" <EOL> pd = self . window . project_data ( ) <EOL> pf = self . window . project_file_name ( ) <EOL> try : <EOL> path = pd [ "<STR_LIT>" ] [ <NUM_LIT:0> ] [ "<STR_LIT:path>" ] <EOL> if pf : <EOL> project = os . path . basename ( expand_folder ( path , pf ) ) <EOL> else : <EOL> project = os . path . basename ( path ) <EOL> except : <EOL> pass <EOL> v = self . window . show_input_panel ( "<STR_LIT>" , project , add_callback , None , None ) <EOL> v . run_command ( "<STR_LIT>" ) <EOL> sublime . set_timeout ( show_input_panel , <NUM_LIT:100> ) <EOL> def import_sublime_project ( self ) : <EOL> pfile = self . window . project_file_name ( ) <EOL> if not pfile : <EOL> sublime . message_dialog ( "<STR_LIT>" ) <EOL> return <EOL> if self . which_project_dir ( pfile ) : <EOL> sublime . message_dialog ( "<STR_LIT>" ) <EOL> return <EOL> ok = sublime . ok_cancel_dialog ( "<STR_LIT>" % os . path . basename ( pfile ) ) <EOL> if ok : <EOL> j = JsonFile ( os . path . join ( self . primary_dir , "<STR_LIT>" ) ) <EOL> data = j . load ( [ ] ) <EOL> if pfile not in data : <EOL> data . append ( pfile ) <EOL> j . save ( data ) <EOL> def append_project ( self , project ) : <EOL> self . update_recent ( project ) <EOL> pd = self . get_project_data ( project ) <EOL> paths = [ expand_folder ( f . get ( "<STR_LIT:path>" ) , self . project_file_name ( project ) ) <EOL> for f in pd . get ( "<STR_LIT>" ) ] <EOL> subl ( [ "<STR_LIT>" ] + paths ) <EOL> def switch_project ( self , project ) : <EOL> self . update_recent ( project ) <EOL> self . check_project ( project ) <EOL> self . close_project_by_window ( self . window ) <EOL> self . close_project_by_name ( project ) <EOL> subl ( [ self . project_file_name ( project ) ] ) <EOL> def open_in_new_window ( self , project ) : <EOL> self . update_recent ( project ) <EOL> self . check_project ( project ) <EOL> self . close_project_by_name ( project ) <EOL> subl ( [ "<STR_LIT>" , self . project_file_name ( project ) ] ) <EOL> def remove_project ( self , project ) : <EOL> def remove_callback ( ) : <EOL> ok = sublime . ok_cancel_dialog ( "<STR_LIT>" % project ) <EOL> if ok : <EOL> pfile = self . project_file_name ( project ) <EOL> if self . which_project_dir ( pfile ) : <EOL> self . close_project_by_name ( project ) <EOL> os . unlink ( self . project_file_name ( project ) ) <EOL> os . unlink ( self . project_workspace ( project ) ) <EOL> else : <EOL> for pdir in self . projects_path : <EOL> j = JsonFile ( os . path . join ( pdir , "<STR_LIT>" ) ) <EOL> data = j . load ( [ ] ) <EOL> if pfile in data : <EOL> data . remove ( pfile ) <EOL> j . save ( data ) <EOL> sublime . set_timeout ( remove_callback , <NUM_LIT:100> ) <EOL> def edit_project ( self , project ) : <EOL> def on_open ( ) : <EOL> self . window . open_file ( self . project_file_name ( project ) ) <EOL> sublime . set_timeout_async ( on_open , <NUM_LIT:100> ) <EOL> def rename_project ( self , project ) : <EOL> def rename_callback ( new_project ) : <EOL> if project == new_project : <EOL> return <EOL> pfile = self . project_file_name ( project ) <EOL> wsfile = self . project_workspace ( project ) <EOL> pdir = self . which_project_dir ( pfile ) <EOL> if not pdir : <EOL> pdir = os . path . dirname ( pfile ) <EOL> new_pfile = os . path . join ( pdir , "<STR_LIT>" % new_project ) <EOL> new_wsfile = new_pfile . replace ( "<STR_LIT>" , "<STR_LIT>" ) <EOL> reopen = self . close_project_by_name ( project ) <EOL> os . rename ( pfile , new_pfile ) <EOL> os . rename ( wsfile , new_wsfile ) <EOL> j = JsonFile ( new_wsfile ) <EOL> data = j . load ( { } ) <EOL> if "<STR_LIT>" in data : <EOL> data [ "<STR_LIT>" ] = "<STR_LIT>" % os . path . basename ( new_project ) <EOL> j . save ( data ) <EOL> if not self . which_project_dir ( pfile ) : <EOL> for pdir in self . projects_path : <EOL> library = os . path . join ( pdir , "<STR_LIT>" ) <EOL> if os . path . exists ( library ) : <EOL> j = JsonFile ( library ) <EOL> data = j . load ( [ ] ) <EOL> if pfile in data : <EOL> data . remove ( pfile ) <EOL> data . append ( new_pfile ) <EOL> j . save ( data ) <EOL> if reopen : <EOL> self . __init__ ( self . window ) <EOL> self . open_in_new_window ( new_project ) <EOL> def show_input_panel ( ) : <EOL> v = self . window . show_input_panel ( "<STR_LIT>" , <EOL> project , rename_callback , None , None ) <EOL> v . run_command ( "<STR_LIT>" ) <EOL> sublime . set_timeout ( show_input_panel , <NUM_LIT:100> ) <EOL> def cancellable ( func ) : <EOL> def _ret ( self , action ) : <EOL> if action >= <NUM_LIT:0> : <EOL> func ( self , action ) <EOL> elif action < <NUM_LIT:0> and self . caller == "<STR_LIT>" : <EOL> sublime . set_timeout ( self . run , <NUM_LIT:10> ) <EOL> return _ret <EOL> class ProjectManager ( sublime_plugin . WindowCommand ) : <EOL> def show_quick_panel ( self , items , on_done ) : <EOL> sublime . set_timeout ( <EOL> lambda : self . window . show_quick_panel ( items , on_done ) , <EOL> <NUM_LIT:10> ) <EOL> def run ( self , action = None , caller = None ) : <EOL> self . manager = Manager ( self . window ) <EOL> if action is None : <EOL> self . show_options ( ) <EOL> elif action == "<STR_LIT>" : <EOL> self . manager . add_project ( ) <EOL> elif action == "<STR_LIT>" : <EOL> self . manager . import_sublime_project ( ) <EOL> elif action == "<STR_LIT>" : <EOL> self . manager . clear_recent_projects ( ) <EOL> sublime . status_message ( "<STR_LIT>" ) <EOL> else : <EOL> self . caller = caller <EOL> callback = eval ( "<STR_LIT>" + action ) <EOL> self . projects , display = self . manager . display_projects ( ) <EOL> if not self . projects : <EOL> sublime . message_dialog ( "<STR_LIT>" ) <EOL> return <EOL> self . show_quick_panel ( display , callback ) <EOL> def show_options ( self ) : <EOL> items = [ <EOL> [ "<STR_LIT>" , "<STR_LIT>" ] , <EOL> [ "<STR_LIT>" , "<STR_LIT>" ] , <EOL> [ "<STR_LIT>" , "<STR_LIT>" ] , <EOL> [ "<STR_LIT>" , "<STR_LIT>" ] , <EOL> [ '<STR_LIT>' , "<STR_LIT>" ] , <EOL> [ "<STR_LIT>" , "<STR_LIT>" ] , <EOL> [ "<STR_LIT>" , "<STR_LIT>" ] , <EOL> [ "<STR_LIT>" , "<STR_LIT>" ] , <EOL> [ "<STR_LIT>" , "<STR_LIT>" ] <EOL> ] <EOL> def callback ( a ) : <EOL> if a < <NUM_LIT:0> : <EOL> return <EOL> elif a <= <NUM_LIT:5> : <EOL> actions = [ "<STR_LIT>" , "<STR_LIT>" , "<STR_LIT>" , "<STR_LIT>" , "<STR_LIT>" , "<STR_LIT>" ] <EOL> self . run ( action = actions [ a ] , caller = "<STR_LIT>" ) <EOL> elif a == <NUM_LIT:6> : <EOL> self . run ( action = "<STR_LIT>" ) <EOL> elif a == <NUM_LIT:7> : <EOL> self . run ( action = "<STR_LIT>" ) <EOL> elif a == <NUM_LIT:8> : <EOL> self . run ( action = "<STR_LIT>" ) <EOL> self . show_quick_panel ( items , callback ) <EOL> @ cancellable <EOL> def on_new ( self , action ) : <EOL> self . manager . open_in_new_window ( self . projects [ action ] ) <EOL> @ cancellable <EOL> def on_switch ( self , action ) : <EOL> self . manager . switch_project ( self . projects [ action ] ) <EOL> @ cancellable <EOL> def on_append ( self , action ) : <EOL> self . manager . append_project ( self . projects [ action ] ) <EOL> @ cancellable <EOL> def on_remove ( self , action ) : <EOL> self . manager . remove_project ( self . projects [ action ] ) <EOL> @ cancellable <EOL> def on_edit ( self , action ) : <EOL> self . manager . edit_project ( self . projects [ action ] ) <EOL> @ cancellable <EOL> def on_rename ( self , action ) : <EOL> self . manager . rename_project ( self . projects [ action ] ) </s>
