Completed
Pull Request — master (#179)
by Björn
21:25 queued 20:00
created

neovim.api.Buffer.__getitem__()   B

Complexity

Conditions 4

Size

Total Lines 22

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 12
CRAP Score 4
Metric Value
cc 4
dl 0
loc 22
ccs 12
cts 12
cp 1
crap 4
rs 8.9197
1
"""API for working with Nvim buffers."""
2 6
from .common import Remote
3 6
from ..compat import IS_PYTHON3
4
5
6 6
__all__ = ('Buffer')
7
8
9 6
if IS_PYTHON3:
10 3
    basestring = str
11
12
13 6
class Buffer(Remote):
14
15
    """A remote Nvim buffer."""
16
17 6
    _api_prefix = "buffer_"
18
19 6
    def __len__(self):
20
        """Return the number of lines contained in a Buffer."""
21 6
        return self._session.request('buffer_line_count', self)
22
23 6
    def __getitem__(self, idx):
24
        """Get a buffer line or slice by integer index.
25
26
        Indexes may be negative to specify positions from the end of the
27
        buffer. For example, -1 is the last line, -2 is the line before that
28
        and so on.
29
30
        When retrieving slices, omiting indexes(eg: `buffer[:]`) will bring
31
        the whole buffer.
32
        """
33 6
        if not isinstance(idx, slice):
34 6
            return self._session.request('buffer_get_line', self, idx)
35 6
        include_end = False
36 6
        start = idx.start
37 6
        end = idx.stop
38 6
        if start is None:
39 6
            start = 0
40 6
        if end is None:
41 6
            end = -1
42 6
            include_end = True
43 6
        return self._session.request('buffer_get_line_slice', self, start, end,
44
                                     True, include_end)
45
46 6
    def __setitem__(self, idx, lines):
47
        """Replace a buffer line or slice by integer index.
48
49
        Like with `__getitem__`, indexes may be negative.
50
51
        When replacing slices, omiting indexes(eg: `buffer[:]`) will replace
52
        the whole buffer.
53
        """
54 6
        if not isinstance(idx, slice):
55 6
            if lines is None:
56 6
                return self._session.request('buffer_del_line', self, idx)
57
            else:
58 6
                return self._session.request('buffer_set_line', self, idx,
59
                                             lines)
60 6
        if lines is None:
61 6
            lines = []
62 6
        include_end = False
63 6
        start = idx.start
64 6
        end = idx.stop
65 6
        if start is None:
66 6
            start = 0
67 6
        if end is None:
68 6
            end = -1
69 6
            include_end = True
70 6
        return self._session.request('buffer_set_line_slice', self, start, end,
71
                                     True, include_end, lines)
72
73 6
    def __iter__(self):
74
        """Iterate lines of a buffer.
75
76
        This will retrieve all lines locally before iteration starts. This
77
        approach is used because for most cases, the gain is much greater by
78
        minimizing the number of API calls by transfering all data needed to
79
        work.
80
        """
81
        lines = self[:]
82
        for line in lines:
83
            yield line
84
85 6
    def __delitem__(self, idx):
86
        """Delete line or slice of lines from the buffer.
87
88
        This is the same as __setitem__(idx, [])
89
        """
90 6
        if not isinstance(idx, slice):
91 6
            self.__setitem__(idx, None)
92
        else:
93 6
            self.__setitem__(idx, [])
94
95 6
    def get_line_slice(self, start, stop, start_incl, end_incl):
96
        """More flexible wrapper for retrieving slices."""
97
        return self._session.request('buffer_get_line_slice', self, start,
98
                                     stop, start_incl, end_incl)
99
100 6
    def set_line_slice(self, start, stop, start_incl, end_incl, lines):
101
        """More flexible wrapper for replacing slices."""
102
        return self._session.request('buffer_set_line_slice', self, start,
103
                                     stop, start_incl, end_incl, lines)
104
105 6
    def append(self, lines, index=-1):
106
        """Append a string or list of lines to the buffer."""
107 6
        if isinstance(lines, basestring):
108 6
            lines = [lines]
109 6
        return self._session.request('buffer_insert', self, index, lines)
110
111 6
    def mark(self, name):
112
        """Return (row, col) tuple for a named mark."""
113 6
        return self._session.request('buffer_get_mark', self, name)
114
115 6
    def range(self, start, end):
116
        """Return a `Range` object, which represents part of the Buffer."""
117
        return Range(self, start, end)
118
119 6
    def add_highlight(self, hl_group, line, col_start=0,
120
                      col_end=-1, src_id=-1, async=None):
121
        """Add a highlight to the buffer."""
122
        if async is None:
123
            async = (src_id != 0)
124
        return self._session.request('buffer_add_highlight', self, src_id,
125
                                     hl_group, line, col_start,
126
                                     col_end, async=async)
127
128 6
    def clear_highlight(self, src_id, line_start=0, line_end=-1, async=True):
129
        """clear highlights from the buffer."""
130
        self._session.request('buffer_clear_highlight', self, src_id,
131
                              line_start, line_end, async=async)
132
133 6
    @property
134
    def name(self):
135
        """Get the buffer name."""
136 6
        return self._session.request('buffer_get_name', self)
137
138 6
    @name.setter
139
    def name(self, value):
140
        """Set the buffer name. BufFilePre/BufFilePost are triggered."""
141 6
        return self._session.request('buffer_set_name', self, value)
142
143 6
    @property
144
    def valid(self):
145
        """Return True if the buffer still exists."""
146 6
        return self._session.request('buffer_is_valid', self)
147
148 6
    @property
149
    def number(self):
150
        """Get the buffer number."""
151 6
        return self._session.request('buffer_get_number', self)
152
153
154 6
class Range(object):
155 6
    def __init__(self, buffer, start, end):
156
        self._buffer = buffer
157
        self.start = start - 1
158
        self.end = end
159
160 6
    def __len__(self):
161
        return self.end - self.start
162
163 6
    def __getitem__(self, idx):
164
        if not isinstance(idx, slice):
165
            return self._buffer[self._normalize_index(idx)]
166
        start = self._normalize_index(idx.start)
167
        end = self._normalize_index(idx.stop)
168
        if start is None:
169
            start = self.start
170
        if end is None:
171
            end = self.end
172
        return self._buffer[start:end]
173
174 6
    def __setitem__(self, idx, lines):
175
        if not isinstance(idx, slice):
176
            self._buffer[self._normalize_index(idx)] = lines
177
            return
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
184
        self._buffer[start:end] = lines
185
186 6
    def __iter__(self):
187
        for i in range(self.start, self.end):
188
            yield self._buffer[i]
189
190 6
    def append(self, lines, i=None):
191
        i = self._normalize_index(i)
192
        if i is None:
193
            i = self.end
194
        self._buffer.append(lines, i)
195
196 6
    def _normalize_index(self, index):
197
        if index is None:
198
            return None
199
        if index < 0:
200
            index = self.end - 1
201
        else:
202
            index += self.start
203
            if index >= self.end:
204
                index = self.end - 1
205
        return index
206