efficient vim config
[dotfiles/.git] / .local / lib / python3.9 / site-packages / pynvim / api / buffer.py
1 """API for working with a Nvim Buffer."""
2 from pynvim.api.common import Remote
3 from pynvim.compat import IS_PYTHON3, check_async
4
5
6 __all__ = ('Buffer')
7
8
9 if IS_PYTHON3:
10     basestring = str
11
12
13 def adjust_index(idx, default=None):
14     """Convert from python indexing convention to nvim indexing convention."""
15     if idx is None:
16         return default
17     elif idx < 0:
18         return idx - 1
19     else:
20         return idx
21
22
23 class Buffer(Remote):
24
25     """A remote Nvim buffer."""
26
27     _api_prefix = "nvim_buf_"
28
29     def __len__(self):
30         """Return the number of lines contained in a Buffer."""
31         return self.request('nvim_buf_line_count')
32
33     def __getitem__(self, idx):
34         """Get a buffer line or slice by integer index.
35
36         Indexes may be negative to specify positions from the end of the
37         buffer. For example, -1 is the last line, -2 is the line before that
38         and so on.
39
40         When retrieving slices, omiting indexes(eg: `buffer[:]`) will bring
41         the whole buffer.
42         """
43         if not isinstance(idx, slice):
44             i = adjust_index(idx)
45             return self.request('nvim_buf_get_lines', i, i + 1, True)[0]
46         start = adjust_index(idx.start, 0)
47         end = adjust_index(idx.stop, -1)
48         return self.request('nvim_buf_get_lines', start, end, False)
49
50     def __setitem__(self, idx, item):
51         """Replace a buffer line or slice by integer index.
52
53         Like with `__getitem__`, indexes may be negative.
54
55         When replacing slices, omiting indexes(eg: `buffer[:]`) will replace
56         the whole buffer.
57         """
58         if not isinstance(idx, slice):
59             i = adjust_index(idx)
60             lines = [item] if item is not None else []
61             return self.request('nvim_buf_set_lines', i, i + 1, True, lines)
62         lines = item if item is not None else []
63         start = adjust_index(idx.start, 0)
64         end = adjust_index(idx.stop, -1)
65         return self.request('nvim_buf_set_lines', start, end, False, lines)
66
67     def __iter__(self):
68         """Iterate lines of a buffer.
69
70         This will retrieve all lines locally before iteration starts. This
71         approach is used because for most cases, the gain is much greater by
72         minimizing the number of API calls by transfering all data needed to
73         work.
74         """
75         lines = self[:]
76         for line in lines:
77             yield line
78
79     def __delitem__(self, idx):
80         """Delete line or slice of lines from the buffer.
81
82         This is the same as __setitem__(idx, [])
83         """
84         self.__setitem__(idx, None)
85
86     def __ne__(self, other):
87         """Test inequality of Buffers.
88
89         Necessary for Python 2 compatibility.
90         """
91         return not self.__eq__(other)
92
93     def append(self, lines, index=-1):
94         """Append a string or list of lines to the buffer."""
95         if isinstance(lines, (basestring, bytes)):
96             lines = [lines]
97         return self.request('nvim_buf_set_lines', index, index, True, lines)
98
99     def mark(self, name):
100         """Return (row, col) tuple for a named mark."""
101         return self.request('nvim_buf_get_mark', name)
102
103     def range(self, start, end):
104         """Return a `Range` object, which represents part of the Buffer."""
105         return Range(self, start, end)
106
107     def add_highlight(self, hl_group, line, col_start=0,
108                       col_end=-1, src_id=-1, async_=None,
109                       **kwargs):
110         """Add a highlight to the buffer."""
111         async_ = check_async(async_, kwargs, src_id != 0)
112         return self.request('nvim_buf_add_highlight', src_id, hl_group,
113                             line, col_start, col_end, async_=async_)
114
115     def clear_highlight(self, src_id, line_start=0, line_end=-1, async_=None,
116                         **kwargs):
117         """Clear highlights from the buffer."""
118         async_ = check_async(async_, kwargs, True)
119         self.request('nvim_buf_clear_highlight', src_id,
120                      line_start, line_end, async_=async_)
121
122     def update_highlights(self, src_id, hls, clear_start=0, clear_end=-1,
123                           clear=False, async_=True):
124         """Add or update highlights in batch to avoid unnecessary redraws.
125
126         A `src_id` must have been allocated prior to use of this function. Use
127         for instance `nvim.new_highlight_source()` to get a src_id for your
128         plugin.
129
130         `hls` should be a list of highlight items. Each item should be a list
131         or tuple on the form `("GroupName", linenr, col_start, col_end)` or
132         `("GroupName", linenr)` to highlight an entire line.
133
134         By default existing highlights are preserved. Specify a line range with
135         clear_start and clear_end to replace highlights in this range. As a
136         shorthand, use clear=True to clear the entire buffer before adding the
137         new highlights.
138         """
139         if clear and clear_start is None:
140             clear_start = 0
141         lua = self._session._get_lua_private()
142         lua.update_highlights(self, src_id, hls, clear_start, clear_end,
143                               async_=async_)
144
145     @property
146     def name(self):
147         """Get the buffer name."""
148         return self.request('nvim_buf_get_name')
149
150     @name.setter
151     def name(self, value):
152         """Set the buffer name. BufFilePre/BufFilePost are triggered."""
153         return self.request('nvim_buf_set_name', value)
154
155     @property
156     def valid(self):
157         """Return True if the buffer still exists."""
158         return self.request('nvim_buf_is_valid')
159
160     @property
161     def number(self):
162         """Get the buffer number."""
163         return self.handle
164
165
166 class Range(object):
167     def __init__(self, buffer, start, end):
168         self._buffer = buffer
169         self.start = start - 1
170         self.end = end - 1
171
172     def __len__(self):
173         return self.end - self.start + 1
174
175     def __getitem__(self, idx):
176         if not isinstance(idx, slice):
177             return self._buffer[self._normalize_index(idx)]
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 + 1
184         return self._buffer[start:end]
185
186     def __setitem__(self, idx, lines):
187         if not isinstance(idx, slice):
188             self._buffer[self._normalize_index(idx)] = lines
189             return
190         start = self._normalize_index(idx.start)
191         end = self._normalize_index(idx.stop)
192         if start is None:
193             start = self.start
194         if end is None:
195             end = self.end
196         self._buffer[start:end + 1] = lines
197
198     def __iter__(self):
199         for i in range(self.start, self.end + 1):
200             yield self._buffer[i]
201
202     def append(self, lines, i=None):
203         i = self._normalize_index(i)
204         if i is None:
205             i = self.end + 1
206         self._buffer.append(lines, i)
207
208     def _normalize_index(self, index):
209         if index is None:
210             return None
211         if index < 0:
212             index = self.end
213         else:
214             index += self.start
215             if index > self.end:
216                 index = self.end
217         return index