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])