Esempio n. 1
0
def find_sentences_backward(view, start_pt: int, count: int = 1) -> Region:
    if isinstance(start_pt, Region):
        start_pt = start_pt.a

    pt = prev_non_ws(view, start_pt)
    sen = Region(pt)
    prev = sen
    while True:
        sen = view.expand_by_class(sen, CLASS_LINE_END | CLASS_PUNCTUATION_END)
        if sen.a <= 0 or view.substr(sen.begin() - 1) in ('.', '\n', '?', '!'):
            if view.substr(sen.begin() - 1) == '.' and not view.substr(sen.begin()) == ' ':
                continue

            if prev == sen:
                break

            prev = sen

            if sen:
                pt = next_non_blank(view, sen.a)
                if pt < sen.b and pt != start_pt:
                    if view.substr(pt) == '\n':
                        if pt + 1 != start_pt:
                            pt += 1

                    return Region(pt)

                if pt > 0:
                    continue

            return sen

    return sen
Esempio n. 2
0
def _get_text_object_bracket(view, s: Region, inclusive: bool, count: int, delims: tuple) -> Region:
    opening = find_prev_lone_bracket(view, max(0, s.begin() - 1), delims)
    closing = find_next_lone_bracket(view, s.end(), delims)

    if not (opening and closing):
        return s

    if inclusive:
        return Region(opening.a, closing.b)

    a = opening.a + 1
    if view.substr(a) == '\n':
        a += 1

    b = closing.b - 1

    if b > a:
        line = view.line(b)

        if next_non_blank(view, line.a) + 1 == line.b:
            row_a, col_a = view.rowcol(a - 1)
            row_b, col_b = view.rowcol(b + 1)
            if (row_b - 1) > row_a:
                line = view.full_line(view.text_point((row_b - 1), 0))

                return Region(a, line.b)

    return Region(a, b)
Esempio n. 3
0
    def _find_sentence_forward(view, start: int):
        char = view.substr(start)
        if char == '\n':
            next_sentence = view.find('\\s+', start)
        else:
            next_sentence = view.find('[\\.\\?\\!][\\)\\]"\']*\\s', start)

        if next_sentence:
            return next_non_blank(view, next_sentence.b)
Esempio n. 4
0
def word_starts(view, start, count=1, internal=False):
    assert start >= 0
    assert count > 0

    pt = start
    for i in range(count):
        # On the last motion iteration, we must do some special stuff if we are still on the
        # starting line of the motion.
        if (internal and (i == count - 1) and (view.line(start) == view.line(pt))):
            if view.substr(pt) == '\n':
                return pt + 1
            return next_word_start(view, pt, internal=True)

        pt = next_word_start(view, pt)
        if not internal or (i != count - 1):
            pt = next_non_blank(view, pt)
            while not (view.size() == pt or view.line(pt).empty() or view.substr(view.line(pt)).strip()):
                pt = next_word_start(view, pt)
                pt = next_non_blank(view, pt)

    if (internal and (view.line(start) != view.line(pt)) and (start != view.line(start).a and not view.substr(view.line(pt - 1)).isspace()) and at_eol(view, pt - 1)):  # FIXME # noqa: E501
        pt -= 1

    return pt
Esempio n. 5
0
    def f(view, s):
        if mode == NORMAL:
            pt = next_non_blank(view, dest)
            if view.substr(pt) == EOF:
                pt = max(pt - 1, 0)

            return Region(pt)
        elif mode == INTERNAL_NORMAL:
            start_line = view.full_line(s.a)
            dest_line = view.full_line(dest)
            if start_line.a == dest_line.a:
                return dest_line
            elif start_line.a < dest_line.a:
                return Region(start_line.a, dest_line.b)
            else:
                return Region(start_line.b, dest_line.a)
        elif mode == VISUAL:
            dest_non_blank = next_non_blank(view, dest)
            if dest_non_blank < s.a and s.a < s.b:
                return Region(s.a + 1, dest_non_blank)
            elif dest_non_blank < s.a:
                return Region(s.a, dest_non_blank)
            elif dest_non_blank > s.b and s.a > s.b:
                return Region(s.a - 1, dest_non_blank + 1)
            return Region(s.a, dest_non_blank + 1)
        elif mode == VISUAL_LINE:
            if dest < s.a and s.a < s.b:
                return Region(view.full_line(s.a).b, dest)
            elif dest < s.a:
                return Region(s.a, dest)
            elif dest >= s.a and s.a > s.b:
                return Region(
                    view.full_line(s.a - 1).a,
                    view.full_line(dest).b)
            return Region(s.a, view.full_line(dest).b)
        return s
