Example #1
0
    def match_ed(self, ed):
        """ returns: bool - is appropriate for specified Editor
            * Checks:
                'selector', 'file_patterns'
        """
        fn = ed.get_filename()
        if fn and self.file_patterns:
            if any(
                    fnmatch(name=fn, pat=pattern)
                    for pattern in self.file_patterns):
                pass
                LOG and log('build match: inbuild: file({}): {}'.format(
                    fn, self.name))
                return True

        lex = ed.get_prop(PROP_LEXER_FILE)
        if lex and self.selectors:
            lex = lex.lower()
            for sel in self.selectors:
                if lex == sel:
                    pass
                    LOG and log('build match: inbuild: lex: {}'.format(sel))
                    return True

        return False
Example #2
0
    def _get_ed_build(self, ed):
        filepath = ed.get_filename()
        if not filepath:
            return

        # custom file-type association
        ext_masks = list(EXTMAP)
        ext_masks.sort(key=lambda s: len(s),
                       reverse=True)  # from most specific
        bnames = (EXTMAP[mask] for mask in ext_masks
                  if fnmatch(filepath, mask))  # matching build-names
        # might be associated to missing build.. search
        build = get_first((self._getbuild(bname) for bname in bnames),
                          notnone=True)
        if build:
            pass
            LOG and log('build match: ext: {}'.format(build.name))
            return build

        # custom lexer association
        edlex = ed.get_prop(PROP_LEXER_FILE)
        if edlex and edlex in LEXMAP:
            build = self._getbuild(LEXMAP[edlex])
            if build:
                pass
                LOG and log('build match: lex: {}'.format(edlex))
                return build

        # sublime selectors
        for b in self.builds:
            if b.match_ed(ed):
                return b
Example #3
0
 def on_macro(self, ed_self, mcr_record):
     ''' Finish for macro-recording.
         Params
             mcr_record   "\n"-separated list of
                             number
                             number,string
                             py:string_module,string_method,string_param
     '''
     pass;                   LOG and log('mcr_record={}',mcr_record)
     if ''==mcr_record:   return app.msg_status('Empty record')
     def_nm      = ''
     nms     = [mcr['nm'] for mcr in self.macros]
     for num in range(1,1000):
         def_nm  = 'Macro{}'.format(num)
         if def_nm not in nms:
             break #for num
     while True:
         mcr_nm      = app.dlg_input('Macro name. Tricks: "!NM" overwrite NM, "=NM" show NM in dialog', def_nm)
         if mcr_nm is None:   return
         mcr_nm      = mcr_nm.strip()
         if ''==mcr_nm:  continue #while
         if mcr_nm[0]=='=':
             self.need_dlg = True
             mcr_nm  = mcr_nm[1:]
         use_old     = False
         if ''==mcr_nm:  continue #while
         if mcr_nm[0]=='!':
             use_old = True
             mcr_nm  = mcr_nm[1:]
         if ''!=mcr_nm:  break #while
     pass;                   LOG and log('self.need_dlg, use_old, mcr_nm={}',(self.need_dlg, use_old, mcr_nm))
     
     if use_old and mcr_nm in nms:
         mcr_ind     = nms.index(mcr_nm)
         self.macros[mcr_ind]['rec'] = mcr_record
         self.macros[mcr_ind]['evl'] = self._record_data_to_cmds(mcr_record)
         id4mcr      = self.macros[mcr_ind]['id']
     else:
         while mcr_nm in nms:
             app.msg_box('Select other name.\nMacros names now:\n\n'+'\n'.join(nms), app.MB_OK)
             mcr_nm  = app.dlg_input('Macro name', mcr_nm)
             if mcr_nm is None:   return
     
         id4mcr      = random.randint(10000, 99999)
         while id4mcr in self.mcr4id:
             id4mcr  = random.randint(10000, 99999)
         self.macros += [{'id' :id4mcr       ##?? conflicts?
                         ,'nm' :mcr_nm
                         ,'rec':mcr_record
                         ,'evl':self._record_data_to_cmds(mcr_record)
                         }]
     self._do_acts()
     
     if self.need_dlg:
         self.need_dlg   = False
         self.last_mcr_id= id4mcr
         self.dlg_config()
Example #4
0
    def _record_data_to_cmds(self, rec_data):
        ''' Coverting from record data to list of API command
            Param
                rec_data    "\n"-separated list of
                                number
                                number,string
                                py:string_module,string_method,string_param
        '''
        # Native converting
        evls    = []
        rcs     = rec_data.splitlines()
        for rc in rcs:
            if False:pass
            elif rc[0] in '0123456789':
                if rc in self.CMD_ID2NM:
                    # For ed.cmd(id)
                    evls += ['ed.cmd(cmds.{})'.format(self.CMD_ID2NM[rc])]
                    continue #for rc
                if ',' in rc:
                    (id_cmd
                    ,tx_cmd)= rc[0:rc.index(',')], rc[1+rc.index(','):]
                    if ''==id_cmd.strip('0123456789') and id_cmd in self.CMD_ID2NM:
                        # For ed.cmd(id, text)
                        evls += ["ed.cmd(cmds.{},{})".format(self.CMD_ID2NM[id_cmd], repr(tx_cmd))]
                        continue #for rc
            elif rc.startswith('py:cuda_macros,'):
                # Skip macro-tools
                continue #for rc
            elif rc[0:3]=='py:':
                # Plugin cmd
                evls += ["app.app_proc(app.PROC_EXEC_PLUGIN, '{}')".format(rc[3:])]
                continue #for rc
            pass;               LOG and log('unknown rec-item: {}',rc)
        
#       return evls
        
        # Optimization
        # (1) ed.cmd(cmds.cCommand_TextInsert,'A')
        #     ed.cmd(cmds.cCommand_TextInsert,'B')
        # convert to
        #     ed.cmd(cmds.cCommand_TextInsert,'AB')
        has_TI          = 1<len([evl for evl in evls 
                      if                        'cmds.cCommand_TextInsert,' in evl])
        if has_TI:
            reTI2       = re.compile(  r"ed.cmd\(cmds.cCommand_TextInsert,'(.+)'\)"
                                    +   C1
                                    +  r"ed.cmd\(cmds.cCommand_TextInsert,'(.+)'\)")
            evls_c1     = C1.join(evls)
            (evls_c1
            ,rpls)      = reTI2.subn(  r"ed.cmd(cmds.cCommand_TextInsert,'\1\2')", evls_c1)
            while 0 < rpls:
                (evls_c1
                ,rpls)  = reTI2.subn(  r"ed.cmd(cmds.cCommand_TextInsert,'\1\2')", evls_c1)
            evls        = evls_c1.split(C1)
           #if has_TI
        pass;                   LOG and log('evls={}',evls)
        return evls
