Search code examples
vim

vimscript: how to reload buffer content without changing focus


I have the following function in my .vimrc:

function s:get_errors()
  let term_buf = filter(map(getbufinfo(), 'v:val.bufnr'), 'getbufvar(v:val, "&buftype") is# "terminal"')[0]
  let lines = getbufline(term_buf, 1, '$')
  let text = join(lines, "\n")
  echo text
endfunction

command PrintErrors call s:get_errors()

My vim session has two buffers: one with my code being edited, and one with a terminal emulator (:term) where building happens (a process is monitoring the FS for file changes and trigger a build each time a file is modified).

My ultimate goal is to process the content of the terminal buffer to extract file path. My current command simply echos the content of the terminal buffer. When I save a code modification, the build happens and might report errors. I see them right away in the terminal buffer, but getbufline seems to have some "lag" and still returns the old content. After some time, the content is updated. If I manually switch to the terminal buffer and back, the content is updated.

My goal is to make sure getbufline always returns the latest available content, and I can't seem to do that using vimscript. How can I refresh to content of the terminal buffer without manually changing the focus to it and back ?


Solution

  • Instead of starting the terminal with :term, you could try a custom command that uses term_start (:help term_start()). That function allows you to install a callback that is run on every line of output of the terminal. Something like this:

    function! HandleOutput(job, line)
      echomsg "Got line: " .. a:line
    endfunction
    
    let job = term_start('irb', { 'out_cb': function('HandleOutput') })
    

    There's a practical problem for irb -- the output contains ANSI escape codes for color and text formatting. You don't get the buffer contents, you get the raw output. But you could strip out these codes, or look for a way to start your build process with no color.