Test Failed
Push — master ( a5ee34...588b1f )
by Justin M.
34s queued 10s
created

pynvim.api.buffer.Buffer.range()   A

Complexity

Conditions 1

Size

Total Lines 3
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 1

Importance

Changes 0
Metric Value
cc 1
eloc 2
nop 3
dl 0
loc 3
rs 10
c 0
b 0
f 0
ccs 2
cts 2
cp 1
crap 1
1
"""API for working with a Nvim Buffer."""
2 6
from .common import Remote
3 6
from ..compat import IS_PYTHON3, check_async
4
5
6 6
__all__ = ('Buffer')
7
8
9 6
if IS_PYTHON3:
10 4
    basestring = str
11
12
13 6
def adjust_index(idx, default=None):
14
    """Convert from python indexing convention to nvim indexing convention."""
15 6
    if idx is None:
16 6
        return default
17 6
    elif idx < 0:
18 6
        return idx - 1
19
    else:
20 6
        return idx
21
22
23 6
class Buffer(Remote):
24
25
    """A remote Nvim buffer."""
26
27 6
    _api_prefix = "nvim_buf_"
28
29 6
    def __len__(self):
30
        """Return the number of lines contained in a Buffer."""
31 6
        return self.request('nvim_buf_line_count')
32
33 6
    def __getitem__(self, idx):
34
        """Get a buffer line or slice by integer index.
35
36
        Indexes may be negative to specify positions from the end of the
37
        buffer. For example, -1 is the last line, -2 is the line before that
38
        and so on.
39
40
        When retrieving slices, omiting indexes(eg: `buffer[:]`) will bring
41
        the whole buffer.
42
        """
43 6
        if not isinstance(idx, slice):
44 6
            i = adjust_index(idx)
45 6
            return self.request('nvim_buf_get_lines', i, i + 1, True)[0]
46 6
        start = adjust_index(idx.start, 0)
47 6
        end = adjust_index(idx.stop, -1)
48 6
        return self.request('nvim_buf_get_lines', start, end, False)
49
50 6
    def __setitem__(self, idx, item):
51
        """Replace a buffer line or slice by integer index.
52
53
        Like with `__getitem__`, indexes may be negative.
54
55
        When replacing slices, omiting indexes(eg: `buffer[:]`) will replace
56
        the whole buffer.
57
        """
58 6
        if not isinstance(idx, slice):
59 6
            i = adjust_index(idx)
60 6
            lines = [item] if item is not None else []
61 6
            return self.request('nvim_buf_set_lines', i, i + 1, True, lines)
62 6
        lines = item if item is not None else []
63 6
        start = adjust_index(idx.start, 0)
64 6
        end = adjust_index(idx.stop, -1)
65 6
        return self.request('nvim_buf_set_lines', start, end, False, lines)
66
67 6
    def __iter__(self):
68
        """Iterate lines of a buffer.
69
70
        This will retrieve all lines locally before iteration starts. This
71
        approach is used because for most cases, the gain is much greater by
72
        minimizing the number of API calls by transfering all data needed to
73
        work.
74
        """
75
        lines = self[:]
76
        for line in lines:
77
            yield line
78
79 6
    def __delitem__(self, idx):
80
        """Delete line or slice of lines from the buffer.
81
82
        This is the same as __setitem__(idx, [])
83
        """
84 6
        self.__setitem__(idx, None)
85
86 6
    def __ne__(self, other):
87
        """Test inequality of Buffers.
88
89
        Necessary for Python 2 compatibility.
90
        """
91 6
        return not self.__eq__(other)
92
93 6
    def append(self, lines, index=-1):
94
        """Append a string or list of lines to the buffer."""
95 6
        if isinstance(lines, (basestring, bytes)):
0 ignored issues
show
introduced by
The variable basestring does not seem to be defined in case IS_PYTHON3 on line 9 is False. Are you sure this can never be the case?
Loading history...
96 6
            lines = [lines]
97 6
        return self.request('nvim_buf_set_lines', index, index, True, lines)
98
99 6
    def mark(self, name):
100
        """Return (row, col) tuple for a named mark."""
101 6
        return self.request('nvim_buf_get_mark', name)
102
103 6
    def range(self, start, end):