Example #5
0
    def run_cmd(self, cmdname):
        import subprocess

        proj_err = [False]

        cmdj = self._get_cmd(cmdname)
        cmdj = self._expand_cmd(cmdj, proj_err=proj_err)

        env = {**os.environ}

        cmd = cmdj.get('shell_cmd') or cmdj.get('cmd')
        is_shell = cmdj['shell'] if 'shell' in cmdj else 'shell_cmd' in cmdj
        cwd = cmdj.get('working_dir')
        file_regex = cmdj.get('file_regex')
        env.update(cmdj.get('env', {}))  # add to environ instead of replacing
        path = cmdj.get('path') or cmdj.get("PATH")

        if path:
            curpath = env.get('PATH', '')
            path = expandvars(path, mp={'$PATH': curpath, '$path': curpath})
            env['PATH'] = path

        set_output_regex(file_regex)

        pass
        LOG and log('?? Popen cmd={}', cmd)
        try:
            cmd_str = ' '.join(cmd) if type(cmd) == list else cmd
            msg_status(_('Running: "{}"').format(cmd_str))
            popen = subprocess.Popen(
                cmd,
                stdout=subprocess.PIPE,
                stderr=subprocess.STDOUT,
                shell=is_shell,
                env=env,
                cwd=cwd,
            )
        except Exception as ex:
            msg_box('{}: {}'.format(type(ex).__name__, ex), MB_ICONWARNING)
            pass
            LOG and log('fail Popen', )
            return
        if popen is None:
            pass
            LOG and log('fail Popen', )
            msg_status(_('Fail running: {}').format(cmd))
            return
        pass
        LOG and log('ok Popen', )

        app_log(LOG_CLEAR, '', panel=LOG_PANEL_OUTPUT)

        notif = None
        if proj_err[0]:
            notif = _('Note: build-system is expecting a Project to be opened')

        return popen, cmdj, notif
Example #6
0
    def dlg_export(self):
        ''' Show dlg for export some macros.
        '''
        if app.app_api_version()<FROM_API_VERSION:  return app.msg_status(_('Need update CudaText'))
        if 0==len(self.macros):                     return app.msg_status(_('No macros for export'))
        exp_file= app.dlg_file(False, '', '', 'Cuda macros|*.cuda-macros')
        exp_file= '' if exp_file is None else exp_file
        exp_file= exp_file+('' if ''==exp_file or exp_file.endswith('.cuda-macros') else '.cuda-macros')
        (WD_LST
        ,HT_LST)= (500
                  ,500)
        
        lmcrs   = len(self.macros)
        crt,sels= '0', ['0'] * lmcrs
        while True:
            pass;               LOG and log('sels={}',sels)

            cnts    = ([
  dict(              tp='lb'    ,tid='file'         ,l=GAP             ,w=70            ,cap=_('Export &to')                    )
 ,dict(cid='file'   ,tp='ed'    ,t=GAP              ,l=GAP+70          ,r=GAP+WD_LST-35 ,en='0'                                 )
 ,dict(cid='brow'   ,tp='bt'    ,tid='file'         ,l=GAP+HT_LST-35   ,r=GAP+WD_LST    ,cap=_('&...')                          )
 ,dict(cid='mcrs'   ,tp='ch-lbx',t=35   ,h=HT_LST   ,l=GAP             ,w=    WD_LST    ,items=[mcr['nm'] for mcr in self.macros])
 ,dict(cid='ch-a'   ,tp='bt'    ,t=GAP+35+HT_LST    ,l=GAP*1           ,w=100           ,cap=_('Check &all')                    )
 ,dict(cid='ch-n'   ,tp='bt'    ,t=GAP+35+HT_LST    ,l=GAP*2+100       ,w=100           ,cap=_('U&ncheck all')                  )
 ,dict(cid='expo'   ,tp='bt'    ,t=GAP+35+HT_LST    ,l=    WD_LST-70*2 ,w=70            ,cap=_('&Export')       ,props='1'      )   # default
 ,dict(cid='-'      ,tp='bt'    ,t=GAP+35+HT_LST    ,l=GAP+WD_LST-70*1 ,w=70            ,cap=_('Close')                         )
                    ])
            vals    = dict( file=exp_file
                           ,mcrs=(crt, sels)
                        )
            btn,    \
            vals,   \
            chds    = dlg_wrapper(_('Export macros')   ,GAP+WD_LST+GAP, GAP*5+HT_LST+25*2-GAP, cnts, vals, focus_cid='mrcs')
            if btn is None or btn=='-': return
            crt,sels= vals['mcrs']
            pass;               LOG and log('sels={}',sels)
            if False:pass
            elif btn=='brow': #ans_s=='file':
                new_exp_file= app.dlg_file(False, '', '', 'Cuda macros|*.cuda-macros')
                if new_exp_file is not None:
                    exp_file    = new_exp_file
                    exp_file    = exp_file+('' if ''==exp_file or exp_file.endswith('.cuda-macros') else '.cuda-macros')
            elif btn=='ch-a': #ans_s=='all':
                sels    = ['1'] * lmcrs
            elif btn=='ch-n': #ans_s=='no':
                sels    = ['0'] * lmcrs
            elif btn=='expo': #ans_s=='exp':
                if '1' not in sels:
                    app.msg_box(_('Select some names'), app.MB_OK)
                    continue
                self.export_to_file(exp_file, [mcr for (ind, mcr) in enumerate(self.macros) if sels[ind]=='1'])
                return
Example #7
0
    def _stop(self):
        pass
        LOG and log('* Finished Building')

        timer_proc(TIMER_STOP, self._on_timer, 0)

        self.readthread.m_stop()
Example #8
0
 def replace_all_sel_to_cb(self):
     pass;                   LOG and log('ok',)
     pass;                   return
     crts    = ed.get_carets()
     if len(crts)>1:
         return app.msg_status(ONLY_SINGLE_CRT.format('Command'))
     (cCrt, rCrt, cEnd, rEnd)    = crts[0]
Example #9
0
    def __init__(self):
        cmd_nms = [
            nm for nm in dir(cmds)
            if nm.startswith('cCommand_') or nm.startswith('cmd_')
        ]
        cmd_nm2id = {nm: eval('cmds.{}'.format(nm)) for nm in cmd_nms}
        self.CMD_ID2NM = {str(cmd_id): nm for nm, cmd_id in cmd_nm2id.items()}
        if len(self.CMD_ID2NM) < len(cmd_nm2id):
            app.msg_status('Repeated values in cudatext_cmd.py')
        pass
        #LOG and log('cmd_nm2id={}',cmd_nm2id)
        pass
        #LOG and log('CMD_ID2NM={}',self.CMD_ID2NM)

        ver_macros = apx._json_loads(
            open(MACROS_JSON).read()) if os.path.exists(MACROS_JSON) else {
                'ver': JSON_FORMAT_VER,
                'list': []
            }
        if ver_macros['ver'] < JSON_FORMAT_VER:
            # Adapt to new format
            pass
        self.tm_ctrl = ver_macros.get('tm_ctrl', {})
        self.dlg_prs = ver_macros.get('dlg_prs', {})
        self.macros = ver_macros['list']
        self.mcr4id = {str(mcr['id']): mcr for mcr in self.macros}

        self.need_dlg = False
        self.last_mcr_id = 0

        pass
        LOG and log('\n\n\nMacros start', )
Example #10
0
    def build(self, name=MAIN_CMD_NAME):
        pass
        LOG and log('.build({})'.format(name))

        if not ed.get_filename():
            msg_status(_('Save document to disk before building'))
            return

        b = self._get_ed_build(ed)
        if not b:
            lex = ed.get_prop(PROP_LEXER_FILE)
            if lex:
                msg = _('No build-system(s) found for lexer ') + lex
            else:
                msg = _('No build-system(s) found for file '
                        ) + os.path.basename(ed.get_filename())
            msg_status(msg)
            return

        if name is None:
            cmd_names = b.list_commands()
            ind = dlg_menu(DMENU_LIST, cmd_names, caption=_('Build with...'))
            if ind is None:
                return
            name = cmd_names[ind]

        self._run_build_cmd(b, name)
