Completed
Pull Request — master (#190)
by Björn
02:21
created

neovim.api.Buffer.__getitem__()   A

Complexity

Conditions 2

Size

Total Lines 17

Duplication

Lines 0
Ratio 0 %

Code Coverage

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