def run(self, edit):
    v = self.view
    if v.sel()[0].size() == 0:
        v.run_command("expand_selection", {"to": "word"})

    cur_start = v.sel()[0].begin()
    cur_end = v.sel()[0].end()

    for sel in v.sel():
        text = v.substr(sel)
        res = self.matcher(text)
        
        if not res:
          #first check one character to the left to see if its a symbol
          sel = Region(sel.begin() - 1, sel.end())
          text = v.substr(sel)
          res = self.matcher(text)

          if not res:
            #now expand selection one character to the right to see if its a string
            sel = Region(sel.begin(), sel.end() + 1)
            text = v.substr(sel)
            res = self.matcher(text)

            if not res:
              #this is a mute point
              continue

        self.replacer(v, edit, sel, text, res)

    v.sel().clear()
    v.sel().add(Region(cur_start, cur_end))
    def run(self, edit):
        sel = self.view.sel()
        current = sel[0].begin()
        line = self.view.line(current)
        length = line.end() - line.begin()

        upper = '/*==' + ('-' * (length - 1))
        bottom = '/' + ('-' * (length - 1)) + '==*/'

        added = self.view.insert(edit, line.begin(), upper + '\n/ ')
        line = Region(line.begin() + added, line.end() + added)
        self.view.insert(edit, line.end(), '\n' + bottom)
    def run(self, edit, **kwargs):
        v = self.view
        if v.sel()[0].size() == 0:
            v.run_command('expand_selection', {'to': 'scope'})

        for sel in v.sel():
            text = v.substr(sel)
            res = re_quotes.match(text)
            if not res:
                #  the current selection doesn't begin and end with a quote.
                #  let's expand the selection one character each direction and try again
                sel = Region(sel.begin() - 1, sel.end() + 1)
                text = v.substr(sel)
                res = re_quotes.match(text)
                if not res:
                    #  still no match... skip it!
                    continue
            oldQuotes = res.group(1)
            if 'key' in kwargs:
                newQuotes = kwargs['key']
            else:
                newQuotes = quoteList[(quoteList.index(oldQuotes) + 1) % len(quoteList)]
            text = res.group(2)
            text = text.replace(newQuotes, "\\" + newQuotes)
            text = text.replace("\\" + oldQuotes, oldQuotes)
            text = newQuotes + text + newQuotes
            v.replace(edit, sel, text)
Exemple #4
0
    def run(self, edit):
        v = self.view
        if v.sel()[0].size() == 0:
            v.run_command("expand_selection", {"to": "scope"})

        for sel in v.sel():
            text = v.substr(sel)
            res = re_quotes.match(text)
            if not res:
                #  the current selection doesn't begin and end with a quote.
                #  let's expand the selection one character each direction and try again
                sel = Region(sel.begin() - 1, sel.end() + 1)
                text = v.substr(sel)
                res = re_quotes.match(text)
                if not res:
                    #  still no match... skip it!
                    continue
            oldQuotes = res.group(1)
            newQuotes = "'" if oldQuotes == '"' else '"'
            text = res.group(2)
            text = string.replace(text, newQuotes, "\\" + newQuotes)
            text = string.replace(text, "\\" + oldQuotes, oldQuotes)
            text = newQuotes + text + newQuotes
            v.replace(edit, sel, text)
def at_word_bound(editor: sublime.View, r: sublime.Region) -> bool:
    ch = editor.substr(r.end())
    return not ch or re_bound_char.match(ch)
def create_tracker(editor: sublime.View, region: sublime.Region,
                   params: dict) -> AbbreviationTracker:
    """
    Creates abbreviation tracker for given range in editor. Parses contents
    of abbreviation in range and returns either valid abbreviation tracker,
    error tracker or `None` if abbreviation cannot be created from given range
    """
    config = get_by_key(params, 'config')
    offset = get_by_key(params, 'offset', 0)
    forced = get_by_key(params, 'forced', False)
    line = editor.line(region.begin())

    if region.a > region.b or (region.a == region.b
                               and not forced) or not line.contains(region):
        # * Invalid range
        # * Mulitline regions are not supported
        return

    abbreviation = editor.substr(region)
    if offset:
        abbreviation = abbreviation[offset:]

    # Basic validation: do not allow empty abbreviations
    # or newlines in abbreviations
    if (not abbreviation
            and not forced) or '\n' in abbreviation or '\r' in abbreviation:
        return

    tracker_params = {
        'forced': forced,
        'offset': offset,
        'line': line,
        'last_pos': region.end(),
    }

    try:
        tracker_params['simple'] = False

        if config.type == 'stylesheet':
            parsed_abbr = stylesheet_abbreviation(abbreviation, config)
        else:
            parsed_abbr = markup_abbreviation(abbreviation, config)
            jsx = config and syntax.is_jsx(config.syntax) and bool(
                get_jsx_prefix())
            tracker_params[
                'simple'] = not jsx and is_simple_markup_abbreviation(
                    parsed_abbr)

        preview_config = get_preview_config(config)
        tracker_params['preview'] = expand(abbreviation, preview_config)
        if forced or config.type != 'stylesheet' or tracker_params['preview']:
            # Create tracker only if preview is not empty for non-forced abbreviation.
            # Empty preview means Emmet was unable to find proper match for given
            # abbreviation. Most likely it happens in stylesheets in `Section` scope
            # NB: empty preview is perfectly valid case for markup abbreviations,
            # for example, `()` abbreviation produces empty output
            return AbbreviationTrackerValid(abbreviation, region, config,
                                            tracker_params)
    except Exception as err:
        if hasattr(err, 'message') and hasattr(err, 'pos'):
            tracker_params['error'] = {
                'message': err.message.split('\n')[0],
                'pos': err.pos,
                'pointer':
                '%s^' % ('-' * err.pos, ) if err.pos is not None else ''
            }
            return AbbreviationTrackerError(abbreviation, region, config,
                                            tracker_params)
        else:
            print('Error while parsing abbreviation')
            traceback.print_exc()