Example #11
0
    def dlg_import(self):
        ''' Show dlg for import some macros.
        '''
        if app.app_api_version()<FROM_API_VERSION:  return app.msg_status(_('Need update CudaText'))
        (imp_file
        ,mcrs)  = self.dlg_import_choose_mcrs()
        if imp_file is None:    return
        lmcrs   = len(mcrs)
        
        WD_LST, \
        HT_LST  = (500
                  ,500)
        crt,sels= '0', ['1'] * lmcrs
        while True:

            cnts    = ([
  dict(              tp='lb'    ,tid='file'         ,l=GAP             ,w=85            ,cap=_('Import &from')              )
 ,dict(cid='file'   ,tp='ed'    ,t=GAP              ,l=GAP+85          ,r=GAP+WD_LST-35 ,en='0'                             )
 ,dict(cid='brow'   ,tp='bt'    ,tid='file'         ,l=GAP+HT_LST-35   ,r=GAP+WD_LST    ,cap=_('&...')                      )
 ,dict(cid='mcrs'   ,tp='ch-lbx',t=35  ,h=HT_LST    ,l=GAP             ,w=    WD_LST    ,items=[mcr['nm'] for mcr in mcrs]  )
 ,dict(cid='ch-a'   ,tp='bt'    ,t=GAP+35+HT_LST    ,l=GAP*1           ,w=100           ,cap=_('Check &all')                )
 ,dict(cid='ch-n'   ,tp='bt'    ,t=GAP+35+HT_LST    ,l=GAP*2+100       ,w=100           ,cap=_('U&ncheck all')              )
 ,dict(cid='impo'   ,tp='bt'    ,t=GAP+35+HT_LST    ,l=    WD_LST-70*2 ,w=70            ,cap=_('&Import')       ,props='1'  )   # default
 ,dict(cid='-'      ,tp='bt'    ,t=GAP+35+HT_LST    ,l=GAP+WD_LST-70*1 ,w=70            ,cap=_('Close')                     )
                    ])
            vals    = dict( file=imp_file
                           ,mcrs=(crt, sels)
                        )
            btn,    \
            vals,   \
            chds    = dlg_wrapper(_('Import macros'), GAP+WD_LST+GAP, GAP*4+HT_LST+25*2, cnts, vals, focus_cid='mrcs')
            if btn is None or btn=='-': return
            crt,sels= vals['mcrs']
            pass;               LOG and log('sels={}',sels)
            if False:pass
            elif btn=='brow': #ans_s=='file':
                (new_imp_file
                ,new_mcrs)  = self.dlg_import_choose_mcrs()
                if new_imp_file is None:    continue #while
                imp_file    = new_imp_file
                mcrs        = new_mcrs
                lmcrs       = len(mcrs)
                crt,sels    = '0', ['1'] * lmcrs
            elif btn=='ch-a': #ans_s=='all':
                sels    = ['1'] * lmcrs
            elif btn=='ch-n': #ans_s=='no':
                sels    = ['0'] * lmcrs
            elif btn=='impo': #ans_s=='imp':
                if '1' not in sels:
                    app.msg_box(_('Select some names'), app.MB_OK)
                    continue
                (good_nms
                ,fail_nms) = self.import_from_list([mcr for (ind, mcr) in enumerate(mcrs) if sels[ind]=='1'])
                l,lt    = '\n', '\n      '
                app.msg_box(   _('Import macros:')     +lt+lt.join(good_nms)
                            +l+''
                            +l+_('Skip duplicates:')   +lt+lt.join(fail_nms)
                           ,app.MB_OK)
Example #12
0
    def cancel(self):
        if not self._is_finished and not self._is_canceled:
            pass
            LOG and log('* cancelling building: finished:{}'.format(
                self._is_finished))
            self._is_canceled = True
            self._stop()

            cancel_line = _('-- Canceled')
            self.lines.append(cancel_line)
            if self.f_can_print(self):
                output(cancel_line)
Example #13
0
 def adapt_menu(self,id_menu=0):
     ''' Add or change top-level menu Macros
         Param id_menu points to exist menu item (ie by ConfigMenu) for filling
     '''
     pass;                   LOG and log('id_menu={}',id_menu)
     PLUG_HINT   = '_'+'cuda_macros:adapt_menu'  # "_" is sign for ConfigMenu. ":" is subst for "," to avoid call "import ..."
     if id_menu!=0:
         # Use this id
         app.app_proc(app.PROC_MENU_CLEAR, str(id_menu))
     else:
         top_nms = app.app_proc(app.PROC_MENU_ENUM, 'top')
         if PLUG_HINT in top_nms:
             # Reuse id from 'top'
             inf     = [inf for inf in top_nms.splitlines() if PLUG_HINT in inf][0]     ##?? 
             id_menu = inf.split('|')[2]
             app.app_proc(app.PROC_MENU_CLEAR, id_menu)
         else:
             # Create BEFORE Plugins
             top_nms = top_nms.splitlines()
             pass;              #LOG and log('top_nms={}',top_nms)
             if app.app_exe_version() >= '1.0.131':
                 plg_ind = [i for (i,nm) in enumerate(top_nms) if '|plugins' in nm][0]
             else: # old, pre i18n
                 plg_ind = top_nms.index('&Plugins|')                                                    ##?? 
             id_menu = app.app_proc( app.PROC_MENU_ADD, '{};{};{};{}'.format('top', PLUG_HINT, _('&Macros'), plg_ind))
     # Fill
     def hotkeys_desc(cmd_id):
         hk_s= get_hotkeys_desc(cmd_id)
         hk_s= '\t\t'+hk_s if hk_s else hk_s
         return hk_s
     hk_s    = hotkeys_desc(                                    'cuda_macros,dlg_config')
     app.app_proc(app.PROC_MENU_ADD, '{};{};{}'.format(id_menu, 'cuda_macros,dlg_config',_('&Macros...')+hk_s))
     app.app_proc(app.PROC_MENU_ADD, '{};;-'.format(   id_menu))
     hk_s    = hotkeys_desc(                                    cmds.cmd_MacroStart)
     app.app_proc(app.PROC_MENU_ADD, '{};{};{}'.format(id_menu, cmds.cmd_MacroStart,     _('&Start record')+hk_s))
     hk_s    = hotkeys_desc(                                    cmds.cmd_MacroStop)
     app.app_proc(app.PROC_MENU_ADD, '{};{};{}'.format(id_menu, cmds.cmd_MacroStop,      _('St&op record')+hk_s))
     hk_s    = hotkeys_desc(                                    cmds.cmd_MacroCancel)
     app.app_proc(app.PROC_MENU_ADD, '{};{};{}'.format(id_menu, cmds.cmd_MacroCancel,    _('&Cancel record')+hk_s))
     app.app_proc(app.PROC_MENU_ADD, '{};;-'.format(   id_menu))
     hk_s    = hotkeys_desc(                                    'cuda_macros,dlg_export')
     app.app_proc(app.PROC_MENU_ADD, '{};{};{}'.format(id_menu, 'cuda_macros,dlg_export',_('&Export...')+hk_s))
     hk_s    = hotkeys_desc(                                    'cuda_macros,dlg_import')
     app.app_proc(app.PROC_MENU_ADD, '{};{};{}'.format(id_menu, 'cuda_macros,dlg_import',_('&Import...')+hk_s))
     if 0==len(self.macros): return
     app.app_proc(app.PROC_MENU_ADD, '{};;-'.format(   id_menu))
     id_sub  = app.app_proc(app.PROC_MENU_ADD, '{};{};{}'.format(id_menu, 0, _('&Run')))
     for mcr in self.macros:
         hk_s= hotkeys_desc(                                       f('cuda_macros,run,{}',mcr['id']))
         app.app_proc(app.PROC_MENU_ADD, '{};{}{};{}'.format(id_sub, 'cuda_macros,run,'  ,mcr['id'], mcr['nm']+hk_s))
