<s> """<STR_LIT>""" <EOL> from datetime import datetime , timedelta <EOL> import time <EOL> import sublime <EOL> import sublime_plugin <EOL> from collections import namedtuple <EOL> import threading <EOL> from . lib . file_strip . json import sanitize_json <EOL> from . lib . multiconf import get as multiget <EOL> import json <EOL> from os . path import exists , join <EOL> import textwrap <EOL> LOAD_RETRIES = <NUM_LIT:5> <EOL> SETTINGS = { } <EOL> if '<STR_LIT>' not in globals ( ) : <EOL> ts_thread = None <EOL> def log ( s ) : <EOL> """<STR_LIT>""" <EOL> print ( "<STR_LIT>" % s ) <EOL> def debug_log ( s ) : <EOL> """<STR_LIT>""" <EOL> if SETTINGS . get ( "<STR_LIT>" , False ) : <EOL> log ( s ) <EOL> def create_settings ( settings_path ) : <EOL> """<STR_LIT>""" <EOL> err = False <EOL> default_theme = { <EOL> "<STR_LIT>" : False , <EOL> "<STR_LIT>" : [ ] , <EOL> } <EOL> j = json . dumps ( default_theme , sort_keys = True , indent = <NUM_LIT:4> , separators = ( '<STR_LIT:U+002C>' , '<STR_LIT>' ) ) <EOL> try : <EOL> with open ( settings_path , '<STR_LIT:w>' ) as f : <EOL> f . write ( j + "<STR_LIT:\n>" ) <EOL> except Exception : <EOL> err = True <EOL> return err <EOL> def total_seconds ( t ) : <EOL> """<STR_LIT>""" <EOL> return ( t . microseconds + ( t . seconds + t . days * <NUM_LIT> * <NUM_LIT> ) * <NUM_LIT:10> ** <NUM_LIT:6> ) / <NUM_LIT:10> ** <NUM_LIT:6> <EOL> def get_current_time ( ) : <EOL> """<STR_LIT>""" <EOL> now = datetime . now ( ) <EOL> seconds = total_seconds ( timedelta ( hours = now . hour , minutes = now . minute , seconds = now . second ) ) <EOL> return seconds , now <EOL> def datetime2sec ( t ) : <EOL> """<STR_LIT>""" <EOL> tm = time . strptime ( t , '<STR_LIT>' ) <EOL> return total_seconds ( timedelta ( hours = tm . tm_hour , minutes = tm . tm_min , seconds = tm . tm_sec ) ) <EOL> def sec2time ( total ) : <EOL> """<STR_LIT>""" <EOL> seconds = total % <NUM_LIT> <EOL> t_minutes = ( total / <NUM_LIT> ) <EOL> minutes = t_minutes % <NUM_LIT> <EOL> hours = t_minutes / <NUM_LIT> <EOL> return "<STR_LIT>" % ( hours , minutes , seconds ) <EOL> def display_message ( msg ) : <EOL> """<STR_LIT>""" <EOL> settings = sublime . load_settings ( "<STR_LIT>" ) <EOL> use_sub_notify = multiget ( settings , "<STR_LIT>" , False ) <EOL> if use_sub_notify : <EOL> sublime . run_command ( "<STR_LIT>" , { "<STR_LIT:title>" : "<STR_LIT>" , "<STR_LIT>" : msg } ) <EOL> else : <EOL> if ThemeScheduler . dialog_open : <EOL> log ( "<STR_LIT>" ) <EOL> log ( msg ) <EOL> return <EOL> ThemeScheduler . dialog_open = True <EOL> sublime . ok_cancel_dialog ( msg ) <EOL> ThemeScheduler . update = True <EOL> ThemeScheduler . dialog_open = False <EOL> class ThemeSchedulerGetNextChangeCommand ( sublime_plugin . ApplicationCommand ) : <EOL> """<STR_LIT>""" <EOL> def run ( self ) : <EOL> """<STR_LIT>""" <EOL> sublime . message_dialog ( "<STR_LIT>" + str ( ThemeScheduler . next_change ) ) <EOL> class ThemeSchedulerRefreshCommand ( sublime_plugin . ApplicationCommand ) : <EOL> """<STR_LIT>""" <EOL> def run ( self ) : <EOL> """<STR_LIT>""" <EOL> manage_thread ( ) <EOL> class ThemeRecord ( namedtuple ( '<STR_LIT>' , [ "<STR_LIT:time>" , "<STR_LIT>" , "<STR_LIT>" , "<STR_LIT>" , "<STR_LIT>" , "<STR_LIT>" ] ) ) : <EOL> """<STR_LIT>""" <EOL> def __str__ ( self ) : <EOL> """<STR_LIT>""" <EOL> return textwrap . dedent ( <EOL> '''<STR_LIT>''' <EOL> ) . strip ( ) % ( <EOL> sec2time ( self . time ) , self . theme , self . msg , <EOL> self . filters , self . ui_theme , self . command <EOL> ) <EOL> __repr__ = __str__ <EOL> class CommandWrapper ( object ) : <EOL> """<STR_LIT>""" <EOL> def __init__ ( self , cmd ) : <EOL> """<STR_LIT>""" <EOL> self . cmd = cmd [ "<STR_LIT>" ] <EOL> self . args = cmd . get ( "<STR_LIT:args>" , { } ) <EOL> def __str__ ( self ) : <EOL> """<STR_LIT>""" <EOL> return self . cmd <EOL> __repr__ = __str__ <EOL> def run ( self ) : <EOL> """<STR_LIT>""" <EOL> sublime . run_command ( self . cmd , self . args ) <EOL> class ThemeScheduler ( object ) : <EOL> """<STR_LIT>""" <EOL> themes = [ ] <EOL> current_theme = "<STR_LIT>" <EOL> current_msg = None <EOL> current_filters = None <EOL> next_change = None <EOL> day = None <EOL> ready = False <EOL> busy = False <EOL> update = False <EOL> current_time = None <EOL> set_safe = False <EOL> dialog_open = False <EOL> current_ui_theme = None <EOL> current_command = None <EOL> @ classmethod <EOL> def reset_msg_state ( cls ) : <EOL> """<STR_LIT>""" <EOL> cls . dialog_open = False <EOL> @ classmethod <EOL> def init ( cls , set_safe = False ) : <EOL> """<STR_LIT>""" <EOL> cls . busy = True <EOL> cls . ready = False <EOL> cls . set_safe = set_safe <EOL> cls . themes = [ ] <EOL> for t in multiget ( SETTINGS , "<STR_LIT>" , [ ] ) : <EOL> theme_time = datetime2sec ( t [ "<STR_LIT:time>" ] ) <EOL> theme = t . get ( "<STR_LIT>" , None ) <EOL> msg = t . get ( "<STR_LIT>" , None ) <EOL> filters = t . get ( "<STR_LIT>" , None ) <EOL> ui_theme = t . get ( "<STR_LIT>" , None ) <EOL> command = t . get ( "<STR_LIT>" , None ) <EOL> if command is not None : <EOL> command = CommandWrapper ( command ) <EOL> cls . themes . append ( ThemeRecord ( theme_time , theme , msg , filters , ui_theme , command ) ) <EOL> seconds , now = get_current_time ( ) <EOL> cls . update_theme ( seconds , now ) <EOL> cls . ready = True <EOL> cls . busy = False <EOL> @ classmethod <EOL> def update_next ( cls , seconds , now ) : <EOL> """<STR_LIT>""" <EOL> cls . next_change = None <EOL> cls . day = None <EOL> closest = None <EOL> lowest = None <EOL> for t in cls . themes : <EOL> if seconds < t . time and ( closest is None or t . time < closest . time ) : <EOL> closest = t <EOL> if lowest is None or t . time < lowest . time : <EOL> lowest = t <EOL> if closest is not None : <EOL> cls . next_change = closest <EOL> elif lowest is not None : <EOL> cls . next_change = lowest <EOL> if lowest is not None : <EOL> cls . lowest = lowest <EOL> if ( cls . next_change . time == cls . lowest . time and seconds < cls . lowest . time ) : <EOL> cls . day = - <NUM_LIT:1> <EOL> else : <EOL> cls . day = now . day <EOL> debug_log ( "<STR_LIT>" % cls . day ) <EOL> debug_log ( "<STR_LIT>" % ( time . ctime ( ) , str ( cls . next_change ) ) ) <EOL> @ classmethod <EOL> def update_current ( cls ) : <EOL> """<STR_LIT>""" <EOL> if cls . next_change is not None : <EOL> closest = None <EOL> greatest = None <EOL> seconds = get_current_time ( ) [ <NUM_LIT:0> ] <EOL> for t in cls . themes : <EOL> if t . time <= seconds and ( closest is None or t . time > closest . time ) : <EOL> closest = t <EOL> elif greatest is None or t . time > greatest . time : <EOL> greatest = t <EOL> if closest is None : <EOL> closest = cls . next_change if greatest is None else greatest <EOL> if closest is not None : <EOL> cls . apply_changes ( <EOL> closest . theme , <EOL> closest . msg , <EOL> closest . filters , <EOL> closest . ui_theme , <EOL> closest . command <EOL> ) <EOL> @ classmethod <EOL> def update_theme ( cls , seconds , now , update = True ) : <EOL> """<STR_LIT>""" <EOL> cls . update_next ( seconds , now ) <EOL> if update : <EOL> cls . update_current ( ) <EOL> @ classmethod <EOL> def on_post_dialog ( cls , seconds , now ) : <EOL> """<STR_LIT>""" <EOL> cls . busy = True <EOL> update = True <EOL> last_next = cls . next_change <EOL> cls . update_next ( seconds , now ) <EOL> if last_next is None : <EOL> if cls . next_change is None : <EOL> debug_log ( "<STR_LIT>" ) <EOL> update = False <EOL> elif cls . next_change is not None and cls . next_change . time == last_next . time : <EOL> debug_log ( "<STR_LIT>" ) <EOL> update = False <EOL> if update : <EOL> debug_log ( "<STR_LIT>" ) <EOL> cls . update_current ( ) <EOL> cls . busy = False <EOL> @ classmethod <EOL> def on_change ( cls , seconds , now ) : <EOL> """<STR_LIT>""" <EOL> cls . busy = True <EOL> if ( <EOL> cls . next_change is not None and <EOL> ( <EOL> cls . next_change . theme != cls . current_theme or <EOL> cls . next_change . msg != cls . current_msg or <EOL> cls . next_change . filters != cls . current_filters or <EOL> cls . next_change . ui_theme != cls . current_ui_theme or <EOL> cls . next_change . command is not None <EOL> ) <EOL> ) : <EOL> debug_log ( "<STR_LIT>" ) <EOL> update = True <EOL> else : <EOL> debug_log ( "<STR_LIT>" ) <EOL> update = False <EOL> cls . update_theme ( seconds , now , update ) <EOL> cls . busy = False <EOL> @ classmethod <EOL> def set_theme ( cls , theme , ui_theme ) : <EOL> """<STR_LIT>""" <EOL> if cls . set_safe : <EOL> pref_file = join ( sublime . packages_path ( ) , '<STR_LIT>' , '<STR_LIT>' ) <EOL> pref = { } <EOL> if exists ( pref_file ) : <EOL> try : <EOL> with open ( pref_file , "<STR_LIT:r>" ) as f : <EOL> content = sanitize_json ( f . read ( ) , True ) <EOL> pref = json . loads ( content ) <EOL> except Exception : <EOL> log ( "<STR_LIT>" ) <EOL> return <EOL> if ui_theme is not None : <EOL> debug_log ( "<STR_LIT>" ) <EOL> pref [ '<STR_LIT>' ] = ui_theme <EOL> if theme is not None : <EOL> debug_log ( "<STR_LIT>" ) <EOL> pref [ '<STR_LIT>' ] = theme <EOL> j = json . dumps ( pref , sort_keys = True , indent = <NUM_LIT:4> , separators = ( '<STR_LIT:U+002C>' , '<STR_LIT>' ) ) <EOL> try : <EOL> with open ( pref_file , '<STR_LIT:w>' ) as f : <EOL> f . write ( j + "<STR_LIT:\n>" ) <EOL> except Exception : <EOL> log ( "<STR_LIT>" ) <EOL> else : <EOL> if ui_theme is not None : <EOL> debug_log ( "<STR_LIT>" ) <EOL> sublime . load_settings ( "<STR_LIT>" ) . set ( "<STR_LIT>" , ui_theme ) <EOL> if theme is not None : <EOL> debug_log ( "<STR_LIT>" ) <EOL> sublime . load_settings ( "<STR_LIT>" ) . set ( "<STR_LIT>" , theme ) <EOL> @ classmethod <EOL> def apply_changes ( cls , theme , msg , filters , ui_theme , command ) : <EOL> """<STR_LIT>""" <EOL> debug_log ( <EOL> "<STR_LIT>" % ( <EOL> theme , msg , filters , ui_theme , command <EOL> ) <EOL> ) <EOL> if cls . next_change is not None : <EOL> cls . current_time = cls . next_change . time <EOL> cls . current_theme = theme <EOL> cls . current_ui_theme = ui_theme <EOL> cls . current_msg = msg <EOL> cls . current_filters = filters <EOL> if filters is not None : <EOL> if is_tweakable ( ) : <EOL> debug_log ( "<STR_LIT>" ) <EOL> sublime . run_command ( <EOL> "<STR_LIT>" , <EOL> { "<STR_LIT>" : theme , "<STR_LIT>" : filters } <EOL> ) <EOL> if ui_theme is not None : <EOL> cls . set_theme ( None , ui_theme ) <EOL> else : <EOL> debug_log ( "<STR_LIT>" ) <EOL> cls . set_theme ( theme , ui_theme ) <EOL> else : <EOL> cls . set_theme ( theme , ui_theme ) <EOL> try : <EOL> if command is not None : <EOL> command . run ( ) <EOL> except Exception as e : <EOL> log ( "<STR_LIT>" % str ( command ) ) <EOL> log ( "<STR_LIT>" % str ( e ) ) <EOL> if msg is not None and isinstance ( msg , str ) : <EOL> sublime . set_timeout ( lambda m = msg : display_message ( m ) , <NUM_LIT> ) <EOL> class TsThread ( threading . Thread ) : <EOL> """<STR_LIT>""" <EOL> INIT = <NUM_LIT:0> <EOL> POST_DIALOG = <NUM_LIT:1> <EOL> CHANGE = <NUM_LIT:2> <EOL> def __init__ ( self ) : <EOL> """<STR_LIT>""" <EOL> self . reset ( ) <EOL> threading . Thread . __init__ ( self ) <EOL> def reset ( self ) : <EOL> """<STR_LIT>""" <EOL> self . abort = False <EOL> def kill ( self ) : <EOL> """<STR_LIT>""" <EOL> self . abort = True <EOL> while self . is_alive ( ) : <EOL> pass <EOL> self . reset ( ) <EOL> def payload ( self , code , s = None , n = None ) : <EOL> """<STR_LIT>""" <EOL> if code == self . INIT : <EOL> ThemeScheduler . init ( ) <EOL> elif code == self . POST_DIALOG : <EOL> ThemeScheduler . on_post_dialog ( s , n ) <EOL> elif code == self . CHANGE : <EOL> ThemeScheduler . on_change ( s , n ) <EOL> def run ( self ) : <EOL> """<STR_LIT>""" <EOL> def is_update_time ( seconds , now ) : <EOL> """<STR_LIT>""" <EOL> update = False <EOL> if ( <EOL> not ThemeScheduler . busy and <EOL> ThemeScheduler . next_change is not None and <EOL> not ThemeScheduler . update and <EOL> ThemeScheduler . day is not None <EOL> ) : <EOL> if ThemeScheduler . day == now . day : <EOL> update = ( <EOL> seconds >= ThemeScheduler . next_change . time and <EOL> ThemeScheduler . next_change . time != ThemeScheduler . lowest . time <EOL> ) <EOL> else : <EOL> update = ( <EOL> seconds >= ThemeScheduler . next_change . time or <EOL> seconds >= ThemeScheduler . lowest . time <EOL> ) <EOL> return update <EOL> sublime . set_timeout ( lambda : self . payload ( self . INIT ) , <NUM_LIT:0> ) <EOL> while not self . abort : <EOL> seconds , now = get_current_time ( ) <EOL> if ThemeScheduler . update : <EOL> ThemeScheduler . update = False <EOL> ThemeScheduler . busy = False <EOL> debug_log ( "<STR_LIT>" ) <EOL> debug_log ( "<STR_LIT>" % str ( ThemeScheduler . busy ) ) <EOL> debug_log ( <EOL> "<STR_LIT>" % ( <EOL> ThemeScheduler . day if ThemeScheduler . day is not None else "<STR_LIT:None>" , <EOL> now . day , <EOL> sec2time ( ThemeScheduler . next_change . time ) if ThemeScheduler . next_change is not None else "<STR_LIT:None>" , <EOL> sec2time ( seconds ) <EOL> ) <EOL> ) <EOL> sublime . set_timeout ( lambda s = seconds , n = now : self . payload ( self . POST_DIALOG , s , n ) , <NUM_LIT:0> ) <EOL> elif ThemeScheduler . ready and is_update_time ( seconds , now ) : <EOL> debug_log ( "<STR_LIT>" ) <EOL> debug_log ( "<STR_LIT>" % str ( ThemeScheduler . busy ) ) <EOL> debug_log ( <EOL> "<STR_LIT>" % ( <EOL> ThemeScheduler . day if ThemeScheduler . day is not None else "<STR_LIT:None>" , <EOL> now . day , <EOL> sec2time ( ThemeScheduler . next_change . time ) if ThemeScheduler . next_change is not None else "<STR_LIT:None>" , <EOL> sec2time ( seconds ) <EOL> ) <EOL> ) <EOL> sublime . set_timeout ( lambda s = seconds , n = now : self . payload ( self . CHANGE , s , n ) , <NUM_LIT:0> ) <EOL> time . sleep ( <NUM_LIT:1> ) <EOL> def manage_thread ( ) : <EOL> """<STR_LIT>""" <EOL> global ts_thread <EOL> if not multiget ( SETTINGS , '<STR_LIT>' , '<STR_LIT:False>' ) : <EOL> if ts_thread is not None : <EOL> ts_thread . kill ( ) <EOL> log ( "<STR_LIT>" ) <EOL> else : <EOL> if ts_thread is not None : <EOL> ts_thread . kill ( ) <EOL> ts_thread = TsThread ( ) <EOL> ts_thread . start ( ) <EOL> log ( "<STR_LIT>" ) <EOL> def is_tweakable ( ) : <EOL> """<STR_LIT>""" <EOL> tweakable = False <EOL> for app_command in sublime_plugin . application_command_classes : <EOL> if app_command . __name__ == "<STR_LIT>" : <EOL> tweakable = app_command . is_ready ( ) <EOL> break <EOL> return tweakable <EOL> def external_plugins_loaded ( plugins ) : <EOL> """<STR_LIT>""" <EOL> for p in plugins : <EOL> command = None <EOL> ready = False <EOL> for app_command in sublime_plugin . application_command_classes : <EOL> if app_command . __name__ == p : <EOL> command = app_command <EOL> break <EOL> if command is not None : <EOL> ready = command . is_ready ( ) <EOL> else : <EOL> ready = True <EOL> return ready <EOL> def load_plugin ( retries ) : <EOL> """<STR_LIT>""" <EOL> global SETTINGS <EOL> ThemeScheduler . reset_msg_state ( ) <EOL> external_plugins = [ "<STR_LIT>" , "<STR_LIT>" ] <EOL> if external_plugins_loaded ( external_plugins ) or retries == <NUM_LIT:0> : <EOL> log ( "<STR_LIT>" ) <EOL> settings_file = "<STR_LIT>" <EOL> settings_path = join ( sublime . packages_path ( ) , '<STR_LIT>' , settings_file ) <EOL> if not exists ( settings_path ) : <EOL> create_settings ( settings_path ) <EOL> SETTINGS = sublime . load_settings ( settings_file ) <EOL> SETTINGS . clear_on_change ( '<STR_LIT>' ) <EOL> SETTINGS . add_on_change ( '<STR_LIT>' , manage_thread ) <EOL> manage_thread ( ) <EOL> else : <EOL> retries_left = retries - <NUM_LIT:1> <EOL> log ( "<STR_LIT>" ) <EOL> sublime . set_timeout ( lambda : load_plugin ( retries_left ) , <NUM_LIT> ) <EOL> def plugin_loaded ( ) : <EOL> """<STR_LIT>""" <EOL> load_plugin ( LOAD_RETRIES ) <EOL> def plugin_unloaded ( ) : <EOL> """<STR_LIT>""" <EOL> ts_thread . kill ( ) </s>