def in_range(region: sublime.Region, pt: int):
    return region.begin() < pt < region.end()
    def run_each(self,
                 edit,
                 region,
                 braces='{}',
                 pressed=None,
                 unindent=False,
                 select=False,
                 replace=False):
        self.view.sel().subtract(region)
        if self.view.settings().get('translate_tabs_to_spaces'):
            tab = ' ' * self.view.settings().get('tab_size')
        else:
            tab = "\t"

        row, col = self.view.rowcol(region.begin())
        indent_point = self.view.text_point(row, 0)
        if indent_point < region.begin():
            indent = self.view.substr(Region(indent_point, region.begin()))
            indent = re.match('[ \t]*', indent).group(0)
        else:
            indent = ''
        line = self.view.substr(self.view.line(region.a))
        selection = self.view.substr(region)

        # for braces that have newlines ("""), insert the current line's indent
        if isinstance(braces, list):
            l_brace = braces[0]
            r_brace = braces[1]
            braces = ''.join(braces)
            braces = braces.replace("\n", "\n" + indent)
            length = len(l_brace)
        else:
            braces = braces.replace("\n", "\n" + indent)
            length = len(braces) / 2
            l_brace = braces[:length]
            r_brace = braces[length:]

        if region.empty():
            after = self.view.substr(Region(region.a, region.a + length))

            insert_braces = braces
            complicated_check = self.complicated_quote_checker(
                insert_braces, region, pressed, after, r_brace)

            if complicated_check:
                insert_braces = complicated_check
            elif pressed and after == r_brace and r_brace[
                    -1] == pressed:  # and (pressed not in QUOTING_BRACKETS or in_string_scope):
                # in this case we pressed the closing character, and that's the character that is to the right
                # so do nothing except advance cursor position
                insert_braces = False
            elif unindent and row > 0 and indent and line == indent:
                # indent has the current line's indent
                # get previous line's indent:
                prev_point = self.view.text_point(row - 1, 0)
                prev_line = self.view.line(prev_point)
                prev_indent = self.view.substr(prev_line)
                prev_indent = re.match('[ \t]*', prev_indent).group(0)

                if (not pressed or pressed == l_brace) and len(indent) > len(
                        prev_indent) and indent[len(prev_indent):] == tab:
                    # move region.a back by 'indent' amount
                    region = Region(region.a - len(tab), region.b - len(tab))
                    # and remove the tab
                    self.view.replace(
                        edit, Region(region.a, region.a + len(tab) - 1), '')
                elif pressed and pressed == r_brace:
                    if len(indent) == len(prev_indent):
                        # move region.a back by 'indent' amount
                        region = Region(region.a - len(tab),
                                        region.b - len(tab))
                        # and remove the tab
                        self.view.replace(
                            edit, Region(region.a, region.a + len(tab) - 1),
                            '')
                    insert_braces = r_brace
            elif pressed and pressed != l_brace:
                # we pressed the closing bracket or quote.  This *never*
                insert_braces = r_brace

            if insert_braces:
                self.view.insert(edit, region.a, insert_braces)
            self.view.sel().add(Region(region.a + length, region.a + length))
        elif selection in QUOTING_BRACKETS and pressed in QUOTING_BRACKETS and selection != pressed:
            # changing a quote from single <=> double, just insert the quote.
            self.view.replace(edit, region, pressed)
            self.view.sel().add(Region(region.end(), region.end()))
        elif pressed and pressed != l_brace:
            b = region.begin() + len(r_brace)
            self.view.replace(edit, region, r_brace)
            self.view.sel().add(Region(b, b))
        else:
            substitute = self.view.substr(region)
            replacement = l_brace + substitute + r_brace
            # if we're inserting "real" brackets, not quotes:
            real_brackets = l_brace in OPENING_BRACKETS and r_brace in CLOSING_BRACKETS
            # check to see if entire lines are selected, and if so do some smart indenting
            bol_is_nl = region.begin() == 0 or self.view.substr(
                region.begin() - 1) == "\n"
            eol_is_nl = region.end(
            ) == self.view.size() - 1 or self.view.substr(region.end() -
                                                          1) == "\n"
            if real_brackets and bol_is_nl and eol_is_nl:
                indent = ''
                final = ''
                m = re.match('([ \t]*)' + tab, self.view.substr(region))
                if m:
                    indent = m.group(1)
                    final = "\n"
                else:
                    substitute = tab + substitute
                replacement = indent + l_brace + "\n" + substitute + indent + r_brace + final
                b = region.begin() + len(replacement) - len("\n" + indent +
                                                            r_brace + final)
            else:
                b = region.begin() + len(replacement)

            if replace and self.view.substr(
                    region.begin() -
                    1) in OPENING_BRACKET_LIKE and self.view.substr(
                        region.end()) in CLOSING_BRACKET_LIKE:
                b -= 1
                self.view.replace(edit,
                                  Region(region.begin() - 1,
                                         region.end() + 1), replacement)
            elif replace and self.view.substr(region.begin(
            )) in OPENING_BRACKET_LIKE and self.view.substr(
                    region.end() - 1) in CLOSING_BRACKET_LIKE:
                replacement = l_brace + replacement[2:-2] + r_brace
                b -= 2
                self.view.replace(edit, region, replacement)
                l_brace = r_brace = ''
            else:
                self.view.replace(edit, region, replacement)

            if select:
                self.view.sel().add(
                    Region(b - len(replacement) + len(l_brace),
                           b - len(r_brace)))
            else:
                self.view.sel().add(Region(b, b))