Example #14
0
 def export_to_file(self, exp_file, mcrs):
     pass;                   LOG and log('exp_file, mcrs={}',(exp_file, mcrs))
     open(exp_file, 'w').write(json.dumps(
         {   'vers':{
                 'ver-mcr':JSON_FORMAT_VER
             ,   'ver-app':app.app_exe_version()
             ,   'ver-api':app.app_api_version()
             }
         ,   'macros':[{
                 'nm':   mcr['nm']
              ,  'evl':  mcr['evl']
                 } for mcr in mcrs]
         }
     ,   indent=4))
Example #15
0
 def export_to_file(self, exp_file, mcrs):
     pass
     LOG and log('exp_file, mcrs={}', (exp_file, mcrs))
     open(exp_file, 'w').write(
         json.dumps(
             {
                 'vers': {
                     'ver-mcr': JSON_FORMAT_VER,
                     'ver-app': app.app_exe_version(),
                     'ver-api': app.app_api_version()
                 },
                 'macros': [{
                     'nm': mcr['nm'],
                     'evl': mcr['evl']
                 } for mcr in mcrs]
             },
             indent=4))
Example #16
0
 def import_from_list(self, mcrs):
     pass
     LOG and log('mcrs={}', (mcrs))
     good_nms = []
     fail_nms = []
     ids = [mcr['id'] for mcr in self.macros]
     my_mcrs = [{'nm': mcr['nm'], 'evl': mcr['evl']} for mcr in self.macros]
     for mcr in mcrs:
         if mcr in my_mcrs:
             fail_nms += [mcr['nm']]
             continue  #for
         good_nms += [mcr['nm']]
         id4mcr = random.randint(10000, 99999)
         while id4mcr in ids:
             id4mcr = random.randint(10000, 99999)
         ids += [id4mcr]
         self.macros += [{'id': id4mcr, 'nm': mcr['nm'], 'evl': mcr['evl']}]
     if good_nms:
         self._do_acts()
     return (good_nms, fail_nms)
Example #17
0
 def import_from_list(self, mcrs):
     pass;                   LOG and log('mcrs={}',(mcrs))
     good_nms    = []
     fail_nms    = []
     ids         = [mcr['id'] for mcr in self.macros]
     my_mcrs     = [{'nm' :mcr['nm'],'evl':mcr['evl']} for mcr in self.macros]
     for mcr in mcrs:
         if mcr in my_mcrs:
             fail_nms += [mcr['nm']]
             continue #for
         good_nms   += [mcr['nm']]
         id4mcr      = random.randint(10000, 99999)
         while id4mcr in ids:
             id4mcr  = random.randint(10000, 99999)
         ids += [id4mcr]
         self.macros+= [{'id' :id4mcr
                        ,'nm' :mcr['nm']
                        ,'evl':mcr['evl']
                        }]
     if good_nms:
         self._do_acts()
     return (good_nms, fail_nms)
Example #18
0
    def run(self, mcr_id, times=1, waits=0, while_chngs=False, till_endln=False):
        ''' Main (and single) way to run any macro
        '''
        pass;                   LOG and log('mcr_id, times, waits, while_chngs, till_endln={}',(mcr_id, times, waits, while_chngs, till_endln))
        mcr     = self.mcr4id.get(str(mcr_id))
        if mcr is None:
            pass;               LOG and log('no id',)
            return app.msg_status(_('No macros: {}').format(mcr_id))
        cmds4eval   = ';'.join(mcr['evl'])
        pass;                   LOG and log('nm, cmds4eval={}',(mcr['nm'], cmds4eval))
        how_t       = 'wait'
        rp_ctrl     = self.tm_ctrl.get('rp_ctrl', 1000)                     # testing one of 1000 execution
        tm_wait     = waits if waits>0 else self.tm_ctrl.get('tm_wait', 10) # sec
        start_t     = datetime.datetime.now()
        pre_body    = '' if not while_chngs else ed.get_text_all()
        for rp in range(times if times>0 else 0xffffffff):
            exec(cmds4eval)
            if till_endln and ed.get_carets()[0][1] == ed.get_line_count()-1:
                pass;           LOG and log('break endln',)
                break   #for rp
            if while_chngs:
                new_body    = ed.get_text_all()
                if pre_body == new_body:    
                    pass;       LOG and log('break no change',)
                    break   #for rp
                pre_body    = new_body
            if  (how_t=='wait'
            and (rp_ctrl-1) == rp % rp_ctrl
            and tm_wait < (datetime.datetime.now()-start_t).seconds):
                cnts    = ([
  dict(              tp='lb'    ,t=GAP          ,l=GAP  ,w=400   ,cap=_('Macro "{}" playback time is too long'.format(mcr['nm'])))
 ,dict(cid='wait'   ,tp='bt'    ,t=GAP*2+25*1   ,l=GAP  ,w=400   ,cap=_('Wait &another {} sec').format(tm_wait)  ,props='1'      )   # default
 ,dict(cid='cont'   ,tp='bt'    ,t=GAP*3+25*2   ,l=GAP  ,w=400   ,cap=_('Continue &without control')                             )
 ,dict(cid='stop'   ,tp='bt'    ,t=GAP*6+25*3   ,l=GAP  ,w=300   ,cap=_('&Cancel playback [ESC]')                                )
                        ])
                btn,vals,chds= dlg_wrapper(_('Playback macro'), GAP*2+400, GAP*7+4*25, cnts, {})
                if btn is None or btn=='stop':
                    pass;       LOG and log('break by user',)
                    app.msg_status(_('Cancel playback macro: {}'.format(mcr['nm'])))
                    break   #for rp
                if btn=='cont': #ans=='cont':
                    how_t   = 'work'
                if btn=='wait': #ans=='wait':
                    start_t = datetime.datetime.now()
           #for rp
        self.last_mcr_id = mcr_id
Example #19
0
 def __init__(self):
     cmd_nms         = [nm                               for nm in dir(cmds) 
                         if nm.startswith('cCommand_') or nm.startswith('cmd_')]
     cmd_nm2id       = {nm:eval('cmds.{}'.format(nm))    for nm in cmd_nms}
     self.CMD_ID2NM  = {str(cmd_id):nm                   for nm,cmd_id in cmd_nm2id.items()}
     if len(self.CMD_ID2NM) < len(cmd_nm2id):
         app.msg_status('Repeated values in cudatext_cmd.py')
     pass;                  #LOG and log('cmd_nm2id={}',cmd_nm2id)
     pass;                  #LOG and log('CMD_ID2NM={}',self.CMD_ID2NM)
     
     ver_macros      = apx._json_loads(open(MACROS_JSON).read()) if os.path.exists(MACROS_JSON) else {'ver':JSON_FORMAT_VER, 'list':[]}
     if ver_macros['ver'] < JSON_FORMAT_VER:
         # Adapt to new format
         pass
     self.tm_ctrl    = ver_macros.get('tm_ctrl', {})
     self.dlg_prs    = ver_macros.get('dlg_prs', {})
     self.macros     = ver_macros['list']
     self.mcr4id     = {str(mcr['id']):mcr for mcr in self.macros}
     
     self.need_dlg   = False
     self.last_mcr_id= 0
     
     pass;                   LOG and log('\n\n\nMacros start',)
