예제 #1
0
 def __init__(self):  #NOTE: init
     if app.app_api_version() < FROM_API_VERSION:
         return app.msg_status(_('Need update application'))
     self.wrap = apx.get_opt('intextbookmk_wrap',
                             apx.get_opt('ibm_wrap', True))
     self.show_wo_alt = apx.get_opt('intextbookmk_compact_show',
                                    apx.get_opt('ibm_compact_show', True))
     #       self.show_wo_alt= apx.get_opt('intextbookmk_compact_show'    , apx.get_opt('ibm_compact_show'    , False))
     self.unlxr_cmnt = apx.get_opt(
         'intextbookmk_no_lexer_comment',
         apx.get_opt('ibm_no_lexer_comment', '//'))
     self.bm_signs = apx.get_opt(
         'intextbookmk_signs',
         apx.get_opt('ibm_signs',
                     ['NOTE:', 'NB!', 'TODO:', 'todo:', 'todo.', 'FIX:']))
     self.bm_signs = [self.bm_signs] if type(
         self.bm_signs) == str else self.bm_signs
     self.bm_sign = self.bm_signs[0]
     self.lxr2cmnt = {NO_LXR_SIGN: self.unlxr_cmnt}
     self.ext2lxr = {}
     for lxr in apx.get_enabled_lexers():
         cmnt = app.lexer_proc(app.LEXER_GET_PROP, lxr)['c_line']
         #           cmnt                    = app.lexer_proc(app.LEXER_GET_COMMENT, lxr)
         if not cmnt:
             continue  #for lxr
         self.lxr2cmnt[lxr] = cmnt
         for ext in app.lexer_proc(app.LEXER_GET_PROP, lxr)['typ']:
             self.ext2lxr[ext] = lxr
예제 #2
0
 def _get_cmt_pair(self, lex):
     ''' Return ((begin_sign, end_sign), only_lines)
             begin_sign    as '/*'
             end_sign      as '*/'
             only_lines    True if each of *_sign must be whole line
     '''
     if lex not in self.pair4lex:
         only_ln = False
         pair1 = app.lexer_proc(app.LEXER_GET_COMMENT_STREAM, lex)
         pair2 = app.lexer_proc(app.LEXER_GET_COMMENT_LINED, lex)
         if pair1 is not None: pair = pair1
         elif pair2 is not None: pair = pair2; only_ln = True
         else: pair = ('', '')
         self.pair4lex[lex] = (pair, only_ln)
     return self.pair4lex[lex]
예제 #3
0
    def __init__(self, ed: ct.Editor):
        self.fp = ed.get_filename()
        if op.exists(self.fp):
            self.fn = op.basename(self.fp)
            self.fdir = op.dirname(self.fp)
        else:
            self.fn = ''
            self.fdir = ''

        x0, y0, x1, y1 = ed.get_carets()[0]
        self.line_index = y0
        self.text_sel = ed.get_text_sel()
        self.clipboard = ct.app_proc(ct.PROC_GET_CLIP, '')
        self.line = ed.get_text_line(y0)
        self.word, _ = get_word_under_cursor(self.line, x0)

        self.lexer = ed.get_prop(ct.PROP_LEXER_FILE)
        prop = ct.lexer_proc(ct.LEXER_GET_PROP, self.lexer)
        if prop:
            prop_str = prop.get('c_str')
            prop_line = prop.get('c_line')
            self.cmt_start = prop_str[0] if prop_str else ''
            self.cmt_end = prop_str[1] if prop_str else ''
            self.cmt_line = prop_line if prop_line else ''
        else:
            self.cmt_start = ''
            self.cmt_end = ''
            self.cmt_line = ''
def snip_replace_macros_in_lines(items, text_sel, text_clip, text_filename):
    for index in range(len(items)):
        s = items[index]
        while True:
            n = s.find(MACRO_SEL)
            if n<0: break
            s = s[:n]+text_sel+s[n+len(MACRO_SEL):]

        while True:
            n = s.find(MACRO_CLIP)
            if n<0: break
            s = s[:n]+text_clip+s[n+len(MACRO_CLIP):]

        while True:
            n = s.find(MACRO_FILENAME)
            if n<0: break
            s = s[:n]+text_filename+s[n+len(MACRO_FILENAME):]

        cmt_start = ''
        cmt_end = ''
        cmt_line = ''
        lexer = app.ed.get_prop(app.PROP_LEXER_FILE)
        prop = app.lexer_proc(app.LEXER_GET_PROP, lexer)
        if prop:
            prop_str = prop.get('c_str')
            prop_line = prop.get('c_line')
            cmt_start = prop_str[0] if prop_str else ''
            cmt_end = prop_str[1] if prop_str else ''
            cmt_line = prop_line if prop_line else ''

        while True:
            n = s.find(MACRO_CMT_START)
            if n<0: break
            s = s[:n]+cmt_start+s[n+len(MACRO_CMT_START):]

        while True:
            n = s.find(MACRO_CMT_END)
            if n<0: break
            s = s[:n]+cmt_end+s[n+len(MACRO_CMT_END):]

        while True:
            n = s.find(MACRO_CMT_LINE)
            if n<0: break
            s = s[:n]+cmt_line+s[n+len(MACRO_CMT_LINE):]

        while True:
            n = s.find(MACRO_DATE)
            if n<0: break
            text_date = s[n:]
            nn = text_date.find('}')
            if nn<0: break
            text_date = text_date[len(MACRO_DATE):nn]
            text_date = datetime.now().strftime(text_date)
            s = s[:n]+text_date+s[n+nn+1:]

        if items[index]!=s:
            items[index] = s
예제 #5
0
 def _get_cmt_pair(self, lex):
     ''' Return ((begin_sign, end_sign), only_lines)
             begin_sign    as '/*'
             end_sign      as '*/'
             only_lines    True if each of *_sign must be whole line
     '''
     if lex not in self.pair4lex:
         only_ln = False
         pair1 = app.lexer_proc(app.LEXER_GET_COMMENT_STREAM, lex)
         pair2 = app.lexer_proc(app.LEXER_GET_COMMENT_LINED, lex)
         if pair1 is not None: pair = pair1
         elif pair2 is not None:
             pair = pair2
             only_ln = True
         else:
             pair = ('', '')
         self.pair4lex[lex] = (pair, only_ln)
     return self.pair4lex[lex]