def add_comment(view: sublime.View, edit: sublime.Edit, region: sublime.Region,
                tokens: dict):
    "Adds comments around given range"
    view.insert(edit, region.end(), ' ' + tokens['end'])
    view.insert(edit, region.begin(), tokens['start'] + ' ')
    def _f(view, s):
        if mode == INTERNAL_NORMAL:
            if len(target) != 1:
                return s

            # The *target* letters w, W, s, and p correspond to a |word|, a
            # |WORD|, a |sentence|, and a |paragraph| respectively.  These are
            # special in that they have nothing to delete, and used with |ds| they
            # are a no-op. With |cs|, one could consider them a slight shortcut for
            # ysi (cswb == ysiwb, more or less).

            noop = 'wWsp'
            if target in noop:
                return s

            valid_targets = '\'"`b()B{}r[]a<>t.,-_;:@#~*\\/'
            if target not in valid_targets:
                return s

            # All marks, except punctuation marks, are only searched for on the
            # current line.

            # If opening punctuation mark is used, contained whitespace is also trimmed.
            trim_contained_whitespace = True if target in '({[<' else False
            search_current_line_only = False if target in 'b()B{}r[]a<>' else True

            # Expand targets into begin and end variables because punctuation marks
            # and their aliases represent themselves and their counterparts e.g. (),
            # []. Target is the same for begin and end for all other valid marks
            # e.g. ', ", `, -, _, etc.

            t_char_begin, t_char_end = _get_punctuation_marks(target)

            s_rowcol_begin = view.rowcol(s.begin())
            s_rowcol_end = view.rowcol(s.end())

            # A t is a pair of HTML or XML tags.
            if target == 't':
                # TODO test dst works when cursor position is inside tag begin <a|bc>x</abc> -> dst -> |x
                # TODO test dst works when cursor position is inside tag end   <abc>x</a|bc> -> dst -> |x
                t_region_end = view.find('<\\/.*?>', s.b)
                t_region_begin = reverse_search(view,
                                                '<.*?>',
                                                start=0,
                                                end=s.b)
            else:
                current = view.substr(s.begin())
                # TODO test ds{char} works when cursor position is on target begin |"x" -> ds" -> |x
                # TODO test ds{char} works when cursor position is on target end   "x|" -> ds" -> |x
                if current == t_char_begin:
                    t_region_begin = Region(s.begin(), s.begin() + 1)
                else:
                    t_region_begin = _rfind(view,
                                            t_char_begin,
                                            start=0,
                                            end=s.begin(),
                                            flags=LITERAL)

                t_region_begin_rowcol = view.rowcol(t_region_begin.begin())

                t_region_end = _find(view,
                                     t_char_end,
                                     start=t_region_begin.end(),
                                     flags=LITERAL)
                t_region_end_rowcol = view.rowcol(t_region_end.end())

                if search_current_line_only:
                    if t_region_begin_rowcol[0] != s_rowcol_begin[0]:
                        return s

                    if t_region_end_rowcol[0] != s_rowcol_end[0]:
                        return s

                if trim_contained_whitespace:
                    t_region_begin_ws = _find(view,
                                              '\\s*.',
                                              start=t_region_begin.end())
                    t_region_end_ws = _rfind(view,
                                             '.\\s*',
                                             start=t_region_begin.end(),
                                             end=t_region_end.begin())

                    if t_region_begin_ws.size() > 1:
                        t_region_begin = Region(t_region_begin.begin(),
                                                t_region_begin_ws.end() - 1)

                    if t_region_end_ws.size() > 1:
                        t_region_end = Region(t_region_end_ws.begin() + 1,
                                              t_region_end.end())

            # Note: Be careful using boolean evaluation on a Region because an empty
            # Region evaluates to False. It evaluates to False because Region
            # invokes `__len__()` which will be zero if the Region is empty e.g.
            # `Region(3).size()` is `0`, whereas `Region(3, 4).size()` is `1`.
            # `sublime.View.find(sub)` returns `Region(-1)` if *sub* not found. This
            # is similar to how the python `str.find(sub)` function works i.e. it
            # returns `-1` if *sub* not found, because *sub* could be found at
            # position `0`. To check if a Region was found use `Region(3) >= 0`. To
            # check if a Region is non empty you can use boolean evaluation i.e. `if
            # Region(3): ...`. In the following case boolean evaluation is
            # intentional.

            if not (t_region_end and t_region_begin):
                return s

            # It's important that the end is replaced first. If we replaced the
            # begin region first then the end replacement would be off-by-one
            # because the begin is reducing the size of the internal buffer by one
            # i.e. it's deleting a character.

            view.replace(edit, t_region_end, '')
            view.replace(edit, t_region_begin, '')

            return Region(t_region_begin.begin())

        return s
Exemple #11
0
def text_substr(text: str, r: sublime.Region) -> str:
    return text[r.begin():r.end()]
Exemple #12
0
def uncomment_region(view, edit, region):
    begin = region.begin()
    end = region.end() - 1

    # We will loop backwards, this means that it will hit the closing
    # punctuation for block comments first.
    i = end + 1
    while i > begin:
        i -= 1
        scopes = view.scope_name(i)

        # Not a punctuation, ignore it.
        if 'punctuation.definition.comment' not in scopes:
            continue

        # Found the second forward slash for the “// ” comment.
        if 'comment.line' in scopes:
            punctuation_region = generate_comment_punctuation_region(view, i)
            view.erase(edit, punctuation_region)
            i = punctuation_region.begin()
            continue

        # We found the beginning of the block comment first, this means that
        # there’s no end to it and we can easily remove it. It can be “/* ”,
        # “/** ”, “{/* ” or “{/** ”.
        if 'punctuation.definition.comment.begin' in scopes:
            punctuation_region = generate_jsjsx_comment_punctuation_region(
                view, i)

            view.erase(edit, punctuation_region)
            i = punctuation_region.begin()
            continue

        # We are looping backwards, so it is expected to find the closing
        # punctuation first which can be “ */” or “ */}”.
        possible_jsx_comment = False
        if i < view.size() and is_jsx_close_brace(view, i + 1):
            possible_jsx_comment = True

        closing_punctuation_region = generate_comment_punctuation_region(
            view, i)

        # Move the cursor 1 character after the beginning punctuation.
        i = scan_reverse(
            view, i,
            not_predicate(
                has_scope_predicate('punctuation.definition.comment.begin')))

        open_punctuation_region = generate_comment_punctuation_region(
            view, i - 1)

        # Correct the regions to include the JSX braces if necessary.
        if possible_jsx_comment:
            if is_jsx_open_brace(view, open_punctuation_region.begin() - 1):
                open_punctuation_region = Region(
                    open_punctuation_region.begin() - 1,
                    open_punctuation_region.end())
                closing_punctuation_region = Region(
                    closing_punctuation_region.begin(),
                    closing_punctuation_region.end() + 1)

        view.erase(edit, closing_punctuation_region)
        view.erase(edit, open_punctuation_region)

        # Move the cursor to the beginning of the block to “consume” it.
        i = open_punctuation_region.begin()
