Completed
Pull Request — master (#328)
by
unknown
22:41
created

Buffer.__repr__()   A

Complexity

Conditions 1

Size

Total Lines 6

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 3
CRAP Score 1

Importance

Changes 0
Metric Value
cc 1
dl 0
loc 6
ccs 3
cts 3
cp 1
crap 1
rs 9.4285
c 0
b 0
f 0
1
"""API for working with a Nvim Buffer."""
2 5
from .common import Remote
3 5
from ..compat import IS_PYTHON3, check_async
4
5
6 5
__all__ = ('Buffer')
7
8
9 5
if IS_PYTHON3:
10 3
    basestring = str
11
12
13 5
def adjust_index(idx, default=None):
14
    """Convert from python indexing convention to nvim indexing convention."""
15 5
    if idx is None:
16 5
        return default
17 5
    elif idx < 0:
18 5
        return idx - 1
19
    else:
20 5
        return idx
21
22
23 5
class Buffer(Remote):
24
25
    """A remote Nvim buffer."""
26
27 5
    _api_prefix = "nvim_buf_"
28
29 5
    def __repr__(self):
30
        """Get text representation of a Buffer."""
31 5
        return 'Buffer(number=%r, name=%r, filetype=%r)' % (
32
            self.number,
33 5
            self.name,
34
            self.options.get('filetype'),
35
        )
36
37
    def __len__(self):
38
        """Return the number of lines contained in a Buffer."""
39
        return self.request('nvim_buf_line_count')
40
41
    def __getitem__(self, idx):
42
        """Get a buffer line or slice by integer index.
43 5
44 5
        Indexes may be negative to specify positions from the end of the
45 5
        buffer. For example, -1 is the last line, -2 is the line before that
46 5
        and so on.
47 5
48 5
        When retrieving slices, omiting indexes(eg: `buffer[:]`) will bring
49
        the whole buffer.
50 5
        """
51
        if not isinstance(idx, slice):
52
            i = adjust_index(idx)
53
            return self.request('nvim_buf_get_lines', i, i + 1, True)[0]
54
        start = adjust_index(idx.start, 0)
55
        end = adjust_index(idx.stop, -1)
56
        return self.request('nvim_buf_get_lines', start, end, False)
57
58 5
    def __setitem__(self, idx, item):
59 5
        """Replace a buffer line or slice by integer index.
60 5
61 5
        Like with `__getitem__`, indexes may be negative.
62 5
63 5
        When replacing slices, omiting indexes(eg: `buffer[:]`) will replace
64 5
        the whole buffer.
65 5
        """
66
        if not isinstance(idx, slice):
67 5
            i = adjust_index(idx)
68
            lines = [item] if item is not None else []
69
            return self.request('nvim_buf_set_lines', i, i + 1, True, lines)
70
        lines = item if item is not None else []
71
        start = adjust_index(idx.start, 0)
72
        end = adjust_index(idx.stop, -1)
73
        return self.request('nvim_buf_set_lines', start, end, False, lines)
74
75
    def __iter__(self):
76
        """Iterate lines of a buffer.
77
78
        This will retrieve all lines locally before iteration starts. This
79 5
        approach is used because for most cases, the gain is much greater by
80
        minimizing the number of API calls by transfering all data needed to
81
        work.
82
        """
83
        lines = self[:]
84 5
        for line in lines:
85
            yield line
86 5
87
    def __delitem__(self, idx):
88 5
        """Delete line or slice of lines from the buffer.
89 5
90 5
        This is the same as __setitem__(idx, [])
91
        """
92 5
        self.__setitem__(idx, None)
93
94 5
    def append(self, lines, index=-1):
95
        """Append a string or list of lines to the buffer."""
96 5
        if isinstance(lines, (basestring, bytes)):
97
            lines = [lines]
98
        return self.request('nvim_buf_set_lines', index, index, True, lines)
99
100 5
    def mark(self, name):
101
        """Return (row, col) tuple for a named mark."""
102
        return self.request('nvim_buf_get_mark', name)
103
104
    def range(self, start, end):
105
        """Return a `Range` object, which represents part of the Buffer."""
106
        return Range(self, start, end)
107
108 5
    def add_highlight(self, hl_group, line, col_start=0,
109
                      col_end=-1, src_id=-1, async_=None,
110
                      **kwargs):
111
        """Add a highlight to the buffer."""
112
        async_ = check_async(async_, kwargs, src_id != 0)
113 5
        return self.request('nvim_buf_add_highlight', src_id, hl_group,
114
                            line, col_start, col_end, async_=async_)
115
116 5
    def clear_highlight(self, src_id, line_start=0, line_end=-1, async_=None,
117
                        **kwargs):
118 5
        """Clear highlights from the buffer."""
119
        async_ = check_async(async_, kwargs, True)
120
        self.request('nvim_buf_clear_highlight', src_id,
121 5
                     line_start, line_end, async_=async_)
122
123 5
    def update_highlights(self, src_id, hls, clear_start=0, clear_end=-1,
124
                          clear=False, async_=True):
125
        """Add or update highlights in batch to avoid unnecessary redraws.
126 5
127
        A `src_id` must have been allocated prior to use of this function. Use
128 5
        for instance `nvim.new_highlight_source()` to get a src_id for your
129
        plugin.
130
131 5
        `hls` should be a list of highlight items. Each item should be a list
132
        or tuple on the form `("GroupName", linenr, col_start, col_end)` or
133
        `("GroupName", linenr)` to highlight an entire line.
134 5
135 5
        By default existing highlights are preserved. Specify a line range with
136
        clear_start and clear_end to replace highlights in this range. As a
137
        shorthand, use clear=True to clear the entire buffer before adding the
138
        new highlights.
139
        """
140 5
        if clear and clear_start is None:
141
            clear_start = 0
142
        lua = self._session._get_lua_private()
0 ignored issues
show
Coding Style Best Practice introduced by
It seems like _get_lua_private was declared protected and should not be accessed from this context.

Prefixing a member variable _ is usually regarded as the equivalent of declaring it with protected visibility that exists in other languages. Consequentially, such a member should only be accessed from the same class or a child class:

class MyParent:
    def __init__(self):
        self._x = 1;
        self.y = 2;

class MyChild(MyParent):
    def some_method(self):
        return self._x    # Ok, since accessed from a child class

class AnotherClass:
    def some_method(self, instance_of_my_child):
        return instance_of_my_child._x   # Would be flagged as AnotherClass is not
                                         # a child class of MyParent
Loading history...
143 5
        lua.update_highlights(self, src_id, hls, clear_start, clear_end,
144
                              async_=async_)
145
146
    @property
147
    def name(self):
148
        """Get the buffer name."""
149
        return self.request('nvim_buf_get_name')
150
151
    @name.setter
152
    def name(self, value):
153
        """Set the buffer name. BufFilePre/BufFilePost are triggered."""
154 5
        return self.request('nvim_buf_set_name', value)
155
156
    @property
157
    def valid(self):
158
        """Return True if the buffer still exists."""
159
        return self.request('nvim_buf_is_valid')
160
161
    @property
162
    def number(self):
163
        """Get the buffer number."""
164
        return self.handle
165
166 5
167
class Range(object):
168
    def __init__(self, buffer, start, end):
169
        self._buffer = buffer
170 5
        self.start = start - 1
171
        self.end = end - 1
172
173
    def __len__(self):
174
        return self.end - self.start + 1
175
176 5
    def __getitem__(self, idx):
177
        if not isinstance(idx, slice):
178
            return self._buffer[self._normalize_index(idx)]
179
        start = self._normalize_index(idx.start)
180
        end = self._normalize_index(idx.stop)
181
        if start is None:
182
            start = self.start
183
        if end is None:
184
            end = self.end + 1
185
        return self._buffer[start:end]
186
187
    def __setitem__(self, idx, lines):
188
        if not isinstance(idx, slice):
189
            self._buffer[self._normalize_index(idx)] = lines
190
            return
191
        start = self._normalize_index(idx.start)
192
        end = self._normalize_index(idx.stop)
193
        if start is None:
194
            start = self.start
195
        if end is None:
196
            end = self.end
197
        self._buffer[start:end + 1] = lines
198
199
    def __iter__(self):
200
        for i in range(self.start, self.end + 1):
201
            yield self._buffer[i]
202
203
    def append(self, lines, i=None):
204
        i = self._normalize_index(i)
205
        if i is None:
206
            i = self.end + 1
207
        self._buffer.append(lines, i)
208
209
    def _normalize_index(self, index):
210
        if index is None:
211
            return None
212
        if index < 0:
213
            index = self.end
214
        else:
215
            index += self.start
216
            if index > self.end:
217
                index = self.end
218
        return index
219