Example #20
0
    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)
Example #21
0
 def run(self, mcr_id, times=1, waits=0, while_chngs=False, till_endln=False):
     ''' Main (and single) way to run any macro
     '''
     pass;                   LOG and log('mcr_id, times, waits, while_chngs, till_endln={}',(mcr_id, times, waits, while_chngs, till_endln))
     mcr     = self.mcr4id.get(str(mcr_id))
     if mcr is None:
         pass;               LOG and log('no id',)
         return app.msg_status('No macros: {}'.format(mcr_id))
     cmds4eval   = ';'.join(mcr['evl'])
     pass;                   LOG and log('nm, cmds4eval={}',(mcr['nm'], cmds4eval))
     how_t       = 'wait'
     rp_ctrl     = self.tm_ctrl.get('rp_ctrl', 1000)                     # testing one of 1000 execution
     tm_wait     = waits if waits>0 else self.tm_ctrl.get('tm_wait', 10) # sec
     start_t     = datetime.datetime.now()
     pre_body    = '' if not while_chngs else ed.get_text_all()
     for rp in range(times if times>0 else 0xffffffff):
         exec(cmds4eval)
         if till_endln and ed.get_carets()[0][1] == ed.get_line_count()-1:
             pass;           LOG and log('break endln',)
             break   #for rp
         if while_chngs:
             new_body    = ed.get_text_all()
             if pre_body == new_body:    
                 pass;       LOG and log('break no change',)
                 break   #for rp
             pre_body    = new_body
         if  (how_t=='wait'
         and (rp_ctrl-1) == rp % rp_ctrl
         and tm_wait < (datetime.datetime.now()-start_t).seconds):
             WD_BTN  = 220
             ans = app.dlg_custom(  'Playback macro', GAP*2+WD_BTN, GAP*7+4*25,  '\n'.join([]
                 +[C1.join(['type=label'     ,POS_FMT(l=GAP,  t=GAP*1+25*0+3,   r=GAP+WD_BTN, b=0)
                           ,'cap=Macro playback time is too long'
                           ] # i=0
                  )]
                 +[C1.join(['type=button'    ,POS_FMT(l=GAP,  t=GAP*2+25*1,    r=GAP+WD_BTN, b=0)
                           ,'cap=Wait &another {} sec'.format(tm_wait)
                           ] # i=1
                  )]
                 +[C1.join(['type=button'    ,POS_FMT(l=GAP,  t=GAP*3+25*2,    r=GAP+WD_BTN, b=0)
                           ,'cap=Continue &without control'
                           ] # i=2
                  )]
                 +[C1.join(['type=button'    ,POS_FMT(l=GAP,  t=GAP*6+25*3,    r=GAP+WD_BTN, b=0)
                           ,'cap=&Cancel playback [ESC]'
                           ] # i=3
                  )]
                 ), 1)    # start focus
             pass;          #LOG and log('ans={}',ans)
             ans     =('break'   if ans is None  else
                       'break'   if ans[0]==3    else
                       'wait'    if ans[0]==1    else
                       'cont'    if ans[0]==2    else 'break')
             if ans=='cont':
                 how_t   = 'work'
             if ans=='wait':
                 start_t = datetime.datetime.now()
             if ans=='break':
                 pass;       LOG and log('break by user',)
                 break   #for rp
        #for rp
     self.last_mcr_id = mcr_id
Example #22
0
    def _record_data_to_cmds(self, rec_data):
        ''' Coverting from record data to list of API command
            Param
                rec_data    "\n"-separated list of
                                number
                                number,string
                                py:string_module,string_method,string_param
        '''
        # Native converting
        evls = []
        rcs = rec_data.splitlines()
        for rc in rcs:
            if False: pass
            elif rc[0] in '0123456789':
                if rc in self.CMD_ID2NM:
                    # For ed.cmd(id)
                    evls += ['ed.cmd(cmds.{})'.format(self.CMD_ID2NM[rc])]
                    continue  #for rc
                if ',' in rc:
                    (id_cmd,
                     tx_cmd) = rc[0:rc.index(',')], rc[1 + rc.index(','):]
                    if '' == id_cmd.strip(
                            '0123456789') and id_cmd in self.CMD_ID2NM:
                        # For ed.cmd(id, text)
                        evls += [
                            "ed.cmd(cmds.{},{})".format(
                                self.CMD_ID2NM[id_cmd], repr(tx_cmd))
                        ]
                        continue  #for rc
            elif rc.startswith('py:cuda_macros,'):
                # Skip macro-tools
                continue  #for rc
            elif rc[0:3] == 'py:':
                # Plugin cmd
                evls += [
                    "app.app_proc(app.PROC_EXEC_PLUGIN, '{}')".format(rc[3:])
                ]
                continue  #for rc
            pass
            LOG and log('unknown rec-item: {}', rc)

#       return evls

# Optimization
# (1) ed.cmd(cmds.cCommand_TextInsert,'A')
#     ed.cmd(cmds.cCommand_TextInsert,'B')
# convert to
#     ed.cmd(cmds.cCommand_TextInsert,'AB')
        has_TI = 1 < len(
            [evl for evl in evls if 'cmds.cCommand_TextInsert,' in evl])
        if has_TI:
            reTI2 = re.compile(r"ed.cmd\(cmds.cCommand_TextInsert,'(.+)'\)" +
                               C1 +
                               r"ed.cmd\(cmds.cCommand_TextInsert,'(.+)'\)")
            evls_c1 = C1.join(evls)
            (evls_c1,
             rpls) = reTI2.subn(r"ed.cmd(cmds.cCommand_TextInsert,'\1\2')",
                                evls_c1)
            while 0 < rpls:
                (evls_c1,
                 rpls) = reTI2.subn(r"ed.cmd(cmds.cCommand_TextInsert,'\1\2')",
                                    evls_c1)
            evls = evls_c1.split(C1)
        #if has_TI
        pass
        LOG and log('evls={}', evls)
        return evls
