def saveAs(self): ''' Save cur session to new file ''' if not _checkAPI(): return sscur = app.app_path(app.APP_FILE_SESSION) sscur_save = app.app_proc(app.PROC_SAVE_SESSION, sscur) if sscur_save == False: return pass app.msg_status(sscur) (ssdir, ssfname) = os.path.split(sscur) ssfname = ssfname.replace('.json', '') ssnew = app.dlg_file(is_open=False, filters=DLG_CUD_FILTER, init_filename=ssfname, init_dir=ssdir) pass app.msg_status(str(ssnew)) if ssnew is None: return ssnew = apx.icase(False, '', ssnew.endswith(CDSESS_EXT), ssnew, os.path.isfile(ssnew), ssnew, True, ssnew + CDSESS_EXT) if os.path.normpath(sscur) == os.path.normpath(ssnew): return # app.app_proc(app.PROC_SAVE_SESSION, sscur) app.app_proc(app.PROC_SAVE_SESSION, ssnew) app.app_proc(app.PROC_SET_SESSION, ssnew) app.msg_status(SAVED.format(stem=juststem(ssnew))) self.top_sess(ssnew)
def __init__(self): self.h_tree = app.app_proc(app.PROC_GET_CODETREE, '') dir = app.app_path(app.APP_DIR_PY) dirs = os.listdir(dir) dirs = [ os.path.join(dir, s) for s in dirs if s.startswith('cuda_tree_') ] for dir in dirs: fn_inf = os.path.join(dir, 'install.inf') s_module = app.ini_read(fn_inf, 'info', 'subdir', '') for index in range(1, MAX_SECTIONS + 1): section = 'treehelper' + str(index) s_method = app.ini_read(fn_inf, section, 'method', '') if not s_method: continue s_lexers = app.ini_read(fn_inf, section, 'lexers', '') if not s_lexers: continue for s_lex in s_lexers.split(','): self.helpers[s_lex] = { 'module': s_module, 'method': s_method, } #print('module', s_module, 'lexers', s_lexers, 'method', s_method) items = sorted(list(self.helpers.keys())) if items: print('TreeHelpers: ' + ', '.join(items))
def saveAs(self): ''' Save cur session to new file ''' if not _checkAPI(): return sscur = app.app_path(app.APP_FILE_SESSION) pass; app.msg_status(sscur) (ssdir ,ssfname) = os.path.split(sscur) ssfname = ssfname.replace('.json', '') ssnew = app.dlg_file(is_open=False, filters=DLG_CUD_FILTER , init_filename=ssfname , init_dir= ssdir ) pass; app.msg_status(str(ssnew)) if ssnew is None: return ssnew = apx.icase(False,'' , ssnew.endswith(CDSESS_EXT) , ssnew , os.path.isfile(ssnew) , ssnew , True , ssnew+CDSESS_EXT ) if os.path.normpath(sscur)==os.path.normpath(ssnew): return app.app_proc(app.PROC_SAVE_SESSION, sscur) app.app_proc(app.PROC_SAVE_SESSION, ssnew) app.app_proc(app.PROC_SET_SESSION, ssnew) app.msg_status(SAVED.format(stem=juststem(ssnew))) self.top_sess(ssnew)
def collect_keys(): keys_json = os.path.join(app.app_path(app.APP_DIR_SETTINGS), 'keys.json') keys = apx._json_loads(open(keys_json).read()) if os.path.isfile(keys_json) else {} cmdinfos = [] pass; #LOG and log('app.app_api_version()={}',(app.app_api_version())) # if True: # app.app_api_version()>='1.0.212': lcmds = app.app_proc(app.PROC_GET_COMMANDS, '') cmdinfos = [('Plugins' ,cmd['name'] ,cmd['key1'] ,cmd['key2'] ,f('{},{},{}', cmd['p_module'], cmd['p_method'], cmd['p_method_params']).rstrip(',') ) if cmd['type']=='plugin' else ('Commands' ,cmd['name'] ,cmd['key1'] ,cmd['key2'] ,cmd['cmd'] ) for cmd in lcmds if cmd['type'] in ('plugin', 'cmd') # if cmd['type']!='lexer' ] return cmdinfos
def add_cud_plugins(cmdinfos, prfx, ctg): # {"commands":{ # "grp":{ # "0":{"caption":"***", "hotkey":"***"}, # "1":{"caption":"***", "hotkey":"***"}, # }, # }} # plugs_json = os.path.join(app.app_path(app.APP_DIR_SETTINGS), 'plugins.json') keys_json = os.path.join(app.app_path(app.APP_DIR_SETTINGS), 'keys.json') # plugs = json_loads(open(plugs_json).read(), object_pairs_hook=collections.OrderedDict) keys = json_loads(open(keys_json).read()) for n in itertools.count(): if not app.app_proc(app.PROC_GET_COMMAND_PLUGIN, str(n)): break#for n (cap ,modul ,meth ,par ,lxrs) = app.app_proc(app.PROC_GET_COMMAND_PLUGIN, str(n)) plug_id = modul+','+meth+(','+par if par else '') dct_keys= keys.get(plug_id, {}) cmdinfos += [(ctg , prfx+cap , ' * '.join(dct_keys.get('s1', [])) , ' * '.join(dct_keys.get('s2', [])) )] #for n return cmdinfos
def get_hotkeys_desc(cmd_id, ext_id=None, keys_js=None, def_ans=''): """ Read one or two hotkeys for command cmd_id [+ext_id] from settings\keys.json Return def_ans If no hotkeys for the command 'Ctrl+Q' 'Ctrl+Q * Ctrl+W' If one hotkey for the command 'Ctrl+Q/Ctrl+T' 'Ctrl+Q * Ctrl+W/Ctrl+T' If two hotkeys for the command """ if keys_js is None: keys_json = app.app_path(app.APP_DIR_SETTINGS) + os.sep + 'keys.json' keys_js = apx._json_loads( open(keys_json).read()) if os.path.exists(keys_json) else {} cmd_id = f('{},{}', cmd_id, ext_id) if ext_id else cmd_id if cmd_id not in keys_js: return def_ans cmd_keys = keys_js[cmd_id] desc = '/'.join([ ' * '.join(cmd_keys.get('s1', [])), ' * '.join(cmd_keys.get('s2', [])) ]).strip('/') return desc
def open(self, ssnew=None): ''' Open new session from file ssnew or after user asking ''' if not _checkAPI(): return # in_dir = app.app_path(app.APP_DIR_DATA) sscur = app.app_path(app.APP_FILE_SESSION) sscur_save = app.app_proc(app.PROC_SAVE_SESSION, sscur) pass #LOG and log('sscur_save={}',(sscur_save)) if sscur_save == False: return if ssnew is None: ssnew = app.dlg_file( is_open=True, filters=DLG_ALL_FILTER, init_filename='!' # '!' to disable check "filename exists" , init_dir='') if ssnew is None: return if ssnew.endswith(SWSESS_EXT) and os.path.isfile(ssnew): # Import from Syn sssyn = ssnew sscud = ssnew[:-len(SWSESS_EXT)] + CDSESS_EXT if os.path.isfile(sscud): sscud = app.dlg_file(is_open=False, filters=DLG_CUD_FILTER, init_filename=os.path.basename(sscud), init_dir=os.path.dirname(sscud)) if not sscud: return if not import_syn_sess(sssyn, sscud): return ssnew = sscud pass #LOG and log('ssnew={}',(ssnew)) ssnew = apx.icase(False, '', ssnew.endswith(CDSESS_EXT), ssnew, os.path.isfile(ssnew), ssnew, True, ssnew + CDSESS_EXT) pass #LOG and log('ssnew={}',(ssnew)) if os.path.isfile(ssnew): # Open # app.app_proc(app.PROC_SAVE_SESSION, sscur) ssnew_load = app.app_proc(app.PROC_LOAD_SESSION, ssnew) pass #LOG and log('ssnew_load={}',(ssnew_load)) if ssnew_load == False: return app.app_proc(app.PROC_SET_SESSION, ssnew) app.msg_status(OPENED.format(stem=juststem(ssnew))) self.top_sess(ssnew) else: # New if app.ID_NO == app.msg_box( CREATE_ASK.format(stem=juststem(ssnew)), app.MB_YESNO): return # app.app_proc(app.PROC_SAVE_SESSION, sscur) app.ed.cmd(cmds.cmd_FileCloseAll) app.app_proc(app.PROC_SET_SESSION, ssnew) app.app_proc(app.PROC_SAVE_SESSION, ssnew) app.msg_status(CREATED.format(stem=juststem(ssnew))) self.top_sess(ssnew)
def _get_cmt_pair(self, lex): ''' Return ((begin_sign, end_sign), only_lines) begin_sign as '/*' end_sign as '*/' only_lines True if each of *_sign must be whole line ''' if lex not in self.pair4lex: # Search lex-pair def_lexs_json = os.path.join(get_def_setting_dir(), 'default_lexers.json') usr_lexs_json = os.path.join(app.app_path(app.APP_DIR_SETTINGS), 'user_lexers.json') def_lexs = _json_loads(open(def_lexs_json).read()) usr_lexs = _json_loads(open( usr_lexs_json).read()) if os.path.exists(usr_lexs_json) else { "Comments": {}, "CommentsForLines": {} } only_ln = False if False: pass elif lex in usr_lexs["Comments"]: pair = usr_lexs["Comments"].get(lex) elif lex in usr_lexs["CommentsForLines"]: pair = usr_lexs["CommentsForLines"].get(lex) only_ln = True elif lex in def_lexs["Comments"]: pair = def_lexs["Comments"].get(lex) elif lex in def_lexs["CommentsForLines"]: pair = def_lexs["CommentsForLines"].get(lex) only_ln = True else: pair = ['', ''] self.pair4lex[lex] = (pair, only_ln) return self.pair4lex[lex]
def save(self): ''' Save cur session to file ''' if not _checkAPI(): return sscur = app.app_path(app.APP_FILE_SESSION) app.app_proc(app.PROC_SAVE_SESSION, sscur) app.msg_status(SAVED.format(stem=juststem(sscur))) self.top_sess(sscur)
def collect_keys(): keys_json = os.path.join(app.app_path(app.APP_DIR_SETTINGS), 'keys.json') keys = apx._json_loads(open(keys_json).read()) if os.path.isfile(keys_json) else {} cmdinfos = [] pass; #LOG and log('app.app_api_version()={}',(app.app_api_version())) # if True: # app.app_api_version()>='1.0.212': lcmds = app.app_proc(app.PROC_GET_COMMANDS, '') cmdinfos = [('Commands' ,cmd['name'] ,cmd['key1'] ,cmd['key2'] ,cmd['cmd'] ) if cmd['type']=='cmd' else ('Plugins' ,cmd['name'] ,cmd['key1'] ,cmd['key2'] ,f('{},{},{}', cmd['p_module'], cmd['p_method'], cmd['p_method_params']).rstrip(',') ) for cmd in lcmds if cmd['type']!='lexer' ] return cmdinfos
def parse_cmnt(cmnt, frm):#, kinfs): tags= set() mt = reTags.search(cmnt) while mt: tags_s = mt.group(0) tags |= set(tags_s.strip(' ()').replace('#', '').split(',')) cmnt = cmnt.replace(tags_s, '') mt = reTags.search(cmnt) dctN= [[int(m.group(1)), m.group(2).rstrip(', ')] for m in reN2S.finditer(cmnt+l)] dctS= [[ m.group(1) , m.group(2).rstrip(', ')] for m in reS2S.finditer(cmnt+l)] lstF= None mt = reFldFr.search(cmnt) if mt: from_short = mt.group(1) from_dir = from_short if os.path.isabs(from_short) else os.path.join(app.app_path(app.APP_DIR_DATA), from_short) pass; #LOG and log('from_dir={}',(from_dir)) if not os.path.isdir(from_dir): log(_('No folder "{}" from\n{}'), from_short, cmnt) else: lstF = [d for d in os.listdir(from_dir) if os.path.isdir(from_dir+os.sep+d) and d.upper()!='README' and d.strip()] lstF = sorted(lstF) pass; #LOG and log('lstF={}',(lstF)) frm,\ lst = ('strs' , lstF) if lstF else \ (frm , [] ) frm,\ dct = ('int2s', dctN) if dctN else \ ('str2s', dctS) if dctS else \ (frm , [] ) return cmnt, frm, dct, lst, list(tags)
def press_ok(self, *args, **kwargs): # edit data dict files = self.data.get('files', {}) new = {} for k, v in self.state.items(): for n, i in enumerate(v.split(';')[1].split(',')): if i == '1': lexer = self.lexers[n] lx = new.get(lexer, []) for x in files[k]: if x not in lx: lx.append(x) new[lexer] = lx if not new: ct.msg_box( _('You must check at least one CudaText lexer, for snippets to work' ), ct.MB_OK + ct.MB_ICONWARNING) return self.data['files'] = new # install path = os.path.join(ct.app_path(ct.APP_DIR_DATA), 'snippets_vs') vs.install_vs_snips(path, self.data) ct.dlg_proc(self.h, ct.DLG_HIDE)
def _get_cmt_pair(self, lex): ''' Return ((begin_sign, end_sign), only_lines) begin_sign as '/*' end_sign as '*/' only_lines True if each of *_sign must be whole line ''' if lex not in self.pair4lex: # Search lex-pair def_lexs_json = os.path.join(get_def_setting_dir() , 'default_lexers.json') usr_lexs_json = os.path.join(app.app_path(app.APP_DIR_SETTINGS), 'user_lexers.json') def_lexs = _json_loads(open(def_lexs_json).read()) usr_lexs = _json_loads(open(usr_lexs_json).read()) if os.path.exists(usr_lexs_json) else {"Comments":{}, "CommentsForLines":{}} only_ln = False if False:pass elif lex in usr_lexs["Comments"]: pair = usr_lexs["Comments"].get(lex) elif lex in usr_lexs["CommentsForLines"]: pair = usr_lexs["CommentsForLines"].get(lex) only_ln = True elif lex in def_lexs["Comments"]: pair = def_lexs["Comments"].get(lex) elif lex in def_lexs["CommentsForLines"]: pair = def_lexs["CommentsForLines"].get(lex) only_ln = True else: pair = ['',''] self.pair4lex[lex] = (pair, only_ln) return self.pair4lex[lex]
def _get_opts(self, keys=()): ''' Get this module options as dict-tree. Load from CudaText\settings\{module-name}.json if this file exists ''' if not self.opts: ops_json = os.path.join(app.app_path(app.APP_DIR_SETTINGS), '{}.json'.format(__name__)) self.opts = _json_loads(open(ops_json).read()) if os.path.exists(ops_json) else self.def_opts return opt(self.opts, keys)
def __init__( self, path_keys_info='' # default.json or parsed data (file or list_of_dicts) , subset='' # To get/set from/to cuda_options_editor.json , how={} # Details to work ): M, m = self.__class__, self m.ed = ed m.how = how m.defn_path = Path(path_keys_info) if str == type( path_keys_info) else json.dumps(path_keys_info) m.subset = subset #m.stores = get_hist('dlg' #, json.loads(open(CFG_JSON).read(), object_pairs_hook=odict) #if os.path.exists(CFG_JSON) else odict()) pass #LOG and log('ok',()) # m.bk_sets = m.stores.get(m.subset+'bk_sets' , False) m.lexr_l = app.lexer_proc(app.LEXER_GET_LEXERS, False) m.lexr_w_l = [ f( '{} {}', '!!' if os.path.isfile( app.app_path(app.APP_DIR_SETTINGS) + os.sep + 'lexer ' + lxr + '.json') else ' ', lxr) for lxr in m.lexr_l ] m.lexr = m.ed.get_prop(app.PROP_LEXER_CARET) m.all_ops = False # Show also options without definition '!!! ALL options' m.opts_defn = { } # Meta-info for options: format, comment, dict of values, chapter, tags m.opts_full = {} # Show all options m.chp_tree = {} # {'Ui':{ops:[], 'kids':{...}, 'path':'Ui/Tabs'} m.pth2chp = {} # path-index for m.chp_tree # Cache m.SKWULFs = [] # Last filtered+sorted m.cols = [] # Last info about listview columns m.itms = [] # Last info about listview cells # m.bk_files = {} # m.do_file('backup-user') if m.bk_sets else 0 m.do_file('load-data') m.for_ulf = 'u' # 'u' for User, 'l' for Lexer, 'f' for File #m.apply_one = m.stores.get(m.subset+'apply_one', False) # Do one call OpsReloadAndApply on exit #m.apply_need= False # Need to call OpsReloadAndApply #m.auto4file = m.stores.get(m.subset+'auto4file', True) # Auto reset file value to over value def/user/lex m.auto4file = True # Auto reset file value to over value def/user/lex
def __init__(self): dir = app.app_path(app.APP_DIR_PY) dirs = os.listdir(dir) dirs = [name for name in dirs if name.startswith('cuda_lint_') and os.path.isdir(os.path.join(dir, name))] for lint in dirs: try: __import__(lint + '.linter', globals(), locals(), [lint + '.linter']) except ImportError: pass
def close(self): sscur = app.app_path(app.APP_FILE_SESSION) sscur_save = app.app_proc(app.PROC_SAVE_SESSION, sscur) if sscur_save == False: return # app.app_proc(app.PROC_SAVE_SESSION, sscur) app.app_proc( app.PROC_SET_SESSION, 'history session.json') # w/o path to use "settings" portable way pass
def _get_cmt_pair(self, lex): ''' ''' if lex not in self.pair4lex: # Search lex-pair def_lexs_json = os.path.join(get_def_setting_dir() , 'default_lexers.json') usr_lexs_json = os.path.join(app.app_path(app.APP_DIR_SETTINGS), 'user_lexers.json') def_lexs = _json_loads(open(def_lexs_json).read()) usr_lexs = _json_loads(open(usr_lexs_json).read()) if os.path.exists(usr_lexs_json) else {"Comments":{}} self.pair4lex[lex] = usr_lexs["Comments"].get(lex, def_lexs["Comments"].get(lex, ['',''])) return self.pair4lex[lex]
def set_autoit_path(self): """set path to AutoIt directory""" d = Au3Parser.autoitpath if os.path.isdir( Au3Parser.autoitpath) else ct.app_path(ct.APP_DIR_EXE) path = ct.dlg_dir(d) if self.check_autoit_path(path): Au3Parser.autoitpath = path self.settings['autoit_dir'] = path with open(self.filesettings, mode='w', encoding='utf-8') as fs: json.dump(self.settings, fs, indent=4) msg('AutoIt path set: {}'.format(path))
def get_hist(key_or_path, default=None, module_name='_auto_detect', to_file=PLING_HISTORY_JSON): """ Read from "plugin history.json" one value by string key or path (list of keys). Parameters key_or_path Key(s) to navigate in json tree Type: str or [str] default Value to return if no suitable node in json tree module_name Start node to navigate. If it is '_auto_detect' then name of caller module is used. If it is None then it is skipped. to_file Name of file to read. APP_DIR_SETTING will be joined if no full path. Return Found value or default Examples (caller module is 'plg') 1. If no "plugin history.json" get_hist('k') returns None get_hist(['p', 'k'], 0) returns 0 2. If "plugin history.json" contains {"k":1, "plg":{"k":2, "p":{"m":3}, "t":[0,1]}, "q":{"n":4}} get_hist('k', 0, None) returns 1 get_hist('k', 0) returns 0 get_hist('k', 0, 'plg') returns 2 get_hist('k', 0, 'oth') returns 0 get_hist(['p','m'], 0) returns 3 get_hist(['p','t'], []) returns [0,1] get_hist('q', 0, None) returns {'n':4} get_hist(['q','n'], 0, None) returns 4 """ to_file = to_file if os.sep in to_file else app.app_path(app.APP_DIR_SETTINGS)+os.sep+to_file if not os.path.exists(to_file): pass; #log('not exists',()) return default data = None try: data = json.loads(open(to_file).read()) except: pass; log('not load: {}',sys.exc_info()) return default if module_name=='_auto_detect': caller_globals = inspect.stack()[1].frame.f_globals module_name = inspect.getmodulename(caller_globals['__file__']) \ if '__file__' in caller_globals else None pass; #log('module_name={}',(module_name)) keys = [key_or_path] if type(key_or_path)==str else key_or_path keys = keys if module_name is None else [module_name]+keys parents,\ key = keys[:-1], keys[-1] for parent in parents: data= data.get(parent) if type(data)!=dict: pass; #log('not dict parent={}',(parent)) return default return data.get(key, default)
def save(self): ''' Save cur session to file ''' if not _checkAPI(): return sscur = app.app_path(app.APP_FILE_SESSION) sscur_save = app.app_proc(app.PROC_SAVE_SESSION, sscur) if sscur_save == False: return # app.app_proc(app.PROC_SAVE_SESSION, sscur) app.msg_status(SAVED.format(stem=juststem(sscur))) self.top_sess(sscur)
def __init__(self): dir = app.app_path(app.APP_DIR_PY) dirs = os.listdir(dir) dirs = [ name for name in dirs if name.startswith('cuda_lint_') and os.path.isdir(os.path.join(dir, name)) ] for lint in dirs: try: __import__(lint + '.linter', globals(), locals(), [lint + '.linter']) except ImportError: pass
def _do_acts(self, what='', acts='|save|second|reg|keys|menu|'): ''' Use macro list ''' pass #LOG and log('what, acts={}',(what, acts)) # Save if '|save|' in acts: open(MACROS_JSON, 'w').write( json.dumps( { 'ver': JSON_FORMAT_VER, 'list': self.macros, 'dlg_prs': self.dlg_prs, 'tm_ctrl': { 'rp_ctrl': self.tm_ctrl.get('rp_ctrl', 1000), 'tm_wait': self.tm_ctrl.get('tm_wait', 10) } }, indent=4)) # Secondary data if '|second|' in acts: self.mcr4id = {str(mcr['id']): mcr for mcr in self.macros} # Register new subcommands if '|reg|' in acts: reg_subs = 'cuda_macros;run;{}'.format('\n'.join( 'macro: {}\t{}'.format(mcr['nm'], mcr['id']) for mcr in self.macros)) pass #LOG and log('reg_subs={}',reg_subs) app.app_proc(app.PROC_SET_SUBCOMMANDS, reg_subs) # Clear keys.json if '|keys|' in acts and ':' in what: # Need delete a key 'cuda_macros,run,NNNNN' mcr_id = what[1 + what.index(':'):] mcr_key = 'cuda_macros,run,{}'.format(mcr_id) keys_json = app.app_path( app.APP_DIR_SETTINGS) + os.sep + 'keys.json' if not os.path.exists(keys_json): return keys = apx._json_loads(open(keys_json).read()) pass #LOG and log('??? key={}',mcr_key) if keys.pop(mcr_key, None) is not None: pass #LOG and log('UPD keys.json deleted key={}',mcr_key) open(keys_json, 'w').write(json.dumps(keys, indent=2)) # [Re]Build menu if '|menu|' in acts: self._adapt_menu()
def do_format(text): fn = app.ed.get_filename() config_file = os.path.join(os.path.dirname(fn), CONFIG) config_cuda = os.path.join(app.app_path(app.APP_DIR_SETTINGS), CONFIG) config_os = os.path.expanduser('~' + os.sep + CONFIG) if os.path.exists(config_file): config = config_file elif os.path.exists(config_cuda): config = config_cuda else: config = config_os return run_app(text, config)
def do_code(self, aid, ag, data=''): m,M = self,self.__class__ lwks_n = ag.cval('lwks') if lwks_n==-1: return [] #continue#while m.cmd_id = m.fl_Is[lwks_n] pass; #LOG and log('m.fl_Is={}',(m.fl_Is)) pass; #LOG and log('lwks_n,m.cmd_id={}',(lwks_n,m.cmd_id)) if False:pass elif aid=='cpnm': cmd_nkk = m.id2nkks[m.cmd_id] app.app_proc(app.PROC_SET_CLIP, cmd_nkk[0]) elif aid=='open': pass; LOG and log('m.cmd_id={}',(m.cmd_id)) if type(m.cmd_id)!=str: return [] #continue#while plug_mdl, \ plug_mth = m.cmd_id.split(',')[0:2] plug_mth = 'def '+ plug_mth + '(self):' plug_dir = app.app_path(app.APP_DIR_PY)+os.sep+plug_mdl plug_py = plug_dir+os.sep+'__init__.py' plug_body = open(plug_py, encoding='UTF-8').read() pass; LOG and log('plug_mdl,plug_mth,plug_dir,plug_py={}',(plug_mdl,plug_mth,plug_dir,plug_py)) mch = re.search(r'from\s+\.(\w+)\s+import\s+Command', plug_body) if mch: # from .other_py import Command plug_py = plug_dir+os.sep+mch.group(1)+'.py' pass; LOG and log('plug_py={}',(plug_py)) plug_body=open(plug_py, encoding='UTF-8').read() if plug_mth not in plug_body: return [] #continue#while # Open app.file_open(plug_py) # Locate user_opt= app.app_proc(app.PROC_GET_FINDER_PROP, '') \ if app.app_api_version()>='1.0.248' else \ app.app_proc(app.PROC_GET_FIND_OPTIONS, '') # Deprecated ed.cmd(cmds.cmd_FinderAction, chr(1).join([] +['findnext'] +[plug_mth] +[''] +['fa'] )) if app.app_api_version()>='1.0.248': app.app_proc(app.PROC_SET_FINDER_PROP, user_opt) else: app.app_proc(app.PROC_SET_FIND_OPTIONS, user_opt) # Deprecated return None #break#while return []
def do_code(self, aid, ag): m,M = self,CfgKeysDlg lwks_n = ag.cval('lwks') if lwks_n==-1: return [] #continue#while m.cmd_id = m.fl_Is[lwks_n] pass; #LOG and log('m.fl_Is={}',(m.fl_Is)) pass; #LOG and log('lwks_n,m.cmd_id={}',(lwks_n,m.cmd_id)) if False:pass elif aid=='cpnm': cmd_nkk = m.id2nkks[m.cmd_id] app.app_proc(app.PROC_SET_CLIP, cmd_nkk[0]) elif aid=='open': pass; LOG and log('m.cmd_id={}',(m.cmd_id)) if type(m.cmd_id)!=str: return [] #continue#while plug_mdl, \ plug_mth = m.cmd_id.split(',')[0:2] plug_mth = 'def '+ plug_mth + '(self):' plug_dir = app.app_path(app.APP_DIR_PY)+os.sep+plug_mdl plug_py = plug_dir+os.sep+'__init__.py' plug_body = open(plug_py, encoding='UTF-8').read() pass; LOG and log('plug_mdl,plug_mth,plug_dir,plug_py={}',(plug_mdl,plug_mth,plug_dir,plug_py)) mch = re.search(r'from\s+\.(\w+)\s+import\s+Command', plug_body) if mch: # from .other_py import Command plug_py = plug_dir+os.sep+mch.group(1)+'.py' pass; LOG and log('plug_py={}',(plug_py)) plug_body=open(plug_py, encoding='UTF-8').read() if plug_mth not in plug_body: return [] #continue#while # Open app.file_open(plug_py) # Locate user_opt= app.app_proc(app.PROC_GET_FINDER_PROP, '') \ if app.app_api_version()>='1.0.248' else \ app.app_proc(app.PROC_GET_FIND_OPTIONS, '') # Deprecated ed.cmd(cmds.cmd_FinderAction, chr(1).join([] +['findnext'] +[plug_mth] +[''] +['fa'] )) if app.app_api_version()>='1.0.248': app.app_proc(app.PROC_SET_FINDER_PROP, user_opt) else: app.app_proc(app.PROC_SET_FIND_OPTIONS, user_opt) # Deprecated return None #break#while return []
def open(self, ssnew=None): ''' Open new session from file ssnew or after user asking ''' if not _checkAPI(): return # in_dir = app.app_path(app.APP_DIR_DATA) sscur = app.app_path(app.APP_FILE_SESSION) if ssnew is None: ssnew = app.dlg_file(is_open=True, filters=DLG_ALL_FILTER , init_filename='!' # '!' to disable check "filename exists" , init_dir= '' ) if ssnew is None: return if ssnew.endswith(SWSESS_EXT) and os.path.isfile(ssnew): # Import from Syn sssyn = ssnew sscud = ssnew[:-len(SWSESS_EXT)]+CDSESS_EXT if os.path.isfile(sscud): sscud = app.dlg_file(is_open=False, filters=DLG_CUD_FILTER , init_filename=os.path.basename(sscud) , init_dir= os.path.dirname( sscud) ) if not sscud: return if not import_syn_sess(sssyn, sscud): return ssnew = sscud ssnew = apx.icase(False,'' , ssnew.endswith(CDSESS_EXT) , ssnew , os.path.isfile(ssnew) , ssnew , True , ssnew+CDSESS_EXT ) if os.path.isfile(ssnew): # Open app.app_proc(app.PROC_SAVE_SESSION, sscur) app.app_proc(app.PROC_LOAD_SESSION, ssnew) app.app_proc(app.PROC_SET_SESSION, ssnew) app.msg_status(OPENED.format(stem=juststem(ssnew))) self.top_sess(ssnew) else: # New if app.ID_NO==app.msg_box(CREATE_ASK.format(stem=juststem(ssnew)), app.MB_YESNO): return app.app_proc(app.PROC_SAVE_SESSION, sscur) app.ed.cmd(cmds.cmd_FileCloseAll) app.app_proc(app.PROC_SET_SESSION, ssnew) app.app_proc(app.PROC_SAVE_SESSION, ssnew) app.msg_status(CREATED.format(stem=juststem(ssnew))) self.top_sess(ssnew)
def load_prj(self): nodes = prj_man.global_project_info.get('nodes') if not nodes: return fn = ct.ed.get_filename() if fn == self.fn and [x for x in nodes if x in self.nodes]: return else: self.nodes = nodes self.fn = fn prj_fn = prj_man.global_project_info['filename'] if os.path.isfile(fn): for n in nodes: if n in fn: if os.path.exists(prj_fn): fn = prj_fn break fpath = os.path.dirname(fn) else: if os.path.exists(prj_fn): fpath = os.path.dirname(prj_fn) else: fpath = None prj_sys_path = [] if os.path.isfile(self.fn): prj_sys_path.append(os.path.dirname(self.fn)) prj_sys_path.extend(sys.path) for n in nodes: if os.path.isdir(n): prj_sys_path.append(n) elif os.path.isfile(n): prj_sys_path.append(os.path.dirname(n)) # only for me stubs_dir = os.path.join(ct.app_path(ct.APP_DIR_PY), 'cuda_stubs_builder', 'stubs') if os.path.exists(stubs_dir): prj_sys_path.append(stubs_dir) self.app.project = jedi.Project( path=fpath, added_sys_path=prj_sys_path)
def _do_acts(self, what='', acts='|save|second|reg|keys|menu|'): ''' Use macro list ''' pass; #LOG and log('what, acts={}',(what, acts)) # Save if '|save|' in acts: open(MACROS_JSON, 'w').write(json.dumps({ 'ver':JSON_FORMAT_VER ,'list':self.macros ,'dlg_prs':self.dlg_prs ,'tm_ctrl':{'rp_ctrl':self.tm_ctrl.get('rp_ctrl', 1000) ,'tm_wait':self.tm_ctrl.get('tm_wait', 10)} }, indent=4)) # Secondary data if '|second|' in acts: self.mcr4id = {str(mcr['id']):mcr for mcr in self.macros} # Register new subcommands if '|reg|' in acts: reg_subs = 'cuda_macros;run;{}'.format('\n'.join( 'macro: {}\t{}'.format(mcr['nm'],mcr['id']) for mcr in self.macros) ) pass; #LOG and log('reg_subs={}',reg_subs) app.app_proc(app.PROC_SET_SUBCOMMANDS, reg_subs) # Clear keys.json if '|keys|' in acts and ':' in what: # Need delete a key 'cuda_macros,run,NNNNN' mcr_id = what[1+what.index(':'):] mcr_key = 'cuda_macros,run,{}'.format(mcr_id) keys_json = app.app_path(app.APP_DIR_SETTINGS)+os.sep+'keys.json' if not os.path.exists(keys_json): return keys = apx._json_loads(open(keys_json).read()) pass; #LOG and log('??? key={}',mcr_key) if keys.pop(mcr_key, None) is not None: pass; #LOG and log('UPD keys.json deleted key={}',mcr_key) open(keys_json, 'w').write(json.dumps(keys, indent=2)) # [Re]Build menu if '|menu|' in acts: self._adapt_menu()
def get_translation(plug_file): ''' Part of i18n. Full i18n-cycle: 1. All GUI-string in code are used in form _('') 2. These string are extracted from code to lang/messages.pot with run python.exe <python-root>\Tools\i18n\pygettext.py -p lang <plugin>.py 3. Poedit (or same program) create <module>\lang\ru_RU\LC_MESSAGES\<module>.po from (cmd "Update from POT") lang/messages.pot It allows to translate all "strings" It creates (cmd "Save") <module>\lang\ru_RU\LC_MESSAGES\<module>.mo 4. <module>.mo can be placed also in dir CudaText\data\langpy\ru_RU\LC_MESSAGES\<module>.mo The dir is used first. 5. get_translation uses the file to realize _('') ''' lng = app.app_proc(app.PROC_GET_LANG, '') plug_dir = os.path.dirname(plug_file) plug_mod = os.path.basename(plug_dir) lng_dirs = [ app.app_path(app.APP_DIR_DATA) + os.sep + 'langpy', plug_dir + os.sep + 'lang', ] _ = lambda x: x pass #return _ for lng_dir in lng_dirs: lng_mo = lng_dir + '/{}/LC_MESSAGES/{}.mo'.format(lng, plug_mod) if os.path.isfile(lng_mo): t = gettext.translation(plug_mod, lng_dir, languages=[lng]) _ = t.gettext t.install() break return _
def get_hotkeys_desc(cmd_id, ext_id=None, keys_js=None, def_ans=''): """ Read one or two hotkeys for command cmd_id [+ext_id] from settings\keys.json Return def_ans If no hotkeys for the command 'Ctrl+Q' 'Ctrl+Q * Ctrl+W' If one hotkey for the command 'Ctrl+Q/Ctrl+T' 'Ctrl+Q * Ctrl+W/Ctrl+T' If two hotkeys for the command """ if keys_js is None: keys_json = app.app_path(app.APP_DIR_SETTINGS)+os.sep+'keys.json' keys_js = apx._json_loads(open(keys_json).read()) if os.path.exists(keys_json) else {} cmd_id = f('{},{}', cmd_id, ext_id) if ext_id else cmd_id if cmd_id not in keys_js: return def_ans cmd_keys= keys_js[cmd_id] desc = '/'.join([' * '.join(cmd_keys.get('s1', [])) ,' * '.join(cmd_keys.get('s2', [])) ]).strip('/') return desc
def load_vals(opt_dfns:list, lexr_json='', ed_=None, full=False, user_json='user.json')->odict: """ Create reformated copy (as odict) of definitions data opt_dfns (see load_definitions) If ed_ then add 'fval' for some options If full==True then append optitions without definition but only with { opt:'opt name' , frm:'int'|'float'|'str' , uval:<value from user.json> , lval:<value from lexer*.json> }} Return {'opt name':{ opt:'opt name', frm: ? , def:, cmt:, dct:, chp:, tgs: ? , uval:<value from user.json> ? , lval:<value from lexer*.json> ? , fval:<value from ed> }} """ user_json = app.app_path(app.APP_DIR_SETTINGS)+os.sep+user_json lexr_def_json = apx.get_def_setting_dir() +os.sep+lexr_json lexr_json = app.app_path(app.APP_DIR_SETTINGS)+os.sep+lexr_json user_vals = apx._json_loads(open(user_json , encoding='utf8').read(), object_pairs_hook=odict) \ if os.path.isfile(user_json) else {} lexr_def_vals = apx._json_loads(open(lexr_def_json, encoding='utf8').read(), object_pairs_hook=odict) \ if os.path.isfile(lexr_def_json) else {} lexr_vals = apx._json_loads(open(lexr_json , encoding='utf8').read(), object_pairs_hook=odict) \ if os.path.isfile(lexr_json) else {} pass; #LOG and log('lexr_vals={}',(lexr_vals)) pass; #LOG and log('lexr_def_vals={}',(lexr_def_vals)) # Fill vals for defined opt pass; #LOG and log('no opt={}',([oi for oi in opt_dfns if 'opt' not in oi])) oinf_valed = odict([(oi['opt'], oi) for oi in opt_dfns]) for opt, oinf in oinf_valed.items(): if opt in lexr_def_vals: # Correct def-vals for lexer oinf['dlx'] = True oinf['def'] = lexr_def_vals[opt] oinf['jdf'] = oinf['def'] if opt in user_vals: # Found user-val for defined opt oinf['uval'] = user_vals[opt] if opt in lexr_vals: # Found lexer-val for defined opt oinf['lval'] = lexr_vals[opt] if ed_ and opt in apx.OPT2PROP: # Found file-val for defined opt fval = ed_.get_prop(apx.OPT2PROP[opt]) oinf['fval'] =fval if full: # Append item for non-defined opt reFontNm = re.compile(r'font\w*_name') def val2frm(val, opt=''): pass; #LOG and log('opt,val={}',(opt,val)) return ('bool' if isinstance(val, bool) else 'int' if isinstance(val, int) else 'float' if isinstance(val, float) else 'json' if isinstance(val, (list, dict)) else 'hotk' if '_hotkey_' in val else 'font' if isinstance(val, str) and reFontNm.search(val) else 'str') for uop,uval in user_vals.items(): if uop in oinf_valed: continue oinf_valed[uop] = odict( [ ('opt' ,uop) , ('frm' ,val2frm(uval,uop)) , ('uval' ,uval) ]+([('lval' ,lexr_vals[uop])] if uop in lexr_vals else []) ) for lop,lval in lexr_vals.items(): if lop in oinf_valed: continue oinf_valed[lop] = odict( [ ('opt' ,lop) , ('frm' ,val2frm(lval,lop)) , ('lval' ,lval) ]) upd_cald_vals(oinf_valed) upd_cald_vals(oinf_valed, '+def') if lexr_def_vals else None # To update oi['jdf'] by oi['def'] return oinf_valed
KIND_WARN = 21 KIND_INFO = 22 color_error = 0 color_warn = 0 color_info = 0 color_error_use = True color_warn_use = True color_info_use = True use_on_open = False use_on_save = False use_on_change = False fn_ini = os.path.join(app.app_path(app.APP_DIR_SETTINGS), 'cuda_lint.ini') #------------------------ def html_to_int(s): s = s.strip() if not s: return app.COLOR_NONE while s[0] == '#': s = s[1:] # get bytes in reverse order to deal with PIL quirk if len(s)==3: s = s[0]*2 + s[1]*2 + s[2]*2 if len(s)!=6: raise Exception('Incorrect color token: '+s) s = s[-2:] + s[2:4] + s[:2] # finally, make it numeric color = int(s, 16) return color
# Written by NotSqrt # Copyright (c) 2013 NotSqrt # Changes for CudaLint by Alexey T. # License: MIT import sys import os import shutil import cudatext as app sys.path.append(os.path.dirname(__file__)) from cuda_lint import PythonLinter, util config_path = os.path.join(app.app_path(app.APP_DIR_SETTINGS), 'pylint.rc') config_def = os.path.join(os.path.dirname(__file__), 'pylint.sample.rc') if not os.path.isfile(config_path) and os.path.isfile(config_def): shutil.copyfile(config_def, config_path) class Pylint(PythonLinter): """Provides an interface to pylint.""" syntax = 'Python' module = 'cuda_lint_pylint' cmd = None version_args = '--version' version_re = r'^pylint.* (?P<version>\d+\.\d+\.\d+),' version_requirement = '>= 1.0' regex = (
OrdDict = collections.OrderedDict FROM_API_VERSION= '1.0.146' # I18N _ = get_translation(__file__) pass; # Logging pass; #from pprint import pformat pass; #pfrm15=lambda d:pformat(d,width=15) pass; LOG = (-2==-2) # Do or dont logging. pass; ##!! waits correction #GAP = 5 fav_json= app.app_path(app.APP_DIR_SETTINGS)+os.sep+'cuda_favorites.json' def get_fav_data(): return json.loads(open(fav_json).read(), object_pairs_hook=OrdDict) \ if os.path.exists(fav_json) else \ OrdDict() def save_fav_data(fvdata): open(fav_json, 'w').write(json.dumps(fvdata, indent=4)) def import_SynFav(fn_ini, files): # Import from Syn chnd = False syn_lns = open(fn_ini, encoding='utf-16').read().splitlines() for syn_ln in syn_lns: if not os.path.isfile(syn_ln) \ or any([os.path.samefile(syn_ln, f) for f in files]): continue files += [syn_ln]
def set_opt(path, value, lev=CONFIG_LEV_USER, ed_cfg=ed): ''' Overridden options tool. Config pairs key:val are add/update/delete into <root>/settings/user.json <root>/settings/lexer <LEXER-NAME>.json ed_cfg props Params path Simple value (e.g. "tab_size") or "/"-separated path inside JSON tree value Value for setting or deleting None Delete pair (last key in path) is not None Add or update pair value lev Level for set opt CONFIG_LEV_USER, CONFIG_LEV_LEX, CONFIG_LEV_FILE ed_cfg Ref to editor to point a lexer Return The value (second param) or None if fail ''' if lev == CONFIG_LEV_FILE: if value is None: # Del! Cannot del from file-lev -- can set as default def_opts = get_app_default_opts() value = def_opts.get(path) else: value = str(value) if False: pass elif path == 'tab_size': ed_cfg.set_prop(app.PROP_TAB_SIZE, value) elif path == 'tab_spaces': ed_cfg.set_prop(app.PROP_TAB_SPACES, value) elif path == 'unprinted_show': ed_cfg.set_prop(app.PROP_UNPRINTED_SHOW, value) elif path == 'unprinted_spaces': ed_cfg.set_prop(app.PROP_UNPRINTED_SPACES, value) elif path == 'unprinted_ends': ed_cfg.set_prop(app.PROP_UNPRINTED_ENDS, value) elif path == 'unprinted_end_details': ed_cfg.set_prop(app.PROP_UNPRINTED_END_DETAILS, value) elif path == 'wrap_mode': ed_cfg.set_prop(app.PROP_WRAP, value) else: app.msg_status(CONFIG_MSG_DONT_SET_FILE) return None # Fail! return value if lev == CONFIG_LEV_LEX and ed_cfg is None: return None # Fail! lex = ed_cfg.get_prop(app.PROP_LEXER_CARET) if ed_cfg is not None else '' cfg_json = os.path.join( app.app_path(app.APP_DIR_SETTINGS), icase(False, '', lev == CONFIG_LEV_USER, 'user.json', lev == CONFIG_LEV_LEX, 'lexer {}.json'.format(lex), '')) pass #LOG and log('cfg_json={}',(cfg_json)) if not os.path.exists(cfg_json) and value is None: return None #?? success or fail? if not os.path.exists(cfg_json): #and value is not None # First pair for this file dct = {path: value} if '/' in path: keys = path.split('/') dct = {} dic = dct for ikey in range(len(keys)): key = keys[ikey] if ikey + 1 < len(keys): dic = dic.setdefault(key, {}) else: dic[key] = value open(cfg_json, 'w').write(json.dumps(dct, indent=4)) return value # Try to modify file body = open(cfg_json).read() value4js = json.dumps({'': value})[len('{"": '):-1] # format for json if '/' in path: # Complex path pass app.msg_status(CONFIG_MSG_DONT_SET_PATH) pass return None # Fail! else: # Simple key # Assumptions: # one key:val into one row re_key_val = r'^\s*,?\s*"{}"\s*:.+'.format(re.escape(path)) cre = re.compile(re_key_val, re.MULTILINE) has_pair = cre.search(body) is not None pass #LOG and log('re_key_val, has_pair={}',(re_key_val,has_pair)) if False: pass elif has_pair and value is None: # Delete! pass #LOG and log('del!',) body = cre.sub('', body) elif has_pair and value is not None: # Update! pass #LOG and log('upd!',) body = cre.sub(' "{}": {},'.format(path, value4js), body) elif not has_pair and value is None: # OK pass elif not has_pair: # Add! before end pass #LOG and log('add!',) body = body.rstrip(' \t\r\n')[:-1].rstrip(' \t\r\n') body = body + '{}\n "{}": {},\n}}'.format( '' if body[-1] in ',{' else ',', path, value4js) open(cfg_json, 'w').write(body) return value
def get_def_setting_dir(): pass #LOG and log('os.path.dirname(app.app_path(app.APP_DIR_SETTINGS))={}', os.path.dirname(app.app_path(app.APP_DIR_SETTINGS))) return os.path.join(os.path.dirname(app.app_path(app.APP_DIR_SETTINGS)), 'settings_default')
def _get_log_file(): return os.path.join(app.app_path(app.APP_DIR_SETTINGS), 'cudax.log')
def close(self): sscur = app.app_path(app.APP_FILE_SESSION) app.app_proc(app.PROC_SAVE_SESSION, sscur) app.app_proc(app.PROC_SET_SESSION, 'history session.json') # w/o path to use "settings" portable way pass; #LOG and log('ok',())
def dlg_config(self): ''' Show dlg for change macros list. ''' if app.app_api_version()<FROM_API_VERSION: return app.msg_status('Need update CudaText') keys_json = app.app_path(app.APP_DIR_SETTINGS)+os.sep+'keys.json' keys = apx._json_loads(open(keys_json).read()) if os.path.exists(keys_json) else {} GAP = 5 ids = [mcr['id'] for mcr in self.macros] mcr_ind = ids.index(self.last_mcr_id) if self.last_mcr_id in ids else -1 pass; LOG and log('self.last_mcr_id, mcr_ind={}',(self.last_mcr_id,mcr_ind)) times = 1 waits = 5 chngs = '0' endln = '0' while True: (WD_LST ,HT_LST)= (self.dlg_prs.get('w_list', 300) ,self.dlg_prs.get('h_list', 500)) (WD_ACTS ,HT_ACTS)=(self.dlg_prs.get('w_acts', 300) ,self.dlg_prs.get('h_acts', 500)) (WD_BTN ,HT_BTN)= (self.dlg_prs.get('w_btn', 150), 24) l_btn = GAP+WD_LST+GAP vw_acts = (WD_ACTS>0) WD_ACTS = max(0, WD_ACTS) rec_on = ed.get_prop(app.PROP_MACRO_REC) lmcrs = len(self.macros) pass; LOG and log('mcr_ind,vw_acts,rec_on={}',(mcr_ind,vw_acts,rec_on)) nmkys = [] for mcr in self.macros: mcr_cid = 'cuda_macros,run,{}'.format(mcr['id']) mcr_keys= keys.get(mcr_cid, {}) kys = '/'.join([' * '.join(mcr_keys.get('s1', [])) ,' * '.join(mcr_keys.get('s2', [])) ]).strip('/') nmkys += [mcr['nm'] + (' ['+kys+']' if kys else '')] mcr_acts= '' if vw_acts and mcr_ind in range(lmcrs): mcr = self.macros[mcr_ind] mcr_acts= '\t'.join(['# '+nmkys[mcr_ind]] + mcr['evl']) ans = app.dlg_custom('Macros' ,GAP+WD_LST+GAP+WD_BTN+GAP+WD_ACTS+GAP,GAP+HT_LST+GAP, '\n'.join([] +[C1.join(['type=listbox' ,POS_FMT(l=GAP, t=GAP, r=GAP+WD_LST, b=GAP+HT_LST) ,'items=' +'\t'.join(nmkys) ,'val=' +str(mcr_ind) # start sel ,'en=' +str(0 if rec_on else 1) # enabled ] # i=0 )] +([C1.join(['type=button' ,POS_FMT(l=l_btn, t=GAP*1+HT_BTN*0, r=l_btn+WD_BTN, b=0) ,'cap=&View actions...' ,'props=' +str(0 if rec_on or 0==lmcrs else 1) # default ,'en=' +str(0 if rec_on or 0==lmcrs else 1) # enabled ] # i=1 )] if vw_acts else []) +[C1.join(['type=button' ,POS_FMT(l=l_btn, t=GAP*2+HT_BTN*1, r=l_btn+WD_BTN, b=0) ,'cap=Hot&keys...' ,'en=' +str(0 if rec_on or 0==lmcrs else 1) # enabled ] # i=2 if vw_acts else i=1 )] +[C1.join(['type=button' ,POS_FMT(l=l_btn, t=GAP*3+HT_BTN*2, r=l_btn+WD_BTN, b=0) ,'cap=Re&name...' ,'en=' +str(0 if rec_on or 0==lmcrs else 1) # enabled ] # i=3 if vw_acts else i=2 )] +[C1.join(['type=button' ,POS_FMT(l=l_btn, t=GAP*4+HT_BTN*3, r=l_btn+WD_BTN, b=0) ,'cap=&Delete...' ,'en=' +str(0 if rec_on or 0==lmcrs else 1) # enabled ] # i=4 if vw_acts else i=3 )] +[C1.join(['type=button' ,POS_FMT(l=l_btn, t=GAP*6+HT_BTN*5, r=l_btn+WD_BTN, b=0) ,'cap=&Run!' ,'props=' +str(1 if not vw_acts and not rec_on else 0) # default ,'en=' +str(0 if rec_on or 0==lmcrs else 1) # enabled ] # i=5 if vw_acts else i=4 )] +[C1.join(['type=label' ,POS_FMT(l=l_btn, t=GAP*7+HT_BTN*6+3, r=l_btn+int(WD_BTN/3),b=0) ,'cap=&Times' ] # i=6 if vw_acts else i=5 )] +[C1.join(['type=spinedit' ,POS_FMT(l=l_btn+int(WD_BTN/3)+GAP, t=GAP*7+HT_BTN*6, r=l_btn+WD_BTN, b=0) ,'val=' +str(times) ,'props=0,{},1'.format(self.dlg_prs.get('times', 1000)) ,'en=' +str(0 if rec_on else 1) # enabled ] # i=7 if vw_acts else i=6 )] +[C1.join(['type=label' ,POS_FMT(l=l_btn, t=GAP*8+HT_BTN*7+3, r=l_btn+int(WD_BTN/3),b=0) ,'cap=&Wait' ] # i=8 if vw_acts else i=7 )] +[C1.join(['type=spinedit' ,POS_FMT(l=l_btn+int(WD_BTN/3)+GAP, t=GAP*8+HT_BTN*7, r=l_btn+WD_BTN-40, b=0) ,'val=' +str(waits) ,'props=1,3600,1' ,'en=' +str(0 if rec_on else 1) # enabled ] # i=9 if vw_acts else i=8 )] +[C1.join(['type=label' ,POS_FMT(l=l_btn+WD_BTN-40+GAP, t=GAP*8+HT_BTN*7+3, r=l_btn+WD_BTN,b=0) ,'cap=sec' ] # i=10 if vw_acts else i=9 )] +[C1.join(['type=check' ,POS_FMT(l=l_btn, t=GAP*9+HT_BTN*8, r=l_btn+WD_BTN,b=0) ,'cap=While text c&hanges' ,'val=' +chngs ] # i=11 if vw_acts else i=10 )] +[C1.join(['type=check' ,POS_FMT(l=l_btn, t=GAP*10+HT_BTN*9, r=l_btn+WD_BTN,b=0) ,'cap=Until c&aret on last line' ,'val=' +endln ] # i=12 if vw_acts else i=11 )] +[C1.join(['type=button' ,POS_FMT(l=l_btn, t=GAP*12+HT_BTN*11, r=l_btn+WD_BTN, b=0) ,'cap={}'.format('&Stop record' if rec_on else '&Start record') ,'props=' +str(1 if rec_on or 0==lmcrs else 0) # default ] # i=13 if vw_acts else i=12 )] +[C1.join(['type=button' ,POS_FMT(l=l_btn, t=GAP*13+HT_BTN*12, r=l_btn+WD_BTN, b=0) ,'cap=Canc&el record' ,'en=' +str(1 if rec_on else 0) # enabled ] # i=14 if vw_acts else i=13 )] +[C1.join(['type=button' ,POS_FMT(l=l_btn, t= HT_LST-HT_BTN*2, r=l_btn+WD_BTN, b=0) ,'cap=C&ustom...' ,'en=' +str(0 if rec_on else 1) # enabled ] # i=15 if vw_acts else i=14 )] +[C1.join(['type=button' ,POS_FMT(l=l_btn, t=GAP+HT_LST-HT_BTN*1, r=l_btn+WD_BTN, b=0) ,'cap=&Close' ] # i=16 if vw_acts else i=15 )] +([C1.join(['type=memo' ,POS_FMT(l=GAP+WD_LST+GAP+WD_BTN+GAP, t=GAP, r=GAP+WD_LST+GAP+WD_BTN+GAP+WD_ACTS, b=GAP+HT_ACTS) ,'val='+mcr_acts ,'props=1,1,1' # ro,mono,border ] # i=17 )] if vw_acts else []) ), apx.icase( vw_acts and not rec_on, 0 # View ,not vw_acts and not rec_on, 0 # View , vw_acts and rec_on, 11 ,not vw_acts and rec_on, 10 )) # start focus pass; LOG and log('ans={}',ans) if ans is None: break #while (ans_i ,vals) = ans ans_s = apx.icase(False,'' ,vw_acts and ans_i==1, 'view' ,vw_acts and ans_i==2, 'hotkeys' ,not vw_acts and ans_i==1, 'hotkeys' ,vw_acts and ans_i==3, 'rename' ,not vw_acts and ans_i==2, 'rename' ,vw_acts and ans_i==4, 'delete' ,not vw_acts and ans_i==3, 'delete' ,vw_acts and ans_i==5, 'run' ,not vw_acts and ans_i==4, 'run' ,vw_acts and ans_i==12,'rec' ,not vw_acts and ans_i==7, 'rec' ,vw_acts and ans_i==14,'cancel' ,not vw_acts and ans_i==13,'cancel' ,vw_acts and ans_i==15,'custom' ,not vw_acts and ans_i==14,'custom' ,vw_acts and ans_i==16,'close' ,not vw_acts and ans_i==15,'close' ,'?') mcr_ind = int(vals.splitlines()[0]) times = int(vals.splitlines()[ 7 if vw_acts else 6]) waits = int(vals.splitlines()[ 9 if vw_acts else 8]) chngs = vals.splitlines()[11 if vw_acts else 10] endln = vals.splitlines()[12 if vw_acts else 11] pass; LOG and log('mcr_ind,times,waits,chngs,endln={}',(mcr_ind,times,waits,chngs,endln)) if 0!=lmcrs and mcr_ind in range(lmcrs): mcr = self.macros[mcr_ind] self.last_mcr_id = mcr['id'] if ans_s=='close': break #while if ans_s=='custom': #Custom custs = app.dlg_input_ex(5, 'Custom dialog Macros' , 'Height of macro list (min 450)' , str(self.dlg_prs.get('h_list', 400)) , 'Width of macro list (min 200)' , str(self.dlg_prs.get('w_list', 500)) , 'Width of action list (min 200, <=0-hide)', str(self.dlg_prs.get('w_acts', 500)) , 'Width of buttons (min 150)' , str(self.dlg_prs.get('w_btn', 150)) , 'Max run times (min 100)' , str(self.dlg_prs.get('times', 1000)) ) if custs is not None: self.dlg_prs['h_list'] = max(450, int(custs[0])); self.dlg_prs['h_acts'] = self.dlg_prs['h_list'] self.dlg_prs['w_list'] = max(200, int(custs[1])) self.dlg_prs['w_acts'] = max(200, int(custs[2])) if int(custs[2])>0 else int(custs[2]) self.dlg_prs['w_btn'] = max(150, int(custs[3])) self.dlg_prs['times'] = max(100, int(custs[4])) open(MACROS_JSON, 'w').write(json.dumps({'ver':JSON_FORMAT_VER, 'list':self.macros, 'dlg_prs':self.dlg_prs}, indent=4)) continue #while if mcr_ind not in range(lmcrs): app.msg_box('Select macro', app.MB_OK) continue #while what = '' changed = False if False:pass elif ans_s=='view': #View continue #while elif ans_s=='rename': #Rename mcr_nm = app.dlg_input('New name for: {}'.format(nmkys[mcr_ind]) ,mcr['nm']) if mcr_nm is None or mcr_nm==mcr['nm']: continue #while while mcr_nm in [mcr['nm'] for mcr in self.macros]: app.msg_box('Select other name.\nMacro names now are:\n\n'+'\n'.join(nmkys), app.MB_OK) mcr_nm = app.dlg_input('New name for: {}'.format(nmkys[mcr_ind]) ,mcr_nm) if mcr_nm is None or mcr_nm==mcr['nm']: break #while mcr_nm if mcr_nm is None or mcr_nm==mcr['nm']: continue #while what = 'rename' mcr['nm'] = mcr_nm changed = True elif ans_s=='delete': #Del if app.msg_box( 'Delete macro\n {}'.format(nmkys[mcr_ind]) , app.MB_YESNO)!=app.ID_YES: continue #while what = 'delete:'+str(mcr['id']) del self.macros[mcr_ind] mcr_ind = min(mcr_ind, len(self.macros)-1) changed = True elif ans_s=='hotkeys': #Hotkeys app.dlg_hotkeys('cuda_macros,run,'+str(mcr['id'])) keys = apx._json_loads(open(keys_json).read()) if os.path.exists(keys_json) else {} changed = True elif ans_s=='run': #Run if (times==0 and waits==0 and chngs=='0' and endln=='0'): app.msg_box('Select stop condition', app.MB_OK) continue self.run(mcr['id'], max(0, times), max(0, waits), chngs=='1', endln=='1') return elif ans_s=='rec' and not rec_on: #Start record return ed.cmd(cmds.cmd_MacroStart) elif ans_s=='rec' and rec_on: #Stop record self.need_dlg = True return ed.cmd(cmds.cmd_MacroStop) # Return for clear rec-mode in StatusBar, will recall from on_macro elif ans_s=='cancel' and rec_on: #Cancel record return ed.cmd(cmds.cmd_MacroCancel) # Return for clear rec-mode in StatusBar if changed: self._do_acts(what)
ToDo: (see end of file) ''' import os, json, random, datetime, re import cudatext as app from cudatext import ed import cudatext_cmd as cmds import cudax_lib as apx from cudax_lib import log pass; # Logging pass; LOG = (-2== 2) # Do or dont logging. FROM_API_VERSION= '1.0.114' JSON_FORMAT_VER = '20151204' MACROS_JSON = app.app_path(app.APP_DIR_SETTINGS)+os.sep+'macros.json' C1 = chr(1) C2 = chr(2) POS_FMT = 'pos={l},{t},{r},{b}'.format GAP = 5 class Command: CMD_ID2NM = {} # {val: name} from cudatext_cmd.py macros = [] # Main list [macro] mcr4id = {} # Derived dict {str_id:macro} # id_menu = 0 def __init__(self):
def get_def_setting_dir(): #pass; LOG and log('os.path.dirname(app.app_path(app.APP_DIR_SETTINGS))={}', os.path.dirname(app.app_path(app.APP_DIR_SETTINGS))) return os.path.join( os.path.dirname(app.app_path(app.APP_DIR_SETTINGS)) , 'settings_default' )
import cudax_lib as apx from .cd_plug_lib import * OrdDict = collections.OrderedDict # I18N _ = get_translation(__file__) pass; LOG = (-1== 1) # Do or dont logging. co_sgns = [sgn for sgn in dir(cmds) if sgn.startswith('cCommand_') or sgn.startswith('cmd_')] CO_SGN2CID = {sgn:eval('cmds.'+sgn) for sgn in co_sgns} CO_CID2SGN = {cid:sgn for sgn,cid in CO_SGN2CID.items()} snip2call_json= app.app_path(app.APP_DIR_SETTINGS)+os.sep+'cuda_snip2call.json' class SnipData: """ SnipData.is_snip(text) # Test sd = SnipData() # Load snips, prepare fields sd.cmd_ids() # Iterate all core/plug cmd-ids sd.get_name(cid) # sd.get_snips(cid)->list # All snips for cmd-id sd.get_cmdid(snip) # 0/1 cmd-id for snip sd.set(snip, cid) # Assign snip to cmd-id. Old snip-assigning will be removed """ # msg_correct_snip = _('Permitted character in snip: letters') msg_correct_snip = _('Snip characters: letters, digits, "_". First character must be letter.') snip_help = _(''' "Snip" is an alternative way to call commands.
import os import string import cudatext as app import cudax_lib as appx from . import opt from .getline import get_line import unicodedata as ud all_unicode = [chr(i) for i in range(0x10000)] unicode_letters = ''.join([c for c in all_unicode if ud.category(c) in ('Lu', 'Ll')]) CHARS = string.ascii_letters + string.digits + '_$' + unicode_letters MARKTAG = 101 #uniq value for all markers plugins fn_ini = os.path.join(app.app_path(app.APP_DIR_SETTINGS), 'cuda_hilite_occurrences.ini') def bool_to_str(v): return '1' if v else '0' def str_to_bool(s): return s=='1' def do_load_ops(): opt.MIN_LEN = int(app.ini_read(fn_ini, 'op', 'min_len', '2')) opt.MAX_LINES = int(app.ini_read(fn_ini, 'op', 'max_lines', '5000')) opt.USE_NEAREST_LINE_COUNT = int(app.ini_read(fn_ini, 'op', 'use_nearest_line_count', '10000')) opt.SEL_ALLOW = str_to_bool(app.ini_read(fn_ini, 'op', 'sel_allow', '1')) opt.SEL_ALLOW_WHITE_SPACE = str_to_bool(app.ini_read(fn_ini, 'op', 'sel_allow_white_space', '0')) opt.SEL_CASE_SENSITIVE = str_to_bool(app.ini_read(fn_ini, 'op', 'sel_case_sensitive', '0')) opt.SEL_WORDS_ONLY = str_to_bool(app.ini_read(fn_ini, 'op', 'sel_words_only', '0')) opt.SEL_WHOLE_WORDS = str_to_bool(app.ini_read(fn_ini, 'op', 'sel_whole_words', '0')) opt.CARET_ALLOW = str_to_bool(app.ini_read(fn_ini, 'op', 'caret_allow', '1'))
def dlg_config(self): ''' Show dlg for change macros list. ''' if app.app_api_version()<FROM_API_VERSION: return app.msg_status(_('Need update CudaText')) keys_json = app.app_path(app.APP_DIR_SETTINGS)+os.sep+'keys.json' keys = apx._json_loads(open(keys_json).read()) if os.path.exists(keys_json) else {} ids = [mcr['id'] for mcr in self.macros] mcr_ind = ids.index(self.last_mcr_id) if self.last_mcr_id in ids else -1 pass; LOG and log('self.last_mcr_id, mcr_ind={}',(self.last_mcr_id,mcr_ind)) times = 1 waits = 5 chngs = '0' endln = '0' while True: WD_LST, \ HT_LST = (self.dlg_prs.get('w_list', 300) ,self.dlg_prs.get('h_list', 500)) WD_ACTS,\ HT_ACTS = (self.dlg_prs.get('w_acts', 300) ,self.dlg_prs.get('h_acts', 500)) WD_BTN, \ HT_BTN = (self.dlg_prs.get('w_btn', 150), 24) WD_BTN_3= int(WD_BTN/3) l_btn = GAP+WD_LST+GAP l_acts = GAP+WD_LST+GAP+WD_BTN+GAP vw_acts = (WD_ACTS>0) WD_ACTS = max(0, WD_ACTS) rec_on = ed.get_prop(app.PROP_MACRO_REC) lmcrs = len(self.macros) pass; LOG and log('mcr_ind,vw_acts,rec_on={}',(mcr_ind,vw_acts,rec_on)) nmkys = [] for mcr in self.macros: mcr_cid = 'cuda_macros,run,{}'.format(mcr['id']) mcr_keys= keys.get(mcr_cid, {}) kys = '/'.join([' * '.join(mcr_keys.get('s1', [])) ,' * '.join(mcr_keys.get('s2', [])) ]).strip('/') nmkys += [mcr['nm'] + (' ['+kys+']' if kys else '')] mcr_acts= [''] # mcr_acts= '' if vw_acts and mcr_ind in range(lmcrs): mcr = self.macros[mcr_ind] mcr_acts= ['# '+nmkys[mcr_ind]] + mcr['evl'] # mcr_acts= '\t'.join(['# '+nmkys[mcr_ind]] + mcr['evl']) def_stst = '1' if rec_on or 0==lmcrs else '0' n_edable = '0' if rec_on or 0==lmcrs else '1' n_vwable = '1' if not vw_acts and not rec_on else '0' only_rec_off= '0' if rec_on else '1' only_rec_on = '1' if rec_on else '0' tims_props = '0,{},1'.format(self.dlg_prs.get('times', 1000)) stst_cap = _('&Stop record') if rec_on else _('&Start record') cnts = ([] +[dict(cid='mrcs' ,tp='lbx' ,t=GAP ,h=HT_LST ,l=GAP ,w=WD_LST ,items=nmkys ,en=only_rec_off )] +( [dict(cid='view' ,tp='bt' ,t=GAP* 1+HT_BTN* 0 ,l=l_btn ,w=WD_BTN ,cap=_('&View actions') ,props=n_edable,en=n_edable )] # default if vw_acts else []) +[dict(cid='keys' ,tp='bt' ,t=GAP* 2+HT_BTN* 1 ,l=l_btn ,w=WD_BTN ,cap=_('Hot&keys...') ,en=n_edable )] +[dict(cid='renm' ,tp='bt' ,t=GAP* 3+HT_BTN* 2 ,l=l_btn ,w=WD_BTN ,cap=_('Re&name...') ,en=n_edable )] +[dict(cid='del' ,tp='bt' ,t=GAP* 4+HT_BTN* 3 ,l=l_btn ,w=WD_BTN ,cap=_('&Delete...') ,en=n_edable )] +[dict(cid='run' ,tp='bt' ,t=GAP* 6+HT_BTN* 5 ,l=l_btn ,w=WD_BTN ,cap=_('&Run!') ,props=n_vwable ,en=n_edable )] # default +[dict( tp='lb' ,tid='times' ,l=l_btn ,w=WD_BTN_3 ,cap=_('&Times') )] +[dict(cid='times' ,tp='sp-ed',t=GAP* 7+HT_BTN* 6 ,l=l_btn+WD_BTN_3+GAP ,r=l_btn+WD_BTN ,props=tims_props,en=only_rec_off )] # min,max,step +[dict( tp='lb' ,tid='waits' ,l=l_btn ,w=WD_BTN_3 ,cap=_('&Wait') )] +[dict(cid='waits' ,tp='sp-ed',t=GAP* 8+HT_BTN* 7 ,l=l_btn+WD_BTN_3+GAP ,r=l_btn+WD_BTN-40 ,props='1,3600,1',en=only_rec_off )] # min,max,step +[dict( tp='lb' ,tid='waits' ,l=l_btn+WD_BTN-40+GAP ,w=WD_BTN ,cap=_('sec') )] +[dict(cid='chngs' ,tp='ch' ,t=GAP* 9+HT_BTN* 8 ,l=l_btn ,w=WD_BTN ,cap=_('While text c&hanges') )] +[dict(cid='endln' ,tp='ch' ,t=GAP*10+HT_BTN* 9 ,l=l_btn ,w=WD_BTN ,cap=_('Until c&aret on last line') )] +[dict(cid='stst' ,tp='bt' ,t=GAP*12+HT_BTN*11 ,l=l_btn ,w=WD_BTN ,cap=stst_cap ,props=def_stst )] +[dict(cid='canc' ,tp='bt' ,t=GAP*13+HT_BTN*12 ,l=l_btn ,w=WD_BTN ,cap=_('Canc&el record') ,en=only_rec_on )] +[dict(cid='adju' ,tp='bt' ,t= HT_LST-HT_BTN*2 ,l=l_btn ,w=WD_BTN ,cap=_('Ad&just...') ,en=only_rec_off )] +[dict(cid='-' ,tp='bt' ,t=GAP+HT_LST-HT_BTN*1 ,l=l_btn ,w=WD_BTN ,cap=_('Close') )] +( [dict(cid='acts' ,tp='me' ,t=GAP ,h=HT_ACTS ,l=l_acts ,w=WD_ACTS ,props='1,1,1' )] # ro,mono,border if vw_acts else []) ) vals = dict( mrcs=mcr_ind ,times=times ,waits=waits ,chngs=chngs ,endln=endln ) if vw_acts: vals.update( dict( acts=mcr_acts )) btn, \ vals, \ chds = dlg_wrapper(_('Macros'), GAP+WD_LST+GAP+WD_BTN+GAP+WD_ACTS+GAP,GAP+HT_LST+GAP, cnts, vals, focus_cid='mrcs') if btn is None or btn=='-': return mcr_ind = vals['mrcs'] times = vals['times'] waits = vals['waits'] chngs = vals['chngs'] endln = vals['endln'] pass; LOG and log('mcr_ind,times,waits,chngs,endln={}',(mcr_ind,times,waits,chngs,endln)) if 0!=lmcrs and mcr_ind in range(lmcrs): mcr = self.macros[mcr_ind] self.last_mcr_id = mcr['id'] # if ans_s=='close': break #while if btn=='adju': #ans_s=='custom': #Custom custs = app.dlg_input_ex(5, _('Custom dialog Macros') , _('Height of macro list (min 450)') , str(self.dlg_prs.get('h_list', 400)) , _('Width of macro list (min 200)') , str(self.dlg_prs.get('w_list', 500)) , _('Width of action list (min 200, <=0-hide)'), str(self.dlg_prs.get('w_acts', 500)) , _('Width of buttons (min 150)') , str(self.dlg_prs.get('w_btn', 150)) , _('Max run times (min 100)') , str(self.dlg_prs.get('times', 1000)) ) if custs is not None: self.dlg_prs['h_list'] = max(450, int(custs[0])); self.dlg_prs['h_acts'] = self.dlg_prs['h_list'] self.dlg_prs['w_list'] = max(200, int(custs[1])) self.dlg_prs['w_acts'] = max(200, int(custs[2])) if int(custs[2])>0 else int(custs[2]) self.dlg_prs['w_btn'] = max(150, int(custs[3])) self.dlg_prs['times'] = max(100, int(custs[4])) open(MACROS_JSON, 'w').write(json.dumps({'ver':JSON_FORMAT_VER, 'list':self.macros, 'dlg_prs':self.dlg_prs}, indent=4)) continue #while if mcr_ind not in range(lmcrs): app.msg_box(_('Select macro'), app.MB_OK) continue #while what = '' changed = False if False:pass elif btn=='view': #ans_s=='view': #View continue #while elif btn=='renm': #ans_s=='rename': #Rename mcr_nm = app.dlg_input(_('New name for: {}').format(nmkys[mcr_ind]) ,mcr['nm']) if mcr_nm is None or mcr_nm==mcr['nm']: continue #while while mcr_nm in [mcr['nm'] for mcr in self.macros]: app.msg_box(_('Select other name.\nMacro names now are:\n\n')+'\n'.join(nmkys), app.MB_OK) mcr_nm = app.dlg_input(_('New name for: {}').format(nmkys[mcr_ind]) ,mcr_nm) if mcr_nm is None or mcr_nm==mcr['nm']: break #while mcr_nm if mcr_nm is None or mcr_nm==mcr['nm']: continue #while what = 'rename' mcr['nm'] = mcr_nm changed = True elif btn=='del': #ans_s=='delete': #Del if app.msg_box( _('Delete macro\n {}').format(nmkys[mcr_ind]) , app.MB_YESNO)!=app.ID_YES: continue #while what = 'delete:'+str(mcr['id']) del self.macros[mcr_ind] mcr_ind = min(mcr_ind, len(self.macros)-1) changed = True elif btn=='keys': #ans_s=='hotkeys': #Hotkeys app.dlg_hotkeys('cuda_macros,run,'+str(mcr['id'])) keys = apx._json_loads(open(keys_json).read()) if os.path.exists(keys_json) else {} changed = True elif btn=='run': #ans_s=='run': #Run if (times==0 and waits==0 and chngs=='0' and endln=='0'): app.msg_box(_('Select stop condition'), app.MB_OK) continue self.run(mcr['id'], max(0, times), max(0, waits), chngs=='1', endln=='1') return elif btn=='stst' and not rec_on: #Start record # elif ans_s=='rec' and not rec_on: #Start record return ed.cmd(cmds.cmd_MacroStart) elif btn=='stst' and rec_on: #Stop record # elif ans_s=='rec' and rec_on: #Stop record self.need_dlg = True return ed.cmd(cmds.cmd_MacroStop) # Return for clear rec-mode in StatusBar, will recall from on_macro elif btn=='canc' and rec_on: #Cancel record # elif ans_s=='cancel' and rec_on: #Cancel record return ed.cmd(cmds.cmd_MacroCancel) # Return for clear rec-mode in StatusBar if changed: self._do_acts(what)
def set_hist(key_or_path, value, module_name='_auto_detect', kill=False, to_file=PLING_HISTORY_JSON): """ Write to "plugin history.json" one value by key or path (list of keys). If any of node doesnot exist it will be added. Or remove (if kill) one key+value pair (if suitable key exists). Parameters key_or_path Key(s) to navigate in json tree Type: str or [str] value Value to set if suitable item in json tree exists module_name Start node to navigate. If it is '_auto_detect' then name of caller module is used. If it is None then it is skipped. kill Need to remove node in tree. if kill==True parm value is ignored to_file Name of file to write. APP_DIR_SETTING will be joined if no full path. Return value (param) if !kill and modification is successful value (killed) if kill and modification is successful None if kill and no path in tree (no changes) KeyError if !kill and path has problem Return value Examples (caller module is 'plg') 1. If no "plugin history.json" it will become set_hist('k',0,None) {"k":0} set_hist('k',1) {"plg":{"k":1}} set_hist('k',1,'plg') {"plg":{"k":1}} set_hist('k',1,'oth') {"oth":{"k":1}} set_hist('k',[1,2]) {"plg":{"k":[1,2]}} set_hist(['p','k'], 1) {"plg":{"p":{"k":1}}} 2. If "plugin history.json" contains {"plg":{"k":1, "p":{"m":2}}} it will contain set_hist('k',0,None) {"plg":{"k":1, "p":{"m":2}},"k":0} set_hist('k',0) {"plg":{"k":0, "p":{"m":2}}} set_hist('k',0,'plg') {"plg":{"k":0, "p":{"m":2}}} set_hist('n',3) {"plg":{"k":1, "p":{"m":2}, "n":3}} set_hist(['p','m'], 4) {"plg":{"k":1, "p":{"m":4}}} set_hist('p',{'m':4}) {"plg":{"k":1, "p":{"m":4}}} set_hist(['p','m','k'], 1) KeyError (old m is not branch node) 3. If "plugin history.json" contains {"plg":{"k":1, "p":{"m":2}}} it will contain set_hist('k', kill=True) {"plg":{ "p":{"m":2}}} set_hist('p', kill=True) {"plg":{"k":1}} set_hist(['p','m'], kill=True) {"plg":{"k":1, "p":{}}} set_hist('n', kill=True) {"plg":{"k":1, "p":{"m":2}}} (nothing to kill) """ to_file = to_file if os.sep in to_file else app.app_path( app.APP_DIR_SETTINGS) + os.sep + to_file body = json.loads(open(to_file).read(), object_pairs_hook=odict) \ if os.path.exists(to_file) and os.path.getsize(to_file) != 0 else \ odict() if module_name == '_auto_detect': caller_globals = inspect.stack()[1].frame.f_globals module_name = inspect.getmodulename(caller_globals['__file__']) \ if '__file__' in caller_globals else None keys = [key_or_path] if type(key_or_path) == str else key_or_path keys = keys if module_name is None else [module_name] + keys parents,\ key = keys[:-1], keys[-1] data = body for parent in parents: if kill and parent not in data: return None data = data.setdefault(parent, odict()) if type(data) != odict: raise KeyError() if kill: if key not in data: return None value = data.pop(key) else: data[key] = value open(to_file, 'w').write(json.dumps(body, indent=2)) return value
def set_opt(path, value, lev=CONFIG_LEV_USER, ed_cfg=ed): ''' Overridden options tool. Config pairs key:val are add/update/delete into <root>/settings/user.json <root>/settings/lexer <LEXER-NAME>.json ed_cfg props Params path Simple value (e.g. "tab_size") or "/"-separated path inside JSON tree value Value for setting or deleting None Delete pair (last key in path) is not None Add or update pair value lev Level for set opt CONFIG_LEV_USER, CONFIG_LEV_LEX, CONFIG_LEV_FILE ed_cfg Ref to editor to point a lexer Return The value (second param) or None if fail ''' if lev==CONFIG_LEV_FILE: if value is None: # Del! Cannot del from file-lev -- can set as default def_opts = get_app_default_opts() value = def_opts.get(path) else: value = str(value) if False:pass elif path=='tab_size': ed_cfg.set_prop(app.PROP_TAB_SIZE, value) elif path=='tab_spaces': ed_cfg.set_prop(app.PROP_TAB_SPACES, value) elif path=='unprinted_show': ed_cfg.set_prop(app.PROP_UNPRINTED_SHOW, value) elif path=='unprinted_spaces': ed_cfg.set_prop(app.PROP_UNPRINTED_SPACES, value) elif path=='unprinted_ends': ed_cfg.set_prop(app.PROP_UNPRINTED_ENDS, value) elif path=='unprinted_end_details': ed_cfg.set_prop(app.PROP_UNPRINTED_END_DETAILS, value) elif path=='wrap_mode': ed_cfg.set_prop(app.PROP_WRAP, value) else: app.msg_status(CONFIG_MSG_DONT_SET_FILE) return None # Fail! return value if lev==CONFIG_LEV_LEX and ed_cfg is None: return None # Fail! lex = ed_cfg.get_prop(app.PROP_LEXER_CARET) if ed_cfg is not None else '' cfg_json= os.path.join(app.app_path(app.APP_DIR_SETTINGS), icase(False,'' ,lev==CONFIG_LEV_USER , 'user.json' ,lev==CONFIG_LEV_LEX , 'lexer {}.json'.format(lex) , '')) pass; #LOG and log('cfg_json={}',(cfg_json)) if not os.path.exists(cfg_json) and value is None: return None #?? success or fail? if not os.path.exists(cfg_json):#and value is not None # First pair for this file dct = {path:value} if '/' in path: keys= path.split('/') dct = {} dic = dct for ikey in range(len(keys)): key = keys[ikey] if ikey+1<len(keys): dic = dic.setdefault(key, {}) else: dic[key] = value open(cfg_json, 'w', encoding='utf8').write(json.dumps(dct, indent=4)) return value # Try to modify file body = open(cfg_json, encoding='utf8').read() value4js= json.dumps({'':value})[len('{"": '):-1] # format for json if '/' in path: # Complex path pass; app.msg_status(CONFIG_MSG_DONT_SET_PATH) pass; return None # Fail! else: # Simple key # Assumptions: # one key:val into one row re_key_val = r'^\s*,?\s*"{}"\s*:.+'.format(re.escape(path)) cre = re.compile(re_key_val, re.MULTILINE) has_pair = cre.search(body) is not None pass; #LOG and log('re_key_val, has_pair={}',(re_key_val,has_pair)) if False:pass elif has_pair and value is None: # Delete! pass; #LOG and log('del!',) body = cre.sub('', body) elif has_pair and value is not None: # Update! pass; #LOG and log('upd!',) body = cre.sub(' "{}": {},'.format(path, value4js), body) elif not has_pair and value is None: # OK pass elif not has_pair: # Add! before end pass; #LOG and log('add!',) body = body.rstrip(' \t\r\n')[:-1].rstrip(' \t\r\n') body= body+'{}\n "{}": {},\n}}'.format( '' if body[-1] in ',{' else ',' , path , value4js) open(cfg_json, 'w', encoding='utf8').write(body) return value
def get_opt(path, def_value=None, lev=CONFIG_LEV_ALL, ed_cfg=ed): ''' Overridden options tool. Config pairs key:val are read from <root>/settings_default/default.json <root>/settings/user.json <root>/settings/lexer <LEXER-NAME>.json ed_cfg props Params path Simple value (e.g. "tab_size") or "/"-separated path inside JSON tree def_value For return if no opt for the path into all config files lev Stop finding level CONFIG_LEV_ALL, CONFIG_LEV_DEF, CONFIG_LEV_USER, CONFIG_LEV_LEX, CONFIG_LEV_FILE ed_cfg Ref to editor to point a lexer Return Last found in config files default[/user[/lexer]] or def_value ''' pass #LOG and log('path, def_va, lev, ed_cfg={}',(path, def_value, lev, ed_cfg)) keys = path.split('/') if '/' in path else () ans = def_value def_opts = get_app_default_opts() if lev == CONFIG_LEV_DEF: ans = def_opts.get(path, def_value) if not keys else _opt_for_keys( def_opts, keys, def_value) pass #LOG and log('lev=DEF ans={}',(ans)) else: usr_json = os.path.join(app.app_path(app.APP_DIR_SETTINGS), 'user.json') usr_opts = _get_file_opts(usr_json) if lev == CONFIG_LEV_USER: pass #LOG and log('def_opts(), usr_opts()={}',(def_opts.get(path),usr_opts.get(path))) ans = usr_opts.get(path, def_opts.get( path, def_value)) if not keys else _opt_for_keys( usr_opts, keys, _opt_for_keys(def_opts, keys, def_value)) pass #LOG and log('lev=USR ans={}',(ans)) else: lex = ed_cfg.get_prop(app.PROP_LEXER_CARET) lex_json = os.path.join(app.app_path(app.APP_DIR_SETTINGS), 'lexer {}.json'.format(lex)) lex_opts = _get_file_opts(lex_json) if lev == CONFIG_LEV_LEX: pass #LOG and log('def_opts(), usr_opts(), lex_opts()={}',(def_opts.get(path),usr_opts.get(path),lex_opts.get(path))) ans = lex_opts.get( path, usr_opts.get(path, def_opts.get( path, def_value))) if not keys else _opt_for_keys( lex_opts, keys, _opt_for_keys( usr_opts, keys, _opt_for_keys(def_opts, keys, def_value))) pass #LOG and log('lev=LEX ans={}',(ans)) else: # lev in (CONFIG_LEV_ALL, CONFIG_LEV_FILE if False: pass elif path == 'tab_size': ans = ed_cfg.get_prop(app.PROP_TAB_SIZE) elif path == 'tab_spaces': ans = ed_cfg.get_prop(app.PROP_TAB_SPACES) elif path == 'unprinted_show': ans = ed_cfg.get_prop(app.PROP_UNPRINTED_SHOW) elif path == 'unprinted_spaces': ans = ed_cfg.get_prop(app.PROP_UNPRINTED_SPACES) elif path == 'unprinted_ends': ans = ed_cfg.get_prop(app.PROP_UNPRINTED_ENDS) elif path == 'unprinted_end_details': ans = ed_cfg.get_prop(app.PROP_UNPRINTED_END_DETAILS) elif path == 'wrap_mode': ans = ed_cfg.get_prop(app.PROP_WRAP) else: pass #LOG and log('def_opts(), usr_opts(), lex_opts()={}',(def_opts.get(path),usr_opts.get(path),lex_opts.get(path))) ans = lex_opts.get( path, usr_opts.get(path, def_opts.get( path, def_value))) if not keys else _opt_for_keys( lex_opts, keys, _opt_for_keys( usr_opts, keys, _opt_for_keys(def_opts, keys, def_value))) pass #LOG and log('lev=ALL ans={}',(ans)) return ans if def_value is None else type(def_value)(ans)
def get_opt(path, def_value=None, lev=CONFIG_LEV_ALL, ed_cfg=ed): ''' Overridden options tool. Config pairs key:val are read from <root>/settings_default/default.json <root>/settings/user.json <root>/settings/lexer <LEXER-NAME>.json ed_cfg props Params path Simple value (e.g. "tab_size") or "/"-separated path inside JSON tree def_value For return if no opt for the path into all config files lev Stop finding level CONFIG_LEV_ALL, CONFIG_LEV_DEF, CONFIG_LEV_USER, CONFIG_LEV_LEX, CONFIG_LEV_FILE ed_cfg Ref to editor to point a lexer Return Last found in config files default[/user[/lexer]] or def_value ''' pass; #LOG and log('path, def_va, lev, ed_cfg={}',(path, def_value, lev, ed_cfg)) keys = path.split('/') if '/' in path else () ans = def_value def_opts = get_app_default_opts() if lev==CONFIG_LEV_DEF: ans = def_opts.get(path, def_value) if not keys else _opt_for_keys(def_opts, keys, def_value) pass; #LOG and log('lev=DEF ans={}',(ans)) else: usr_json = os.path.join(app.app_path(app.APP_DIR_SETTINGS), 'user.json') usr_opts = _get_file_opts(usr_json) if lev==CONFIG_LEV_USER: pass; #LOG and log('def_opts(), usr_opts()={}',(def_opts.get(path),usr_opts.get(path))) ans = usr_opts.get(path , def_opts.get(path, def_value)) if not keys else _opt_for_keys(usr_opts, keys ,_opt_for_keys(def_opts, keys, def_value)) pass; #LOG and log('lev=USR ans={}',(ans)) else: lex = ed_cfg.get_prop(app.PROP_LEXER_CARET) lex_json= os.path.join(app.app_path(app.APP_DIR_SETTINGS), 'lexer {}.json'.format(lex)) lex_opts= _get_file_opts(lex_json) if lev==CONFIG_LEV_LEX: pass; #LOG and log('def_opts(), usr_opts(), lex_opts()={}',(def_opts.get(path),usr_opts.get(path),lex_opts.get(path))) ans = lex_opts.get(path ,usr_opts.get(path ,def_opts.get(path, def_value))) if not keys else _opt_for_keys(lex_opts, keys ,_opt_for_keys(usr_opts, keys ,_opt_for_keys(def_opts, keys, def_value))) pass; #LOG and log('lev=LEX ans={}',(ans)) else: # lev in (CONFIG_LEV_ALL, CONFIG_LEV_FILE if False:pass elif path=='tab_size': ans = ed_cfg.get_prop(app.PROP_TAB_SIZE) elif path=='tab_spaces': ans = ed_cfg.get_prop(app.PROP_TAB_SPACES) elif path=='unprinted_show': ans = ed_cfg.get_prop(app.PROP_UNPRINTED_SHOW) elif path=='unprinted_spaces': ans = ed_cfg.get_prop(app.PROP_UNPRINTED_SPACES) elif path=='unprinted_ends': ans = ed_cfg.get_prop(app.PROP_UNPRINTED_ENDS) elif path=='unprinted_end_details': ans = ed_cfg.get_prop(app.PROP_UNPRINTED_END_DETAILS) elif path=='wrap_mode': ans = ed_cfg.get_prop(app.PROP_WRAP) else: pass; #LOG and log('def_opts(), usr_opts(), lex_opts()={}',(def_opts.get(path),usr_opts.get(path),lex_opts.get(path))) ans = lex_opts.get(path ,usr_opts.get(path ,def_opts.get(path, def_value))) if not keys else _opt_for_keys(lex_opts, keys ,_opt_for_keys(usr_opts, keys ,_opt_for_keys(def_opts, keys, def_value))) pass; #LOG and log('lev=ALL ans={}',(ans)) return ans if def_value is None else type(def_value)(ans)
OptFetchResult = collections.namedtuple('OptFetchResult', 'opts filter sort') pass; LOG = (-1== 1) or apx.get_opt('_opts_dlg_log',False) # Do or dont logging. pass; from pprint import pformat pass; pf=lambda d:pformat(d,width=150) pass; pf80=lambda d:pformat(d,width=80) pass; pf60=lambda d:pformat(d,width=60) pass; ##!! waits correction _ = apx.get_translation(__file__) # I18N VERSION = re.split('Version:', __doc__)[1].split("'")[1] VERSION_V, \ VERSION_D = VERSION.split(' ') MAX_HIST = apx.get_opt('ui_max_history_edits', 20) CFG_JSON = app.app_path(app.APP_DIR_SETTINGS)+os.sep+'cuda_options_editor.json' HTM_RPT_FILE= str(Path(tempfile.gettempdir()) / 'CudaText_option_report.html') FONT_LST = ['default'] \ + [font for font in app.app_proc(app.PROC_ENUM_FONTS, '') if not font.startswith('@')] NO_CHAP = _('_no_') pass; #FONT_LST=FONT_LST[:3] def f(s, *args, **kwargs):return s.format(*args, **kwargs) def log(msg='', *args, **kwargs): if args or kwargs:
Version: '1.0.3 2016-07-12' ''' import os, json, configparser, itertools import cudatext as app import cudatext_cmd as cmds import cudax_lib as apx from .cd_plug_lib import * pass; LOG = (-1==-1) # Do or dont logging. pass; from pprint import pformat pass; pf=lambda d:pformat(d,width=150) CDSESS_EXT = '.cuda-session' SWSESS_EXT = '.synw-session' SESS_JSON = os.path.join(app.app_path(app.APP_DIR_SETTINGS), 'cuda_sess_manager.json') # Localization NEED_NEWER_API = 'Plugin needs newer app version' NO_RECENT = 'No recent sessions' NO_PREV = 'No previous session' SAVED = 'Session "{stem}" is saved' OPENED = 'Session "{stem}" is opened' CREATE_ASK = 'Session "{stem}" not found\n\nCreate it?' CREATED = 'Session "{stem}" is created' DLG_ALL_FILTER = 'CudaText sessions|*{}|SynWrite sessions|*{}|All files|*.*'.format(CDSESS_EXT, SWSESS_EXT) DLG_CUD_FILTER = 'CudaText sessions|*{}'.format(CDSESS_EXT) class Command: def recent(self): ''' Show list, use user select '''
def do_report(fn): lex = ed.get_prop(app.PROP_LEXER_CARET) def_json = os.path.join(apx.get_def_setting_dir(), "default.json") usr_json = os.path.join(app.app_path(app.APP_DIR_SETTINGS), "user.json") lex_json = os.path.join(app.app_path(app.APP_DIR_SETTINGS), "lexer {}.json".format(lex)) # def_opts = apx.get_app_default_opts() # pass; LOG and log('?? get_app_default_opts') # def_opts = apx.get_app_default_opts( object_pairs_hook=collections.OrderedDict) # if 'font_name' != list(def_opts.keys())[0]: # pass; apx.log('Not natural order') # return False def_opts = apx._get_file_opts(def_json, {}, object_pairs_hook=collections.OrderedDict) usr_opts = apx._get_file_opts(usr_json, {}, object_pairs_hook=collections.OrderedDict) lex_opts = apx._get_file_opts(lex_json, {}, object_pairs_hook=collections.OrderedDict) def_opts = pickle.loads(pickle.dumps(def_opts)) # clone to pop usr_opts = pickle.loads(pickle.dumps(usr_opts)) # clone to pop lex_opts = pickle.loads(pickle.dumps(lex_opts)) # clone to pop fil_opts = get_ovrd_ed_opts(ed) cmt_opts = {} # Find Commentary for def opts in def file # Rely: _commentary_ is some (0+) lines between opt-line and prev opt-line def_body = open(def_json).read() def_body = def_body.replace("\r\n", "\n").replace("\r", "\n") def_body = def_body[def_body.find("{") + 1 :] # Cut head with start '{' def_body = def_body.lstrip() for opt in def_opts.keys(): pos_opt = def_body.find('"{}"'.format(opt)) cmt = def_body[:pos_opt].strip() cmt = re.sub("^\s*//", "", cmt, flags=re.M) cmt = cmt.strip() cmt_opts[opt] = html.escape(cmt) def_body = def_body[def_body.find("\n", pos_opt) + 1 :] # Cut the opt with open(fn, "w", encoding="utf8") as f: f.write(RPT_HEAD) f.write("<h4>Hign priority: editor options</h4>") f.write("<table>\n") f.write("<tr>\n") f.write("<th>Option name</th>\n") f.write("<th>Value in<br>default</th>\n") f.write("<th>Value in<br>user</th>\n") f.write("<th>Value in<br>lexer<br>{}</th>\n".format(lex)) f.write( '<th title="{}">Value in<br>file<br>{}</th>\n'.format( ed.get_filename(), os.path.basename(ed.get_filename()) ) ) f.write("<th>Comment</th>\n") f.write("</tr>\n") for opt in fil_opts.keys(): winner = "def" winner = "usr" if opt in usr_opts else winner winner = "lex" if opt in lex_opts else winner winner = "fil" if opt in fil_opts else winner f.write("<tr>\n") f.write("<td>{}</td>\n".format(opt)) f.write('<td class="{}">{}</td>\n'.format("win" if winner == "def" else "nxt", def_opts.get(opt, ""))) f.write('<td class="{}">{}</td>\n'.format("win" if winner == "usr" else "nxt", usr_opts.get(opt, ""))) f.write('<td class="{}">{}</td>\n'.format("win" if winner == "lex" else "nxt", lex_opts.get(opt, ""))) f.write('<td class="{}">{}</td>\n'.format("win" if winner == "fil" else "nxt", fil_opts.get(opt, ""))) f.write("<td><pre>{}</pre></td>\n".format(cmt_opts.get(opt, ""))) f.write("</tr>\n") def_opts.pop(opt, None) usr_opts.pop(opt, None) lex_opts.pop(opt, None) f.write("</table><br/>\n") f.write("<h4>Overridden default options</h4>") f.write("<table>\n") f.write("<tr>\n") f.write("<th>Option name</th>\n") f.write("<th>Value in<br>default</th>\n") f.write("<th>Value in<br>user</th>\n") f.write("<th>Value in<br>lexer<br>{}</th>\n".format(lex)) f.write("<th>Comment</th>\n") f.write("</tr>\n") for opt in def_opts.keys(): winner = "def" winner = "usr" if opt in usr_opts else winner winner = "lex" if opt in lex_opts else winner winner = "fil" if opt in fil_opts else winner f.write("<tr>\n") f.write("<td>{}</td>\n".format(opt)) f.write('<td class="{}">{}</td>\n'.format("win" if winner == "def" else "nxt", def_opts.get(opt, ""))) f.write('<td class="{}">{}</td>\n'.format("win" if winner == "usr" else "nxt", usr_opts.get(opt, ""))) f.write('<td class="{}">{}</td>\n'.format("win" if winner == "lex" else "nxt", lex_opts.get(opt, ""))) f.write("<td><pre>{}</pre></td>\n".format(cmt_opts.get(opt, ""))) f.write("</tr>\n") usr_opts.pop(opt, None) lex_opts.pop(opt, None) f.write("</table><br/>\n") f.write("<h4>Overridden user-only options</h4>") f.write("<table>\n") f.write("<tr>\n") f.write("<th>Option name</th>\n") f.write("<th>Value in<br>user</th>\n") f.write("<th>Value in<br>lexer<br>{}</th>\n".format(lex)) f.write("<th>Comment</th>\n") f.write("</tr>\n") for opt in usr_opts.keys(): winner = "usr" winner = "lex" if opt in lex_opts else winner f.write("<tr>\n") f.write("<td>{}</td>\n".format(opt)) f.write('<td class="{}">{}</td>\n'.format("win" if winner == "usr" else "nxt", usr_opts.get(opt, ""))) f.write('<td class="{}">{}</td>\n'.format("win" if winner == "lex" else "nxt", lex_opts.get(opt, ""))) f.write("<td><pre>{}</pre></td>\n".format(cmt_opts.get(opt, ""))) f.write("</tr>\n") lex_opts.pop(opt, None) for opt in lex_opts.keys(): winner = "lex" f.write("<tr>\n") f.write("<td>{}</td>\n".format(opt)) f.write('<td class="{}"></td> \n'.format("non")) f.write('<td class="{}">{}</td>\n'.format("win", lex_opts.get(opt, ""))) f.write("<td><pre>{}</pre></td>\n".format(cmt_opts.get(opt, ""))) f.write("</tr>\n") lex_opts.pop(opt, None) f.write("</table><br/>\n") f.write(RPT_FOOT) return True