Exemple #13
0
    def run_each(self,
                 edit,
                 region,
                 braces='{}',
                 pressed=None,
                 unindent=False,
                 select=False,
                 replace=False):
        '''
        Options:
            braces    a list of matching braces or a string containing the pair
            pressed   the key pressed; used for closing vs opening logic
            unindent  removes one "tab" from a newline.  true for braces that handle indent, like {}
            select    whether to select the region inside the braces
            replace   whether to insert new braces where the old braces were
        '''
        if self.view.settings().get('translate_tabs_to_spaces'):
            tab = ' ' * self.view.settings().get('tab_size')
        else:
            tab = "\t"

        row, col = self.view.rowcol(region.begin())
        indent_point = self.view.text_point(row, 0)
        if indent_point < region.begin():
            indent = self.view.substr(Region(indent_point, region.begin()))
            indent = re.match('[ \t]*', indent).group(0)
        else:
            indent = ''
        line = self.view.substr(self.view.line(region.a))
        selection = self.view.substr(region)

        # for braces that have newlines ("""), insert the current line's indent
        if isinstance(braces, list):
            l_brace = braces[0]
            r_brace = braces[1]
            braces = ''.join(braces)
            braces = braces.replace("\n", "\n" + indent)
            length = len(l_brace)
        else:
            braces = braces.replace("\n", "\n" + indent)
            length = len(braces) // 2
            l_brace = braces[:length]
            r_brace = braces[length:]

        if region.empty():
            after = self.view.substr(Region(region.a, region.a + length))

            insert_braces = braces
            complicated_check = self.complicated_quote_checker(
                insert_braces, region, pressed, after, r_brace)

            if complicated_check:
                insert_braces = complicated_check
            elif pressed and after == r_brace and r_brace[
                    -1] == pressed:  # and (pressed not in QUOTING_BRACKETS or in_string_scope):
                # in this case we pressed the closing character, and that's the character that is to the right
                # so do nothing except advance cursor position
                insert_braces = False
            elif unindent and row > 0 and indent and line == indent:
                # indent has the current line's indent
                # get previous line's indent:
                prev_point = self.view.text_point(row - 1, 0)
                prev_line = self.view.line(prev_point)
                prev_indent = self.view.substr(prev_line)
                prev_indent = re.match('[ \t]*', prev_indent).group(0)

                if (not pressed or pressed == l_brace) and len(indent) > len(
                        prev_indent) and indent[len(prev_indent):] == tab:
                    # move region.a back by 'indent' amount
                    region = Region(region.a - len(tab), region.b - len(tab))
                    # and remove the tab
                    self.view.replace(
                        edit, Region(region.a, region.a + len(tab) - 1), '')
                elif pressed and pressed == r_brace:
                    # move region.a back by 'indent' amount
                    region = Region(region.a - len(tab), region.b - len(tab))
                    # and remove the tab
                    self.view.replace(edit,
                                      Region(region.a, region.a + len(tab)),
                                      '')
                    insert_braces = r_brace
            elif pressed and pressed != l_brace:
                # we pressed the closing bracket or quote.  This *never*
                insert_braces = r_brace

            if insert_braces:
                self.view.insert(edit, region.a, insert_braces)
            self.view.sel().add(Region(region.a + length, region.a + length))
        elif selection in QUOTING_BRACKETS and pressed in QUOTING_BRACKETS and selection != pressed:
            # changing a quote from single <=> double, just insert the quote.
            self.view.replace(edit, region, pressed)
            self.view.sel().add(Region(region.end(), region.end()))
        elif pressed and pressed != l_brace:
            b = region.begin() + len(r_brace)
            self.view.replace(edit, region, r_brace)
            self.view.sel().add(Region(b, b))
        else:
            substitute = self.view.substr(region)
            replacement = l_brace + substitute + r_brace
            # if we're inserting "real" brackets, not quotes:
            real_brackets = l_brace in OPENING_BRACKETS and r_brace in CLOSING_BRACKETS

            # check to see if entire lines are selected, and if so do some smart indenting
            # bol_is_nl => allman style {}
            # bol_at_nl => kernigan&ritchie
            if region.begin() == 0:
                bol_is_nl = True
                bol_at_nl = False
            elif len(self.view) == region.begin() + 1:
                bol_is_nl = False
                bol_at_nl = False
            else:
                bol_is_nl = self.view.substr(region.begin() - 1) == "\n"
                bol_at_nl = l_brace == '{' and self.view.substr(region.begin(
                )) == "\n" and self.view.substr(region.begin() - 1) != "\n"
            eol_is_nl = region.end() == self.view.size() or self.view.substr(
                region.end()) == "\n"
            eol_at_nl = self.view.substr(region.end() - 1) == "\n"
            if eol_is_nl:
                eol_is_nl = self.view.line(region.begin()) != self.view.line(
                    region.end())

            if real_brackets and (bol_is_nl or bol_at_nl) and (eol_is_nl
                                                               or eol_at_nl):
                indent = ''
                if bol_at_nl and substitute:
                    substitute = substitute[1:]
                m = re.match('([ \t]*)' + tab, substitute)
                if m:
                    indent = m.group(1)
                else:
                    substitute = tab + substitute
                b = region.begin() - len("\n" + indent + r_brace)

                if bol_at_nl:
                    replacement = l_brace + "\n" + substitute
                    if eol_at_nl:
                        replacement += indent + r_brace + "\n"
                        b -= 1
                    else:
                        replacement += r_brace + "\n"
                        b += len(indent)

                    if not self.view.substr(region.begin() - 1) == ' ':
                        replacement = ' ' + replacement
                else:
                    replacement = indent + l_brace + "\n" + substitute + indent + r_brace + "\n"
                    b -= 1
                b += len(replacement)
            else:
                b = region.begin() + len(replacement)

            if replace and self.view.substr(
                    region.begin() -
                    1) in OPENING_BRACKET_LIKE and self.view.substr(
                        region.end()) in CLOSING_BRACKET_LIKE:
                b -= 1
                self.view.replace(edit,
                                  Region(region.begin() - 1,
                                         region.end() + 1), replacement)
            elif replace and self.view.substr(region.begin(
            )) in OPENING_BRACKET_LIKE and self.view.substr(
                    region.end() - 1) in CLOSING_BRACKET_LIKE:
                replacement = l_brace + replacement[2:-2] + r_brace
                b -= 2
                self.view.replace(edit, region, replacement)
                l_brace = r_brace = ''
            else:
                self.view.replace(edit, region, replacement)

            if select:
                self.view.sel().add(
                    Region(b - len(replacement) + len(l_brace),
                           b - len(r_brace)))
            else:
                self.view.sel().add(Region(b, b))
