1

I am trying to make a plugin, which will be displaying a content of registers in the side bar and updating this side bar at every register's changing. To accomplish this task I decided to set a hook on the TextYankPost event and to write a changed register's dictionary into the side bar window when this event happens.

But there is a problem - the autocmd doesn't allow writing commands like :put inside a called function, so when I do:

function! Write_to_buffer()
    put ='hello'
endfunction

autocmd TextYankPost * :call Write_to_buffer()

I get an error

Error detected while processing function Write_to_buffer:
line    1:
E523: Not allowed here

Without a writing command all works as expected:

function! Write_to_buffer()
    echo 'hello'
endfunction

autocmd TextYankPost * :call Write_to_buffer()

The :h E523 says:

When on, ":autocmd", shell and write commands are not allowed in ".vimrc" and ".exrc" in the current directory and map commands are displayed. Switch it off only if you know that you will not run into problems, or when the 'exrc' option is off. On Unix this option is only used if the ".vimrc" or ".exrc" is not owned by you. This can be dangerous if the systems allows users to do a "chown". You better set 'secure' at the end of your ~/.vimrc then.

Both secure and exrc options are off in my case:

echo printf('secure = %s, exrc = %s', &secure, &exrc)
" Output: secure = 0, exrc = 0 

So the questions:

  1. Is the usage of the autocmd for tracking register changes right/optimal?
  2. How can a function called by the autocmd be used for writing into a buffer?
2

Is the usage of the autocmd for tracking register changes right/optimal?

Well, there are many ways to change a register. Something like :let @0 = 'Some text' will change the register 0 just like yank does. So you can't make it truly robust. That's simply impossible, I believe (unless you poll the timer, but that does not seem like a nice way to deal with this either).

How can a function called by the autocmd be used for writing into a buffer?

This problem doesn't apply to autocommands in general (i.e. you can write to buffer while inside an autocommand). It's specific to this individual autocommand. A quote from :h TextYankPost: "It is not allowed to change the buffer text, see :h textlock". So, for example, you can save "a pending update" in a list, and apply it later (maybe from within :h CursorHold, or :h SafeStateAgain or by a timer etc.).

| improve this answer | |
  • 1
    I found a way to fix E523 error while TextYankPost happens here. I applied a timer_start trick and printing to a buffer have started to work. Now I am thinking about of two variants: 1) To find a way to catch a :let @0 = 'Some text' case. One of my thoughts was catching a :let command execution in the command line by CmdwinLeave event but it haven't worked. 2) Usage of timer_start with a repeat option. This way I can check the reg's dictionary every second. What do you think? Is the first variant (catching let command) possible? – MiniMax Feb 23 at 13:37
  • 2
    @MiniMax No, I don't think that will make much sense. There are standalone scripts/plugins manipulating registers; also CmdlineLeave is triggered before command execution, and parsing by hand is very complicated: say, setreg() can be a part of an arbitrary VimScript expression, and so on. So if you're really going to implement such thing, you'll come to timer-based update sooner or later. – Matt Feb 23 at 13:52

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.