2

I have a job I want to run in the background of vim, and update my status line with the periodic results of that job.

I'm able to setup the timer, call the external job and get my response back. I'm able to echom the response and see it in :messages.

I am unable to get my global variable to take hold of the new value though.

Here is the vimscript:

let g:please_vim_why = 'an echo example'
let g:why_vim_why = -1
function! TimerRun(timer)
  call jobstart('date', {'on_stdout': 'TimerCallback'})
endfunction
function! TimerCallback(j, d, e)
  echom a:d[0]
  let g:why_vim_why = a:d[0]
endfunction
let timer = timer_start(2000, 'TimerRun', {'repeat': -1})

Run via nvim -u godwhyvimwhydoyouhateme.vim to load it as your vimrc.

Now if you go :echo g:please_vim_why, you'll see the response, 'an echo example'.

If you run :messages, you'll see a repeated output of the date.

If you run :echo g:why_vim_why you will see no output.

I thought maybe it might be a:d is scoped and gets garbage collected after the function, but let g:why_vim_why = 'not a good joke' . a:d[0], sets the variable to 'not a good joke' but doesn't concatenate anything.

Why VIM? Why?

5
  • Nice detailed question with a minimum working example. +1 I observe the same behaviour in neovim 0.3.4 when I test your example, but don't know either why this is happening.
    – user4879
    Feb 10, 2019 at 4:48
  • So you think it's not the code at fault? I can't figure why it wouldn't work, perhaps I should create an issue on GH? Vimscript is awkward to use though so I'm first leaning towards me not understanding it.
    – purplelulu
    Feb 10, 2019 at 5:07
  • 2
    This seems to be neovim only. In Vim the example works as expected (slightly different syntax, like job_start instead of jobstart).
    – Ralf
    Feb 10, 2019 at 8:37
  • BTW: You should not crosspost. See FAQ
    – Ralf
    Feb 10, 2019 at 9:25
  • 1
    @purplelulu it would probably be worth it to raise an issue on the neovim github, seeing as it appears to be a neovim only issue as Ralf pointed out.
    – user4879
    Feb 10, 2019 at 11:18

1 Answer 1

6

The on_stdout callback will be called twice for each execution of date in this example.

First it will be called with the result from date as an array with two elements ['the-date', ''] where '' is an artifact of the newline output by date. (If you run a job such as echo -n "no new line", you'd only receive ['no new line'].

Second it will be called with [''] to signal EOF on stdout.

The second call is clobbering the first, which makes it appear as if the result is going missing somehow.

You can either check the length of the argument (i.e. if len(a:d[0])...) or pass the option 'stdout_buffered': 1 to jobstart to only receive output when all output from the command is collected.

All this is explained in :h on_stdout.

2
  • 1
    Glad to see you were able to fix your problem! I’ve edited the last sentence a bit to be less snarky for future readers, in the hope that it will make things feel more welcoming. Great answer!
    – D. Ben Knoble
    Feb 10, 2019 at 16:15
  • Great job troubleshooting this one!
    – filbranden
    Feb 10, 2019 at 16:16

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

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