Exemple #14
0
def uncomment_lines(view, edit, region):
    begin = region.begin()
    end = region.end()

    i = end + 1
    while i > begin:
        i -= 1
        scopes = view.scope_name(i)

        if 'punctuation.definition.comment' not in scopes:
            continue

        # Found the second forward slash for the “// ” comment.
        if 'comment.line' in scopes:
            i = get_comment_beginning_pos(view, i)
            content_begin = get_comment_content_beginning(view, i)
            view.erase(edit, Region(i, content_begin))
            continue

        # We found the beginning of the block comment first which means that there’s
        # no end to it and we can easily remove it. It can be “/* ”, “/** ”, “{/* ”
        # or “{/** ”.
        if 'punctuation.definition.comment.begin' in scopes:
            i = get_comment_beginning_pos(view, i)
            content_begin = get_comment_content_beginning(view, i)

            # We need to check the braces for possible JSX interpolation.
            if i > 0 and is_jsx_open_brace(view, i - 1):
                # It was a JSX block comment.
                i -= 1

            # We have “i” positioned at the beginning of the comment or the brace if
            # it is a JSX comment.
            view.erase(edit, Region(i, content_begin))
            continue

        # We are looping backwards, so it is expected to find the closing punctuation
        # first which can be “ */” or “ */}”.
        possible_jsx_comment = False

        if i < view.size() and is_jsx_close_brace(view, i + 1):
            possible_jsx_comment = True

        close_block = i

        # Now, we need to find the the openning of the block.
        while 'punctuation.definition.comment.begin' not in scopes:
            i -= 1
            scopes = view.scope_name(i)

        open_block = i

        # This will generate a region that allows us to remove the block punctuation.
        open_block = expand_openning_block_punctuation(view, open_block)
        close_block = expand_closing_block_punctuation(view, close_block)

        # Correct the regions to include the JSX braces if necessary.
        if possible_jsx_comment:
            if open_block.begin() > 0 and is_jsx_open_brace(
                    view,
                    open_block.begin() - 1):
                open_block = Region(open_block.begin() - 1, open_block.end())
                close_block = Region(close_block.begin(),
                                     close_block.end() + 1)

        view.erase(edit, close_block)
        view.erase(edit, open_block)

        # Move the cursor to the beginning of the block to “consume” it.
        i = open_block.begin()
def create_tracker(editor: sublime.View, region: sublime.Region,
                   params: dict) -> AbbreviationTracker:
    """
    Creates abbreviation tracker for given range in editor. Parses contents
    of abbreviation in range and returns either valid abbreviation tracker,
    error tracker or `None` if abbreviation cannot be created from given range
    """
    config = get_by_key(params, 'config')
    offset = get_by_key(params, 'offset', 0)
    forced = get_by_key(params, 'forced', False)

    if region.a > region.b or (region.a == region.b and not forced):
        # Invalid range
        return

    abbreviation = editor.substr(region)
    if offset:
        abbreviation = abbreviation[offset:]

    # Basic validation: do not allow empty abbreviations
    # or newlines in abbreviations
    if (not abbreviation
            and not forced) or '\n' in abbreviation or '\r' in abbreviation:
        return

    tracker_params = {
        'forced': forced,
        'offset': offset,
        'last_pos': region.end(),
        'last_length': editor.size(),
    }

    try:
        tracker_params['simple'] = False

        if config.type == 'stylesheet':
            parsed_abbr = stylesheet_abbreviation(abbreviation, config)
        else:
            parsed_abbr = markup_abbreviation(abbreviation, config)
            jsx = config and syntax.is_jsx(config.syntax)
            tracker_params[
                'simple'] = not jsx and is_simple_markup_abbreviation(
                    parsed_abbr)

        preview_config = get_preview_config(config)
        tracker_params['preview'] = expand(abbreviation, preview_config)
        if tracker_params['preview'] or forced:
            # Create tracker only if preview is not empty for non-forced abbreviation.
            # Empty preview means Emmet was unable to find proper match for given
            # abbreviation. Most likely it happens in stylesheets in `Section` scope
            return AbbreviationTrackerValid(abbreviation, region, config,
                                            tracker_params)
    except Exception as err:
        if hasattr(err, 'message') and hasattr(err, 'pos'):
            tracker_params['error'] = {
                'message': err.message,
                'pos': err.pos,
                'pointer':
                '%s^' % ('-' * err.pos, ) if err.pos is not None else ''
            }
            return AbbreviationTrackerError(abbreviation, region, config,
                                            tracker_params)
        else:
            print(repr(err))
