Exemplo n.º 1
0
    def run(self, edit, range=".", pattern=""):
        range = range or "."

        # we either accept a full pattern plus flags and count arg
        # ... or ...
        # simply a command in the following forms:
        #   :s
        #   :s gi
        #   :s gi 10
        #   :s 10
        try:
            sep, left, _, right, _, flags, count = ExSubstitute.parts_rgex.search(pattern).groups()
            ExSubstitute.last_pattern = (left, right)
            ExSubstitute.last_flags = flags
        except AttributeError:
            if not ExSubstitute.last_pattern:
                sublime.status_message("VintageEx: No pattern available.")
                return
            left, _, right = pattern.strip().partition(" ")
            flags, count = "", None
            if left and left.strip().isalpha():
                flags = left
                if right and right.isdigit():
                    count = int(right)
                elif right:
                    sublime.status_message("VintageEx: Bad pattern.")
                    return
            elif left and left.strip().isdigit():
                count = int(left)

            if flags or count:
                pattern = ""

        if not pattern:
            left, right = ExSubstitute.last_pattern

        re_flags = 0
        re_flags |= re.IGNORECASE if (flags and "i" in flags) else 0
        left = re.compile(left, flags=re_flags)

        if count and range == ".":
            range = ".,.+%d" % int(count)
        elif count:
            a, b = ex_range.calculate_range(self.view, range)
            if not a and b:
                b = max(a, b)
            range = "%d,%d+%d" % (b, b, int(count))

        target_region = get_region_by_range(self.view, range)
        replace_count = 0 if (flags and "g" in flags) else 1
        for r in reversed(target_region):
            # be explicit about replacing the line, because we might be looking
            # at a Ctrl+D sequence of regions (not spanning a whole line)
            # TODO: Improve this: make sure view.line() doesn't extend past
            # the desired line. For example, in VISUAL LINE MODE.
            if self.view.substr(r.end() - 1) == "\n":
                r = sublime.Region(r.begin(), r.end() - 1)
            line_text = self.view.substr(self.view.line(r))
            rv = re.sub(left, right, line_text, count=replace_count)
            self.view.replace(edit, self.view.line(r), rv)
Exemplo n.º 2
0
 def run(self, edit, range=''):
     if not range:
         # No-op: user issued ":".
         return
     a, b = ex_range.calculate_range(self.view, range, is_only_range=True)
     self.view.run_command('vi_goto_line', {'repeat': b})
     self.view.show(self.view.sel()[0])
Exemplo n.º 3
0
 def run(self, edit, range=''):
     if not range:
         # No-op: user issued ":".
         return
     a, b = ex_range.calculate_range(self.view, range, is_only_range=True)[0]
     self.view.run_command('vi_goto_line', {'repeat': b})
     self.view.show(self.view.sel()[0])
Exemplo n.º 4
0
    def run(self, edit, range='.', pattern=''):
        range = range or '.'

        # we either accept a full pattern plus flags and count arg
        # ... or ...
        # simply a command in the following forms:
        #   :s
        #   :s gi
        #   :s gi 10
        #   :s 10
        try:
            sep, left, _, right, _, flags, count = \
                            ExSubstitute.parts_rgex.search(pattern).groups()
            ExSubstitute.last_pattern = (left, right)
            ExSubstitute.last_flags = flags
        except AttributeError:
            if not ExSubstitute.last_pattern:
                sublime.status_message("VintageEx: No pattern available.")
                return
            left, _, right = pattern.strip().partition(' ')
            flags, count = '', None
            if left and left.strip().isalpha():
                flags = left
                if right and right.isdigit():
                    count = int(right)
                elif right:
                    sublime.status_message('VintageEx: Bad pattern.')
                    return
            elif left and left.strip().isdigit():
                count = int(left)

            if flags or count:
                pattern = ''

        if not pattern:
            left, right = ExSubstitute.last_pattern

        re_flags = 0
        re_flags |= re.IGNORECASE if (flags and 'i' in flags) else 0
        left = re.compile(left, flags=re_flags)

        if count and range == '.':
            range = '.,.+%d' % int(count)
        elif count:
            a, b = ex_range.calculate_range(self.view, range)
            if not a and b:
                b = max(a, b)
            range = "%d,%d+%d" % (b, b, int(count))

        target_region = get_region_by_range(self.view, range)
        replace_count = 0 if (flags and 'g' in flags) else 1
        for r in reversed(target_region):
            # be explicit about replacing the line, because we might be looking
            # at a Ctrl+D sequence of regions (not spanning a whole line)
            line_text = self.view.substr(self.view.line(r))
            rv = re.sub(left, right, line_text, count=replace_count)
            self.view.replace(edit, self.view.line(r), rv)
