Пример #1
0
    def _f(view, s):
        if mode == INTERNAL_NORMAL:
            old = target
            new = replacement
            open_, close_ = _get_punctuation_marks(old)
            new_open, new_close = _get_punctuation_mark_replacements(new)

            if open_ == 't':
                open_, close_ = ('<[^>\\/]+>', '<\\/[^>]+>')
                next_ = view.find(close_, s.b)
                if next_:
                    prev_ = reverse_search(view,
                                           open_,
                                           end=next_.begin(),
                                           start=0)
                else:
                    prev_ = None
            else:
                if open_ == close_:
                    line = view.line(s.b)
                    prev_ = None
                    next_ = view.find(close_, s.b, flags=LITERAL)
                    if next_:
                        if next_.a > line.b:
                            next_ = None
                        else:
                            prev_ = reverse_search(view,
                                                   open_,
                                                   end=s.b,
                                                   start=0,
                                                   flags=LITERAL)
                            if not prev_ or (prev_ and prev_.a < line.a):
                                prev_ = next_
                                next_ = view.find(close_,
                                                  s.b + 1,
                                                  flags=LITERAL)
                else:
                    next_ = view.find(close_, s.b, flags=LITERAL)
                    if next_:
                        prev_ = reverse_search(view,
                                               open_,
                                               end=s.b,
                                               start=0,
                                               flags=LITERAL)
                    else:
                        next_ = None

            if not (next_ and prev_):
                return s

            view.replace(edit, next_, new_close)
            view.replace(edit, prev_, new_open)

            return Region(prev_.begin())

        return s
Пример #2
0
    def _f(view, s):
        if mode == INTERNAL_NORMAL:
            old = target
            new = replacement
            open_, close_ = _get_punctuation_marks(old)
            new_open, new_close = _get_punctuation_mark_replacements(new)

            # Replacements > 1 are always tags, and the first character could be
            # "t", which is an alias for "<".
            if len(replacement) > 1:
                new_open = '<' + new_open[1:]

            # Replacements > 1 are always tags, and the first character could be
            # "t", which is an alias for "<".
            if len(replacement) > 1:
                new_close = '</' + new_close[1:]

            if open_ == 't':
                open_, close_ = ('<[^>\\/]+>', '<\\/[^>]+>')
                next_ = view.find(close_, s.b)
                if next_:
                    prev_ = reverse_search(view,
                                           open_,
                                           end=next_.begin(),
                                           start=0)
                else:
                    prev_ = None
            else:
                next_ = view.find(close_, s.b, flags=LITERAL)
                if next_:
                    prev_ = reverse_search(view,
                                           open_,
                                           end=s.b,
                                           start=0,
                                           flags=LITERAL)
                else:
                    next_ = None

            if not (next_ and prev_):
                return s

            view.replace(edit, next_, new_close)
            view.replace(edit, prev_, new_open)

            return Region(prev_.begin())

        return s
Пример #3
0
def _rfind(view, sub, start, end, flags=0):
    # TODO Make start and end optional arguments interpreted as in slice notation.
    # TODO [refactor] into reusable api.
    res = reverse_search(view, sub, start, end, flags)
    if res is None:
        return Region(-1)

    return res
Пример #4
0
    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
Пример #5
0
def _rfind(view, sub, start, end, flags=0):
    res = reverse_search(view, sub, start, end, flags)
    if res is None:
        return Region(-1)

    return res