Exemple #16
0
 def from_region(self, view: sublime.View,
                 region: sublime.Region) -> 'Range':
     return Range(Point.from_text_point(view, region.begin()),
                  Point.from_text_point(view, region.end()))
Exemple #17
0
def region_contains(region: sublime.Region, pt: int) -> bool:
    return region.begin() < pt < region.end()
Exemple #18
0
    def run_each(self, edit, region, braces='{}', pressed=None, unindent=False, select=False, replace=False):
        self.view.sel().subtract(region)
        if self.view.settings().get('translate_tabs_to_spaces'):
            tab = ' ' * self.view.settings().get('tab_size')
        else:
            tab = "\t"

        row, col = self.view.rowcol(region.begin())
        indent_point = self.view.text_point(row, 0)
        if indent_point < region.begin():
            indent = self.view.substr(Region(indent_point, region.begin()))
            indent = re.match('[ \t]*', indent).group(0)
        else:
            indent = ''
        line = self.view.substr(self.view.line(region.a))
        selection = self.view.substr(region)

        # for braces that have newlines ("""), insert the current line's indent
        braces = braces.replace("\n", "\n" + indent)
        length = len(braces) / 2
        l_brace = braces[:length]
        r_brace = braces[length:]

        if region.empty():
            after = self.view.substr(Region(region.a, region.a + length))

            insert_braces = braces
            complicated_check = self.complicated_quote_checker(insert_braces, region, pressed, after, r_brace)

            if complicated_check:
                insert_braces = complicated_check
            elif pressed and after == r_brace and r_brace[-1] == pressed:  # and (pressed not in QUOTING_BRACKETS or in_string_scope):
                # in this case we pressed the closing character, and that's the character that is to the right
                # so do nothing except advance cursor position
                insert_braces = False
            elif unindent and row > 0 and indent and line == indent:
                # indent has the current line's indent
                # get previous line's indent:
                prev_point = self.view.text_point(row - 1, 0)
                prev_line = self.view.line(prev_point)
                prev_indent = self.view.substr(prev_line)
                prev_indent = re.match('[ \t]*', prev_indent).group(0)

                if (not pressed or pressed == l_brace) and len(indent) > len(prev_indent) and indent[len(prev_indent):] == tab:
                    # move region.a back by 'indent' amount
                    region = Region(region.a - len(tab), region.b - len(tab))
                    # and remove the tab
                    self.view.replace(edit, Region(region.a, region.a + len(tab) - 1), '')
                elif pressed and pressed == r_brace:
                    if len(indent) == len(prev_indent):
                        # move region.a back by 'indent' amount
                        region = Region(region.a - len(tab), region.b - len(tab))
                        # and remove the tab
                        self.view.replace(edit, Region(region.a, region.a + len(tab) - 1), '')
                    insert_braces = r_brace
            elif pressed and pressed != l_brace:
                # we pressed the closing bracket or quote.  This *never*
                insert_braces = r_brace

            if insert_braces:
                self.view.insert(edit, region.a, insert_braces)
            self.view.sel().add(Region(region.a + length, region.a + length))
        elif selection in QUOTING_BRACKETS and pressed in QUOTING_BRACKETS and selection != pressed:
            # changing a quote from single <=> double, just insert the quote.
            self.view.replace(edit, region, pressed)
            self.view.sel().add(Region(region.end(), region.end()))
        elif pressed and pressed != l_brace:
            b = region.begin() + len(r_brace)
            self.view.replace(edit, region, r_brace)
            self.view.sel().add(Region(b, b))
        else:
            substitute = self.view.substr(region)
            replacement = l_brace + substitute + r_brace
            # if we're inserting "real" brackets, not quotes:
            real_brackets = l_brace in OPENING_BRACKETS and r_brace in CLOSING_BRACKETS
            # check to see if entire lines are selected, and if so do some smart indenting
            bol_is_nl = region.begin() == 0 or self.view.substr(region.begin() - 1) == "\n"
            eol_is_nl = region.end() == self.view.size() - 1 or self.view.substr(region.end() - 1) == "\n"
            if real_brackets and bol_is_nl and eol_is_nl:
                indent = ''
                final = ''
                m = re.match('([ \t]*)' + tab, self.view.substr(region))
                if m:
                    indent = m.group(1)
                    final = "\n"
                else:
                    substitute = tab + substitute
                replacement = indent + l_brace + "\n" + substitute + indent + r_brace + final
                b = region.begin() + len(replacement) - len("\n" + indent + r_brace + final)
            else:
                b = region.begin() + len(replacement)

            if replace and self.view.substr(region.begin() - 1) in OPENING_BRACKET_LIKE and self.view.substr(region.end()) in CLOSING_BRACKET_LIKE:
                b -= 1
                self.view.replace(edit, Region(region.begin() - 1, region.end() + 1), replacement)
            elif replace and self.view.substr(region.begin()) in OPENING_BRACKET_LIKE and self.view.substr(region.end() - 1) in CLOSING_BRACKET_LIKE:
                replacement = l_brace + replacement[2:-2] + r_brace
                b -= 2
                self.view.replace(edit, region, replacement)
                l_brace = r_brace = ''
            else:
                self.view.replace(edit, region, replacement)

            if select:
                self.view.sel().add(Region(b - len(replacement) + len(l_brace), b - len(r_brace)))
            else:
                self.view.sel().add(Region(b, b))
