@rpc_export('python_do_range', sync=True)
    def python_do_range(self, start, stop, code):
        self._set_current_range(start, stop)
        nvim = self.nvim
        start -= 1
        stop -= 1
        fname = '_vim_pydo'

        # define the function
        function_def = 'def %s(line, linenr):\n %s' % (fname, code,)
        exec(function_def, self.module.__dict__)
        # get the function
        function = self.module.__dict__[fname]
        while start <= stop:
            # Process batches of 5000 to avoid the overhead of making multiple
            # API calls for every line. Assuming an average line length of 100
            # bytes, approximately 488 kilobytes will be transferred per batch,
            # which can be done very quickly in a single API call.
            sstart = start
            sstop = min(start + 5000, stop)
            lines = nvim.current.buffer.get_line_slice(sstart, sstop, True,
                                                       True)

            exception = None
            newlines = []
            linenr = sstart + 1
            for i, line in enumerate(lines):
                result = function(line, linenr)
                if result is None:
                    # Update earlier lines, and skip to the next
                    if newlines:
                        end = sstart + len(newlines) - 1
                        nvim.current.buffer.set_line_slice(sstart, end,
                                                           True, True,
                                                           newlines)
                    sstart += len(newlines) + 1
                    newlines = []
                    pass
                elif isinstance(result, basestring):
                    newlines.append(result)
                else:
                    exception = TypeError('pydo should return a string ' +
                                          'or None, found %s instead'
                                          % result.__class__.__name__)
                    break
                linenr += 1

            start = sstop + 1
            if newlines:
                end = sstart + len(newlines) - 1
                nvim.current.buffer.set_line_slice(sstart, end, True, True,
                                                   newlines)
            if exception:
                raise exception
        # delete the function
        del self.module.__dict__[fname]
Handle the `pydo` ex command.
dataset/ETHPy150Open neovim/python-client/neovim/plugin/script_host.py/ScriptHost.python_do_range