Completed
Pull Request — master (#179)
by Björn
24:48
created

neovim.api.Buffer.__init__()   A

Complexity

Conditions 1

Size

Total Lines 12

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 5
CRAP Score 1
Metric Value
cc 1
dl 0
loc 12
ccs 5
cts 5
cp 1
crap 1
rs 9.4285

1 Method

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