예제 #6
0
    def __init__(
            self,
            path_keys_info=''  # default.json or parsed data (file or list_of_dicts)
        ,
            subset=''  # To get/set from/to cuda_options_editor.json
        ,
            how={}  # Details to work
    ):
        M, m = self.__class__, self

        m.ed = ed
        m.how = how

        m.defn_path = Path(path_keys_info) if str == type(
            path_keys_info) else json.dumps(path_keys_info)

        m.subset = subset
        #m.stores    = get_hist('dlg'
        #, json.loads(open(CFG_JSON).read(), object_pairs_hook=odict)
        #if os.path.exists(CFG_JSON) else odict())
        pass
        #LOG and log('ok',())
        #       m.bk_sets   = m.stores.get(m.subset+'bk_sets'    , False)
        m.lexr_l = app.lexer_proc(app.LEXER_GET_LEXERS, False)
        m.lexr_w_l = [
            f(
                '{} {}', '!!' if os.path.isfile(
                    app.app_path(app.APP_DIR_SETTINGS) + os.sep + 'lexer ' +
                    lxr + '.json') else '  ', lxr) for lxr in m.lexr_l
        ]

        m.lexr = m.ed.get_prop(app.PROP_LEXER_CARET)
        m.all_ops = False  # Show also options without definition

        '!!! ALL options'
        m.opts_defn = {
        }  # Meta-info for options: format, comment, dict of values, chapter, tags
        m.opts_full = {}  # Show all options
        m.chp_tree = {}  # {'Ui':{ops:[], 'kids':{...}, 'path':'Ui/Tabs'}
        m.pth2chp = {}  # path-index for m.chp_tree

        # Cache
        m.SKWULFs = []  # Last filtered+sorted
        m.cols = []  # Last info about listview columns
        m.itms = []  # Last info about listview cells

        #       m.bk_files  = {}
        #       m.do_file('backup-user')    if m.bk_sets else 0

        m.do_file('load-data')

        m.for_ulf = 'u'  # 'u' for User, 'l' for Lexer, 'f' for File

        #m.apply_one = m.stores.get(m.subset+'apply_one', False) # Do one call OpsReloadAndApply on exit
        #m.apply_need= False                                     # Need to call OpsReloadAndApply
        #m.auto4file = m.stores.get(m.subset+'auto4file', True)  # Auto reset file value to over value def/user/lex
        m.auto4file = True  # Auto reset file value to over value def/user/lex
예제 #7
0
    def __init__(self):#NOTE: init
        if app.app_api_version()<FROM_API_VERSION:  return app.msg_status(_('Need update application'))
        self.wrap       = apx.get_opt('intextbookmk_wrap'            , apx.get_opt('ibm_wrap'            , True))
        self.show_wo_alt= apx.get_opt('intextbookmk_compact_show'    , apx.get_opt('ibm_compact_show'    , True))
#       self.show_wo_alt= apx.get_opt('intextbookmk_compact_show'    , apx.get_opt('ibm_compact_show'    , False))
        self.unlxr_cmnt = apx.get_opt('intextbookmk_no_lexer_comment', apx.get_opt('ibm_no_lexer_comment', '//'))
        self.bm_signs   = apx.get_opt('intextbookmk_signs'           , apx.get_opt('ibm_signs'           , ['NOTE:', 'NB!', 'TODO:', 'todo:', 'todo.', 'FIX:']))
        self.bm_signs   = [self.bm_signs] if type(self.bm_signs)==str else self.bm_signs
        self.bm_sign    = self.bm_signs[0]
        self.lxr2cmnt   = {NO_LXR_SIGN:self.unlxr_cmnt}
        self.ext2lxr    = {}
        for lxr in apx.get_enabled_lexers():
            cmnt                    = app.lexer_proc(app.LEXER_GET_PROP, lxr)['c_line']
#           cmnt                    = app.lexer_proc(app.LEXER_GET_COMMENT, lxr)
            if not cmnt:
                continue#for lxr
            self.lxr2cmnt[lxr]      = cmnt
            for ext in app.lexer_proc(app.LEXER_GET_PROP, lxr)['typ']:
                self.ext2lxr[ext]   = lxr
예제 #8
0
    def __init__(self):
        self.cfg = Setting()
        self.parser = Parser()
        self.change_parser()
        self.date = Date()

        if MYLEXER not in ct.lexer_proc(ct.LEXER_GET_LEXERS, ''):
            ct.msg_box(
                'Plugin "Plain Tasks" could not find it\'s required lexer ToDo.'
                +
                ' Please install this lexer from "Plugins / Addon Manager / Install" and restart CudaText.',
                ct.MB_OK + ct.MB_ICONERROR)
예제 #9
0
    def _menu_ed_lex(self, id_dlg, id_ctl, data='', info=''):
        pkg = self._get_sel_pkg()
        snips_fn, group_lexers = self._get_sel_group(pkg)

        group_lexers = set(group_lexers) if group_lexers else set()

        ### menu
        h_menu = ct.menu_proc(0, ct.MENU_CREATE)

        # fill
        app_lexs = ct.lexer_proc(ct.LEXER_GET_LEXERS, '')
        for lex in app_lexs:
            caption = '** ' + lex if lex in group_lexers else lex  # mark lexers of current snippet group
            command = lambda l=lex: self.ed.set_prop(ct.PROP_LEXER_FILE, l)
            ct.menu_proc(h_menu, ct.MENU_ADD, command=command, caption=caption)

        ct.menu_proc(h_menu, ct.MENU_SHOW)
예제 #10
0
    def _menu_add_lex(self, *args, lex=None, **vargs):
        if lex is None:  # initial call: show menu
            lexs = ct.lexer_proc(ct.LEXER_GET_LEXERS, '')

            h_menu = ct.menu_proc(0, ct.MENU_CREATE)
            for lex in lexs:
                ct.menu_proc(h_menu,
                             ct.MENU_ADD,
                             command=lambda l=lex: self._menu_add_lex(lex=l),
                             caption=lex)
            ct.menu_proc(h_menu, ct.MENU_SHOW)

        else:  # add specified lexer
            p = ct.dlg_proc(self.h, ct.DLG_CTL_PROP_GET, index=self.n_lex)
            val = p['val']
            newval = lex if not val else val + ', ' + lex
            p = ct.dlg_proc(self.h,
                            ct.DLG_CTL_PROP_SET,
                            index=self.n_lex,
                            prop={'val': newval})