104
        """Return a `Range` object, which represents part of the Buffer."""
105 6
        return Range(self, start, end)
106
107 6
    def add_highlight(self, hl_group, line, col_start=0,
108
                      col_end=-1, src_id=-1, async_=None,
109
                      **kwargs):
110
        """Add a highlight to the buffer."""
111 6
        async_ = check_async(async_, kwargs, src_id != 0)
112 6
        return self.request('nvim_buf_add_highlight', src_id, hl_group,
113
                            line, col_start, col_end, async_=async_)
114
115 6
    def clear_highlight(self, src_id, line_start=0, line_end=-1, async_=None,
116
                        **kwargs):
117
        """Clear highlights from the buffer."""
118
        async_ = check_async(async_, kwargs, True)
119
        self.request('nvim_buf_clear_highlight', src_id,
120
                     line_start, line_end, async_=async_)
121
122 6
    def update_highlights(self, src_id, hls, clear_start=0, clear_end=-1,
123
                          clear=False, async_=True):
124
        """Add or update highlights in batch to avoid unnecessary redraws.
125
126
        A `src_id` must have been allocated prior to use of this function. Use
127
        for instance `nvim.new_highlight_source()` to get a src_id for your
128
        plugin.
129
130
        `hls` should be a list of highlight items. Each item should be a list
131
        or tuple on the form `("GroupName", linenr, col_start, col_end)` or
132
        `("GroupName", linenr)` to highlight an entire line.
133
134
        By default existing highlights are preserved. Specify a line range with
135
        clear_start and clear_end to replace highlights in this range. As a
136
        shorthand, use clear=True to clear the entire buffer before adding the
137
        new highlights.
138
        """
139 6
        if clear and clear_start is None:
140
            clear_start = 0
141 6
        lua = self._session._get_lua_private()
142 6
        lua.update_highlights(self, src_id, hls, clear_start, clear_end,
143
                              async_=async_)
144
145 6
    @property
146
    def name(self):
147
        """Get the buffer name."""
148 6
        return self.request('nvim_buf_get_name')
149
150 6
    @name.setter
151
    def name(self, value):
152
        """Set the buffer name. BufFilePre/BufFilePost are triggered."""
153 6
        return self.request('nvim_buf_set_name', value)
154
155 6
    @property
156
    def valid(self):
157
        """Return True if the buffer still exists."""
158 6
        return self.request('nvim_buf_is_valid')
159
160 6
    @property
161
    def number(self):
162
        """Get the buffer number."""
163 6
        return self.handle
164
165
166 6
class Range(object):
167 6
    def __init__(self, buffer, start, end):
168 6
        self._buffer = buffer
169 6
        self.start = start - 1
170 6
        self.end = end - 1
171
172 6
    def __len__(self):
173
        return self.end - self.start + 1
174
175 6
    def __getitem__(self, idx):
176
        if not isinstance(idx, slice):
177
            return self._buffer[self._normalize_index(idx)]
178
        start = self._normalize_index(idx.start)
179
        end = self._normalize_index(idx.stop)
180
        if start is None:
181
            start = self.start
182
        if end is None:
183
            end = self.end + 1
184
        return self._buffer[start:end]
185
186 6
    def __setitem__(self, idx, lines):
187 6
        if not isinstance(idx, slice):
188
            self._buffer[self._normalize_index(idx)] = lines
189
            return
190 6
        start = self._normalize_index(idx.start)
191 6
        end = self._normalize_index(idx.stop)
192 6
        if start is None:
193
            start = self.start
194 6
        if end is None:
195
            end = self.end
196 6
        self._buffer[start:end + 1] = lines
197
198 6
    def __iter__(self):
199
        for i in range(self.start, self.end + 1):
200
            yield self._buffer[i]
201
202 6
    def append(self, lines, i=None):
203
        i = self._normalize_index(i)
204
        if i is None:
205
            i = self.end + 1
206
        self._buffer.append(lines, i)
207
208 6
    def _normalize_index(self, index):
209 6
        if index is None:
210
            return None
211 6
        if index < 0:
212
            index = self.end
213
        else:
214 6
            index += self.start
215 6
            if index > self.end:
216 6
                index = self.end
217
        return index
218