def duplicate(self): if ed.get_sel_mode() != app.SEL_NORMAL: return app.msg_status(ONLY_NORM_SEL_MODE.format(DUPLICATION)) crts = ed.get_carets() if len(crts) > 1: return app.msg_status(ONLY_SINGLE_CRT.format(DUPLICATION)) (cCrt, rCrt, cEnd, rEnd) = crts[0] bEmpSel = -1 == rEnd bUseFLn = get_opt('duplicate_full_line_if_no_sel', True) bSkip = get_opt('duplicate_move_down', True) if bEmpSel: if not bUseFLn: return # Dup whole row row_txt = ed.get_text_line(rCrt) ed.insert(0, rCrt, row_txt + '\n') # Move crt to next row if bSkip and (rCrt + 1) < ed.get_line_count(): _move_caret_down(cCrt, rCrt) return (rFr, cFr), (rTo, cTo) = minmax((rCrt, cCrt), (rEnd, cEnd)) pass #LOG and log('(cFr , rFr , cTo , rTo) ={}',(cFr , rFr , cTo , rTo)) sel_txt = ed.get_text_substr(cFr, rFr, cTo, rTo) pass #LOG and log('sel_txt={}',repr(sel_txt)) ed.insert(cFr, rFr, sel_txt)
def _jump_to_ibm(self, what): ibms, \ msg = self._ibms_in_tab(ed, self.bm_signs) if not ibms and msg: return app.msg_status(msg) if not ibms: return app.msg_status(_('No in-text bookmarks')) rCrt = ed.get_carets()[0][1] if 1==len(ibms) \ and rCrt==ibms[0][1]: return app.msg_status(_('No more bookmarks')) line_ns = [ line_n for (tab_id, line_n, bm_msg, line_s, tab_info) in ibms ] if self.wrap: line_ns = [-line_ns[-1]] + line_ns + [line_ns[0] + 0xFFFFFFFF] line_cns = [ line_n for line_n in line_ns if (line_n > rCrt if what == 'next' else line_n < rCrt) ] if not line_cns: return app.msg_status(_('No bookmark for jump')) line_n = min(line_cns) if what == 'next' else max(line_cns) line_n = -line_n if line_n < 0 else line_n line_n = line_n - 0xFFFFFFFF if line_n >= 0xFFFFFFFF else line_n ed.set_caret(0, line_n) if not (ed.get_prop(app.PROP_LINE_TOP) <= line_n <= ed.get_prop( app.PROP_LINE_BOTTOM)): ed.set_prop( app.PROP_LINE_TOP, str(max(0, line_n - max(5, apx.get_opt('find_indent_vert')))))
def duplicate(self): if ed.get_sel_mode() != app.SEL_NORMAL: return app.msg_status(ONLY_NORM_SEL_MODE.format(DUPLICATION)) crts = ed.get_carets() if len(crts)>1: return app.msg_status(ONLY_SINGLE_CRT.format(DUPLICATION)) (cCrt, rCrt, cEnd, rEnd) = crts[0] if -1==cEnd: # Empty sel -- dup whole row row_txt = ed.get_text_line(rCrt) ed.insert(0, rCrt, row_txt+'\n') # Move crt to next row if (rCrt+1)<ed.get_line_count(): colCrt = pos2pos(cCrt , rCrt, 'smb2col') smbCrt1 = pos2pos(colCrt, rCrt+1, 'col2smb') ed.set_caret(smbCrt1, rCrt+1) return (rFr, cFr), (rTo, cTo) = minmax((rCrt, cCrt), (rEnd, cEnd)) #pass; LOG and log('(cCrt, rCrt, cEnd, rEnd)={}',(cCrt, rCrt, cEnd, rEnd)) pass; LOG and log('(cFr , rFr , cTo , rTo) ={}',(cFr , rFr , cTo , rTo)) sel_txt = ed.get_text_substr(cFr, rFr, cTo, rTo) pass; LOG and log('sel_txt={}',repr(sel_txt)) ed.insert(cFr, rFr, sel_txt) if -1==rEnd: # or rCrt==rEnd: # Move crt to next row colCrt = pos2pos(cCrt , rCrt, 'smb2col') smbCrt1 = pos2pos(colCrt, rCrt+1, 'col2smb') ed.set_caret(smbCrt1, rCrt+1)
def dlg_ibms_in_tab(self): ibms, \ msg = self._ibms_in_tab(ed, self.bm_signs) if not ibms and msg: return app.msg_status(msg) if not ibms: return app.msg_status(_('No in-text bookmarks')) line_max= max([line_n for (tab_id, line_n, bm_msg, line_s, tab_info) in ibms]) ln_wd = len(str(line_max)) pass; #LOG and log('ln_wd={}',(ln_wd)) ibms = [(bm_msg, line_n, f('{} {}', str(1+line_n).rjust(ln_wd, ' '), line_s)) for (tab_id, line_n, bm_msg, line_s, tab_info) in ibms] pass; #LOG and log('ibms=¶{}',pf(ibms)) rCrt = ed.get_carets()[0][1] near = min([(abs(line_n-rCrt), ind) for ind, (bm_msg, line_n, line_s) in enumerate(ibms)])[1] if self.show_wo_alt: ans = app.dlg_menu(app.MENU_LIST, '\n'.join( [f('{}\t{}', line_nd, bm_msg) for bm_msg, line_n, line_nd in ibms] ), near) else: ans = app.dlg_menu(app.MENU_LIST_ALT, '\n'.join( [f('{}\t{}', bm_msg, line_nd) for bm_msg, line_n, line_nd in ibms] ), near) if ans is None: return bm_msg, line_n, line_nd = ibms[ans] ed.set_caret(0, line_n) if not (ed.get_prop(app.PROP_LINE_TOP) <= line_n <= ed.get_prop(app.PROP_LINE_BOTTOM)): ed.set_prop(app.PROP_LINE_TOP, str(max(0, line_n - max(5, apx.get_opt('find_indent_vert')))))
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]
def do_conv(self, mode): carets = ed.get_carets() num_carets = len(carets) num_formats = 0 for caret in carets: x, y, nlen, text = get_word_info(caret) if text == "" and num_carets == 1: msg_status("Place caret under a word") return if text == "": continue text2 = do_conv_string(text, mode) if text == text2 and num_carets == 1: msg_status("Word is already formatted: " + MODES_STR[mode]) return if text == text2: continue ed.replace(x, y, x + nlen, y, text2) ed.set_caret(x, y, x + len(text2), y, app.CARET_ADD) num_formats += 1 msg_status( str(num_formats) + " " + ("word" if num_formats <= 1 else "carets") + " formatted: " + MODES_STR[mode])
def duplicate(self): if ed.get_sel_mode() != app.SEL_NORMAL: return app.msg_status(ONLY_NORM_SEL_MODE.format(DUPLICATION)) crts = ed.get_carets() if len(crts)>1: return app.msg_status(ONLY_SINGLE_CRT.format(DUPLICATION)) (cCrt, rCrt, cEnd, rEnd) = crts[0] bEmpSel = -1==rEnd bUseFLn = get_opt('duplicate_full_line_if_no_sel', True) bSkip = get_opt('duplicate_move_down', True) if bEmpSel: if not bUseFLn: return # Dup whole row row_txt = ed.get_text_line(rCrt) ed.insert(0, rCrt, row_txt+'\n') # Move crt to next row if bSkip and (rCrt+1)<ed.get_line_count(): _move_caret_down(cCrt, rCrt) return (rFr, cFr), (rTo, cTo) = minmax((rCrt, cCrt), (rEnd, cEnd)) pass; #LOG and log('(cFr , rFr , cTo , rTo) ={}',(cFr , rFr , cTo , rTo)) sel_txt = ed.get_text_substr(cFr, rFr, cTo, rTo) pass; #LOG and log('sel_txt={}',repr(sel_txt)) ed.insert(cFr, rFr, sel_txt)
def _subst(self, which, wdex): """ Do completion. Params which Which variant to use 'next' / 'prev' / '#N' wdex What list to use 'word' / 'expr' / 'curr' """ pass #LOG and log('which, wdex={}',(which, wdex)) if wdex!='curr' and \ not self._prep_sess(wdex): return if not self.sess.bids: return app.msg_status(_('No in-text completions')) shft = 1 if which == 'next' else -1 if which == 'prev' else 0 bids_i = int(which) if which.isdigit() else \ self.sess.bids_i + shft if self.incr_bfr else \ self.sess.bids_i bids_i = bids_i % len(self.sess.bids) sub_s = self.sess.bids[bids_i] add_s = sub_s[len(self.sess.src_what):] pass #LOG and log('i, sub_s, add_s={}',(bids_i, sub_s, add_s)) if self.sess.added: ed.cmd(cmds.cCommand_Undo) pass #LOG and log('undo mod_ver, line={}',(ed.get_prop(app.PROP_MODIFIED_VERSION), ed.get_text_line(self.sess.row))) ed.delete(self.sess.src_kill_b, self.sess.row, self.sess.src_kill_e, self.sess.row) pass #LOG and log('kill mod_ver, line={}',(ed.get_prop(app.PROP_MODIFIED_VERSION), ed.get_text_line(self.sess.row))) ed.insert(self.sess.src_what_e, self.sess.row, add_s) pass #LOG and log('insr mod_ver, line={}',(ed.get_prop(app.PROP_MODIFIED_VERSION), ed.get_text_line(self.sess.row))) self.sess.added = True if False: pass elif self.sess.sel_sub == 'be': ed.set_caret(self.sess.src_what_e + len(add_s), self.sess.row, self.sess.src_what_b, self.sess.row) elif self.sess.sel_sub == 'eb': ed.set_caret(self.sess.src_what_b, self.sess.row, self.sess.src_what_e + len(add_s), self.sess.row) else: ed.set_caret(self.sess.src_what_e + len(add_s), self.sess.row) # ed.set_caret(self.sess.src_crt, self.sess.row) self.sess.pre_mver = ed.get_prop(app.PROP_MODIFIED_VERSION) self.sess.pre_crt0 = ed.get_carets()[0] # next_i = (self.sess.bids_i+shft) % len(self.sess.bids) # next_info = '' if 1==len(self.sess.bids) else \ # f(_('. Next #{}: "{}"'), next_i, self.sess.bids[next_i][:50]) # app.msg_status(f(_('In-text completion #{} ({}){}'), 1+self.sess.bids_i, len(self.sess.bids), next_info)) app.msg_status( f(_('In-text completion #{} ({})'), 1 + self.sess.bids_i, len(self.sess.bids))) # shft = 1 if which=='next' or which[0]=='#' else -1 self.sess.bids_i = bids_i self.incr_bfr = True
def process_ocurrences(sel_occurrences=False): global occurrences ed.attr(app.MARKERS_DELETE_BY_TAG, MARKTAG) app.msg_status('') if sel_occurrences: # In this part of the events, occurrences variable must have data. # If not, force matches considering no min length selection. if len(occurrences) == 0 and opt.MARK_IGNORE_MIN_LEN: log("No previous occurrences information") res = _get_occurrences(sel_occurrences) if not res: occurrences = () return else: occurrences = res return occurrences else: # The highlight function on_caret event only works with one caret. if len(ed.get_carets()) != 1: return res = _get_occurrences() if res is None: occurrences = () return else: occurrences = res return occurrences
def dlg_ibms_in_tabs(self): ibms = [] for h_tab in app.ed_handles(): ted = app.Editor(h_tab) t_ibms, \ msg = self._ibms_in_tab(ted, self.bm_signs) ibms += t_ibms #for h_tab if not ibms: return app.msg_status(_('No in-text bookmarks in tabs')) line_max= max([line_n for (tab_id, line_n, bm_msg, line_s, tab_info) in ibms]) ln_wd = len(str(line_max)) ibms = [(tab_id, line_n, bm_msg, f('{} {}', str(1+line_n).rjust(ln_wd, ' '), line_s), tab_info) for (tab_id, line_n, bm_msg, line_s, tab_info) in ibms] tid = ed.get_prop(app.PROP_TAB_ID) rCrt = ed.get_carets()[0][1] near = min([(abs(line_n-rCrt) if tid==tab_id else 0xFFFFFF, ind) for ind, (tab_id, line_n, bm_msg, line_s, tab_info) in enumerate(ibms)])[1] ans = app.dlg_menu(app.MENU_LIST_ALT, '\n'.join( [f('({}) {}\t{}', tab_info, bm_msg, line_s) for tab_id, line_n, bm_msg, line_s, tab_info in ibms] ), near) if ans is None: return tab_id, line_n, bm_msg, line_s, tab_info = ibms[ans] ted = apx.get_tab_by_id(tab_id) ted.focus() ed.set_caret(0, line_n) if not (ed.get_prop(app.PROP_LINE_TOP) <= line_n <= ed.get_prop(app.PROP_LINE_BOTTOM)): ed.set_prop(app.PROP_LINE_TOP, str(max(0, line_n - max(5, apx.get_opt('find_indent_vert')))))
def do_insert(self, s): x, y, x1, y1 = ed.get_carets()[0] if y1 >= 0: if (y, x) > (y1, x1): x, y, x1, y1 = x1, y1, x, y ed.set_caret(x, y) ed.replace(x, y, x1, y1, s) else: ed.insert(x, y, s) app.msg_status('Date/time inserted')
def add_ibm(self): lxr = ed.get_prop(app.PROP_LEXER_FILE) lxr = lxr if lxr else NO_LXR_SIGN # if lxr not in self.lxr2cmnt: return app.msg_status(f(_('Cannot add in-text bookmark into document with Lexer {}. No to-end-of-line comment.'), lxr)) if lxr not in self.lxr2cmnt: return app.msg_status(f(_('Cannot add in-text bookmark: no line-comments defined for lexer {}.'), lxr)) cmnt = self.lxr2cmnt[lxr] bm_msg = app.dlg_input(_('Enter message for in-text bookmark. Empty is good.'), '') if bm_msg is None: return (cCrt, rCrt ,cEnd, rEnd)= ed.get_carets()[0] line_s = ed.get_text_line( rCrt) ed.set_text_line( rCrt, line_s + cmnt + self.bm_sign + ' ' + bm_msg)
def _subst(self, which, wdex): """ Do completion. Params which Which variant to use 'next' / 'prev' / '#N' wdex What list to use 'word' / 'expr' / 'curr' """ pass; #LOG and log('which, wdex={}',(which, wdex)) if wdex!='curr' and \ not self._prep_sess(wdex): return if not self.sess.bids: return app.msg_status(_('No in-text completions')) shft = 1 if which=='next' else -1 if which=='prev' else 0 bids_i = int(which) if which.isdigit() else \ self.sess.bids_i + shft if self.incr_bfr else \ self.sess.bids_i bids_i = bids_i % len(self.sess.bids) sub_s = self.sess.bids[bids_i] add_s = sub_s[len(self.sess.src_what):] pass; #LOG and log('i, sub_s, add_s={}',(bids_i, sub_s, add_s)) if self.sess.added: ed.cmd(cmds.cCommand_Undo) pass; #LOG and log('undo mod_ver, line={}',(ed.get_prop(app.PROP_MODIFIED_VERSION), ed.get_text_line(self.sess.row))) ed.delete( self.sess.src_kill_b, self.sess.row ,self.sess.src_kill_e, self.sess.row) pass; #LOG and log('kill mod_ver, line={}',(ed.get_prop(app.PROP_MODIFIED_VERSION), ed.get_text_line(self.sess.row))) ed.insert( self.sess.src_what_e, self.sess.row, add_s) pass; #LOG and log('insr mod_ver, line={}',(ed.get_prop(app.PROP_MODIFIED_VERSION), ed.get_text_line(self.sess.row))) self.sess.added = True if False:pass elif self.sess.sel_sub=='be': ed.set_caret(self.sess.src_what_e+len(add_s), self.sess.row ,self.sess.src_what_b, self.sess.row) elif self.sess.sel_sub=='eb': ed.set_caret(self.sess.src_what_b, self.sess.row ,self.sess.src_what_e+len(add_s), self.sess.row) else: ed.set_caret(self.sess.src_what_e+len(add_s), self.sess.row) # ed.set_caret(self.sess.src_crt, self.sess.row) self.sess.pre_mver = ed.get_prop(app.PROP_MODIFIED_VERSION) self.sess.pre_crt0 = ed.get_carets()[0] # next_i = (self.sess.bids_i+shft) % len(self.sess.bids) # next_info = '' if 1==len(self.sess.bids) else \ # f(_('. Next #{}: "{}"'), next_i, self.sess.bids[next_i][:50]) # app.msg_status(f(_('In-text completion #{} ({}){}'), 1+self.sess.bids_i, len(self.sess.bids), next_info)) app.msg_status(f(_('In-text completion #{} ({})'), 1+self.sess.bids_i, len(self.sess.bids))) # shft = 1 if which=='next' or which[0]=='#' else -1 self.sess.bids_i = bids_i self.incr_bfr = True
def tree_path_to_status(): pass; #log('?',()) path_l, gap = _get_best_tree_path(ed.get_carets()[0][1]) if not path_l: return ID_TREE = app.app_proc(app.PROC_SIDEPANEL_GET_CONTROL, 'Code tree') if not ID_TREE: return id_sel = app.tree_proc(ID_TREE, app.TREE_ITEM_GET_SELECTED) id_need = path_l[-1][0] if id_need != id_sel: app.tree_proc(ID_TREE, app.TREE_ITEM_SELECT, id_need) path = '['+ '] / ['.join([cap.rstrip(':')[:40] for (nid,cap) in path_l]) + ']' return app.msg_status_alt( path if gap==0 else f('[{:+}] {}', -gap, path) , 10)
def open_selected(self): pass; #LOG and log('ok',) bs_dir = os.path.dirname(ed.get_filename()) crts = ed.get_carets() for (cCrt, rCrt, cEnd, rEnd) in crts: if -1==cEnd: continue if rCrt!=rEnd: continue (rTx1, cTx1), (rTx2, cTx2) = apx.minmax((rCrt, cCrt), (rEnd, cEnd)) selTx = ed.get_text_substr(cTx1, rTx1, cTx2, rTx2) op_file = os.path.join(bs_dir, selTx) if not os.path.exists(op_file): app.msg_status(NO_FILE_FOR_OPEN.format(op_file)) continue op_ed = _file_open(op_file) op_ed.focus()
def add_ibm(self): lxr = ed.get_prop(app.PROP_LEXER_FILE) lxr = lxr if lxr else NO_LXR_SIGN # if lxr not in self.lxr2cmnt: return app.msg_status(f(_('Cannot add in-text bookmark into document with Lexer {}. No to-end-of-line comment.'), lxr)) if lxr not in self.lxr2cmnt: return app.msg_status( f( _('Cannot add in-text bookmark: no line-comments defined for lexer {}.' ), lxr)) cmnt = self.lxr2cmnt[lxr] bm_msg = app.dlg_input( _('Enter message for in-text bookmark. Empty is good.'), '') if bm_msg is None: return (cCrt, rCrt, cEnd, rEnd) = ed.get_carets()[0] line_s = ed.get_text_line(rCrt) ed.set_text_line(rCrt, line_s + cmnt + self.bm_sign + ' ' + bm_msg)
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
def dlg_ibms_in_tabs(self): ibms = [] for h_tab in app.ed_handles(): ted = app.Editor(h_tab) t_ibms, \ msg = self._ibms_in_tab(ted, self.bm_signs) ibms += t_ibms #for h_tab if not ibms: return app.msg_status(_('No in-text bookmarks in tabs')) line_max = max( [line_n for (tab_id, line_n, bm_msg, line_s, tab_info) in ibms]) ln_wd = len(str(line_max)) ibms = [(tab_id, line_n, bm_msg, f('{} {}', str(1 + line_n).rjust(ln_wd, ' '), line_s), tab_info) for (tab_id, line_n, bm_msg, line_s, tab_info) in ibms] tid = ed.get_prop(app.PROP_TAB_ID) rCrt = ed.get_carets()[0][1] near = min([(abs(line_n - rCrt) if tid == tab_id else 0xFFFFFF, ind) for ind, (tab_id, line_n, bm_msg, line_s, tab_info) in enumerate(ibms)])[1] ans = dlg_menu( (app.DMENU_LIST if self.show_wo_alt else app.DMENU_LIST_ALT) + app.DMENU_EDITORFONT + app.DMENU_CENTERED, w=900, h=800, cap=f(_('In-text bookmarks (all tabs): {}'), len(ibms)), its=[ f('({}) {}', tab_info, bm_msg) for tab_id, line_n, bm_msg, line_s, tab_info in ibms ] if self.show_wo_alt else [ f('({}) {}\t{}', tab_info, bm_msg, line_s) for tab_id, line_n, bm_msg, line_s, tab_info in ibms ], sel=near) if ans is None: return tab_id, line_n, bm_msg, line_s, tab_info = ibms[ans] ted = apx.get_tab_by_id(tab_id) ted.focus() ed.set_caret(0, line_n) if not (ed.get_prop(app.PROP_LINE_TOP) <= line_n <= ed.get_prop( app.PROP_LINE_BOTTOM)): ed.set_prop( app.PROP_LINE_TOP, str(max(0, line_n - max(5, apx.get_opt('find_indent_vert')))))
def cmt_toggle_stream(self): ''' ''' if ed.get_sel_mode() != app.SEL_NORMAL: return app.msg_status(ONLY_NORM_SEL_MODE.format(COMMENTING)) lex = ed.get_prop(app.PROP_LEXER_CARET) (bgn ,end) = self._get_cmt_pair(lex) if not bgn: return app.msg_status(CMT_NO_STRM_4LEX.format(lex)) crts = ed.get_carets() pass; LOG and log('lex, get_carets()={}', (lex, crts)) pass; LOG and log('bgn,end={}', (bgn,end)) for icrt, (c1, r1, c2, r2) in enumerate(crts): pass; LOG and log('(r1, c1), (r2, c2)={}', ((r1, c1), (r2, c2))) if -1==c2: # Empty sel continue (r1, c1), (r2, c2) = minmax((r1, c1), (r2, c2)) pass; LOG and log('(r1, c1), (r2, c2)={}', ((r1, c1), (r2, c2))) selTx = ed.get_text_substr(c1, r1, c2, r2) cmted = selTx.startswith(bgn) and selTx.endswith(end) pass; LOG and log('cmted, selTx={}', (cmted, selTx)) if False:pass elif not cmted and r1==r2: # Comment ON, sel into one row ed.insert(c2, r2, end) ed.insert(c1, r1, bgn) ed.set_caret(c1, r1, c2+len(bgn)+len(end), r2, app.CARET_SET_INDEX+icrt) elif not cmted and r1!=r2: # Comment ON, sel ends on diff rows ed.insert(c2, r2, end) ed.insert(c1, r1, bgn) ed.set_caret(c1, r1, c2 +len(end), r2, app.CARET_SET_INDEX+icrt) elif cmted and r1==r2: # Comment OFF, sel into one row ed.delete(c2-len(end), r2, c2, r2) ed.delete(c1, r1, c1+len(bgn), r1) ed.set_caret(c1, r1, c2-len(bgn)-len(end), r2, app.CARET_SET_INDEX+icrt) elif cmted and r1!=r2: # Comment OFF, sel ends on diff rows ed.delete(c2-len(end), r2, c2, r2) ed.delete(c1, r1, c1+len(bgn), r1) ed.set_caret(c1, r1, c2 -len(end), r2, app.CARET_SET_INDEX+icrt)
def jump_to_matching_bracket(self): ''' Jump single (only!) caret to matching bracket. Pairs: [] {} () <> «» ''' pass; #LOG and log('') crts = ed.get_carets() if len(crts)>1: return app.msg_status(ONLY_SINGLE_CRT.format('Command')) (cCrt, rCrt, cEnd, rEnd) = crts[0] if cEnd!=-1: return app.msg_status(ONLY_FOR_NO_SEL.format('Command')) (c_opn, c_cls ,col, row) = find_matching_char(ed, cCrt, rCrt) if c_opn!='' and -1!=col: pass; #LOG and log('set_caret(col, row)={}', (col, row)) ed.set_caret(col, row) else: return app.msg_status(NO_PAIR_BRACKET.format(c_opn))
def _jump_to_ibm(self, what): ibms, \ msg = self._ibms_in_tab(ed, self.bm_signs) if not ibms and msg: return app.msg_status(msg) if not ibms: return app.msg_status(_('No in-text bookmarks')) rCrt = ed.get_carets()[0][1] if 1==len(ibms) \ and rCrt==ibms[0][1]: return app.msg_status(_('No more bookmarks')) line_ns = [line_n for (tab_id, line_n, bm_msg, line_s, tab_info) in ibms] if self.wrap: line_ns = [-line_ns[-1]] + line_ns + [line_ns[0]+0xFFFFFFFF] line_cns= [line_n for line_n in line_ns if (line_n>rCrt if what=='next' else line_n<rCrt)] if not line_cns: return app.msg_status(_('No bookmark for jump')) line_n = min(line_cns) if what=='next' else max(line_cns) line_n = -line_n if line_n<0 else line_n line_n = line_n-0xFFFFFFFF if line_n>=0xFFFFFFFF else line_n ed.set_caret(0, line_n) if not (ed.get_prop(app.PROP_LINE_TOP) <= line_n <= ed.get_prop(app.PROP_LINE_BOTTOM)): ed.set_prop(app.PROP_LINE_TOP, str(max(0, line_n - max(5, apx.get_opt('find_indent_vert')))))
def dlg_ibms_in_tab(self): ibms, \ msg = self._ibms_in_tab(ed, self.bm_signs) if not ibms and msg: return app.msg_status(msg) if not ibms: return app.msg_status(_('No in-text bookmarks')) line_max = max( [line_n for (tab_id, line_n, bm_msg, line_s, tab_info) in ibms]) ln_wd = len(str(line_max)) pass #LOG and log('ln_wd={}',(ln_wd)) pass #LOG and log('self.show_wo_alt={}',(self.show_wo_alt)) ibms = [(bm_msg, line_n, f('{} {}', str(1 + line_n).rjust(ln_wd, ' '), line_s)) for (tab_id, line_n, bm_msg, line_s, tab_info) in ibms] pass #LOG and log('ibms=¶{}',pf(ibms)) rCrt = ed.get_carets()[0][1] near = min([(abs(line_n - rCrt), ind) for ind, (bm_msg, line_n, line_s) in enumerate(ibms)])[1] ans = dlg_menu( (app.DMENU_LIST if self.show_wo_alt else app.DMENU_LIST_ALT) + app.DMENU_EDITORFONT, w=900, cap=f(_('Tab in-text bookmarks: {}'), len(ibms)), its=[ f('{}\t{}', line_nd, bm_msg) for bm_msg, line_n, line_nd in ibms ] if self.show_wo_alt else [f('{}\t{}', bm_msg, line_nd) for bm_msg, line_n, line_nd in ibms], sel=near) if ans is None: return bm_msg, line_n, line_nd = ibms[ans] ed.set_caret(0, line_n) if not (ed.get_prop(app.PROP_LINE_TOP) <= line_n <= ed.get_prop( app.PROP_LINE_BOTTOM)): ed.set_prop( app.PROP_LINE_TOP, str(max(0, line_n - max(5, apx.get_opt('find_indent_vert')))))
def on_caret(self, ed_self): if self.skip_rec: self.skip_rec = False return crts = ed.get_carets() if len(crts)>1: pass; #LOG and log('skip: many carets',()) return new_item= HistItem(*crts[0]) pass; #LOG and log('new_item={}',(new_item)) tab_id = ed_self.get_prop(app.PROP_TAB_ID) # уникальный ID вкладки if tab_id not in self.history: self.history[tab_id] = [new_item] self.poses[ tab_id] = 0 pass; #LOG and log('new tab',()) return hist, \ pos = self.history[tab_id] \ , self.poses[ tab_id] pre_item= hist[pos] if abs(pre_item.y - new_item.y) > GAP_SIZE: # Дальний скачок # - Начать новое наращивание истории # - Запомнить текущую каретку (или выделение) для последующего перехода del hist[pos+1:] hist += [new_item] self.poses[tab_id] = pos+1 if len(hist)>HIST_MAX: del hist[0] self.poses[tab_id] -= 1 pass; #LOG and log('long gap pos,hist={}',(self.poses[tab_id], hist)) else: # Ближний скачок # - Изменяем данные о текущем положении в истории # - Сохраняем возможность для forward-перехода pass; #LOG and log('short gap',()) hist[pos] = new_item
def get_word_under_caret(): """ Gets a tuple (word_under_caret, (x1, y1, x2, y2)) containing the word under the current caret. """ lex = ed.get_prop(app.PROP_LEXER_CARET) carets = ed.get_carets() # In this point the "one caret" rule is valid, so x2 and y2 is equal to -1 # and there is no a selection x1, y1 = carets[0][:2] current_line = get_line(y1) # if len(current_line) > opt.MAX_LINE_LEN: return n_x1 = n_x2 = x1 if current_line: if x1 > 0 and is_word(current_line[x1 - 1], lex): n_x1 = next((i for i in range(x1 - 1, -1, -1) if not is_word(current_line[i], lex)), -1) + 1 if x1 < len(current_line) and is_word(current_line[x1], lex): n_x2 = next((i for i in range(x1 + 1, len(current_line)) if not is_word(current_line[i], lex)), len(current_line)) else: return if n_x1 == n_x2: return word_under_caret = current_line[n_x1: n_x2] return word_under_caret, (n_x1, y1, n_x2, y1)
def paste_to_1st_col(self): ''' Paste from clipboard without replacement caret/selection but only insert before current line ''' pass; #LOG and log('') clip = app.app_proc(app.PROC_GET_CLIP, '') if not clip: return clip = clip.replace('\r\n', '\n').replace('\r', '\n') if not (clip[-1] in '\r\n'): clip= clip + '\n' rnews = clip.count('\n') crts = ed.get_carets() if len(crts)>1: return app.msg_status(ONLY_SINGLE_CRT.format('Command')) (cCrt, rCrt, cEnd, rEnd) = crts[0] r4ins = min(rCrt, rCrt if -1==rEnd else rEnd) ed.insert(0, r4ins, clip) rCrtN = rCrt+ rnews rEndN = rEnd+(rnews if -1!=rEnd else 0) pass; #LOG and log('(rCrtN, rEndN)={}',(rCrtN, rEndN)) ed.set_caret(cCrt, rCrtN ,cEnd, rEndN) pass; return ##?? for icrt, (cCrt, rCrt, cEnd, rEnd) in reversed(list(enumerate(crts))): # for icrt, (cCrt, rCrt, cEnd, rEnd) in enumerate(crts): pass; #LOG and log('icrt, (cCrt, rCrt, cEnd, rEnd), rnews={}',(icrt, (cCrt, rCrt, cEnd, rEnd), rnews)) rCrtA = rCrt+rnews*icrt rEndA = rEnd+rnews*icrt if -1!=rEnd else -1 r4ins = min(rCrt, rCrt if -1==rEnd else rEnd) pass; #LOG and log('(rCrtA, rEndA), r4ins={}',((rCrtA, rEndA), r4ins)) ed.insert(0, r4ins, clip) rCrtN = rCrt+ rnews rEndN = rEnd+(rnews if -1!=rEnd else 0) pass; #LOG and log('(rCrtN, rEndN)={}',(rCrtN, rEndN)) ed.set_caret(cCrt, rCrtN ,cEnd, rEndN ,app.CARET_SET_INDEX+icrt)
def _get_current_text(): caret_pos = ed.get_carets()[0] x1, y1, x2, y2 = caret_pos is_selection = y2 >= 0 current_text = '' if is_selection: if opt.SEL_ALLOW: # Sorting caret's values if (y1, x1) > (y2, x2): x1, x2 = x2, x1 y1, y2 = y2, y1 caret_pos = (x1, y1, x2, y2) # After sorting y2 always will be greater or equal to y1 # No multi-line allowed if (y2 - y1) > 0: return current_text = ed.get_text_sel() else: return else: # Sometimes caret can be beyond text end temp = get_line(y1) if (temp is None) or (len(temp) < x1): return # if len(temp) > opt.MAX_LINE_LEN: return if opt.CARET_ALLOW: temp = get_word_under_caret() if not temp: return current_text, caret_pos = temp return current_text, caret_pos, is_selection
def symbol_menu_levels(levels=0): pass; log4fun=-1== 1 # Order log in the function if app.app_api_version() >= '1.0.277' and \ ed.get_prop(app.PROP_CODETREE_MODIFIED_VERSION) < ed.get_prop(app.PROP_MODIFIED_VERSION): ed.cmd(cmds.cmd_TreeUpdate) h_tree = app.app_proc(app.PROC_GET_CODETREE, '') def tree_items_to_list(props=None, id_node=0, prefix='', more_levels=1000): '''Get all tree nodes to "props" starting from id_node (e.g. 0)''' props = [] if props is None else props nodes = app.tree_proc(h_tree, app.TREE_ITEM_ENUM, id_node) if not nodes: nodes = app.tree_proc(h_tree, app.TREE_ITEM_ENUM, id_node) if not nodes: return for id_kid, cap in nodes: prop = app.tree_proc(h_tree, app.TREE_ITEM_GET_PROPS, id_kid) rng = app.tree_proc(h_tree, app.TREE_ITEM_GET_RANGE, id_kid) subs = prop['sub_items'] if rng[0]>=0: prop['rng'] = rng prop['_t'] = f('{}{}\t{}' , prefix , prop['text'] , f('{}:{}', 1+rng[1], 1+rng[3])) props.append(prop) if subs and more_levels: # need items with sub_items too tree_items_to_list(props, id_kid, prefix+' '*4, more_levels-1) return props #def tree_items_to_list old_api = app.app_api_version() < '1.0.277' w = get_hist('symbols.w', 600) h = get_hist('symbols.h', 550) while True: props = tree_items_to_list(more_levels=(levels-1 if levels else 1000)) if not props: ed.cmd(cmds.cmd_TreeUpdate) props = tree_items_to_list() if not props: return app.msg_status(_('No items in Code Tree')) items = [p['_t'] for p in props] crt_row = ed.get_carets()[0][1] covers = [(p['rng'][3]-p['rng'][1], n) for n,p in enumerate(props) if p['rng'][1] <= crt_row <= p['rng'][3]] start_item = min(covers)[1] if covers else 0 res = dlg_menu(app.MENU_LIST+app.MENU_NO_FULLFILTER+app.MENU_EDITORFONT , w=w, h=h , sel=start_item , cap=_('Code Tree symbols') + f(' ({})' , len(items)) +(f(' (up {})' , levels ) if levels else '') , its=items + ([_('<Update Code Tree>')] if old_api else []) + [_(' <All levels>')] + [_(' <Only 1 up level>')] + [_(' <Only 2 up levels>')] + [_(' <Only 3 up levels>')] ) if res is None: return if res==len(props) and old_api: ed.cmd(cmds.cmd_TreeUpdate) continue#while if res==0+len(props) + (1 if old_api else 0): levels = 0 continue#while if res==1+len(props) + (1 if old_api else 0): levels = 1 continue#while if res==2+len(props) + (1 if old_api else 0): levels = 2 continue#while if res==3+len(props) + (1 if old_api else 0): levels = 3 continue#while break #while x, y, x1, y1 = props[res]['rng'] ed.set_caret(x, y)
def cmt_toggle_stream(self): ''' ''' if ed.get_sel_mode() != app.SEL_NORMAL: return app.msg_status(ONLY_NORM_SEL_MODE.format(COMMENTING)) lex = ed.get_prop(app.PROP_LEXER_CARET) ((bgn_sgn, end_sgn), bOnlyLn) = self._get_cmt_pair(lex) if not bgn_sgn: return app.msg_status(CMT_NO_STRM_4LEX.format(lex)) bUseFLn = get_opt('comment_full_line_if_no_sel', True) crts = ed.get_carets() pass #LOG and log('lex, get_carets()={}', (lex, crts)) pass #LOG and log('(bgn_sgn,end_sgn),bOnlyLn,bUseFLn={}', ((bgn_sgn,end_sgn),bOnlyLn,bUseFLn)) for icrt, (cCrt, rCrt, cEnd, rEnd) in enumerate(crts): pass #LOG and log('(cCrt, rCrt), (cEnd, rEnd)={}', ((cCrt, rCrt), (cEnd, rEnd))) bEmpSel = -1 == rEnd bDrtSel = -1 == rEnd or (rCrt, cCrt) > (rEnd, cEnd) if False: pass elif bEmpSel and (bUseFLn or bOnlyLn): # Use full line line = ed.get_text_line(rCrt) (cTx1, rTx1), (cTx2, rTx2) = (0, rCrt), (len(line), rCrt) elif bOnlyLn: # and not bEmpSel # Only full lines rTx1, rTx2 = minmax(rCrt, rEnd) line = ed.get_text_line(rTx2) (cTx1, rTx1), (cTx2, rTx2) = (0, rTx1), (len(line), rTx2) elif bEmpSel: # and not bUseFLn and not bOnlyLn continue else: (rTx1, cTx1), (rTx2, cTx2) = minmax((rCrt, cCrt), (rEnd, cEnd)) selTx = ed.get_text_substr(cTx1, rTx1, cTx2, rTx2) pass #LOG and log('(rTx1, cTx1), (rTx2, cTx2), selTx={}', ((rTx1, cTx1), (rTx2, cTx2), repr(selTx))) do_uncmt = selTx.startswith(bgn_sgn) and selTx.endswith(end_sgn) pass #LOG and log('do_uncmt={}', (do_uncmt)) if False: pass elif not do_uncmt and bOnlyLn: # Comment! ed.insert(0, rTx2 + 1, end_sgn + '\n') #! true insert sequence ed.insert(0, rTx1, bgn_sgn + '\n') #! true insert sequence (cNSel1, rNSel1, cNSel2, rNSel2) = 0, rTx1, len(end_sgn), rTx2 + 2 elif not do_uncmt: # Comment! ed.insert(cTx2, rTx2, end_sgn) #! true insert sequence ed.insert(cTx1, rTx1, bgn_sgn) #! true insert sequence if False: pass elif rTx1 == rTx2: # sel into one row (cNSel1, rNSel1, cNSel2, rNSel2 ) = cTx1, rTx1, cTx2 + len(bgn_sgn) + len(end_sgn), rTx2 elif rTx1 != rTx2: # sel ends on diff rows (cNSel1, rNSel1, cNSel2, rNSel2) = cTx1, rTx1, cTx2 + len(end_sgn), rTx2 elif do_uncmt and bOnlyLn: # UnComment! ed.delete(0, rTx2, 0, rTx2 + 1) #! true delete sequence ed.delete(0, rTx1, 0, rTx1 + 1) #! true delete sequence (cNSel1, rNSel1, cNSel2, rNSel2) = 0, rTx1, len(ed.get_text_line(rTx2 - 2)), rTx2 - 2 elif do_uncmt: # UnComment! ed.delete(cTx2 - len(end_sgn), rTx2, cTx2, rTx2) #! true delete sequence ed.delete(cTx1, rTx1, cTx1 + len(bgn_sgn), rTx1) #! true delete sequence if False: pass elif rTx1 == rTx2: # sel into one row (cNSel1, rNSel1, cNSel2, rNSel2 ) = cTx1, rTx1, cTx2 - len(bgn_sgn) - len(end_sgn), rTx2 elif rTx1 != rTx2: # sel ends on diff rows (cNSel1, rNSel1, cNSel2, rNSel2) = cTx1, rTx1, cTx2 - len(end_sgn), rTx2 pass #LOG and log('bDrtSel, (cNSel1, rNSel1), (cNSel2, rNSel2)={}', (bDrtSel, (cNSel1, rNSel1), (cNSel2, rNSel2))) if bDrtSel: ed.set_caret(cNSel2, rNSel2, cNSel1, rNSel1, app.CARET_SET_INDEX + icrt) else: ed.set_caret(cNSel1, rNSel1, cNSel2, rNSel2, app.CARET_SET_INDEX + icrt) #for icrt bSkip = get_opt('comment_move_down', True) if False: pass elif 1 == len(crts) and bEmpSel and bUseFLn and bSkip: _move_caret_down(cCrt, rCrt) if bOnlyLn and not do_uncmt: crt = ed.get_carets()[0] _move_caret_down(crt[0], crt[1]) crt = ed.get_carets()[0] _move_caret_down(crt[0], crt[1])
def _prep_sess(self, wdex='word'): """ Params wdex Type of sess: 'word' / 'expr' """ crts = ed.get_carets() if len(crts) > 1: return app.msg_status(_("Command doesnt work with multi-carets")) (cCrt, rCrt, cEnd, rEnd) = crts[0] if -1 != rEnd and rCrt != rEnd: return app.msg_status( _("Command doesnt work with multi-line selection")) stayed = self.sess \ and self.sess.pre_mver == ed.get_prop(app.PROP_MODIFIED_VERSION) \ and self.sess.pre_crt0 == crts[0] cEnd, rEnd = (cCrt, rCrt) if -1 == rEnd else (cEnd, rEnd) sel_be_eb = 'be' if cCrt > cEnd else 'eb' if cCrt < cEnd else '' ((rSelB, cSelB), (rSelE, cSelE)) = apx.minmax((rCrt, cCrt), (rEnd, cEnd)) pass #LOG and stayed and log('stayed,(wdex,self.sess.wdex)={}',(stayed,(wdex,self.sess.wdex))) if stayed and wdex == self.sess.wdex: # Sess OK return True what = '' # Str to find what_b = -1 # Pos what begin what_e = -1 # Pos what end kill_b = -1 # Pos kill begin kill_e = -1 # Pos kill end wbnd = True # Need left word bound sel = '' if stayed and wdex != self.sess.wdex: # Change sess type what = self.sess.src_what what_b = self.sess.src_what_b what_e = self.sess.src_what_e kill_b = self.sess.src_kill_b kill_e = self.sess.src_kill_e wbnd = self.sess.src_wbnd if not stayed: # New sess line = ed.get_text_line(rCrt) sel = ed.get_text_sel() if sel: # Use selection to find what = sel what_b = cSelB what_e = cSelE wbnd = 0 == cSelB or line[cSelB - 1].isspace() else: # Use "chars around caret" to find what tx_bfr = line[:cCrt] ch_bfr = tx_bfr[-1] if tx_bfr else ' ' tx_aft = line[cCrt:] ch_aft = tx_aft[0] if tx_aft else ' ' pass #LOG and log('ch_bfr,ch_aft,tx_bfr,tx_aft={}',(ch_bfr,ch_aft,tx_bfr,tx_aft)) shf_l = 0 shf_r = 0 if ch_bfr.isalnum() or ch_bfr in self.wdsgns: tx_bfr_r = ''.join(reversed(tx_bfr)) shf_l = len(self.base_re.match(tx_bfr_r).group()) if ch_aft.isalnum() or ch_aft in self.wdsgns: shf_r = len(self.base_re.match(tx_aft).group()) what_b = cCrt - shf_l if self.kill: what_e = cCrt kill_b = cCrt kill_e = cCrt + shf_r else: what_e = cCrt + shf_r what = line[what_b:what_e] pass #LOG and log('(shf_l,shf_r), (what_b,what_e), what={}',((shf_l,shf_r), (what_b,what_e), what)) if not what \ or not what.strip(): return app.msg_status(_('No data for search')) if len(what) < self.min_len: return app.msg_status( f(_('Need |base|>={}, but |"{}"|=={}'), self.min_len, what, len(what))) pass #LOG and log('what,wbnd={}',(what,wbnd)) asword = wdex == 'word' asexpr = wdex == 'expr' # Make new Sess if not stayed: pass #LOG and log('new sess',()) self.sess = Command.Sess() self.sess.row = rCrt self.sess.sel_sub = sel_be_eb self.sess.src_crt = cCrt self.sess.src_what = what self.sess.src_what_b = what_b self.sess.src_what_e = what_e self.sess.src_kill_b = kill_b self.sess.src_kill_e = kill_e self.sess.src_wbnd = wbnd self.sess.wdex = wdex what_re = re.compile('' + (r'\b' if wbnd else '') + re.escape(what) + (self.wdcmpl if asword else self.excmpl)) # + r'[\w'+re.escape(self.wdsgns)+']+') pass #LOG and log('what_re={}',(what_re.pattern)) bids_d = OrdDict() for line_n in range(ed.get_line_count()): if line_n == self.sess.row: continue #for line_n line = ed.get_text_line(line_n) if asexpr and self.expair: # Find+expand upto close brackets/quotes lbids_l = [] for m in what_re.finditer(line): lbid = m.group(0) ok = False for op, cl in self.opn2cls.items(): if op in lbid and lbid.count(op) > lbid.count( cl): # Try expand to good cl ext_bgn = m.end() ext_end = line.find(cl, ext_bgn) while -1 != ext_end: lbid_ext = lbid + line[ext_bgn:ext_end + 1] if lbid_ext.count(op) == lbid_ext.count(cl): lbid, ok = lbid_ext, True break #while ext_end = line.find(cl, ext_end + 1) if ok: break #for op #for op ok = False for qu in self.quotes: if qu in lbid and 1 == lbid.count( qu) % 2: # Try expand to good qu ext_bgn = m.end() ext_end = line.find(qu, ext_bgn) while -1 != ext_end: lbid_ext = lbid + line[ext_bgn:ext_end + 1] if 0 == lbid_ext.count(qu) % 2: lbid, ok = lbid_ext, True break #while ext_end = line.find(cl, ext_end + 1) if ok: break #for qu #for qu lbids_l.append(lbid) #for m else: # Find only lbids_l = what_re.findall(line) if lbids_l: bids_d.update({ bid: line_n for bid in lbids_l if bid not in bids_d or abs(line_n - self.sess.row) < abs( bids_d[bid] - self.sess.row) }) # closest if not bids_d: return app.msg_status(_('No in-text completions')) self.sess.bids = list(bids_d.keys()) self.sess.bids_c = list(bids_d.values()) self.sess.bids_i= min([(abs(bid_r-self.sess.row), bid_i) for (bid_i,bid_r) in enumerate(self.sess.bids_c) ])[1] \ if len(self.sess.bids)>1 and self.near else \ 0 self.incr_bfr = False # Dont increment before use pass #LOG and log('bids={}',(list(zip(self.sess.bids, self.sess.bids_c)))) pass #LOG and log('sess={}',(self.sess)) pass #return False return True
def _cmt_toggle_line(self, cmt_type): ''' Add/Remove line comment Params cmt_type '1st' at begin of line 'bod' at first not blank ''' if not _check_API('1.0.107'): return if ed.get_sel_mode() != app.SEL_NORMAL: return app.msg_status(ONLY_NORM_SEL_MODE.format(COMMENTING)) lex = ed.get_prop(app.PROP_LEXER_CARET) cmt_sgn = app.lexer_proc(app.LEXER_GET_COMMENT, lex) pass; LOG and log('lex, cmt_sgn={}', (lex, cmt_sgn)) if not cmt_sgn: return app.msg_status(CMT_NO_LINE_4LEX.format(lex)) crts = ed.get_carets() if len(crts)>1: return app.msg_status(ONLY_SINGLE_CRT.format(COMMENTING)) no_tab = ed.get_prop(app.PROP_TAB_SPACES) # only blanks opts = self._get_opts('cmt') save_bd_col = no_tab and opts.get('save_body_col', False) blnks4cmt = '\t'.expandtabs(len(cmt_sgn)) (cCrt, rCrt ,cEnd, rEnd)= crts[0] (rCmtBgn ,rCmtEnd) = minmax(rCrt, rEnd if -1!=rEnd else rCrt) uncmtAll = ed.get_text_line(rCmtBgn).lstrip().startswith(cmt_sgn) pass; LOG and log('rCmtBgn,rCmtEnd,uncmtAll={}', (rCmtBgn,rCmtEnd,uncmtAll)) for rCmt in range(rCmtBgn, rCmtEnd+1): line = ed.get_text_line(rCmt) pos_body= line.index(line.lstrip()) pass; LOG and log('rCmtBgn,rCmtEnd,uncmtAll={}', (rCmtBgn,rCmtEnd,uncmtAll)) if uncmtAll: # Uncomment! if not line[pos_body:].startswith(cmt_sgn): # Already no comment continue if save_bd_col: line = line.replace(cmt_sgn, blnks4cmt, 1) else: line = line.replace(cmt_sgn, '' , 1) else: # Comment! if cmt_type=='bod' and line[pos_body:].startswith(cmt_sgn): # Body comment already sets - willnot double it continue if False:pass elif cmt_type=='1st' and save_bd_col and line.startswith(blnks4cmt) : line = line.replace(blnks4cmt, cmt_sgn, 1) # elif cmt_type=='1st' and save_bd_col # !line.startswith(blnks4cmt) : elif cmt_type=='1st':# !save_bd_col line = cmt_sgn+line elif cmt_type=='bod' and save_bd_col and line.startswith(blnks4cmt) : line = line.replace(blnks4cmt, cmt_sgn, 1) line = line[:pos_body-len(cmt_sgn)]+cmt_sgn+line[pos_body:] # elif cmt_type=='bod' and save_bd_col # !line.startswith(blnks4cmt) : elif cmt_type=='bod':# !save_bd_col line = line[:pos_body] +cmt_sgn+line[pos_body:] ed.set_text_line(rCmt, line) #for rCmt if -1==rEnd and opts.get('skip-line-after', True) and (rCrt+1)<ed.get_line_count(): colCrt = pos2pos(cCrt , rCrt, 'smb2col') smbCrt1 = pos2pos(colCrt, rCrt+1, 'col2smb') ed.set_caret(smbCrt1, rCrt+1)
def find_tree_node(): pass; log4fun=-1==-1 # Order log in the function HELP_C = _(''' Search starts on Enter. • A found node after current one will be selected. • All found nodes are remembered and dialog can jump over them by [Shift+]Enter or by menu commands. • If option "O" (wrapped search) is tuned on: - Search continues from the start, when end of the tree is reached - Jumps to previous/next nodes are looped too • Option ".*" (regular expression) allows to use Python reg.ex. See "docs.python.org/3/library/re.html". • Option "w" (whole words) is ignored if entered string contains not a word. • If option "Close on success" (in menu) is tuned on, dialog will close after successful search. • Option "Show full tree path" (in menu) shows in the statusbar the path of the found node (names of all parents). • Command "Restore initial selection" (in menu) restores only first of initial carets. ''').strip() ed_crts = ed.get_carets() # Carets at start opts = d(reex=False,case=False,word=False,wrap=False,hist=[],clos=False,fpth=False) opts.update(get_hist('tree.find_node', opts)) # Scan Tree ID_TREE = app.app_proc(app.PROC_SIDEPANEL_GET_CONTROL, 'Code tree') if not ID_TREE: return app.msg_status(_('No CodeTree')) if not app.tree_proc(ID_TREE, app.TREE_ITEM_ENUM, 0): # 0 is root ed.cmd(cmds.cmd_TreeUpdate) # Try to build tree tree_t = [] # [{nid:ID, sub:[{nid:ID, sub:{}, cap:'smth', path:['rt','smth']},], cap:'rt', path:[]},] tree_p = [] # [,(ID, 'smth',['rt','smth']),] def scan_tree(id_prnt, tree_nds, path_prnt): nonlocal tree_p kids = app.tree_proc(ID_TREE, app.TREE_ITEM_ENUM, id_prnt) if kids is None: return None for nid, cap in kids: path = path_prnt + [cap] tree_p += [(nid, cap, path)] sub = scan_tree(nid, [], path) return tree_nds #def scan_tree scan_tree(0, tree_t, []) # 0 is root pass; #log('tree_t={}',pfrm100(tree_t)) if iflog(log4fun,_log4mod) else 0 pass; #log('tree_p={}',pfrm100(tree_p)) if iflog(log4fun,_log4mod) else 0 # How to select node def select_node(nid): app.tree_proc(ID_TREE, app.TREE_ITEM_SELECT, nid) c_min, r_min, \ c_max, r_max = app.tree_proc(ID_TREE, app.TREE_ITEM_GET_RANGE, nid) ed.set_caret(c_min, r_min) #def select_node # Ask MAX_HIST= apx.get_opt('ui_max_history_edits', 20) stbr = None status = lambda msg: app.statusbar_proc(stbr, app.STATUSBAR_SET_CELL_TEXT, tag=1, value=msg) def add_to_hist(val, lst): """ Add/Move val to list head. """ if val in lst: if 0 == lst.index(val): return lst lst.remove(val) lst.insert(0, val) if len(lst)>MAX_HIST: del lst[MAX_HIST:] return lst #def add_to_hist compile_pttn= lambda pttn_s, reex, case, word: re.compile( pttn_s if reex else r'\b'+pttn_s+r'\b' if word and re.match('^\w+$', pttn_s) else re.escape(pttn_s) , 0 if case else re.I) prev_wt = None # Prev what ready_l = [] # [(nid,cap|path,ndn)] ready_p = -1 # pos in ready_l nfnd_st = lambda: status(_('No suitable nodes')) ready_st= lambda: status(f('{pos}/{all}: {cap}', pos=1+ready_p, all=len(ready_l), cap=ready_l[ready_p][1])) ready_er= lambda: status(_('Error')) def do_attr(ag, aid, data=''): nonlocal prev_wt prev_wt = '' return d(fid='what') def do_menu(ag, aid, data=''): def wnen_menu(ag, tag): nonlocal opts, prev_wt if tag in ('prev','next'): return do_next(ag, tag) if tag in ('fpth','clos'): prev_wt = ''; opts[tag] = not opts[tag] elif tag=='help': app.msg_box(HELP_C, app.MB_OK) elif tag=='rest': ed.set_caret(*ed_crts[0]); return None return [] #def wnen_menu ag.show_menu( [ d( tag='help' ,cap=_('&Help...') ),d( cap='-' ),d( tag='prev' ,cap=_('Find &previous') ,key='Shift+Enter' ),d( tag='next' ,cap=_('F&ind next') ,key='Enter' ),d( cap='-' ),d( cap=_('&Options') ,sub= [ d(tag='fpth' ,cap=_('Show full tree path') ,ch=opts['fpth'] ),d(tag='clos' ,cap=_('Close on success') ,ch=opts['clos'] )]),d( cap='-' ),d( tag='rest' ,cap=_('Restore initial selection and close dialog &=') ,key='Shift+Esc' )] , aid , cmd4all=wnen_menu # Set cmd=wnen_menu for all nodes ) return d(fid='what') #def do_menu def do_next(ag, aid, data=''): if not ready_l: return d(fid='what') nonlocal ready_p ready_n = ready_p + (-1 if aid=='prev' else 1) ready_n = ready_n % len(ready_l) if opts['wrap'] else max(0, min(len(ready_l)-1, ready_n), 0) pass; #log('ready_n,ready_p={}',(ready_n,ready_p)) if iflog(log4fun,_log4mod) else 0 if ready_p == ready_n: return d(fid='what') ready_p = ready_n ready_st() select_node(ready_l[ready_p][0]) return d(fid='what') #def do_next def do_find(ag, aid, data=''): nonlocal opts, tree_p, prev_wt, ready_l, ready_p # What/how/where will search what = ag.val('what') if prev_wt==what and ready_l: return do_next(ag, 'next') prev_wt = what pass; #log('what={}',(what)) if iflog(log4fun,_log4mod) else 0 if not what: ready_l, ready_p = [], -1 return d(fid='what') opts['hist']= add_to_hist(what, opts['hist']) opts.update(ag.vals(['reex','case','word','wrap'])) pass; #log('opts={}',(opts)) if iflog(log4fun,_log4mod) else 0 tree_sid = app.tree_proc(ID_TREE, app.TREE_ITEM_GET_SELECTED) # cur nodes = tree_p # To find from top if tree_sid and opts['clos']: # To find from cur # Trick: [..,i,sid]+[j,..] switch to [j,..] or [j,..]+[..,i] to search first after cur nids = [nid for nid, cap, path in tree_p] pos = nids.index(tree_sid) nodes = tree_p[pos+1:] + (tree_p[:pos] if opts['wrap'] else []) # Search ready_l = [] tree_ndn= -1 try: pttn_r = compile_pttn(what, opts['reex'], opts['case'], opts['word']) except: ready_er() return d(ctrls=[('what',d(items=opts['hist']))] ,fid='what') for ndn, (nid, cap, path) in enumerate(nodes): if not pttn_r.search(cap): continue if opts['clos']: select_node(nid) return None # Close dlg ready_l+= [(nid, ' / '.join(path) if opts['fpth'] else cap, ndn)] tree_ndn= ndn if ndn==tree_sid else tree_ndn pass; #log('ready_l={}',(ready_l)) if iflog(log4fun,_log4mod) else 0 ready_p = -1 if not ready_l else \ 0 if not tree_sid else \ first_true(enumerate(ready_l), 0, (lambda n_nid_cap_ndn: n_nid_cap_ndn[1][2]>tree_ndn))[0] pass; #log('ready_p={}',(ready_p)) if iflog(log4fun,_log4mod) else 0 # Show results if ready_p!=-1: select_node(ready_l[ready_p][0]) if opts['clos']: return None # Close dlg ready_st() else: nfnd_st() return d(ctrls=[('what',d(items=opts['hist']))] ,fid='what') #def do_find def do_key_down(ag, key, data=''): scam = data if data else app.app_proc(app.PROC_GET_KEYSTATE, '') pass; #log('key,data,scam={}',(key,data,scam)) if iflog(log4fun,_log4mod) else 0 if 0:pass elif (scam,key)==('s',VK_ENTER): # Shift+Enter ag.update(do_next(ag, 'prev')) elif (scam,key)==('s',VK_ESCAPE): # Shift+Esc ed.set_caret(*ed_crts[0]) return None else: return [] # Nothing return False # Stop event #def do_key_down ag = DlgAg( form =dict(cap=_('Find tree node'), w=365, h=58, h_max=58 ,on_key_down=do_key_down ,border=app.DBORDER_TOOLSIZE # ,resize=True ) , ctrls =[0 ,('find',d(tp='bttn',y=0 ,x=-99 ,w=44 ,cap='' ,sto=False ,def_bt=T ,on=do_find )) # Enter ,('reex',d(tp='chbt',tid='what' ,x=5+38*0 ,w=39 ,cap='.&*' ,hint=_('Regular expression') ,on=do_attr )) # &* ,('case',d(tp='chbt',tid='what' ,x=5+38*1 ,w=39 ,cap='&aA' ,hint=_('Case sensitive') ,on=do_attr )) # &a ,('word',d(tp='chbt',tid='what' ,x=5+38*2 ,w=39 ,cap='"&w"' ,hint=_('Whole words') ,on=do_attr )) # &w ,('wrap',d(tp='chbt',tid='what' ,x=5+38*3 ,w=39 ,cap='&O' ,hint=_('Wrapped search') ,on=do_attr )) # &/ ,('what',d(tp='cmbx',y =5 ,x=5+38*4+5 ,w=155 ,items=opts['hist'] ,a='r>' )) # ,('menu',d(tp='bttn',tid='what' ,x=320 ,w=40 ,cap='&=' ,on=do_menu ,a='>>' )) # &= ,('stbr',d(tp='stbr' ,x=0 ,r=365 ,ali=ALI_BT ,a='r>' )) # ][1:] , fid ='what' , vals = {k:opts[k] for k in ('reex','case','word','wrap')} #,options={'gen_repro_to_file':'repro_dlg_find_tree_node.py'} ) stbr = ag.chandle('stbr') app.statusbar_proc(stbr, app.STATUSBAR_ADD_CELL , tag=1) app.statusbar_proc(stbr, app.STATUSBAR_SET_CELL_AUTOSTRETCH , tag=1, value=True) ag.show(lambda ag: set_hist('tree.find_node', upd_dict(opts, ag.vals(['reex','case','word','wrap']))))
def set_nearest_tree_node(): path_l, gap = _get_best_tree_path(ed.get_carets()[0][1]) if not path_l: return ID_TREE = app.app_proc(app.PROC_SIDEPANEL_GET_CONTROL, 'Code tree') if not ID_TREE: return app.tree_proc(ID_TREE, app.TREE_ITEM_SELECT, path_l[-1][0])
def cmt_toggle_stream(self): ''' ''' if ed.get_sel_mode() != app.SEL_NORMAL: return app.msg_status(f(_('{} works only with normal selection'), _('Commenting'))) lex = ed.get_prop(app.PROP_LEXER_CARET) ((bgn_sgn ,end_sgn) ,bOnlyLn)=self._get_cmt_pair(lex) if not bgn_sgn: return app.msg_status(f(_('No stream comment for lexer "{}"'), lex)) bUseFLn = apx.get_opt('comment_full_line_if_no_sel', True) crts = ed.get_carets() pass; #LOG and log('lex, get_carets()={}', (lex, crts)) pass; #LOG and log('(bgn_sgn,end_sgn),bOnlyLn,bUseFLn={}', ((bgn_sgn,end_sgn),bOnlyLn,bUseFLn)) for icrt, (cCrt, rCrt, cEnd, rEnd) in enumerate(crts): pass; #LOG and log('(cCrt, rCrt), (cEnd, rEnd)={}', ((cCrt, rCrt), (cEnd, rEnd))) bEmpSel = -1==rEnd bDrtSel = -1==rEnd or (rCrt, cCrt)>(rEnd, cEnd) if False:pass elif bEmpSel and (bUseFLn or bOnlyLn): # Use full line line = ed.get_text_line(rCrt) (cTx1, rTx1), (cTx2, rTx2) = (0, rCrt), (len(line), rCrt) elif bOnlyLn: # and not bEmpSel # Only full lines rTx1, rTx2 = apx.minmax(rCrt, rEnd) line = ed.get_text_line(rTx2) (cTx1, rTx1), (cTx2, rTx2) = (0, rTx1), (len(line), rTx2) elif bEmpSel: # and not bUseFLn and not bOnlyLn continue else: (rTx1, cTx1), (rTx2, cTx2) = apx.minmax((rCrt, cCrt), (rEnd, cEnd)) selTx = ed.get_text_substr(cTx1, rTx1, cTx2, rTx2) pass; #LOG and log('(rTx1, cTx1), (rTx2, cTx2), selTx={}', ((rTx1, cTx1), (rTx2, cTx2), repr(selTx))) do_uncmt= selTx.startswith(bgn_sgn) and selTx.endswith(end_sgn) pass; #LOG and log('do_uncmt={}', (do_uncmt)) if False:pass elif not do_uncmt and bOnlyLn: # Comment! ed.insert(0, rTx2+1, end_sgn+'\n') #! true insert sequence ed.insert(0, rTx1, bgn_sgn+'\n') #! true insert sequence (cNSel1, rNSel1 ,cNSel2, rNSel2) = 0, rTx1, len(end_sgn), rTx2+2 elif not do_uncmt: # Comment! ed.insert(cTx2, rTx2, end_sgn) #! true insert sequence ed.insert(cTx1, rTx1, bgn_sgn) #! true insert sequence if False:pass elif rTx1==rTx2: # sel into one row (cNSel1, rNSel1 ,cNSel2, rNSel2) = cTx1, rTx1, cTx2+len(bgn_sgn)+len(end_sgn), rTx2 elif rTx1!=rTx2: # sel ends on diff rows (cNSel1, rNSel1 ,cNSel2, rNSel2) = cTx1, rTx1, cTx2 +len(end_sgn), rTx2 elif do_uncmt and bOnlyLn: # UnComment! ed.delete(0, rTx2, 0, rTx2+1) #! true delete sequence ed.delete(0, rTx1, 0, rTx1+1) #! true delete sequence (cNSel1, rNSel1 ,cNSel2, rNSel2) = 0, rTx1, len(ed.get_text_line(rTx2-2)), rTx2-2 elif do_uncmt: # UnComment! ed.delete(cTx2-len(end_sgn), rTx2, cTx2, rTx2) #! true delete sequence ed.delete(cTx1, rTx1, cTx1+len(bgn_sgn), rTx1) #! true delete sequence if False:pass elif rTx1==rTx2: # sel into one row (cNSel1, rNSel1 ,cNSel2, rNSel2) = cTx1, rTx1, cTx2-len(bgn_sgn)-len(end_sgn), rTx2 elif rTx1!=rTx2: # sel ends on diff rows (cNSel1, rNSel1 ,cNSel2, rNSel2) = cTx1, rTx1, cTx2 -len(end_sgn), rTx2 pass; #LOG and log('bDrtSel, (cNSel1, rNSel1), (cNSel2, rNSel2)={}', (bDrtSel, (cNSel1, rNSel1), (cNSel2, rNSel2))) if bDrtSel: ed.set_caret(cNSel2, rNSel2, cNSel1, rNSel1, app.CARET_SET_INDEX+icrt) else: ed.set_caret(cNSel1, rNSel1, cNSel2, rNSel2, app.CARET_SET_INDEX+icrt) #for icrt bSkip = apx.get_opt('comment_move_down', True) if False:pass elif 1==len(crts) and bEmpSel and bUseFLn and bSkip: apx._move_caret_down(cCrt, rCrt) if bOnlyLn and not do_uncmt: crt=ed.get_carets()[0]; apx._move_caret_down(crt[0], crt[1]) crt=ed.get_carets()[0]; apx._move_caret_down(crt[0], crt[1])
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
def find_cb_string(self, updn, bgn_crt_fin='crt'): ''' Find clipboard value in text. Params updn 'up'|'dn' - direction bgn_crt_fin 'bgn'|'crt'|'fin' - start point ''' clip = app.app_proc(app.PROC_GET_CLIP, '') if ''==clip: return clip = clip.replace('\r\n', '\n').replace('\r', '\n') pass; #LOG and log('clip={}',repr(clip)) crts = ed.get_carets() if len(crts)>1: return app.msg_status(ONLY_SINGLE_CRT.format('Command')) # Prepare bgn-, crt-, fin-point (cBgn, rBgn) = (0, 0) (cCrt, rCrt ,cEnd, rEnd) = crts[0] lst_line_ind = ed.get_line_count()-1 lst_line = ed.get_text_line(lst_line_ind) (cFin, rFin) = (max(0, len(lst_line)-1), lst_line_ind) if bgn_crt_fin=='crt': # Some cases for natural (not wrap) find if updn=='dn' and (cFin, rFin) == (cCrt, rCrt): # Caret at finish - immediately find from start return self.find_cb_string(updn, bgn_crt_fin='bgn') if updn=='up' and (cBgn, rBgn) == (cCrt, rCrt): # Caret at start - immediately find from finish return self.find_cb_string(updn, bgn_crt_fin='fin') if updn=='dn' and (cBgn, rBgn) == (cCrt, rCrt): # Caret already at start - switch wrap off bgn_crt_fin = 'bgn' if updn=='up' and (cFin, rFin) == (cCrt, rCrt): # Caret already at finish - switch wrap off bgn_crt_fin = 'fin' (cPnt, rPnt ,cEnd, rEnd) = apx.icase(False,0 ,bgn_crt_fin=='bgn', (cBgn, rBgn, cBgn, rBgn) ,bgn_crt_fin=='crt', (cCrt, rCrt, cEnd, rEnd) ,bgn_crt_fin=='fin', (cFin, rFin, cFin, rFin) ) # Main part if '\n' not in clip: # 1) Find inside each line row = rPnt line = ed.get_text_line(row) pos = line.find(clip, cPnt) if updn=='dn' else line.rfind(clip, 0, cPnt) while -1==pos: row = apx.icase(updn=='dn', row+1, updn=='up', row-1, -1) if row<0 or row==ed.get_line_count(): break #while line = ed.get_text_line(row) pos = line.find(clip) if updn=='dn' else line.rfind(clip) if False:pass elif -1==pos and bgn_crt_fin!='crt': return app.msg_status(FIND_FAIL_FOR_STR.format(clip)) elif -1==pos:#and bgn_crt_fin=='crt' # Wrap! return self.find_cb_string(updn, bgn_crt_fin=apx.icase(updn=='dn', 'bgn', 'fin')) elif updn=='dn': ed.set_caret(pos+len(clip), row, pos, row) elif updn=='up': ed.set_caret(pos, row, pos+len(clip), row) return # 2) Find m-line pass; #LOG and log('') clpls = clip.split('\n') pass; #LOG and log('clpls={}',(clpls)) clip = repr(clip) if False:pass elif updn=='dn': found = False row = max(rPnt, rEnd if rEnd!=-1 else rPnt) if row+len(clpls) < ed.get_line_count(): txtls = [ed.get_text_line(r) for r in range(row, row+len(clpls))] pass; #LOG and log('txtls={}',(txtls)) while True: if self._find_cb_string_included_mlines(txtls, clpls): # Found! found = True break #while row = row+1 pass; #LOG and log('row={}',(row)) if row+len(clpls) >= ed.get_line_count(): pass; #LOG and log('nfnd12',) break #while txtls = txtls[1:]+[ed.get_text_line(row+len(clpls)-1)] pass; #LOG and log('txtls={}',(txtls)) #while if False:pass elif not found and bgn_crt_fin!='crt': return app.msg_status(FIND_FAIL_FOR_STR.format(clip)) elif not found:#and bgn_crt_fin=='crt' # Wrap! return self.find_cb_string(updn, bgn_crt_fin=apx.icase(updn=='dn', 'bgn', 'fin')) ed.set_caret(len(clpls[-1]), row+len(clpls)-1, len(txtls[0])-len(clpls[0]), row) elif updn=='up': found = False row = min(rPnt, rEnd if rEnd!=-1 else rPnt) if row-len(clpls)+1 >= 0: txtls = [ed.get_text_line(r) for r in range(row-len(clpls)+1, row+1)] pass; #LOG and log('txtls={}',(txtls)) while True: if self._find_cb_string_included_mlines(txtls, clpls): # Found! found = True break #while row = row-1 pass; #LOG and log('row={}',(row)) if row-len(clpls)+1 < 0: break #while txtls = [ed.get_text_line(row-len(clpls)+1)]+txtls[:-1] pass; #LOG and log('txtls={}',(txtls)) #while if False:pass elif not found and bgn_crt_fin!='crt': return app.msg_status(FIND_FAIL_FOR_STR.format(clip)) elif not found:#and bgn_crt_fin=='crt' # Wrap! return self.find_cb_string(updn, bgn_crt_fin=apx.icase(updn=='dn', 'bgn', 'fin')) ed.set_caret(len(clpls[-1]), row, len(txtls[0])-len(clpls[0]), row-len(clpls)+1)
def _prep_sess(self, wdex='word'): """ Params wdex Type of sess: 'word' / 'expr' """ crts = ed.get_carets() if len(crts)>1: return app.msg_status(_("Command doesnt work with multi-carets")) (cCrt, rCrt ,cEnd, rEnd)= crts[0] if -1!=rEnd and rCrt!=rEnd: return app.msg_status(_("Command doesnt work with multi-line selection")) stayed = self.sess \ and self.sess.pre_mver == ed.get_prop(app.PROP_MODIFIED_VERSION) \ and self.sess.pre_crt0 == crts[0] cEnd, rEnd = (cCrt, rCrt) if -1==rEnd else (cEnd, rEnd) sel_be_eb = 'be' if cCrt>cEnd else 'eb' if cCrt<cEnd else '' ((rSelB, cSelB) ,(rSelE, cSelE))= apx.minmax((rCrt, cCrt), (rEnd, cEnd)) pass; #LOG and stayed and log('stayed,(wdex,self.sess.wdex)={}',(stayed,(wdex,self.sess.wdex))) if stayed and wdex==self.sess.wdex: # Sess OK return True what = '' # Str to find what_b = -1 # Pos what begin what_e = -1 # Pos what end kill_b = -1 # Pos kill begin kill_e = -1 # Pos kill end wbnd = True # Need left word bound sel = '' if stayed and wdex!=self.sess.wdex: # Change sess type what = self.sess.src_what what_b = self.sess.src_what_b what_e = self.sess.src_what_e kill_b = self.sess.src_kill_b kill_e = self.sess.src_kill_e wbnd = self.sess.src_wbnd if not stayed: # New sess line = ed.get_text_line(rCrt) sel = ed.get_text_sel() if sel: # Use selection to find what = sel what_b = cSelB what_e = cSelE wbnd = 0==cSelB or line[cSelB-1].isspace() else: # Use "chars around caret" to find what tx_bfr = line[:cCrt ] ch_bfr = tx_bfr[-1] if tx_bfr else ' ' tx_aft = line[ cCrt:] ch_aft = tx_aft[ 0] if tx_aft else ' ' pass; #LOG and log('ch_bfr,ch_aft,tx_bfr,tx_aft={}',(ch_bfr,ch_aft,tx_bfr,tx_aft)) shf_l = 0 shf_r = 0 if ch_bfr.isalnum() or ch_bfr in self.wdsgns: tx_bfr_r= ''.join(reversed(tx_bfr)) shf_l = len(self.base_re.match(tx_bfr_r).group()) if ch_aft.isalnum() or ch_aft in self.wdsgns: shf_r = len(self.base_re.match(tx_aft).group()) what_b = cCrt-shf_l if self.kill: what_e = cCrt kill_b = cCrt kill_e = cCrt+shf_r else: what_e = cCrt+shf_r what = line[what_b:what_e] pass; #LOG and log('(shf_l,shf_r), (what_b,what_e), what={}',((shf_l,shf_r), (what_b,what_e), what)) if not what \ or not what.strip(): return app.msg_status(_('No data for search')) if len(what) < self.min_len: return app.msg_status(f(_('Need |base|>={}, but |"{}"|=={}'), self.min_len, what, len(what))) pass; #LOG and log('what,wbnd={}',(what,wbnd)) asword = wdex=='word' asexpr = wdex=='expr' # Make new Sess if not stayed: pass; #LOG and log('new sess',()) self.sess = Command.Sess() self.sess.row = rCrt self.sess.sel_sub = sel_be_eb self.sess.src_crt = cCrt self.sess.src_what = what self.sess.src_what_b= what_b self.sess.src_what_e= what_e self.sess.src_kill_b= kill_b self.sess.src_kill_e= kill_e self.sess.src_wbnd = wbnd self.sess.wdex = wdex what_re = re.compile('' + (r'\b' if wbnd else '') + re.escape(what) + (self.wdcmpl if asword else self.excmpl) ) # + r'[\w'+re.escape(self.wdsgns)+']+') pass; #LOG and log('what_re={}',(what_re.pattern)) bids_d = OrdDict() for line_n in range(ed.get_line_count()): if line_n == self.sess.row: continue#for line_n line = ed.get_text_line(line_n) if asexpr and self.expair: # Find+expand upto close brackets/quotes lbids_l = [] for m in what_re.finditer(line): lbid = m.group(0) ok = False for op, cl in self.opn2cls.items(): if op in lbid and lbid.count(op) > lbid.count(cl): # Try expand to good cl ext_bgn = m.end() ext_end = line.find(cl, ext_bgn) while -1!=ext_end: lbid_ext = lbid + line[ext_bgn:ext_end+1] if lbid_ext.count(op) == lbid_ext.count(cl): lbid,ok = lbid_ext, True break#while ext_end = line.find(cl, ext_end+1) if ok: break#for op #for op ok = False for qu in self.quotes: if qu in lbid and 1 == lbid.count(qu) % 2: # Try expand to good qu ext_bgn = m.end() ext_end = line.find(qu, ext_bgn) while -1!=ext_end: lbid_ext = lbid + line[ext_bgn:ext_end+1] if 0 == lbid_ext.count(qu) % 2: lbid,ok = lbid_ext, True break#while ext_end = line.find(cl, ext_end+1) if ok: break#for qu #for qu lbids_l.append(lbid) #for m else: # Find only lbids_l = what_re.findall(line) if lbids_l: bids_d.update({bid:line_n for bid in lbids_l if bid not in bids_d or abs(line_n-self.sess.row)<abs(bids_d[bid]-self.sess.row) }) # closest if not bids_d: return app.msg_status(_('No in-text completions')) self.sess.bids = list(bids_d.keys()) self.sess.bids_c= list(bids_d.values()) self.sess.bids_i= min([(abs(bid_r-self.sess.row), bid_i) for (bid_i,bid_r) in enumerate(self.sess.bids_c) ])[1] \ if len(self.sess.bids)>1 and self.near else \ 0 self.incr_bfr = False # Dont increment before use pass; #LOG and log('bids={}',(list(zip(self.sess.bids, self.sess.bids_c)))) pass; #LOG and log('sess={}',(self.sess)) pass; #return False return True
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
def cmt_toggle_stream(self): ''' ''' if ed.get_sel_mode() != app.SEL_NORMAL: return app.msg_status(f(_('{} works only with normal selection'), _('Commenting'))) lex = ed.get_prop(app.PROP_LEXER_CARET) ((bgn_sgn ,end_sgn) ,bOnlyLn)=self._get_cmt_pair(lex) if not bgn_sgn: return app.msg_status(f(_('No stream comment for lexer "{}"'), lex)) bUseFLn = True crts = ed.get_carets() pass; #LOG and log('lex, get_carets()={}', (lex, crts)) pass; #LOG and log('(bgn_sgn,end_sgn),bOnlyLn,bUseFLn={}', ((bgn_sgn,end_sgn),bOnlyLn,bUseFLn)) for icrt, (cCrt, rCrt, cEnd, rEnd) in enumerate(crts): pass; #LOG and log('(cCrt, rCrt), (cEnd, rEnd)={}', ((cCrt, rCrt), (cEnd, rEnd))) bEmpSel = -1==rEnd bDrtSel = -1==rEnd or (rCrt, cCrt)>(rEnd, cEnd) bEntireLn = (rEnd>=0) and (cEnd==0) and (cCrt==0) bEntireLn1 = bEntireLn and abs(rEnd-rCrt)==1 bEntireLn2 = bEntireLn and abs(rEnd-rCrt)>1 if False:pass elif bEmpSel and (bUseFLn or bOnlyLn): # Use full line line = ed.get_text_line(rCrt) (cTx1, rTx1), (cTx2, rTx2) = (0, rCrt), (len(line), rCrt) elif bOnlyLn: # and not bEmpSel # Only full lines rTx1, rTx2 = apx.minmax(rCrt, rEnd) line = ed.get_text_line(rTx2) (cTx1, rTx1), (cTx2, rTx2) = (0, rTx1), (len(line), rTx2) elif bEmpSel: # and not bUseFLn and not bOnlyLn continue else: (rTx1, cTx1), (rTx2, cTx2) = apx.minmax((rCrt, cCrt), (rEnd, cEnd)) selTx = ed.get_text_substr(cTx1, rTx1, cTx2, rTx2) pass; #LOG and log('(rTx1, cTx1), (rTx2, cTx2), selTx={}', ((rTx1, cTx1), (rTx2, cTx2), repr(selTx))) do_uncmt= selTx.startswith(bgn_sgn) #and selTx.endswith(end_sgn) # don't check for ending of selection - for HTML and entire selected line(s) pass; #LOG and log('do_uncmt={}', (do_uncmt)) if False:pass elif not do_uncmt and bOnlyLn: # Comment! ed.insert(0, rTx2+1, end_sgn+'\n') #! true insert sequence ed.insert(0, rTx1, bgn_sgn+'\n') #! true insert sequence (cNSel1, rNSel1 ,cNSel2, rNSel2) = 0, rTx1, len(end_sgn), rTx2+2 elif not do_uncmt: # Comment! if bEntireLn1: s = ed.get_text_line(rTx1) ed.set_text_line(rTx1, bgn_sgn+s+end_sgn) (cNSel1, rNSel1 ,cNSel2, rNSel2) = (0, rTx1, 0, rTx2) elif bEntireLn2: ed.insert(0, rTx2, end_sgn+'\n') ed.insert(0, rTx1, bgn_sgn+'\n') (cNSel1, rNSel1 ,cNSel2, rNSel2) = (0, rTx1, 0, rTx2+2) else: ed.insert(cTx2, rTx2, end_sgn) #! true insert sequence ed.insert(cTx1, rTx1, bgn_sgn) #! true insert sequence if False:pass elif rTx1==rTx2: # sel into one row (cNSel1, rNSel1 ,cNSel2, rNSel2) = cTx1, rTx1, cTx2+len(bgn_sgn)+len(end_sgn), rTx2 elif rTx1!=rTx2: # sel ends on diff rows (cNSel1, rNSel1 ,cNSel2, rNSel2) = cTx1, rTx1, cTx2 +len(end_sgn), rTx2 elif do_uncmt and bOnlyLn: # UnComment! ed.delete(0, rTx2, 0, rTx2+1) #! true delete sequence ed.delete(0, rTx1, 0, rTx1+1) #! true delete sequence (cNSel1, rNSel1 ,cNSel2, rNSel2) = 0, rTx1, len(ed.get_text_line(rTx2-2)), rTx2-2 elif do_uncmt: # UnComment! if selTx.endswith(end_sgn): ed.delete(cTx2-len(end_sgn), rTx2, cTx2, rTx2) #! true delete sequence ed.delete(cTx1, rTx1, cTx1+len(bgn_sgn), rTx1) #! true delete sequence if False:pass elif rTx1==rTx2: # sel into one row (cNSel1, rNSel1 ,cNSel2, rNSel2) = cTx1, rTx1, cTx2-len(bgn_sgn)-len(end_sgn), rTx2 elif rTx1!=rTx2: # sel ends on diff rows (cNSel1, rNSel1 ,cNSel2, rNSel2) = cTx1, rTx1, cTx2 -len(end_sgn), rTx2 elif bEntireLn1: s = ed.get_text_line(rTx1) if s.startswith(bgn_sgn): s = s[len(bgn_sgn):] if s.endswith(end_sgn): s = s[:-len(end_sgn)] ed.set_text_line(rTx1, s) (cNSel1, rNSel1 ,cNSel2, rNSel2) = (0, rTx1, 0, rTx2) elif bEntireLn2: ed.delete(0, rTx2-1, 0, rTx2) ed.delete(0, rTx1, 0, rTx1+1) (cNSel1, rNSel1 ,cNSel2, rNSel2) = (0, rTx1, 0, rTx2-2) pass; #LOG and log('bDrtSel, (cNSel1, rNSel1), (cNSel2, rNSel2)={}', (bDrtSel, (cNSel1, rNSel1), (cNSel2, rNSel2))) if bDrtSel: ed.set_caret(cNSel2, rNSel2, cNSel1, rNSel1, app.CARET_SET_INDEX+icrt) else: ed.set_caret(cNSel1, rNSel1, cNSel2, rNSel2, app.CARET_SET_INDEX+icrt) #for icrt bSkip = apx.get_opt('comment_move_down', True) if False:pass elif 1==len(crts) and bEmpSel and bUseFLn and bSkip: apx._move_caret_down(cCrt, rCrt) if bOnlyLn and not do_uncmt: crt=ed.get_carets()[0]; apx._move_caret_down(crt[0], crt[1]) crt=ed.get_carets()[0]; apx._move_caret_down(crt[0], crt[1])