1 """API for working with a Nvim Buffer."""
2 from pynvim.api.common import Remote
3 from pynvim.compat import IS_PYTHON3, check_async
13 def adjust_index(idx, default=None):
14 """Convert from python indexing convention to nvim indexing convention."""
25 """A remote Nvim buffer."""
27 _api_prefix = "nvim_buf_"
30 """Return the number of lines contained in a Buffer."""
31 return self.request('nvim_buf_line_count')
33 def __getitem__(self, idx):
34 """Get a buffer line or slice by integer index.
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
40 When retrieving slices, omiting indexes(eg: `buffer[:]`) will bring
43 if not isinstance(idx, slice):
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)
50 def __setitem__(self, idx, item):
51 """Replace a buffer line or slice by integer index.
53 Like with `__getitem__`, indexes may be negative.
55 When replacing slices, omiting indexes(eg: `buffer[:]`) will replace
58 if not isinstance(idx, slice):
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)
68 """Iterate lines of a buffer.
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
79 def __delitem__(self, idx):
80 """Delete line or slice of lines from the buffer.
82 This is the same as __setitem__(idx, [])
84 self.__setitem__(idx, None)
86 def __ne__(self, other):
87 """Test inequality of Buffers.
89 Necessary for Python 2 compatibility.
91 return not self.__eq__(other)
93 def append(self, lines, index=-1):
94 """Append a string or list of lines to the buffer."""
95 if isinstance(lines, (basestring, bytes)):
97 return self.request('nvim_buf_set_lines', index, index, True, lines)
100 """Return (row, col) tuple for a named mark."""
101 return self.request('nvim_buf_get_mark', name)
103 def range(self, start, end):
104 """Return a `Range` object, which represents part of the Buffer."""
105 return Range(self, start, end)
107 def add_highlight(self, hl_group, line, col_start=0,
108 col_end=-1, src_id=-1, async_=None,
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_)
115 def clear_highlight(self, src_id, line_start=0, line_end=-1, async_=None,
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_)
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.
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
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.
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
139 if clear and clear_start is None:
141 lua = self._session._get_lua_private()
142 lua.update_highlights(self, src_id, hls, clear_start, clear_end,
147 """Get the buffer name."""
148 return self.request('nvim_buf_get_name')
151 def name(self, value):
152 """Set the buffer name. BufFilePre/BufFilePost are triggered."""
153 return self.request('nvim_buf_set_name', value)
157 """Return True if the buffer still exists."""
158 return self.request('nvim_buf_is_valid')
162 """Get the buffer number."""
167 def __init__(self, buffer, start, end):
168 self._buffer = buffer
169 self.start = start - 1
173 return self.end - self.start + 1
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)
184 return self._buffer[start:end]
186 def __setitem__(self, idx, lines):
187 if not isinstance(idx, slice):
188 self._buffer[self._normalize_index(idx)] = lines
190 start = self._normalize_index(idx.start)
191 end = self._normalize_index(idx.stop)
196 self._buffer[start:end + 1] = lines
199 for i in range(self.start, self.end + 1):
200 yield self._buffer[i]
202 def append(self, lines, i=None):
203 i = self._normalize_index(i)
206 self._buffer.append(lines, i)
208 def _normalize_index(self, index):