Esempio n. 6
0
def inner_lines(view, s, count=1):
    """
    Return a region spanning @count inner lines.

    Inner lines are lines excluding leading/trailing whitespace at outer ends.

    Assumes we're operating in INTERNAL_NORMAL mode.

    @view
      Target view.
    @s
      Selection in @view taken as starting point.
    @count
      Number of lines to include in returned region.
    """
    end = view.text_point(row_at(view, s.b) + (count - 1), 0)
    begin = view.line(s.b).a
    begin = next_non_blank(view, begin)

    return Region(begin, view.line(end).b)
Esempio n. 7
0
def get_text_object_region(view, s, text_object, inclusive=False, count=1):
    # type: (...) -> Region
    try:
        delims, type_ = PAIRS[text_object]
    except KeyError:
        return s

    if type_ == TAG:
        begin_tag, end_tag, _ = find_containing_tag(view, s.begin())

        if not (begin_tag and end_tag):
            return s

        if inclusive:
            return Region(begin_tag.a, end_tag.b)
        else:
            return Region(begin_tag.b, end_tag.a)

    if type_ == PARAGRAPH:
        return find_paragraph_text_object(view, s, inclusive=inclusive, count=count)

    if type_ == BRACKET:
        opening = find_prev_lone_bracket(view, max(0, s.begin() - 1), delims)
        closing = find_next_lone_bracket(view, s.end(), delims)

        if not (opening and closing):
            return s

        if inclusive:
            return Region(opening.a, closing.b)

        a = opening.a + 1
        if view.substr(a) == '\n':
            a += 1

        b = closing.b - 1

        if b > a:
            line = view.line(b)
            if next_non_blank(view, line.a) + 1 == line.b:
                row_a, col_a = view.rowcol(a)
                row_b, col_b = view.rowcol(b)
                if (row_b - 1) > row_a:
                    line = view.full_line(view.text_point((row_b - 1), 0))

                    return Region(a, line.b)

        return Region(a, b)

    if type_ == QUOTE:
        # Vim only operates on the current line.
        line = view.line(s)

        # FIXME: Escape sequences like \" are probably syntax-dependant.
        prev_quote = reverse_search_by_pt(view, r'(?<!\\\\)' + delims[0], start=line.a, end=s.b)
        next_quote = find_in_range(view, r'(?<!\\\\)' + delims[0], start=s.b, end=line.b)

        if next_quote and not prev_quote:
            prev_quote = next_quote
            next_quote = find_in_range(view, r'(?<!\\\\)' + delims[0], start=prev_quote.b, end=line.b)

        if not (prev_quote and next_quote):
            return s

        if inclusive:
            return Region(prev_quote.a, next_quote.b)

        return Region(prev_quote.a + 1, next_quote.b - 1)

    if type_ == WORD:
        w = a_word(view, s.b, inclusive=inclusive, count=count)
        if s.size() <= 1:
            return w

        return Region(s.a, w.b)

    if type_ == BIG_WORD:
        w = a_big_word(view, s.b, inclusive=inclusive, count=count)
        if s.size() <= 1:
            return w

        return Region(s.a, w.b)

    if type_ == SENTENCE:
        # FIXME: This doesn't work well.
        # TODO: Improve this.
        sentence_start = view.find_by_class(s.b, forward=False, classes=CLASS_EMPTY_LINE)
        sentence_start_2 = reverse_search_by_pt(view, r'[.?!:]\s+|[.?!:]$', start=0, end=s.b)
        if sentence_start_2:
            sentence_start = (sentence_start + 1 if (sentence_start > sentence_start_2.b) else sentence_start_2.b)
        else:
            sentence_start = sentence_start + 1

        sentence_end = find_in_range(view, r'([.?!:)](?=\s))|([.?!:)]$)', start=s.b, end=view.size())
        if not sentence_end:
            return s

        if inclusive:
            return Region(sentence_start, sentence_end.b)
        else:
            return Region(sentence_start, sentence_end.b)

    # Support for a port of the Indent Object plugin:
    # https://github.com/michaeljsmith/vim-indent-object
    if type_ == INDENT:
        start, end = find_indent_text_object(view, s, inclusive)

        return Region(start, end)

    if type_ == LINE:
        start, end = find_line_text_object(view, s)

        return Region(start, end)

    return s