Exemplo n.º 5
0
    def testCalculateCorrectRange(self):
        values = (
            (calculate_range(g_test_view, '0'), [(0, 0)]),
            (calculate_range(g_test_view, '1'), [(1, 1)]),
            (calculate_range(g_test_view, '1,1'), [(1, 1)]),
            (calculate_range(g_test_view, '%,1'), [(1, 538)]),
            (calculate_range(g_test_view, '1,%'), [(1, 538)]),
            (calculate_range(g_test_view, '1+99,160-10'), [(100, 150)]),
            (calculate_range(g_test_view, '/THIRTY/+10,100'), [(40, 100)]),
        )

        select_line(g_test_view, 31)
        values += (
            (calculate_range(g_test_view, '10,/THIRTY/'), [(10, 31)]),
            (calculate_range(g_test_view, '10;/THIRTY/'), [(10, 30)]),
        )

        for actual, expected in values:
            self.assertEquals(actual, expected)
Exemplo n.º 6
0
    def testCalculateCorrectRange(self):
        values = (
            (calculate_range(g_test_view, '0'), [(0, 0)]),
            (calculate_range(g_test_view, '1'), [(1, 1)]),
            (calculate_range(g_test_view, '1,1'), [(1, 1)]),
            (calculate_range(g_test_view, '%,1'), [(1, 538)]),
            (calculate_range(g_test_view, '1,%'), [(1, 538)]),
            (calculate_range(g_test_view, '1+99,160-10'), [(100, 150)]),
            (calculate_range(g_test_view, '/THIRTY/+10,100'), [(40, 100)]),
        )

        select_line(g_test_view, 31)
        values += (
            (calculate_range(g_test_view, '10,/THIRTY/'), [(10, 31)]),
            (calculate_range(g_test_view, '10;/THIRTY/'), [(10, 30)]),
        )

        for actual, expected in values:
            self.assertEquals(actual, expected)
Exemplo n.º 7
0
def compute_address(view, text_range):
    """Computes a single-line address based on ``text_range``, which is a
    string that should be a valid Vi(m) address.

    Return values:
        - SUCCESS: address (positive integer)
        - ERROR: -1 (can't compute valid address)
    """
    # xxx strip in the parsing phase instead
    text_range = text_range.strip()
    # Note that some address error checking is also performed at the parsing
    # stage, so that '%' doesn't reach here, for example.
    a, b = ex_range.calculate_range(view, text_range.strip())
    address = (max(a, b) if all((a, b)) else (a or b)) or 0
    return address - 1
Exemplo n.º 8
0
def compute_address(view, text_range):
    """Computes a single-line address based on ``text_range``, which is a
    string that should be a valid Vi(m) address.

    Return values:
        - SUCCESS: address (positive integer)
        - ERROR: -1 (can't compute valid address)
    """
    # xxx strip in the parsing phase instead
    text_range = text_range.strip()
    # Note that some address error checking is also performed at the parsing
    # stage, so that '%' doesn't reach here, for example.
    a, b = ex_range.calculate_range(view, text_range.strip())
    address = (max(a, b) if all((a, b)) else (a or b)) or 0
    return address - 1