예제 #11
0
 def _get_cmt_pair(self, lex):
     ''' Return ((begin_sign, end_sign), only_lines)
             begin_sign    as '/*'
             end_sign      as '*/'
             only_lines    True if each of *_sign must be whole line
     '''
     if lex not in self.pair4lex:
         only_ln = False
         prop = app.lexer_proc(app.LEXER_GET_PROP, lex)
         pair1 = prop['c_str'] if prop else None
         pair2 = prop['c_lined'] if prop else None
         if pair1 is not None:
             pair = pair1
         elif pair2 is not None:
             pair = pair2
             only_ln = True
         else:
             pair = ('', '')
         self.pair4lex[lex] = (pair, only_ln)
     return self.pair4lex[lex]
예제 #12
0
    def _on_group_selected(self, id_dlg, id_ctl, data='', info=''):
        #pass; print('group sel')

        # disable all below 'group'
        self._enable_ctls(False, self.n_alias, self.n_edit, self.n_add_snip,
                          self.n_del_snip)

        self.ed.set_text_all('')

        pkg = self._get_sel_pkg()
        snips_fn, lexers = self._get_sel_group(pkg)

        #pass; print(' * selected B:group: {0}, lexers:{1}'.format(snips_fn, lexers))

        if not pkg or not snips_fn:
            return

        if self.file_snippets.get((pkg['path'], snips_fn)) is None:
            self._load_package_snippets(pkg['path'])
            #pass; print('   + loaded group snips')

        # enable stuff
        self._enable_ctls(True, self.n_lex, self.n_snippets, self.n_add_group,
                          self.n_del_group, self.n_add_lex, self.n_add_snip)

        ### fill groups
        # lexers
        ct.dlg_proc(self.h,
                    ct.DLG_CTL_PROP_SET,
                    index=self.n_lex,
                    prop={
                        'val': ', '.join(lexers),
                    })

        # snippet names
        snip_items = [
            name for name, val in self.file_snippets.get((pkg['path'],
                                                          snips_fn)).items()
            if 'body' in val and 'prefix' in val
        ]
        snip_items.sort()
        self.snip_items = [*snip_items]

        snip_items = '\t'.join(snip_items)
        ct.dlg_proc(
            self.h,
            ct.DLG_CTL_PROP_SET,
            index=self.n_snippets,
            prop={
                'val': None,  # selected item
                'items': snip_items,
            })

        # set editor lexer to first existing lexer of snippet group
        if lexers:
            ed_lex = self.ed.get_prop(ct.PROP_LEXER_FILE)
            if not ed_lex or ed_lex not in lexers:  # dont change if current editor lex is in group
                app_lexs = ct.lexer_proc(ct.LEXER_GET_LEXERS, '')
                for lex in lexers:
                    if lex in app_lexs:
                        self.ed.set_prop(ct.PROP_LEXER_FILE, lex)
예제 #13
0
    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)
예제 #14
0
    def _cmt_toggle_line(self, cmt_act, cmt_type='', ed_=ed):
        ''' Add/Remove full line comment
            Params
                cmt_act     'del'   uncomment all lines
                            'add'   comment all lines
                            'bgn'   (un)comment all as toggled first line
                cmt_type    '1st'   at begin of line
                            'bod'   at first not blank
        '''
