## Async VimScript (1/2) ### Timers and Jobs Thomas Allen [thomas@oinksoft.com](mailto:thomas@oinksoft.com) Septemper 18, 2018 Vim Chicago Hashrocket, Chicago, IL
## History * vi, vim: Single-threaded * Emacs, IDEs, Neovim: Multi-threaded
## Vim 8 Async * Terminals (`:help terminal`) * Timers (`:help timer`) * Jobs (`:help channel`) * Channels (`:help channel`)

Timers

Execute a function after a number of milliseconds pass.

Single: Exit immediately, but cancel before it can run.

let timer_id = timer_start(0, {id -> execute('quit!')})
call timer_stop(timer_id)

Timers (2)

Loop: Delete lines, rotate.

let s:timeouts = [5000, 10000, 30000, 1000, 1000, 3200, 500, 700]

function! s:noop(timer_id)
  " Rotate
  let s:timeouts = insert(s:timeouts, remove(s:timeouts, len(s:timeouts) - 1))
  normal dd
  call timer_start(s:timeouts[0], function('<SID>noop'))
endfunction

call s:noop(0)

Timers (3)

Weather in the statusline.

function! s:fetch_weather(station_code)
  let out = system('weather --imperial ' . shellescape(a:station_code))
  " Parse...
endfunction

function! s:sync_statusline_weather(station_code, interval, timer_id)
  let conditions = s:fetch_weather(a:station_code)
  if conditions != s:last_conditions
    let s:last_conditions = conditions
    " Force statusline render
    execute 'let &ro = &ro'
  endif
  call timer_start(
        \ a:interval,
        \ function('<SID>sync_statusline_weather'),
        \ [a:interval, a:station_code])
endfunction

call s:sync_statusline_weather('klot', 60 * 1000, 0)
set statusline=%!FormatConditions()

Jobs

Run a shell command without blocking.

find to the location list:

function! s:on_find(chan, msg)
  lgetexpr split(a:msg, '')
endfunction

call job_start('find . -print0', {
      \ 'out_mode': 'raw',
      \ 'callback': function('<SID>on_find')
      \ })

Jobs (2)

HTTP response.

function! s:on_line(chan, msg)
  if empty(a:msg)
    let body = "Hello from Vim!"
    call ch_sendraw(a:chan, join([
          \ "HTTP/1.1 200 OK",
          \ "Content-Length: " . len(body),
          \ "Content-Type: text/plain",
          \ "",
          \ body
          \ ], "\n"))
  endif
endfunction

" Save reference to long-running job or it will be garbage collected
let server = call job_start('nc -lp 3000', {
      \ 'callback': function('<SID>on_line'),
      \ 'in_mode': 'raw',
      \ 'out_mode': 'nl'
      \ })
## Q/A