Exemplo n.º 9
0
def get_region_by_range(view, text_range, split_visual=False):
    # If GLOBAL_RANGES exists, the ExGlobal command has been run right before
    # the current command, and we know we must process these lines.
    # XXX move this further down into the range parsing?
    global GLOBAL_RANGES
    if GLOBAL_RANGES:
        rv = GLOBAL_RANGES[:]
        GLOBAL_RANGES = []
        return rv

    regions = ex_range.calculate_range(view, text_range)
    lines = []
    for region in regions:
        a, b = region
        r = sublime.Region(view.text_point(a - 1, 0), view.full_line(view.text_point(b - 1, 0)).end())
        lines.extend(view.split_by_newlines(r))

    return lines
Exemplo n.º 10
0
def get_region_by_range(view, text_range, split_visual=False):
    # If GLOBAL_RANGES exists, the ExGlobal command has been run right before
    # the current command, and we know we must process these lines.
    # XXX move this further down into the range parsing?
    global GLOBAL_RANGES
    if GLOBAL_RANGES:
        rv = GLOBAL_RANGES[:]
        GLOBAL_RANGES = []
        return rv

    regions = ex_range.calculate_range(view, text_range)
    lines = []
    for region in regions:
        a, b = region
        r = sublime.Region(view.text_point(a - 1, 0),
                           view.full_line(view.text_point(b - 1, 0)).end())
        lines.extend(view.split_by_newlines(r))

    return lines
Exemplo n.º 11
0
    def run(self, edit, range='', name='', plusplus_args='', forced=False):
        target_line = self.view.line(self.view.sel()[0].begin())
        if range:
            range = max(ex_range.calculate_range(self.view, range)[0])
            target_line = self.view.line(self.view.text_point(range, 0))
        target_point = min(target_line.b + 1, self.view.size())

        # cheat a little bit to get the parsing right:
        #   - forced == True means we need to execute a command
        if forced:
            if sublime.platform() == 'linux':
                for s in self.view.sel():
                    the_shell = os.path.expandvars("$SHELL")
                    p = subprocess.Popen([the_shell, '-c', name],
                                                        stdout=subprocess.PIPE)
                    self.view.insert(edit, s.begin(), p.communicate()[0][:-1])
            elif sublime.platform() == 'windows':
                for s in self.view.sel():
                    p = subprocess.Popen(['cmd.exe', '/C', name],
                                            stdout=subprocess.PIPE,
                                            startupinfo=get_startup_info()
                                            )
                    cp = 'cp' + get_oem_cp()
                    rv = p.communicate()[0].decode(cp)[:-2].strip()
                    self.view.insert(edit, s.begin(), rv)
            else:
                ex_error.handle_not_implemented()
        # Read a file into the current view.
        else:
            # Read the current buffer's contents and insert below current line.
            if not name:
                new_contents = self.view.substr(
                                        sublime.Region(0, self.view.size()))
                if self.view.substr(target_line.b) != '\n':
                    new_contents = '\n' + new_contents
                self.view.insert(edit, target_point, new_contents)
                return
            # XXX read file "name"
            # we need proper filesystem autocompletion here
            else:
                ex_error.handle_not_implemented()
                return
