1

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".

2

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 😅

2
  • Perfect! setline(lnum) = "content" preserves the marks. vim.current.buffer[lnum] = "content" seems to use a different function internally.
    – tejasvi88
    Jul 18 at 16:11
  • Except for movement, :execute 'normal! r'.replacement_char would almost be easier, heh
    – D. Ben Knoble
    Jul 18 at 16:41

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.