#       if not apx._check_API('1.0.108'):    return
        lex         = ed_.get_prop(app.PROP_LEXER_CARET)
        prop        = app.lexer_proc(app.LEXER_GET_PROP, lex)
        cmt_sgn     = prop['c_line'] if prop else None
        pass;                  #LOG and log('cmt_type, lex, cmt_sgn={}', (cmt_type, lex, cmt_sgn))
        if not cmt_sgn:
            return app.msg_status(f(_('No line comment for lexer "{}"'), lex))
        # Analize
        bEmpSel     = False
        rWrks       = []
        bUseRepLns  = app.app_api_version()>='1.0.177'
        y1,y2,lines = (-1, -1, []) if bUseRepLns else (None, None, None) # To use API replace_lines
        pass;                  #LOG and log('ed_.get_sel_mode(),app.SEL_NORMAL,app.SEL_COLUMN={}', (ed_.get_sel_mode(),app.SEL_NORMAL,app.SEL_COLUMN))
        crts        = ed_.get_carets()
        if False:pass
        elif ed_.get_sel_mode() == app.SEL_NORMAL:
            bEmpSel     = 1==len(crts) and -1==crts[0][3]
            for (cCrt, rCrt ,cEnd, rEnd) in crts:
                (rCrtMin
                ,rCrtMax)   = apx.minmax(rCrt, rEnd if -1!=rEnd else rCrt)
                if -1!=rEnd and rCrt>rEnd and 0==cCrt:
                    rCrtMax = rCrtMax-1    # For direct section along left bound
                rWrks      += list(range(rCrtMin, rCrtMax+1))
            bUseRepLns  = bUseRepLns and 1==len(crts)
        elif ed_.get_sel_mode() == app.SEL_COLUMN:
            (cBgn
            ,rSelBgn
            ,cEnd
            ,rSelEnd)   = ed_.get_sel_rect()
            rWrks       = list(range(rSelBgn, rSelEnd+1))
        if not rWrks:
            rWrks       = [crts[0][1]]
        pass;                  #LOG and log('rWrks={}', (rWrks))
        y1,y2       = (rWrks[0],rWrks[-1]) if bUseRepLns else (y1,y2)
        pass;                  #LOG and log('y1,y2,lines={}', (y1,y2,lines))
        do_uncmt    = ed_.get_text_line(rWrks[0]).lstrip().startswith(cmt_sgn) \
                        if cmt_act=='bgn' else \
                      True \
                        if cmt_act=='del' else \
                      False
        # Work
        save_bd_col = apx.get_opt('comment_save_column' , False)
        at_min_bd   = apx.get_opt('comment_equal_column', False)
        col_min_bd  = 1000 # infinity
        if at_min_bd:
            for rWrk in rWrks:
                line        = ed_.get_text_line(rWrk)
                pos_body    = line.index(line.lstrip())
                pos_body    = len(line) if 0==len(line.lstrip()) else pos_body
                col_min_bd  = min(pos_body, col_min_bd)
                if 0==col_min_bd:
                    break # for rWrk
        blnks4cmt   = ' '*len(cmt_sgn) # '\t'.expandtabs(len(cmt_sgn))
        pass;                  #LOG and log('rWrks,do_uncmt, save_cols, at_min_bd, col_min_bd={}', (rWrks,do_uncmt,save_bd_col,at_min_bd,col_min_bd))
        for rWrk in rWrks:
            line    = ed_.get_text_line(rWrk)
            pos_body= line.index(line.lstrip())
            pos_body= len(line) if 0==len(line.lstrip()) else pos_body
            pass;              #LOG and log('rWrk,pos_body,line={}', (rWrk,pos_body,line))
            if do_uncmt:
                # Uncomment!
                if not line[pos_body:].startswith(cmt_sgn):
                    # Already no comment
                    if bUseRepLns:
                        lines += [line]
                    continue    #for rWrk
                if False:pass
                elif len(line)==len(cmt_sgn): # and line.startswith(cmt_sgn)
                    line = ''
                elif save_bd_col and (' '==line[0] or
                                      ' '==line[pos_body+len(cmt_sgn)]):
                    # Before or after cmt_sgn must be blank
                    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
                    if bUseRepLns:
                        lines += [line]
                    continue    #for rWrk
                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):
                    pos_cmnt = col_min_bd if at_min_bd else pos_body
                    pass;          #LOG and log('pos_cmnt={}', (pos_cmnt))
                    if pos_cmnt>=len(cmt_sgn):
                        line = line[:pos_cmnt-len(cmt_sgn)]+cmt_sgn+line[pos_cmnt:             ]
                    else:
                        line = line[:pos_cmnt             ]+cmt_sgn+line[pos_cmnt+len(cmt_sgn):]
                   #line = line[:pos_cmnt-len(cmt_sgn)]+cmt_sgn+line[pos_cmnt:]
                   #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
                    pos_cmnt = col_min_bd if at_min_bd else pos_body
                    pass;      #LOG and log('pos_cmnt={}', (pos_cmnt))
                    line = line[:pos_cmnt]             +cmt_sgn+line[pos_cmnt:]
                   #line = line[:pos_body]             +cmt_sgn+line[pos_body:]

            pass;              #LOG and log('new line={}', (line))
            if bUseRepLns:
                lines += [line]
            else:
                ed_.set_text_line(rWrk, line)
            #for rWrk
        if bUseRepLns:
            ed_.replace_lines(y1, y2, lines)
        bSkip    = apx.get_opt('comment_move_down', True)
        if bEmpSel and bSkip:
            (cCrt, rCrt, cEnd, rEnd)    = crts[0]
            apx._move_caret_down(cCrt, rCrt)
예제 #15
0
    def _cmt_toggle_line(self, cmt_type, ed_=ed):
        ''' Add/Remove full line comment
            Params
                cmt_type    '1st'    at begin of line
                            'bod'    at first not blank
        '''
        if not _check_API('1.0.108'):    return
        lex         = ed_.get_prop(app.PROP_LEXER_CARET)
        cmt_sgn     = app.lexer_proc(app.LEXER_GET_COMMENT, lex)
        pass;                  #LOG and log('cmt_type, lex, cmt_sgn={}', (cmt_type, lex, cmt_sgn))
        if not cmt_sgn:
            return app.msg_status(CMT_NO_LINE_4LEX.format(lex))
        # Analize
        bEmpSel     = False
        rWrks       = []
        pass;                  #LOG and log('ed_.get_sel_mode(),app.SEL_NORMAL,app.SEL_COLUMN={}', (ed_.get_sel_mode(),app.SEL_NORMAL,app.SEL_COLUMN))
        if False:pass
        elif ed_.get_sel_mode() == app.SEL_NORMAL:
            crts        = ed_.get_carets()
            bEmpSel     = 1==len(crts) and -1==crts[0][3]
            for (cCrt, rCrt ,cEnd, rEnd) in crts:
                (rCrtMin
                ,rCrtMax)   = minmax(rCrt, rEnd if -1!=rEnd else rCrt)
                if -1!=rEnd and rCrt>rEnd and 0==cCrt:
                    rCrtMax = rCrtMax-1    # For direct section along left bound
                rWrks      += list(range(rCrtMin, rCrtMax+1))
        elif ed_.get_sel_mode() == app.SEL_COLUMN:
            (cBgn
            ,rSelBgn
            ,cEnd
            ,rSelEnd)   = ed_.get_sel_rect()
            rWrks       = list(range(rSelBgn, rSelEnd+1))
        if not rWrks:
            rWrks       = [crts[0][1]]
        do_uncmt    = ed_.get_text_line(rWrks[0]).lstrip().startswith(cmt_sgn)
        # Work
        save_bd_col = get_opt('comment_save_column' , False)
        at_min_bd   = get_opt('comment_equal_column', False)
        col_min_bd  = 1000 # infinity
        if at_min_bd:
            for rWrk in rWrks:
                line        = ed_.get_text_line(rWrk)
                pos_body    = line.index(line.lstrip())
                pos_body    = len(line) if 0==len(line.lstrip()) else pos_body
                col_min_bd  = min(pos_body, col_min_bd)
                if 0==col_min_bd:
                    break # for rWrk
        blnks4cmt   = '\t'.expandtabs(len(cmt_sgn))
        pass;                  #LOG and log('rWrks,do_uncmt, save_cols, at_min_bd, col_min_bd={}', (rWrks,do_uncmt,save_bd_col,at_min_bd,col_min_bd))
        for rWrk in rWrks:
            line    = ed_.get_text_line(rWrk)
            pos_body= line.index(line.lstrip())
            pos_body= len(line) if 0==len(line.lstrip()) else pos_body
            pass;              #LOG and log('rWrk,pos_body,line={}', (rWrk,pos_body,line))
            if do_uncmt:
                # Uncomment!
                if not line[pos_body:].startswith(cmt_sgn):
                    # Already no comment
                    continue    #for rWrk
                if False:pass
                elif len(line)==len(cmt_sgn): # and line.startswith(cmt_sgn)
                    line = ''
                elif save_bd_col and (' '==line[0] or
                                      ' '==line[pos_body+len(cmt_sgn)]):
                    # Before or after cmt_sgn must be blank
                    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    #for rWrk
                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):
                    pos_cmnt = col_min_bd if at_min_bd else pos_body
                    pass;          #LOG and log('pos_cmnt={}', (pos_cmnt))
                    if pos_cmnt>=len(cmt_sgn):
                        line = line[:pos_cmnt-len(cmt_sgn)]+cmt_sgn+line[pos_cmnt:             ]
                    else:
                        line = line[:pos_cmnt             ]+cmt_sgn+line[pos_cmnt+len(cmt_sgn):]
                   #line = line[:pos_cmnt-len(cmt_sgn)]+cmt_sgn+line[pos_cmnt:]
                   #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
                    pos_cmnt = col_min_bd if at_min_bd else pos_body
                    pass;      #LOG and log('pos_cmnt={}', (pos_cmnt))
                    line = line[:pos_cmnt]             +cmt_sgn+line[pos_cmnt:]
                   #line = line[:pos_body]             +cmt_sgn+line[pos_body:]

            pass;              #LOG and log('new line={}', (line))
            ed_.set_text_line(rWrk, line)
            #for rWrk
        bSkip    = get_opt('comment_move_down', True)
        if bEmpSel and bSkip:
            _move_caret_down(cCrt, rCrt)