Exemplo n.º 12
0
    def run(self, edit, range='', name='', plusplus_args='', forced=False):
        target_line = self.view.line(self.view.sel()[0].begin())
        if range:
            range = max(ex_range.calculate_range(self.view, range)[0])
            target_line = self.view.line(self.view.text_point(range, 0))
        target_point = min(target_line.b + 1, self.view.size())

        # cheat a little bit to get the parsing right:
        #   - forced == True means we need to execute a command
        if forced:
            if sublime.platform() == 'linux':
                for s in self.view.sel():
                    the_shell = os.path.expandvars("$SHELL")
                    p = subprocess.Popen([the_shell, '-c', name],
                                                        stdout=subprocess.PIPE)
                    self.view.insert(edit, s.begin(), p.communicate()[0][:-1])
            elif sublime.platform() == 'windows':
                for s in self.view.sel():
                    p = subprocess.Popen(['cmd.exe', '/C', name],
                                            stdout=subprocess.PIPE,
                                            startupinfo=get_startup_info()
                                            )
                    cp = 'cp' + get_oem_cp()
                    rv = p.communicate()[0].decode(cp)[:-2].strip()
                    self.view.insert(edit, s.begin(), rv)
            else:
                ex_error.handle_not_implemented()
        # Read a file into the current view.
        else:
            # Read the current buffer's contents and insert below current line.
            if not name:
                new_contents = self.view.substr(
                                        sublime.Region(0, self.view.size()))
                if self.view.substr(target_line.b) != '\n':
                    new_contents = '\n' + new_contents
                self.view.insert(edit, target_point, new_contents)
                return
            # XXX read file "name"
            # we need proper filesystem autocompletion here
            else:
                ex_error.handle_not_implemented()
                return
Exemplo n.º 13
0
def get_region_by_range(view, text_range, split_visual=False):
    # xxx move this further down into the range parsing?
    global GLOBAL_RANGES
    if GLOBAL_RANGES:
        rv = GLOBAL_RANGES[:]
        GLOBAL_RANGES = []
        return rv

    if text_range.replace(" ", "") == "'<,'>":
        if not split_visual:
            return list(view.sel())
        else:
            rv = []
            for r in list(view.sel()):
                rv.extend(view.split_by_newlines(r))
            return rv

    a, b = ex_range.calculate_range(view, text_range)
    r = sublime.Region(view.text_point(a - 1, 0), view.full_line(view.text_point(b - 1, 0)).end())
    return view.split_by_newlines(r)
Exemplo n.º 14
0
def get_region_by_range(view, text_range, split_visual=False):
    # xxx move this further down into the range parsing?
    global GLOBAL_RANGES
    if GLOBAL_RANGES:
        rv = GLOBAL_RANGES[:]
        GLOBAL_RANGES = []
        return rv

    if text_range.replace(' ', '') == "'<,'>":
        if not split_visual:
            return list(view.sel())
        else:
            rv = []
            for r in list(view.sel()):
                rv.extend(view.split_by_newlines(r))
            return rv

    a, b = ex_range.calculate_range(view, text_range)
    r = sublime.Region(view.text_point(a - 1, 0),
                       view.full_line(view.text_point(b - 1, 0)).end())
    return view.split_by_newlines(r)
Exemplo n.º 15
0
def get_region_by_range(view, text_range, split_visual=False):
    # If GLOBAL_RANGES exists, the ExGlobal command has been run right before
    # the current command, and we know we must process these lines.
    # XXX move this further down into the range parsing?
    global GLOBAL_RANGES
    if GLOBAL_RANGES:
        rv = GLOBAL_RANGES[:]
        GLOBAL_RANGES = []
        return rv

    if text_range.replace(" ", "") == "'<,'>":
        if not split_visual:
            return list(view.sel())
        else:
            rv = []
            for r in list(view.sel()):
                rv.extend(view.split_by_newlines(r))
            return rv

    a, b = ex_range.calculate_range(view, text_range)
    r = sublime.Region(view.text_point(a - 1, 0), view.full_line(view.text_point(b - 1, 0)).end())
    return view.split_by_newlines(r)
Exemplo n.º 16
0
def get_region_by_range(view, text_range, split_visual=False):
    # If GLOBAL_RANGES exists, the ExGlobal command has been run right before
    # the current command, and we know we must process these lines.
    # XXX move this further down into the range parsing?
    global GLOBAL_RANGES
    if GLOBAL_RANGES:
        rv = GLOBAL_RANGES[:]
        GLOBAL_RANGES = []
        return rv

    if text_range.replace(' ', '') == "'<,'>":
        if not split_visual:
            return list(view.sel())
        else:
            rv = []
            for r in list(view.sel()):
                rv.extend(view.split_by_newlines(r))
            return rv

    a, b = ex_range.calculate_range(view, text_range)
    r = sublime.Region(view.text_point(a - 1, 0),
                       view.full_line(view.text_point(b - 1, 0)).end())
    return view.split_by_newlines(r)