Exemple #19
0
def resolve_indent_text_object(view, s: Region, inclusive: bool = True, big: bool = False):
    # Look for the minimum indentation in the current visual region.
    idnt = 1000
    idnt_pt = None
    for line in view.lines(s):
        if not re.match('^\\s*$', view.substr(line)):
            level = view.indentation_level(line.a)
            if level < idnt:
                idnt = min(idnt, level)
                idnt_pt = line.a

    # If the selection has no indentation at all, find which indentation level
    # is the largest, the previous non blank before tphe cursor or the next non
    # blank after the cursor, and start the selection from that point.

    if idnt == 1000:
        pnb_pt = prev_non_ws(view, s.begin())
        pnb_indent_level = view_indentation_level(view, pnb_pt)

        nnb_pt = next_non_ws(view, s.end())
        nnb_indent_level = view_indentation_level(view, nnb_pt)

        if pnb_indent_level > nnb_indent_level:
            idnt_pt = s.a = s.b = pnb_pt
        elif nnb_indent_level > pnb_indent_level:
            idnt_pt = s.a = s.b = nnb_pt
        else:
            idnt_pt = pnb_pt

    if idnt == 0 and idnt_pt is not None:
        expanded = view.expand_by_class(s, CLASS_EMPTY_LINE)
        s.a = expanded.a
        s.b = expanded.b

        if not inclusive:
            # Case: ii and iI. Strip any leading whitespace.
            leading_ws = view_find(view, '\\s*', s.a)
            if leading_ws is not None:
                s.a = view.line(leading_ws.b).a

            s.b = prev_non_blank(view, s.b)
        elif big:
            # Case: aI. Add a line below.
            if view.substr(s.b) == '\n':
                s.b += 1

    elif idnt > 0 and idnt_pt is not None:
        indented_region = view_indented_region(view, idnt_pt, inclusive)

        if indented_region.begin() < s.begin():
            s.a = indented_region.begin()

        if indented_region.end() > s.end():
            s.b = indented_region.end()

        if inclusive:
            # Case: ai. Add a line above.
            s.a = view.line(view.text_point(view.rowcol(s.a)[0] - 1, 0)).a

            # Case: aI. Add a line below.
            if big:
                s.b = view.full_line(view.text_point(view.rowcol(s.b - 1)[0] + 1, 0)).b

    return s
    def run_each(self, edit, region, braces="{}", pressed=None, unindent=False, select=False, replace=False):
        """
        Options:
            braces    a list of matching braces or a string containing the pair
            pressed   the key pressed; used for closing vs opening logic
            unindent  removes one "tab" from a newline.  true for braces that handle indent, like {}
            select    whether to select the region inside the braces
            replace   whether to insert new braces where the old braces were
        """
        if self.view.settings().get("translate_tabs_to_spaces"):
            tab = " " * self.view.settings().get("tab_size")
        else:
            tab = "\t"

        row, col = self.view.rowcol(region.begin())
        indent_point = self.view.text_point(row, 0)
        if indent_point < region.begin():
            indent = self.view.substr(Region(indent_point, region.begin()))
            indent = re.match("[ \t]*", indent).group(0)
        else:
            indent = ""
        line = self.view.substr(self.view.line(region.a))
        selection = self.view.substr(region)

        # for braces that have newlines ("""), insert the current line's indent
        if isinstance(braces, list):
            l_brace = braces[0]
            r_brace = braces[1]
            braces = "".join(braces)
            braces = braces.replace("\n", "\n" + indent)
            length = len(l_brace)
        else:
            braces = braces.replace("\n", "\n" + indent)
            length = len(braces) // 2
            l_brace = braces[:length]
            r_brace = braces[length:]

        if region.empty():
            after = self.view.substr(Region(region.a, region.a + length))

            insert_braces = braces
            complicated_check = self.complicated_quote_checker(insert_braces, region, pressed, after, r_brace)

            if complicated_check:
                insert_braces = complicated_check
            elif (
                pressed and after == r_brace and r_brace[-1] == pressed
            ):  # and (pressed not in QUOTING_BRACKETS or in_string_scope):
                # in this case we pressed the closing character, and that's the character that is to the right
                # so do nothing except advance cursor position
                insert_braces = False
            elif unindent and row > 0 and indent and line == indent:
                # indent has the current line's indent
                # get previous line's indent:
                prev_point = self.view.text_point(row - 1, 0)
                prev_line = self.view.line(prev_point)
                prev_indent = self.view.substr(prev_line)
                prev_indent = re.match("[ \t]*", prev_indent).group(0)

                if (
                    (not pressed or pressed == l_brace)
                    and len(indent) > len(prev_indent)
                    and indent[len(prev_indent) :] == tab
                ):
                    # move region.a back by 'indent' amount
                    region = Region(region.a - len(tab), region.b - len(tab))
                    # and remove the tab
                    self.view.replace(edit, Region(region.a, region.a + len(tab) - 1), "")
                elif pressed and pressed == r_brace:
                    if len(indent) == len(prev_indent):
                        # move region.a back by 'indent' amount
                        region = Region(region.a - len(tab), region.b - len(tab))
                        # and remove the tab
                        self.view.replace(edit, Region(region.a, region.a + len(tab) - 1), "")
                    insert_braces = r_brace
            elif pressed and pressed != l_brace:
                # we pressed the closing bracket or quote.  This *never*
                insert_braces = r_brace

            if insert_braces:
                self.view.insert(edit, region.a, insert_braces)
            self.view.sel().add(Region(region.a + length, region.a + length))
        elif selection in QUOTING_BRACKETS and pressed in QUOTING_BRACKETS and selection != pressed:
            # changing a quote from single <=> double, just insert the quote.
            self.view.replace(edit, region, pressed)
            self.view.sel().add(Region(region.end(), region.end()))
        elif pressed and pressed != l_brace:
            b = region.begin() + len(r_brace)
            self.view.replace(edit, region, r_brace)
            self.view.sel().add(Region(b, b))
        else:
            substitute = self.view.substr(region)
            replacement = l_brace + substitute + r_brace
            # if we're inserting "real" brackets, not quotes:
            real_brackets = l_brace in OPENING_BRACKETS and r_brace in CLOSING_BRACKETS

            # check to see if entire lines are selected, and if so do some smart indenting
            # bol_is_nl => allman style {}
            # bol_at_nl => kernigan&ritchie
            if region.begin() == 0:
                bol_is_nl = True
                bol_at_nl = False
            elif len(self.view) == region.begin() + 1:
                bol_is_nl = False
                bol_at_nl = False
            else:
                bol_is_nl = self.view.substr(region.begin() - 1) == "\n"
                bol_at_nl = (
                    l_brace == "{"
                    and self.view.substr(region.begin()) == "\n"
                    and self.view.substr(region.begin() - 1) != "\n"
                )
            eol_is_nl = region.end() == self.view.size() or self.view.substr(region.end()) == "\n"
            eol_at_nl = self.view.substr(region.end() - 1) == "\n"
            if eol_is_nl:
                eol_is_nl = self.view.line(region.begin()) != self.view.line(region.end())

            if real_brackets and (bol_is_nl or bol_at_nl) and (eol_is_nl or eol_at_nl):
                indent = ""
                if bol_at_nl and substitute:
                    substitute = substitute[1:]
                m = re.match("([ \t]*)" + tab, substitute)
                if m:
                    indent = m.group(1)
                else:
                    substitute = tab + substitute
                b = region.begin() - len("\n" + indent + r_brace)

                if bol_at_nl:
                    replacement = l_brace + "\n" + substitute
                    if eol_at_nl:
                        replacement += indent + r_brace + "\n"
                        b -= 1
                    else:
                        replacement += r_brace + "\n"
                        b += len(indent)

                    if not self.view.substr(region.begin() - 1) == " ":
                        replacement = " " + replacement
                else:
                    replacement = indent + l_brace + "\n" + substitute + indent + r_brace + "\n"
                    b -= 1
                b += len(replacement)
            else:
                b = region.begin() + len(replacement)

            if (
                replace
                and self.view.substr(region.begin() - 1) in OPENING_BRACKET_LIKE
                and self.view.substr(region.end()) in CLOSING_BRACKET_LIKE
            ):
                b -= 1
                self.view.replace(edit, Region(region.begin() - 1, region.end() + 1), replacement)
            elif (
                replace
                and self.view.substr(region.begin()) in OPENING_BRACKET_LIKE
                and self.view.substr(region.end() - 1) in CLOSING_BRACKET_LIKE
            ):
                replacement = l_brace + replacement[2:-2] + r_brace
                b -= 2
                self.view.replace(edit, region, replacement)
                l_brace = r_brace = ""
            else:
                self.view.replace(edit, region, replacement)

            if select:
                self.view.sel().add(Region(b - len(replacement) + len(l_brace), b - len(r_brace)))
            else:
                self.view.sel().add(Region(b, b))