예제 #16
0
    def _cmt_toggle_line(self, cmt_act, cmt_type='', ed_=ed):
        ''' Add/Remove full line comment
            Params
                cmt_act     'del'   uncomment all lines
                            'add'   comment all lines
                            'bgn'   (un)comment all as toggled first line
                cmt_type    '1st'   at begin of line
                            'bod'   at first not blank
        '''
        #       if not apx._check_API('1.0.108'):    return
        lex = ed_.get_prop(app.PROP_LEXER_CARET)
        if not lex:
            return
        prop = app.lexer_proc(app.LEXER_GET_PROP, lex)
        if not prop:
            return
        cmt_sgn = prop['c_line']
        pass
        #log('cmt_type, lex, cmt_sgn={}', (cmt_type, lex, cmt_sgn))
        if not cmt_sgn:
            return app.msg_status(
                f(_('Lexer "{}" don\'t support "line comments"'), lex))
        # Analize
        empty_sel = False
        rWrks = []
        use_rep_lines = True  # use API replace_lines()
        y1, y2, lines = (-1, -1, []) if use_rep_lines else (None, None, None)
        pass
        #LOG and log('ed_.get_sel_mode(),app.SEL_NORMAL,app.SEL_COLUMN={}', (ed_.get_sel_mode(),app.SEL_NORMAL,app.SEL_COLUMN))
        crts = ed_.get_carets()
        if False: pass
        elif ed_.get_sel_mode() == app.SEL_NORMAL:
            empty_sel = 1 == len(crts) and -1 == crts[0][3]
            for (cCrt, rCrt, cEnd, rEnd) in crts:
                (rCrtMin, rCrtMax) = apx.minmax(rCrt,
                                                rEnd if -1 != rEnd else rCrt)
                if -1 != rEnd and rCrt > rEnd and 0 == cCrt:
                    rCrtMax = rCrtMax - 1  # For direct section along left bound
                rWrks += list(range(rCrtMin, rCrtMax + 1))
            use_rep_lines = use_rep_lines and 1 == len(crts)
        elif ed_.get_sel_mode() == app.SEL_COLUMN:
            (cBgn, rSelBgn, cEnd, rSelEnd) = ed_.get_sel_rect()
            rWrks = list(range(rSelBgn, rSelEnd + 1))
        if not rWrks:
            rWrks = [crts[0][1]]
        pass
        #log('rWrks={}', (rWrks))
        y1, y2 = (rWrks[0], rWrks[-1]) if use_rep_lines else (y1, y2)
        pass
        #LOG and log('y1,y2,lines={}', (y1,y2,lines))
        do_uncmt    = ed_.get_text_line(rWrks[0]).lstrip().startswith(cmt_sgn) \
                        if cmt_act=='bgn' else \
                      True \
                        if cmt_act=='del' else \
                      False
        # Work
        save_bd_col = apx.get_opt('comment_save_column', False)
        at_min_bd = apx.get_opt('comment_equal_column', False)
        col_min_bd = 1000  # infinity
        col_kept = False  # plugin applied the "Try to keep text position"
        if at_min_bd:
            for rWrk in rWrks:
                line = ed_.get_text_line(rWrk)
                pos_body = line.index(line.lstrip())
                pos_body = len(line) if 0 == len(line.lstrip()) else pos_body
                col_min_bd = min(pos_body, col_min_bd)
                if 0 == col_min_bd:
                    break  # for rWrk
        blnks4cmt = ' ' * len(cmt_sgn)  # '\t'.expandtabs(len(cmt_sgn))
        pass
        #log('rWrks,do_uncmt, save_cols, at_min_bd, col_min_bd={}', (rWrks,do_uncmt,save_bd_col,at_min_bd,col_min_bd))
        for rWrk in rWrks:
            line = ed_.get_text_line(rWrk)
            pos_body = line.index(line.lstrip())
            pos_body = len(line) if 0 == len(line.lstrip()) else pos_body
            pass
            #LOG and log('rWrk,pos_body,line={}', (rWrk,pos_body,line))
            if do_uncmt:
                # Uncomment!
                if not line[pos_body:].startswith(cmt_sgn):
                    # Already no comment
                    if use_rep_lines:
                        lines += [line]
                    continue  #for rWrk
                if False: pass
                elif len(line) == len(cmt_sgn):  # and line.startswith(cmt_sgn)
                    line = ''
                elif save_bd_col and (' ' == line[0]
                                      or ' ' == line[pos_body + len(cmt_sgn)]):
                    # Before or after cmt_sgn must be blank
                    line = line.replace(cmt_sgn, blnks4cmt, 1)
                    col_kept = True
                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
                    if use_rep_lines:
                        lines += [line]
                    continue  #for rWrk
                if False: pass
                elif cmt_type == '1st' and save_bd_col and line.startswith(
                        blnks4cmt):
                    line = line.replace(blnks4cmt, cmt_sgn, 1)
                    col_kept = True
            #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):
                    col_kept = True
                    pos_cmnt = col_min_bd if at_min_bd else pos_body
                    pass
                    #LOG and log('pos_cmnt={}', (pos_cmnt))
                    if pos_cmnt >= len(cmt_sgn):
                        line = line[:pos_cmnt -
                                    len(cmt_sgn)] + cmt_sgn + line[pos_cmnt:]
                    else:
                        line = line[:pos_cmnt] + cmt_sgn + line[pos_cmnt +
                                                                len(cmt_sgn):]
                #line = line[:pos_cmnt-len(cmt_sgn)]+cmt_sgn+line[pos_cmnt:]
                #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
                    pos_cmnt = col_min_bd if at_min_bd else pos_body
                    pass
                    #LOG and log('pos_cmnt={}', (pos_cmnt))
                    line = line[:pos_cmnt] + cmt_sgn + line[pos_cmnt:]
                #line = line[:pos_body]             +cmt_sgn+line[pos_body:]

            pass
            #LOG and log('new line={}', (line))
            if use_rep_lines:
                lines += [line]
            else:
                pass
                log('line={}', (line))
                ed_.set_text_line(rWrk, line)
            #for rWrk
        if use_rep_lines:
            pass
            #log('y1, y2, len(lines), lines={}',(y1, y2, len(lines), lines))
            if y1 == y2:
                ed_.set_text_line(y1, lines[0])
            else:
                ed_.replace_lines(y1, y2, lines)
        # move caret down
        (cCrt, rCrt, cEnd, rEnd) = crts[0]
        move_down = apx.get_opt('comment_move_down',
                                True) and (rCrt + 1 < ed_.get_line_count())
        if empty_sel and move_down:
            apx._move_caret_down(cCrt, rCrt)
        # shift caret horizontally if it's on the same line
        if not move_down and empty_sel and not col_kept:
            dx = len(cmt_sgn)
            if do_uncmt:
                dx = -dx
            cCrt = max(0, cCrt + dx)
            ed_.set_caret(cCrt, rCrt)
    def __init__(self, data=None):
        self.data = data
        self.items = list(self.data.get('files', {}).keys())
        self.lexers = ct.lexer_proc(ct.LEXER_GET_LEXERS, False)
        self.state = {k: '-1;' + ',' * len(self.lexers) for k in self.items}

        w, h = 600, 400
        self.h = ct.dlg_proc(0, ct.DLG_CREATE)
        ct.dlg_proc(self.h,
                    ct.DLG_PROP_SET,
                    prop={
                        'cap': _('Setup snippet lexer(s)'),
                        'w': w,
                        'h': h,
                        'resize': False,
                        "keypreview": True,
                    })

        self.g1 = ct.dlg_proc(self.h, ct.DLG_CTL_ADD, 'panel')
        ct.dlg_proc(self.h,
                    ct.DLG_CTL_PROP_SET,
                    index=self.g1,
                    prop={
                        'name': 'g1',
                        'h': 40,
                        'align': ct.ALIGN_BOTTOM,
                    })

        self.ls = ct.dlg_proc(self.h, ct.DLG_CTL_ADD, 'listbox')
        ct.dlg_proc(self.h,
                    ct.DLG_CTL_PROP_SET,
                    index=self.ls,
                    prop={
                        'name': 'ls',
                        'w': w // 2,
                        'align': ct.ALIGN_LEFT,
                        'items': '\t'.join(self.items),
                        'val': 0,
                        'sp_a': 4,
                        'on_click': self.load_state,
                    })

        self.chls = ct.dlg_proc(self.h, ct.DLG_CTL_ADD, 'checklistbox')
        ct.dlg_proc(self.h,
                    ct.DLG_CTL_PROP_SET,
                    index=self.chls,
                    prop={
                        'name': 'chls',
                        'w': w // 2,
                        'align': ct.ALIGN_RIGHT,
                        'items': '\t'.join(self.lexers),
                        'sp_a': 4,
                        'on_click': self.update_state,
                    })

        self.b = ct.dlg_proc(self.h, ct.DLG_CTL_ADD, 'button')
        ct.dlg_proc(self.h,
                    ct.DLG_CTL_PROP_SET,
                    index=self.b,
                    prop={
                        'name': 'b',
                        'w': 100,
                        'a_l': None,
                        'a_r': ('g1', ']'),
                        'a_t': ('g1', '['),
                        'sp_r': 4,
                        'sp_t': 4,
                        'p': 'g1',
                        'cap': 'Ok',
                        'on_change': self.press_ok,
                    })