Exemplo n.º 17
0
 def run(self, edit, range=""):
     assert range, "Range required."
     a, b = ex_range.calculate_range(self.view, range, is_only_range=True)
     target = (max(a, b) if all((a, b)) else (a or b)) or 0
     self.view.run_command("vi_goto_line", {"repeat": target})
     self.view.show(self.view.sel()[0])
Exemplo n.º 18
0
            ExSubstitute.most_recent_replacement = replacement
            ExSubstitute.most_recent_flags = flags

        computed_flags = 0
        computed_flags |= re.IGNORECASE if (flags and 'i' in flags) else 0
        try:
            pattern = re.compile(pattern, flags=computed_flags)
        except Exception, e:
            sublime.status_message("VintageEx [regex error]: %s ... in pattern '%s'" % (e.message, pattern))
            print "VintageEx [regex error]: %s ... in pattern '%s'" % (e.message, pattern)
            return

        if count and range == '.':
            range = '.,.+%d' % int(count)
        elif count:
            a, b = ex_range.calculate_range(self.view, range)[0]
            if not a and b:
                b = max(a, b)
            range = "%d,%d+%d" % (b, b, int(count))

        target_region = get_region_by_range(self.view, range)
        replace_count = 0 if (flags and 'g' in flags) else 1
        for r in reversed(target_region):
            # be explicit about replacing the line, because we might be looking
            # at a Ctrl+D sequence of regions (not spanning a whole line)
            # TODO: Improve this: make sure view.line() doesn't extend past
            # the desired line. For example, in VISUAL LINE MODE.
            if self.view.substr(r.end() - 1) == '\n':
                r = sublime.Region(r.begin(), r.end() - 1)
            line_text = self.view.substr(self.view.line(r))
            rv = re.sub(pattern, replacement, line_text, count=replace_count)
Exemplo n.º 19
0
        computed_flags = 0
        computed_flags |= re.IGNORECASE if (flags and 'i' in flags) else 0
        try:
            pattern = re.compile(pattern, flags=computed_flags)
        except Exception, e:
            sublime.status_message(
                "VintageEx [regex error]: %s ... in pattern '%s'" %
                (e.message, pattern))
            print "VintageEx [regex error]: %s ... in pattern '%s'" % (
                e.message, pattern)
            return

        if count and range == '.':
            range = '.,.+%d' % int(count)
        elif count:
            a, b = ex_range.calculate_range(self.view, range)[0]
            if not a and b:
                b = max(a, b)
            range = "%d,%d+%d" % (b, b, int(count))

        target_region = get_region_by_range(self.view, range)
        replace_count = 0 if (flags and 'g' in flags) else 1
        for r in reversed(target_region):
            # be explicit about replacing the line, because we might be looking
            # at a Ctrl+D sequence of regions (not spanning a whole line)
            # TODO: Improve this: make sure view.line() doesn't extend past
            # the desired line. For example, in VISUAL LINE MODE.
            if self.view.substr(r.end() - 1) == '\n':
                r = sublime.Region(r.begin(), r.end() - 1)
            line_text = self.view.substr(self.view.line(r))
            rv = re.sub(pattern, replacement, line_text, count=replace_count)
Exemplo n.º 20
0
 def run(self, edit, range=''):
     assert range, 'Range required.'
     a, b = ex_range.calculate_range(self.view, range, is_only_range=True)
     target = (max(a, b) if all((a, b)) else (a or b)) or 0
     self.view.run_command('vi_goto_line', {'repeat': target})
     self.view.show(self.view.sel()[0])