It is possible to modify buffer at the line granularity. E.g. :py3 vim.current.buffer[0] = "abc"
. But it deletes the attached marks even if a single character is replaced. Is it possible to modify the buffer characterwise? Something like :py3 vim.current.buffer[0][0] = "a"
.
1 Answer
The vim.current.buffer
list is a list of strings:
:pyx import vim; print(type(vim.current.buffer[0]))
<class 'str'>
and strings are immutable in Python; something like a_str[2] = 'b'
doesn't work either. This is just a property of the Python programming language (and many other languages, including VimScript).
The general way to do this is to get the line and then modify it:
:pyx line = vim.current.buffer[0] # hello
:pyx vim.current.buffer[0] = 'w' + line[1:] # wello
Or shorter:
:pyx vim.current.buffer[0] = 'w' + vim.current.buffer[0][1:]
Or in VimScript with getline()
and setline()
.
Using things like substitute()
or str.replace()
in Python is also useful. With substitute()
you can use \%c
to replace a specific column:
:call setline('.', substitute(getline('.'), '\%2c.', 'a', ''))
\%2c
matches the next character (.
for any character in this case) at this column, turning hello
in to hallo
. You can also match multiple columns; see :help \%c
for details. I'm not sure how to call this from Python though but it's probably possible 😅
-
Perfect!
setline(lnum) = "content"
preserves the marks.vim.current.buffer[lnum] = "content"
seems to use a different function internally. Jul 18, 2021 at 16:11 -
Except for movement,
:execute 'normal! r'.replacement_char
would almost be easier, heh– D. Ben Knoble ♦Jul 18, 2021 at 16:41