예제 #18
0
def get_enabled_lexers():
    all_lxrs  = app.lexer_proc(app.LEXER_GET_LIST, '').splitlines()
    enb_lxrs  = [lxr for lxr in all_lxrs if app.lexer_proc(app.LEXER_GET_ENABLED, lxr)]
    return enb_lxrs
예제 #19
0
def get_enabled_lexers():
    return app.lexer_proc(app.LEXER_GET_LEXERS, False)
예제 #20
0
파일: __init__.py 프로젝트: heX16/CudaText
def get_enabled_lexers():
    return app.lexer_proc(app.LEXER_GET_LEXERS, False)
예제 #21
0
def get_enabled_lexers():
    all_lxrs = app.lexer_proc(app.LEXER_GET_LIST, '').splitlines()
    enb_lxrs = [
        lxr for lxr in all_lxrs if app.lexer_proc(app.LEXER_GET_ENABLED, lxr)
    ]
    return enb_lxrs
예제 #22
0
    def _cmt_toggle_line(self, cmt_type, ed_=ed):
        ''' Add/Remove full line comment
            Params
                cmt_type    '1st'    at begin of line
                            'bod'    at first not blank
        '''
        if not _check_API('1.0.108'): return
        lex = ed_.get_prop(app.PROP_LEXER_CARET)
        cmt_sgn = app.lexer_proc(app.LEXER_GET_COMMENT, lex)
        pass
        #LOG and log('cmt_type, lex, cmt_sgn={}', (cmt_type, lex, cmt_sgn))
        if not cmt_sgn:
            return app.msg_status(CMT_NO_LINE_4LEX.format(lex))
        # Analize
        bEmpSel = False
        rWrks = []
        pass
        #LOG and log('ed_.get_sel_mode(),app.SEL_NORMAL,app.SEL_COLUMN={}', (ed_.get_sel_mode(),app.SEL_NORMAL,app.SEL_COLUMN))
        crts = ed_.get_carets()
        if False: pass
        elif ed_.get_sel_mode() == app.SEL_NORMAL:
            bEmpSel = 1 == len(crts) and -1 == crts[0][3]
            for (cCrt, rCrt, cEnd, rEnd) in crts:
                (rCrtMin, rCrtMax) = minmax(rCrt, rEnd if -1 != rEnd else rCrt)
                if -1 != rEnd and rCrt > rEnd and 0 == cCrt:
                    rCrtMax = rCrtMax - 1  # For direct section along left bound
                rWrks += list(range(rCrtMin, rCrtMax + 1))
        elif ed_.get_sel_mode() == app.SEL_COLUMN:
            (cBgn, rSelBgn, cEnd, rSelEnd) = ed_.get_sel_rect()
            rWrks = list(range(rSelBgn, rSelEnd + 1))
        if not rWrks:
            rWrks = [crts[0][1]]
        do_uncmt = ed_.get_text_line(rWrks[0]).lstrip().startswith(cmt_sgn)
        # Work
        save_bd_col = get_opt('comment_save_column', False)
        at_min_bd = get_opt('comment_equal_column', False)
        col_min_bd = 1000  # infinity
        if at_min_bd:
            for rWrk in rWrks:
                line = ed_.get_text_line(rWrk)
                pos_body = line.index(line.lstrip())
                pos_body = len(line) if 0 == len(line.lstrip()) else pos_body
                col_min_bd = min(pos_body, col_min_bd)
                if 0 == col_min_bd:
                    break  # for rWrk
        blnks4cmt = ' ' * len(cmt_sgn)  # '\t'.expandtabs(len(cmt_sgn))
        pass
        #LOG and log('rWrks,do_uncmt, save_cols, at_min_bd, col_min_bd={}', (rWrks,do_uncmt,save_bd_col,at_min_bd,col_min_bd))
        for rWrk in rWrks:
            line = ed_.get_text_line(rWrk)
            pos_body = line.index(line.lstrip())
            pos_body = len(line) if 0 == len(line.lstrip()) else pos_body
            pass
            #LOG and log('rWrk,pos_body,line={}', (rWrk,pos_body,line))
            if do_uncmt:
                # Uncomment!
                if not line[pos_body:].startswith(cmt_sgn):
                    # Already no comment
                    continue  #for rWrk
                if False: pass
                elif len(line) == len(cmt_sgn):  # and line.startswith(cmt_sgn)
                    line = ''
                elif save_bd_col and (' ' == line[0]
                                      or ' ' == line[pos_body + len(cmt_sgn)]):
                    # Before or after cmt_sgn must be blank
                    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  #for rWrk
                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):
                    pos_cmnt = col_min_bd if at_min_bd else pos_body
                    pass
                    #LOG and log('pos_cmnt={}', (pos_cmnt))
                    if pos_cmnt >= len(cmt_sgn):
                        line = line[:pos_cmnt -
                                    len(cmt_sgn)] + cmt_sgn + line[pos_cmnt:]
                    else:
                        line = line[:pos_cmnt] + cmt_sgn + line[pos_cmnt +
                                                                len(cmt_sgn):]
                #line = line[:pos_cmnt-len(cmt_sgn)]+cmt_sgn+line[pos_cmnt:]
                #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
                    pos_cmnt = col_min_bd if at_min_bd else pos_body
                    pass
                    #LOG and log('pos_cmnt={}', (pos_cmnt))
                    line = line[:pos_cmnt] + cmt_sgn + line[pos_cmnt:]
                #line = line[:pos_body]             +cmt_sgn+line[pos_body:]

            pass
            #LOG and log('new line={}', (line))
            ed_.set_text_line(rWrk, line)
            #for rWrk
        bSkip = get_opt('comment_move_down', True)
        if bEmpSel and bSkip:
            (cCrt, rCrt, cEnd, rEnd) = crts[0]
            _move_caret_down(cCrt, rCrt)