Exemple #21
0
def get_region_end(r: Region) -> dict:
    return {'start': r.end()}
Exemple #22
0
def region_to_range(view: sublime.View, region: sublime.Region) -> 'Range':
    return Range(offset_to_point(view, region.begin()),
                 offset_to_point(view, region.end()))
Exemple #23
0
def uncomment_region(view, edit, region):
    begin = region.begin()
    end = region.end() - 1

    # We will loop backwards, this means that it will hit the closing
    # punctuation for block comments first.
    i = end + 1
    while i > begin:
        i -= 1
        scopes = view.scope_name(i)

        # Not a punctuation, ignore it.
        if 'punctuation.definition.comment' not in scopes:
            continue

        # Found the second forward slash for the “// ” comment.
        if 'comment.line' in scopes:
            punctuation_region = generate_comment_punctuation_region(view, i)
            view.erase(edit, punctuation_region)
            i = punctuation_region.begin()
            continue

        # We found the beginning of the block comment first, this means that
        # there’s no end to it and we can easily remove it. It can be “/* ”,
        # “/** ”, “{/* ” or “{/** ”.
        if 'punctuation.definition.comment.begin' in scopes:
            punctuation_region = generate_jsjsx_comment_punctuation_region(
                view, i
            )

            view.erase(edit, punctuation_region)
            i = punctuation_region.begin()
            continue

        # We are looping backwards, so it is expected to find the closing
        # punctuation first which can be “ */” or “ */}”.
        possible_jsx_comment = False
        if i < view.size() and is_jsx_close_brace(view, i + 1):
            possible_jsx_comment = True

        closing_punctuation_region = generate_comment_punctuation_region(
            view, i
        )

        # Move the cursor 1 character after the beginning punctuation.
        i = scan_reverse(view, i, not_predicate(has_scope_predicate(
            'punctuation.definition.comment.begin'
        )))

        open_punctuation_region = generate_comment_punctuation_region(
            view, i - 1
        )

        # Correct the regions to include the JSX braces if necessary.
        if possible_jsx_comment:
            if is_jsx_open_brace(view, open_punctuation_region.begin() - 1):
                open_punctuation_region = Region(
                    open_punctuation_region.begin() - 1,
                    open_punctuation_region.end()
                )
                closing_punctuation_region = Region(
                    closing_punctuation_region.begin(),
                    closing_punctuation_region.end() + 1
                )

        view.erase(edit, closing_punctuation_region)
        view.erase(edit, open_punctuation_region)

        # Move the cursor to the beginning of the block to “consume” it.
        i = open_punctuation_region.begin()