Example #23
0
 def run(self,
         mcr_id,
         times=1,
         waits=0,
         while_chngs=False,
         till_endln=False):
     ''' Main (and single) way to run any macro
     '''
     pass
     LOG and log('mcr_id, times, waits, while_chngs, till_endln={}',
                 (mcr_id, times, waits, while_chngs, till_endln))
     mcr = self.mcr4id.get(str(mcr_id))
     if mcr is None:
         pass
         LOG and log('no id', )
         return app.msg_status('No macros: {}'.format(mcr_id))
     cmds4eval = ';'.join(mcr['evl'])
     pass
     LOG and log('nm, cmds4eval={}', (mcr['nm'], cmds4eval))
     how_t = 'wait'
     rp_ctrl = self.tm_ctrl.get('rp_ctrl',
                                1000)  # testing one of 1000 execution
     tm_wait = waits if waits > 0 else self.tm_ctrl.get('tm_wait',
                                                        10)  # sec
     start_t = datetime.datetime.now()
     pre_body = '' if not while_chngs else ed.get_text_all()
     for rp in range(times if times > 0 else 0xffffffff):
         exec(cmds4eval)
         if till_endln and ed.get_carets()[0][1] == ed.get_line_count() - 1:
             pass
             LOG and log('break endln', )
             break  #for rp
         if while_chngs:
             new_body = ed.get_text_all()
             if pre_body == new_body:
                 pass
                 LOG and log('break no change', )
                 break  #for rp
             pre_body = new_body
         if (how_t == 'wait' and (rp_ctrl - 1) == rp % rp_ctrl and tm_wait <
             (datetime.datetime.now() - start_t).seconds):
             WD_BTN = 220
             ans = app.dlg_custom(
                 'Playback macro',
                 GAP * 2 + WD_BTN,
                 GAP * 7 + 4 * 25,
                 '\n'.join([] + [
                     C1.join([
                         'type=label',
                         POS_FMT(l=GAP,
                                 t=GAP * 1 + 25 * 0 + 3,
                                 r=GAP + WD_BTN,
                                 b=0), 'cap=Macro playback time is too long'
                     ]  # i=0
                             )
                 ] + [
                     C1.join([
                         'type=button',
                         POS_FMT(
                             l=GAP, t=GAP * 2 + 25 * 1, r=GAP + WD_BTN, b=0
                         ), 'cap=Wait &another {} sec'.format(tm_wait)
                     ]  # i=1
                             )
                 ] + [
                     C1.join([
                         'type=button',
                         POS_FMT(
                             l=GAP, t=GAP * 3 + 25 * 2, r=GAP +
                             WD_BTN, b=0), 'cap=Continue &without control'
                     ]  # i=2
                             )
                 ] + [
                     C1.join([
                         'type=button',
                         POS_FMT(
                             l=GAP, t=GAP * 6 + 25 * 3, r=GAP +
                             WD_BTN, b=0), 'cap=&Cancel playback [ESC]'
                     ]  # i=3
                             )
                 ]),
                 1)  # start focus
             pass
             #LOG and log('ans={}',ans)
             ans = ('break'
                    if ans is None else 'break' if ans[0] == 3 else 'wait'
                    if ans[0] == 1 else 'cont' if ans[0] == 2 else 'break')
             if ans == 'cont':
                 how_t = 'work'
             if ans == 'wait':
                 start_t = datetime.datetime.now()
             if ans == 'break':
                 pass
                 LOG and log('break by user', )
                 break  #for rp
     #for rp
     self.last_mcr_id = mcr_id
Example #24
0
 def dlg_import(self):
     ''' Show dlg for import some macros.
     '''
     if app.app_api_version()<FROM_API_VERSION:  return app.msg_status('Need update CudaText')
     (imp_file
     ,mcrs)  = self.dlg_import_choose_mcrs()
     if imp_file is None:    return
     lmcrs   = len(mcrs)
     
     GAP     = 5
     (WD_LST
     ,HT_LST)= (500
               ,500)
     crt,sels= '0', ['1'] * lmcrs
     while True:
         ans = app.dlg_custom('Import macros'   ,GAP+WD_LST+GAP, GAP*5+HT_LST+25*2, '\n'.join([]
         +[C1.join(['type=label'         ,POS_FMT(l=GAP,             t=GAP+3,            r=GAP+85,     b=0)
                   ,'cap=Import &from'
                   ] # i=0
          )]
         +[C1.join(['type=edit'         ,POS_FMT(l=GAP+85,           t=GAP,              r=GAP+WD_LST-35,b=0)
                   ,'val={}'.format(imp_file)
                   ] # i=1
          )]
         +[C1.join(['type=button'        ,POS_FMT(l=GAP+HT_LST-35,   t=GAP-2,            r=GAP+WD_LST,   b=0)
                   ,'cap=&...'
                   ] # i=2
          )]
         +[C1.join(['type=checklistbox' ,POS_FMT(l=GAP,             t=GAP*2+30,          r=GAP+WD_LST,   b=GAP+25+HT_LST)
                   ,'items=' +'\t'.join([mcr['nm'] for mcr in mcrs])
                   ,'val='   + crt+';'+','.join(sels)
                   ] # i=3
          )]
         +[C1.join(['type=button'        ,POS_FMT(l=GAP*1,           t=GAP*3+25+HT_LST,  r=GAP*1+80*1,   b=0)
                   ,'cap=Check &all'
                   ] # i=4
          )]
         +[C1.join(['type=button'        ,POS_FMT(l=GAP*2+80,        t=GAP*3+25+HT_LST,  r=GAP*2+80*2,   b=0)
                   ,'cap=U&ncheck all'
                   ] # i=5
          )]
         +[C1.join(['type=button'        ,POS_FMT(l=    WD_LST-60*2, t=GAP*3+25+HT_LST,  r=    WD_LST-60*1,   b=0)
                   ,'cap=&Import'
                   ] # i=6
          )]
         +[C1.join(['type=button'        ,POS_FMT(l=GAP+WD_LST-60*1, t=GAP*3+25+HT_LST,  r=GAP+WD_LST-60*0,   b=0)
                   ,'cap=&Close'
                   ] # i=7
          )]
         ), 3)    # start focus
         pass;               LOG and log('ans={}',ans)
         if ans is None:  break #while
         (ans_i
         ,vals)  = ans
         ans_s   = apx.icase(False,''
                    ,ans_i==2, 'file'
                    ,ans_i==4, 'all'
                    ,ans_i==5, 'no'
                    ,ans_i==6, 'imp'
                    ,ans_i==7, 'close'
                    )
         if ans_s=='close':  break #while
         v_3     = vals.splitlines()[3]
         crt,sels= v_3.split(';')
         sels    = sels.strip(',').split(',')
         pass;               LOG and log('sels={}',sels)
         if False:pass
         elif ans_s=='file':
             (new_imp_file
             ,new_mcrs)  = self.dlg_import_choose_mcrs()
             if new_imp_file is None:    continue #while
             imp_file    = new_imp_file
             mcrs        = new_mcrs
             lmcrs       = len(mcrs)
             crt,sels    = '0', ['1'] * lmcrs
         elif ans_s=='all':
             sels    = ['1'] * lmcrs
         elif ans_s=='no':
             sels    = ['0'] * lmcrs
         elif ans_s=='imp':
             if '1' not in sels:
                 app.msg_box('Select some names', app.MB_OK)
                 continue
             (good_nms
             ,fail_nms) = self.import_from_list([mcr for (ind, mcr) in enumerate(mcrs) if sels[ind]=='1'])
             l,lt    = '\n', '\n      '
             app.msg_box(   'Import macros:'     +lt+lt.join(good_nms)
                         +l+''
                         +l+'Skip duplicates:'   +lt+lt.join(fail_nms)
                        ,app.MB_OK)
