Completed
Pull Request — master (#328)
by
unknown
23:55
created

Buffer.__repr__()   A

Complexity

Conditions 1

Size

Total Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 1
CRAP Score 1

Importance

Changes 0
Metric Value
cc 1
dl 0
loc 2
ccs 1
cts 1
cp 1
crap 1
rs 10
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
        return 'Buffer(number=%d, name=%r)' % (self.number, self.name)
31 5
32
    def __len__(self):
33 5
        """Return the number of lines contained in a Buffer."""
34
        return self.request('nvim_buf_line_count')
35
36
    def __getitem__(self, idx):
37
        """Get a buffer line or slice by integer index.
38
39
        Indexes may be negative to specify positions from the end of the
40
        buffer. For example, -1 is the last line, -2 is the line before that
41
        and so on.
42
43 5
        When retrieving slices, omiting indexes(eg: `buffer[:]`) will bring
44 5
        the whole buffer.
45 5
        """
46 5
        if not isinstance(idx, slice):
47 5
            i = adjust_index(idx)
48 5
            return self.request('nvim_buf_get_lines', i, i + 1, True)[0]
49
        start = adjust_index(idx.start, 0)
50 5
        end = adjust_index(idx.stop, -1)
51
        return self.request('nvim_buf_get_lines', start, end, False)
52
53
    def __setitem__(self, idx, item):
54
        """Replace a buffer line or slice by integer index.
55
56
        Like with `__getitem__`, indexes may be negative.
57
58 5
        When replacing slices, omiting indexes(eg: `buffer[:]`) will replace
59 5
        the whole buffer.
60 5
        """
61 5
        if not isinstance(idx, slice):
62 5
            i = adjust_index(idx)
63 5
            lines = [item] if item is not None else []
64 5
            return self.request('nvim_buf_set_lines', i, i + 1, True, lines)
65 5
        lines = item if item is not None else []
66
        start = adjust_index(idx.start, 0)
67 5
        end = adjust_index(idx.stop, -1)
68
        return self.request('nvim_buf_set_lines', start, end, False, lines)
69
70
    def __iter__(self):
71
        """Iterate lines of a buffer.
72
73
        This will retrieve all lines locally before iteration starts. This
74
        approach is used because for most cases, the gain is much greater by
75
        minimizing the number of API calls by transfering all data needed to
76
        work.
77
        """
78
        lines = self[:]
79 5
        for line in lines:
80
            yield line
81
82
    def __delitem__(self, idx):
83
        """Delete line or slice of lines from the buffer.
84 5
85
        This is the same as __setitem__(idx, [])
86 5
        """
87
        self.__setitem__(idx, None)
88 5
89 5
    def append(self, lines, index=-1):
90 5
        """Append a string or list of lines to the buffer."""
91
        if isinstance(lines, (basestring, bytes)):
92 5
            lines = [lines]
93
        return self.request('nvim_buf_set_lines', index, index, True, lines)
94 5
95
    def mark(self, name):
96 5
        """Return (row, col) tuple for a named mark."""
97
        return self.request('nvim_buf_get_mark', name)
98
99
    def range(self, start, end):
100 5
        """Return a `Range` object, which represents part of the Buffer."""
101
        return Range(self, start, end)
102
103
    def add_highlight(self, hl_group, line, col_start=0,
104
                      col_end=-1, src_id=-1, async_=None,
105
                      **kwargs):
106
        """Add a highlight to the buffer."""
107
        async_ = check_async(async_, kwargs, src_id != 0)
108 5
        return self.request('nvim_buf_add_highlight', src_id, hl_group,
109
                            line, col_start, col_end, async_=async_)
110
111
    def clear_highlight(self, src_id, line_start=0, line_end=-1, async_=None,
112
                        **kwargs):
113 5
        """Clear highlights from the buffer."""
114
        async_ = check_async(async_, kwargs, True)
115
        self.request('nvim_buf_clear_highlight', src_id,
116 5
                     line_start, line_end, async_=async_)
117
118 5
    @property
119
    def name(self):
120
        """Get the buffer name."""
121 5
        return self.request('nvim_buf_get_name')
122
123 5
    @name.setter
124
    def name(self, value):
125
        """Set the buffer name. BufFilePre/BufFilePost are triggered."""
126 5
        return self.request('nvim_buf_set_name', value)
127
128 5
    @property
129
    def valid(self):
130
        """Return True if the buffer still exists."""
131 5
        return self.request('nvim_buf_is_valid')
132
133
    @property
134 5
    def number(self):
135 5
        """Get the buffer number."""
136
        return self.handle
137
138
139
class Range(object):
140 5
    def __init__(self, buffer, start, end):
141
        self._buffer = buffer
142
        self.start = start - 1
143 5
        self.end = end - 1
144
145
    def __len__(self):
146
        return self.end - self.start + 1
147
148
    def __getitem__(self, idx):
149
        if not isinstance(idx, slice):
150
            return self._buffer[self._normalize_index(idx)]
151
        start = self._normalize_index(idx.start)
152
        end = self._normalize_index(idx.stop)
153
        if start is None:
154 5
            start = self.start
155
        if end is None:
156
            end = self.end + 1
157
        return self._buffer[start:end]
158
159
    def __setitem__(self, idx, lines):
160
        if not isinstance(idx, slice):
161
            self._buffer[self._normalize_index(idx)] = lines
162
            return
163
        start = self._normalize_index(idx.start)
164
        end = self._normalize_index(idx.stop)
165
        if start is None:
166 5
            start = self.start
167
        if end is None:
168
            end = self.end
169
        self._buffer[start:end + 1] = lines
170 5
171
    def __iter__(self):
172
        for i in range(self.start, self.end + 1):
173
            yield self._buffer[i]
174
175
    def append(self, lines, i=None):
176 5
        i = self._normalize_index(i)
177
        if i is None:
178
            i = self.end + 1
179
        self._buffer.append(lines, i)
180
181
    def _normalize_index(self, index):
182
        if index is None:
183
            return None
184
        if index < 0:
185
            index = self.end
186
        else:
187
            index += self.start
188
            if index > self.end:
189
                index = self.end
190
        return index
191