Home Explore Blog CI



neovim

2nd chunk of `runtime/doc/job_control.txt`
ea9c17a6f6ea6333a0ed21a05e1fee6989c6adb08cafe5510000000100000e12
   let job2 = jobstart(['bash', '-c', 'for i in {1..10}; do echo hello $i!; sleep 1; done'], extend({'shell': 'shell 2'}, s:callbacks))

To test the above script, copy it to a file ~/foo.vim and run it: >bash
    nvim -u ~/foo.vim
<
Description of what happens:
  - Two bash shells are spawned by |jobstart()| with their stdin/stdout/stderr
    streams connected to nvim.
  - The first shell is idle, waiting to read commands from its stdin.
  - The second shell is started with -c which executes the command (a for-loop
    printing 0 through 9) and then exits.
  - `OnEvent()` callback is passed to |jobstart()| to handle various job
    events. It displays stdout/stderr data received from the shells.

For |on_stdout| and |on_stderr| see |channel-callback|.
							*on_exit*
Arguments passed to on_exit callback:
  0: |job-id|
  1: Exit-code of the process, or 128+SIGNUM if by signal (e.g. 143 on SIGTERM).
  2: Event type: "exit"


  Note: Buffered stdout/stderr data which has not been flushed by the sender
	will not trigger the on_stdout/on_stderr callback (but if the process
	ends, the on_exit callback will be invoked).
        For example, "ruby -e" buffers output, so small strings will be
        buffered unless "auto-flushing" ($stdout.sync=true) is enabled. >vim
          function! Receive(job_id, data, event)
            echom printf('%s: %s',a:event,string(a:data))
          endfunction
          call jobstart(['ruby', '-e',
            \ '$stdout.sync = true; 5.times do sleep 1 and puts "Hello Ruby!" end'],
            \ {'on_stdout': 'Receive'})
<       https://github.com/neovim/neovim/issues/1592

  Note 2:
	Job event handlers may receive partial (incomplete) lines. For a given
	invocation of on_stdout/on_stderr, `a:data` is not guaranteed to end
	with a newline.
	  - `abcdefg` may arrive as `['abc']`, `['defg']`.
	  - `abc\nefg` may arrive as `['abc', '']`, `['efg']` or `['abc']`,
	    `['','efg']`, or even `['ab']`, `['c','efg']`.
	Easy way to deal with this: initialize a list as `['']`, then append
	to it as follows: >vim
	  let s:chunks = ['']
	  func! s:on_stdout(job_id, data, event) dict
	    let s:chunks[-1] .= a:data[0]
	    call extend(s:chunks, a:data[1:])
	  endf
<

The |jobstart-options| dictionary is passed as |self| to the callback.
The above example could be written in this "object-oriented" style: >vim

    let Shell = {}

    function Shell.on_stdout(_job_id, data, event)
      call append(line('$'),
            \ printf('[%s] %s: %s', a:event, self.name, join(a:data[:-2])))
    endfunction

    let Shell.on_stderr = function(Shell.on_stdout)

    function Shell.on_exit(job_id, _data, event)
      let msg = printf('job %d ("%s") finished', a:job_id, self.name)
      call append(line('$'), printf('[%s] BOOM!', a:event))
      call append(line('$'), printf('[%s] %s!', a:event, msg))
    endfunction

    function Shell.new(name, cmd)
      let object = extend(copy(g:Shell), {'name': a:name})
      let object.cmd = ['sh', '-c', a:cmd]
      let object.id = jobstart(object.cmd, object)
      $
      return object
    endfunction

    let instance = Shell.new('bomb',
          \ 'for i in $(seq 9 -1 1); do echo $i 1>&$((i % 2 + 1)); sleep 1; done')
<
To send data to the job's stdin, use |chansend()|: >vim
    :call chansend(job1, "ls\n")
    :call chansend(job1, "invalid-command\n")
    :call chansend(job1, "exit\n")
<
A job may be killed at any time with the |jobstop()| function:
>vim
    :call jobstop(job1)
<
Individual streams can be closed without killing the job, see |chanclose()|.

 vim:tw=78:ts=8:noet:ft=help:norl:

Title: Nvim Job Control: Advanced Usage and Considerations
Summary
This section delves into advanced aspects of Nvim job control. It emphasizes that buffered stdout/stderr data may not immediately trigger callbacks unless explicitly flushed. It also notes that job event handlers might receive partial lines. An example demonstrates how to handle partial lines by initializing a list as [''] and appending to it. The section further illustrates an object-oriented approach using a 'Shell' object with custom event handlers. Finally, it shows how to send data to a job's stdin using chansend() and how to terminate a job with jobstop(), also mentioning the ability to close individual streams with chanclose().