Example #25
0
    def on_macro(self, ed_self, mcr_record):
        ''' Finish for macro-recording.
            Params
                mcr_record   "\n"-separated list of
                                number
                                number,string
                                py:string_module,string_method,string_param
        '''
        pass
        LOG and log('mcr_record={}', mcr_record)
        if '' == mcr_record: return app.msg_status('Empty record')
        def_nm = ''
        nms = [mcr['nm'] for mcr in self.macros]
        for num in range(1, 1000):
            def_nm = 'Macro{}'.format(num)
            if def_nm not in nms:
                break  #for num
        while True:
            mcr_nm = app.dlg_input(
                'Macro name. Tricks: "!NM" overwrite NM, "=NM" show NM in dialog',
                def_nm)
            if mcr_nm is None: return
            mcr_nm = mcr_nm.strip()
            if '' == mcr_nm: continue  #while
            if mcr_nm[0] == '=':
                self.need_dlg = True
                mcr_nm = mcr_nm[1:]
            use_old = False
            if '' == mcr_nm: continue  #while
            if mcr_nm[0] == '!':
                use_old = True
                mcr_nm = mcr_nm[1:]
            if '' != mcr_nm: break  #while
        pass
        LOG and log('self.need_dlg, use_old, mcr_nm={}',
                    (self.need_dlg, use_old, mcr_nm))

        if use_old and mcr_nm in nms:
            mcr_ind = nms.index(mcr_nm)
            self.macros[mcr_ind]['rec'] = mcr_record
            self.macros[mcr_ind]['evl'] = self._record_data_to_cmds(mcr_record)
            id4mcr = self.macros[mcr_ind]['id']
        else:
            while mcr_nm in nms:
                app.msg_box(
                    'Select other name.\nMacros names now:\n\n' +
                    '\n'.join(nms), app.MB_OK)
                mcr_nm = app.dlg_input('Macro name', mcr_nm)
                if mcr_nm is None: return

            id4mcr = random.randint(10000, 99999)
            while id4mcr in self.mcr4id:
                id4mcr = random.randint(10000, 99999)
            self.macros += [{
                'id': id4mcr  ##?? conflicts?
                ,
                'nm': mcr_nm,
                'rec': mcr_record,
                'evl': self._record_data_to_cmds(mcr_record)
            }]
        self._do_acts()

        if self.need_dlg:
            self.need_dlg = False
            self.last_mcr_id = id4mcr
            self.dlg_config()
Example #26
0
    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)
Example #27
0
    def dlg_export(self):
        ''' Show dlg for export some macros.
        '''
        if app.app_api_version() < FROM_API_VERSION:
            return app.msg_status('Need update CudaText')
        if 0 == len(self.macros): return app.msg_status('No macros for export')
        exp_file = app.dlg_file(False, '', '', 'Cuda macros|*.cuda-macros')
        exp_file = '' if exp_file is None else exp_file
        exp_file = exp_file + ('' if '' == exp_file
                               or exp_file.endswith('.cuda-macros') else
                               '.cuda-macros')
        (WD_LST, HT_LST) = (500, 500)

        lmcrs = len(self.macros)
        crt, sels = '0', ['0'] * lmcrs
        while True:
            pass
            LOG and log('sels={}', sels)
            ans = app.dlg_custom(
                'Export macros',
                GAP + WD_LST + GAP,
                GAP * 5 + HT_LST + 25 * 2,
                '\n'.join([] + [
                    C1.join([
                        'type=label',
                        POS_FMT(l=GAP, t=GAP + 3, r=GAP +
                                70, b=0), 'cap=Export &to'
                    ]  # i=0
                            )
                ] + [
                    C1.join([
                        'type=edit',
                        POS_FMT(l=GAP + 70, t=GAP, r=GAP + WD_LST -
                                35, b=0), 'val={}'.format(exp_file)
                    ]  # i=1
                            )
                ] + [
                    C1.join([
                        'type=button',
                        POS_FMT(l=GAP + HT_LST - 35,
                                t=GAP - 2,
                                r=GAP + WD_LST,
                                b=0), 'cap=&...'
                    ]  # i=2
                            )
                ] + [
                    C1.join([
                        'type=checklistbox',
                        POS_FMT(l=GAP,
                                t=GAP * 2 + 30,
                                r=GAP + WD_LST,
                                b=GAP + 25 + HT_LST), 'items=' +
                        '\t'.join([mcr['nm'] for mcr in self.macros]), 'val=' +
                        crt + ';' + ','.join(sels)
                    ]  # i=3
                            )
                ] + [
                    C1.join([
                        'type=button',
                        POS_FMT(l=GAP * 1,
                                t=GAP * 3 + 25 + HT_LST,
                                r=GAP * 1 + 80 * 1,
                                b=0), 'cap=Check &all'
                    ]  # i=4
                            )
                ] + [
                    C1.join([
                        'type=button',
                        POS_FMT(l=GAP * 2 + 80,
                                t=GAP * 3 + 25 + HT_LST,
                                r=GAP * 2 + 80 * 2,
                                b=0), 'cap=U&ncheck all'
                    ]  # i=5
                            )
                ] + [
                    C1.join([
                        'type=button',
                        POS_FMT(l=WD_LST - 60 * 2,
                                t=GAP * 3 + 25 + HT_LST,
                                r=WD_LST - 60 * 1,
                                b=0), 'cap=&Export'
                    ]  # i=6
                            )
                ] + [
                    C1.join([
                        'type=button',
                        POS_FMT(l=GAP + WD_LST - 60 * 1,
                                t=GAP * 3 + 25 + HT_LST,
                                r=GAP + WD_LST - 60 * 0,
                                b=0), 'cap=&Close'
                    ]  # i=7
                            )
                ]),
                3)  # start focus
            pass
            LOG and log('ans={}', ans)
            if ans is None: break  #while
            (ans_i, vals) = ans
            ans_s = apx.icase(False, '', ans_i == 2, 'file', ans_i == 4, 'all',
                              ans_i == 5, 'no', ans_i == 6, 'exp', ans_i == 7,
                              'close')
            if ans_s == 'close': break  #while
            v_3 = vals.splitlines()[3]
            crt, sels = v_3.split(';')
            sels = sels.strip(',').split(',')
            pass
            LOG and log('sels={}', sels)
            if False: pass
            elif ans_s == 'file':
                new_exp_file = app.dlg_file(False, '', '',
                                            'Cuda macros|*.cuda-macros')
                if new_exp_file is not None:
                    exp_file = new_exp_file
                    exp_file = exp_file + ('' if '' == exp_file
                                           or exp_file.endswith('.cuda-macros')
                                           else '.cuda-macros')
            elif ans_s == 'all':
                sels = ['1'] * lmcrs
            elif ans_s == 'no':
                sels = ['0'] * lmcrs
            elif ans_s == 'exp':
                if '1' not in sels:
                    app.msg_box('Select some names', app.MB_OK)
                    continue
                self.export_to_file(exp_file, [
                    mcr for (ind, mcr) in enumerate(self.macros)
                    if sels[ind] == '1'
                ])
                return
