Ejemplo n.º 1
0
def resolve_internal_normal_target(view,
                                   s: Region,
                                   target: int,
                                   linewise: bool = None,
                                   inclusive: bool = None) -> None:
    # An Internal Normal resolver may have modifiers such as linewise,
    # inclusive, exclusive, etc. Modifiers determine how the selection, relative
    # to the target should be resolved.

    # XXX Should modifiers be a bitwise options param rather than indivisual
    # params? This can be easily refactored later!
    # * For the moment, ensure at least one modifier is specified!
    # * For the moment, modifier can only be used individually!
    if linewise is None and inclusive is None:
        raise NotImplementedError()
    if linewise is not None and inclusive is not None:
        raise NotImplementedError()

    if linewise:
        resolve_visual_target(s, target)

        if s.b >= s.a:
            s.a = view.line(s.a).a
            s.b = view.full_line(s.b).b
        else:
            s.b = view.line(s.b).a
            s.a = view.full_line(s.a).b

    if inclusive:
        s.b = target

        if s.b >= s.a:
            s.b += 1
        else:
            s.a += 1
Ejemplo n.º 2
0
def resolve_visual_line_target(view, s: Region, target: int) -> None:
    if s.a < s.b:  # A --> B
        if target < s.a:  # TARGET < A --> B
            s.a = view.full_line(s.a).b
            s.b = view.line(target).a
        elif target > s.a:
            s.b = view.full_line(target).b
        elif target == s.a:
            s.b = s.a
            s.a = view.full_line(target).b
    elif s.a > s.b:  # B <-- A
        if target > s.a:  # B <-- A < TARGET
            s.a = view.line(s.a - 1).a
            s.b = view.full_line(target).b
        elif target < s.a:  # TARGET < B <-- TARGET < A
            s.b = view.line(target).a
        elif target == s.a:  # A === TARGET
            s.a = view.line(s.a - 1).a
            s.b = view.full_line(target).b
    elif s.a == s.b:  # A === B

        # If A and B are equal, it means the Visual selection is not "well
        # formed". Instead of raising an error, or not resolving the selection,
        # the selection is coerced to be "well formed" and then resolved.

        if target > s.a:
            s.a = view.line(s.a).a
            s.b = view.full_line(target).b
        elif target < s.a:
            s.a = view.full_line(s.a).b
            s.b = view.line(target).a
        elif target == s.a:
            s.a = view.line(target).a
            s.b = view.full_line(target).b
Ejemplo n.º 3
0
def _get_text_object_tag(view, s: Region, inclusive: bool, count: int) -> Region:
    # When the active cursor position is on leading whitespace before a tag on
    # the same line then the start point of the text object is the tag.
    line = view.line(get_insertion_point_at_b(s))
    tag_in_line = view_find_in_range(view, '^\\s*<[^>]+>', line.begin(), line.end())
    if tag_in_line:
        if s.b >= s.a and s.b < tag_in_line.end():
            if s.empty():
                s.a = s.b = tag_in_line.end()
            else:
                s.a = tag_in_line.end()
                s.b = tag_in_line.end() + 1

    begin_tag, end_tag, _ = find_containing_tag(view, s.begin())
    if not (begin_tag and end_tag):
        return s

    # The normal method is to select a <tag> until the matching </tag>. For "at"
    # the tags are included, for "it" they are excluded. But when "it" is
    # repeated the tags will be included (otherwise nothing would change).
    if not inclusive:
        if s == Region(begin_tag.end(), end_tag.begin()):
            inclusive = True

    if inclusive:
        return Region(begin_tag.a, end_tag.b)
    else:
        return Region(begin_tag.b, end_tag.a)
Ejemplo n.º 4
0
    def highlight_error(self, region: sublime.Region, message: str):
        self.phantom_set = sublime.PhantomSet(self.view, 'json_errors')

        char_match = self.json_char_matcher.search(message)
        if char_match:
            if region.a > region.b:
                region.b += int(char_match.group(1))
                region.a = region.b + 1
            else:
                region.a += int(char_match.group(1))
                region.b = region.a + 1

        self.phantoms.append(
            sublime.Phantom(
                region,
                self.create_phantom_html(message, 'error'),
                sublime.LAYOUT_BELOW,
                self.navigation,
            ))
        self.phantom_set.update(self.phantoms)
        self.view.show(region)
        self.view.set_status('json_errors', message)
Ejemplo n.º 5
0
def resolve_visual_target(s: Region, target: int) -> None:
    if s.a < s.b:  # A --> B
        if target < s.a:  # TARGET < A --> B
            s.a += 1
            s.b = target
        else:
            s.b = target + 1
    elif s.a > s.b:  # B <-- A
        if target >= s.a:  # B <-- A <= TARGET
            s.a -= 1
            s.b = target + 1
        else:
            s.b = target
    else:  # A === B

        # If A and B are equal, it means the Visual selection is not "well
        # formed". Instead of raising an error, or not resolving the selection,
        # the selection is coerced to be "well formed" and then resolved.

        if target == s.b:  # B === TARGET
            s.b = target + 1
        else:
            s.b = target
Ejemplo n.º 6
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