예제 #23
0
    def _cmt_toggle_line(self, cmt_act, cmt_type='', ed_=ed):
        ''' Add/Remove line-comments
            Params
                cmt_act     'del' - uncomment all lines
                            'add' - comment all lines
                            'bgn' - comment or uncomment, detect it by the 1st selected line
                cmt_type    '1st' - at begin of line
                            'bod' - at first non-blank char
        '''
        #       if not apx._check_API('1.0.108'):    return
        lex = ed_.get_prop(app.PROP_LEXER_CARET)
        if not lex:
            return app.msg_status(_('Commenting requires an active lexer'))
        prop = app.lexer_proc(app.LEXER_GET_PROP, lex)
        if not prop:
            return
        cmt_sgn = prop['c_line']
        pass
        #log('cmt_type, lex, cmt_sgn={}', (cmt_type, lex, cmt_sgn))
        if not cmt_sgn:
            return app.msg_status(
                f(_('Lexer "{}" doesn\'t support "line comments"'), lex))
        # Analyze
        empty_sel = False
        rWrks = []
        use_rep_lines = True  # use API replace_lines()
        y1, y2, lines = (-1, -1, []) if use_rep_lines else (None, None, None)
        pass
        #LOG and log('ed_.get_sel_mode(),app.SEL_NORMAL,app.SEL_COLUMN={}', (ed_.get_sel_mode(),app.SEL_NORMAL,app.SEL_COLUMN))
        crts = ed_.get_carets()
        if False: pass
        elif ed_.get_sel_mode() == app.SEL_NORMAL:
            empty_sel = 1 == len(crts) and -1 == crts[0][3]
            for (cCrt, rCrt, cEnd, rEnd) in crts:
                # sort 2 pairs
                if rEnd >= 0 and (rCrt, cCrt) > (rEnd, cEnd):
                    cCrt, rCrt, cEnd, rEnd = cEnd, rEnd, cCrt, rCrt
                # selection until start of line?
                if rEnd > 0 and cEnd == 0:
                    rEnd -= 1
                rWrks += list(range(rCrt, rEnd + 1))
            use_rep_lines = use_rep_lines and 1 == len(crts)
        elif ed_.get_sel_mode() == app.SEL_COLUMN:
            (cBgn, rSelBgn, cEnd, rSelEnd) = ed_.get_sel_rect()
            rWrks = list(range(rSelBgn, rSelEnd + 1))
        if not rWrks:
            rWrks = [crts[0][1]]
        pass
        #log('rWrks={}', (rWrks))
        y1, y2 = (rWrks[0], rWrks[-1]) if use_rep_lines else (y1, y2)
        pass
        #LOG and log('y1,y2,lines={}', (y1,y2,lines))

        # read options
        save_bd_col = apx.get_opt('comment_save_column', False)
        at_min_bd = apx.get_opt('comment_equal_column', False)
        skip_blank = apx.get_opt('comment_skip_blank', False)
        by_1st = apx.get_opt('comment_toggle_by_nonempty', False)

        if by_1st:
            # find index of first non-blank line
            row1st = -1
            for i in range(y1, y2 + 1):
                sline = ed_.get_text_line(i)
                if sline and sline.strip():
                    row1st = i
                    break
            if row1st < 0:
                app.msg_status(_('Cannot handle blank lines / multi-carets'))
                return
        else:
            row1st = rWrks[0]

        # do we need to 'comment' or 'uncomment'?
        do_uncmt    = ed_.get_text_line(row1st).lstrip().startswith(cmt_sgn) \
                        if cmt_act=='bgn' else \
                      True \
                        if cmt_act=='del' else \
                      False
        # work
        col_min_bd = 1000  # infinity
        col_kept = False  # plugin applied the "Try to keep text position"
        if at_min_bd:
            for rWrk in rWrks:
                line = ed_.get_text_line(rWrk)
                pos_body = line.index(line.lstrip())
                pos_body = len(line) if 0 == len(line.lstrip()) else pos_body
                col_min_bd = min(pos_body, col_min_bd)
                if 0 == col_min_bd:
                    break  # for rWrk
        blnks4cmt = ' ' * len(cmt_sgn)  # '\t'.expandtabs(len(cmt_sgn))
        pass
        #log('rWrks,do_uncmt, save_cols, at_min_bd, col_min_bd={}', (rWrks,do_uncmt,save_bd_col,at_min_bd,col_min_bd))
        for rWrk in rWrks:
            line = ed_.get_text_line(rWrk)
            if skip_blank and not line.strip():
                lines += [line]
                continue
            pos_body = line.index(line.lstrip())
            pos_body = len(line) if 0 == len(line.lstrip()) else pos_body
            pass
            #LOG and log('rWrk,pos_body,line={}', (rWrk,pos_body,line))
            if do_uncmt:
                # Uncomment!
                if not line[pos_body:].startswith(cmt_sgn):
                    # Already no comment
                    if use_rep_lines:
                        lines += [line]
                    continue  #for rWrk
                if False: pass
                elif len(line) == len(cmt_sgn):  # and line.startswith(cmt_sgn)
                    line = ''
                elif save_bd_col and (' ' == line[0]
                                      or ' ' == line[pos_body + len(cmt_sgn)]):
                    # Before or after cmt_sgn must be blank
                    line = line.replace(cmt_sgn, blnks4cmt, 1)
                    col_kept = True
                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
                    if use_rep_lines:
                        lines += [line]
                    continue  #for rWrk
                if False: pass
                elif cmt_type == '1st' and save_bd_col and line.startswith(
                        blnks4cmt):
                    line = line.replace(blnks4cmt, cmt_sgn, 1)
                    col_kept = True
            #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):
                    col_kept = True
                    pos_cmnt = col_min_bd if at_min_bd else pos_body
                    pass
                    #LOG and log('pos_cmnt={}', (pos_cmnt))
                    if pos_cmnt >= len(cmt_sgn):
                        line = line[:pos_cmnt -
                                    len(cmt_sgn)] + cmt_sgn + line[pos_cmnt:]
                    else:
                        line = line[:pos_cmnt] + cmt_sgn + line[pos_cmnt +
                                                                len(cmt_sgn):]
                #line = line[:pos_cmnt-len(cmt_sgn)]+cmt_sgn+line[pos_cmnt:]
                #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
                    pos_cmnt = col_min_bd if at_min_bd else pos_body
                    pass
                    #LOG and log('pos_cmnt={}', (pos_cmnt))
                    line = line[:pos_cmnt] + cmt_sgn + line[pos_cmnt:]
                #line = line[:pos_body]             +cmt_sgn+line[pos_body:]

            pass
            #LOG and log('new line={}', (line))
            if use_rep_lines:
                lines += [line]
            else:
                pass
                log('line={}', (line))
                ed_.set_text_line(rWrk, line)
            #for rWrk
        if use_rep_lines:
            pass
            #log('y1, y2, len(lines), lines={}',(y1, y2, len(lines), lines))
            if y1 == y2:
                ed_.set_text_line(y1, lines[0])
            else:
                ed_.replace_lines(y1, y2, lines)
        # move caret down
        (cCrt, rCrt, cEnd, rEnd) = crts[0]
        move_down = apx.get_opt('comment_move_down',
                                True) and (rCrt + 1 < ed_.get_line_count())
        if empty_sel and move_down:
            apx._move_caret_down(cCrt, rCrt)
        # shift caret horizontally if it's on the same line
        if not move_down and empty_sel and not col_kept:
            dx = len(cmt_sgn)
            if do_uncmt:
                dx = -dx
            cCrt = max(0, cCrt + dx)
            ed_.set_caret(cCrt, rCrt)