Example #28
0
 def dlg_export(self):
     ''' Show dlg for export some macros.
     '''
     if app.app_api_version()<FROM_API_VERSION:  return app.msg_status('Need update CudaText')
     if 0==len(self.macros):                     return app.msg_status('No macros for export')
     exp_file= app.dlg_file(False, '', '', 'Cuda macros|*.cuda-macros')
     exp_file= '' if exp_file is None else exp_file
     exp_file= exp_file+('' if ''==exp_file or exp_file.endswith('.cuda-macros') else '.cuda-macros')
     (WD_LST
     ,HT_LST)= (500
               ,500)
     
     lmcrs   = len(self.macros)
     crt,sels= '0', ['0'] * lmcrs
     while True:
         pass;               LOG and log('sels={}',sels)
         ans = app.dlg_custom('Export macros'   ,GAP+WD_LST+GAP, GAP*5+HT_LST+25*2, '\n'.join([]
         +[C1.join(['type=label'         ,POS_FMT(l=GAP,             t=GAP+3,            r=GAP+70,     b=0)
                   ,'cap=Export &to'
                   ] # i=0
          )]
         +[C1.join(['type=edit'         ,POS_FMT(l=GAP+70,           t=GAP,              r=GAP+WD_LST-35,b=0)
                   ,'val={}'.format(exp_file)
                   ] # i=1
          )]
         +[C1.join(['type=button'        ,POS_FMT(l=GAP+HT_LST-35,   t=GAP-2,            r=GAP+WD_LST,   b=0)
                   ,'cap=&...'
                   ] # i=2
          )]
         +[C1.join(['type=checklistbox' ,POS_FMT(l=GAP,             t=GAP*2+30,          r=GAP+WD_LST,   b=GAP+25+HT_LST)
                   ,'items=' +'\t'.join([mcr['nm'] for mcr in self.macros])
                   ,'val='   + crt+';'+','.join(sels)
                   ] # i=3
          )]
         +[C1.join(['type=button'        ,POS_FMT(l=GAP*1,           t=GAP*3+25+HT_LST,  r=GAP*1+80*1,   b=0)
                   ,'cap=Check &all'
                   ] # i=4
          )]
         +[C1.join(['type=button'        ,POS_FMT(l=GAP*2+80,        t=GAP*3+25+HT_LST,  r=GAP*2+80*2,   b=0)
                   ,'cap=U&ncheck all'
                   ] # i=5
          )]
         +[C1.join(['type=button'        ,POS_FMT(l=    WD_LST-60*2, t=GAP*3+25+HT_LST,  r=    WD_LST-60*1,   b=0)
                   ,'cap=&Export'
                   ] # i=6
          )]
         +[C1.join(['type=button'        ,POS_FMT(l=GAP+WD_LST-60*1, t=GAP*3+25+HT_LST,  r=GAP+WD_LST-60*0,   b=0)
                   ,'cap=&Close'
                   ] # i=7
          )]
         ), 3)    # start focus
         pass;               LOG and log('ans={}',ans)
         if ans is None:  break #while
         (ans_i
         ,vals)  = ans
         ans_s   = apx.icase(False,''
                    ,ans_i==2, 'file'
                    ,ans_i==4, 'all'
                    ,ans_i==5, 'no'
                    ,ans_i==6, 'exp'
                    ,ans_i==7, 'close'
                    )
         if ans_s=='close':  break #while
         v_3     = vals.splitlines()[3]
         crt,sels= v_3.split(';')
         sels    = sels.strip(',').split(',')
         pass;               LOG and log('sels={}',sels)
         if False:pass
         elif ans_s=='file':
             new_exp_file= app.dlg_file(False, '', '', 'Cuda macros|*.cuda-macros')
             if new_exp_file is not None:
                 exp_file    = new_exp_file
                 exp_file    = exp_file+('' if ''==exp_file or exp_file.endswith('.cuda-macros') else '.cuda-macros')
         elif ans_s=='all':
             sels    = ['1'] * lmcrs
         elif ans_s=='no':
             sels    = ['0'] * lmcrs
         elif ans_s=='exp':
             if '1' not in sels:
                 app.msg_box('Select some names', app.MB_OK)
                 continue
             self.export_to_file(exp_file, [mcr for (ind, mcr) in enumerate(self.macros) if sels[ind]=='1'])
             return
Example #29
0
    def dlg_import(self):
        ''' Show dlg for import some macros.
        '''
        if app.app_api_version() < FROM_API_VERSION:
            return app.msg_status('Need update CudaText')
        (imp_file, mcrs) = self.dlg_import_choose_mcrs()
        if imp_file is None: return
        lmcrs = len(mcrs)

        GAP = 5
        (WD_LST, HT_LST) = (500, 500)
        crt, sels = '0', ['1'] * lmcrs
        while True:
            ans = app.dlg_custom(
                'Import macros',
                GAP + WD_LST + GAP,
                GAP * 5 + HT_LST + 25 * 2,
                '\n'.join([] + [
                    C1.join([
                        'type=label',
                        POS_FMT(l=GAP, t=GAP + 3, r=GAP +
                                85, b=0), 'cap=Import &from'
                    ]  # i=0
                            )
                ] + [
                    C1.join([
                        'type=edit',
                        POS_FMT(l=GAP + 85, t=GAP, r=GAP + WD_LST -
                                35, b=0), 'val={}'.format(imp_file)
                    ]  # i=1
                            )
                ] + [
                    C1.join([
                        'type=button',
                        POS_FMT(l=GAP + HT_LST - 35,
                                t=GAP - 2,
                                r=GAP + WD_LST,
                                b=0), 'cap=&...'
                    ]  # i=2
                            )
                ] + [
                    C1.join([
                        'type=checklistbox',
                        POS_FMT(l=GAP,
                                t=GAP * 2 + 30,
                                r=GAP + WD_LST,
                                b=GAP + 25 + HT_LST), 'items=' +
                        '\t'.join([mcr['nm'] for mcr in mcrs]), 'val=' + crt +
                        ';' + ','.join(sels)
                    ]  # i=3
                            )
                ] + [
                    C1.join([
                        'type=button',
                        POS_FMT(l=GAP * 1,
                                t=GAP * 3 + 25 + HT_LST,
                                r=GAP * 1 + 80 * 1,
                                b=0), 'cap=Check &all'
                    ]  # i=4
                            )
                ] + [
                    C1.join([
                        'type=button',
                        POS_FMT(l=GAP * 2 + 80,
                                t=GAP * 3 + 25 + HT_LST,
                                r=GAP * 2 + 80 * 2,
                                b=0), 'cap=U&ncheck all'
                    ]  # i=5
                            )
                ] + [
                    C1.join([
                        'type=button',
                        POS_FMT(l=WD_LST - 60 * 2,
                                t=GAP * 3 + 25 + HT_LST,
                                r=WD_LST - 60 * 1,
                                b=0), 'cap=&Import'
                    ]  # i=6
                            )
                ] + [
                    C1.join([
                        'type=button',
                        POS_FMT(l=GAP + WD_LST - 60 * 1,
                                t=GAP * 3 + 25 + HT_LST,
                                r=GAP + WD_LST - 60 * 0,
                                b=0), 'cap=&Close'
                    ]  # i=7
                            )
                ]),
                3)  # start focus
            pass
            LOG and log('ans={}', ans)
            if ans is None: break  #while
            (ans_i, vals) = ans
            ans_s = apx.icase(False, '', ans_i == 2, 'file', ans_i == 4, 'all',
                              ans_i == 5, 'no', ans_i == 6, 'imp', ans_i == 7,
                              'close')
            if ans_s == 'close': break  #while
            v_3 = vals.splitlines()[3]
            crt, sels = v_3.split(';')
            sels = sels.strip(',').split(',')
            pass
            LOG and log('sels={}', sels)
            if False: pass
            elif ans_s == 'file':
                (new_imp_file, new_mcrs) = self.dlg_import_choose_mcrs()
                if new_imp_file is None: continue  #while
                imp_file = new_imp_file
                mcrs = new_mcrs
                lmcrs = len(mcrs)
                crt, sels = '0', ['1'] * lmcrs
            elif ans_s == 'all':
                sels = ['1'] * lmcrs
            elif ans_s == 'no':
                sels = ['0'] * lmcrs
            elif ans_s == 'imp':
                if '1' not in sels:
                    app.msg_box('Select some names', app.MB_OK)
                    continue
                (good_nms, fail_nms) = self.import_from_list([
                    mcr for (ind, mcr) in enumerate(mcrs) if sels[ind] == '1'
                ])
                l, lt = '\n', '\n      '
                app.msg_box(
                    'Import macros:' + lt + lt.join(good_nms) + l + '' + l +
                    'Skip duplicates:' + lt + lt.join(fail_nms), app.MB_OK)
Example #30
0
    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)