2014-09-13 12:21:15 -07:00
|
|
|
*job_control.txt* For Nvim. {Nvim}
|
|
|
|
|
|
|
|
|
|
|
|
NVIM REFERENCE MANUAL by Thiago de Arruda
|
|
|
|
|
|
|
|
|
|
|
|
Nvim's facilities for job control *job-control*
|
|
|
|
|
|
|
|
1. Introduction |job-control-intro|
|
|
|
|
2. Usage |job-control-usage|
|
|
|
|
|
|
|
|
==============================================================================
|
|
|
|
1. Introduction *job-control-intro*
|
|
|
|
|
|
|
|
Job control is a simple way to perform multitasking in vimscript. Wikipedia
|
2014-12-08 17:00:05 -07:00
|
|
|
contains a more generic/detailed description:
|
2014-09-13 12:21:15 -07:00
|
|
|
|
|
|
|
"Job control in computing refers to the control of multiple tasks or Jobs on a
|
|
|
|
computer system, ensuring that they each have access to adequate resources to
|
|
|
|
perform correctly, that competition for limited resources does not cause a
|
|
|
|
deadlock where two or more jobs are unable to complete, resolving such
|
|
|
|
situations where they do occur, and terminating jobs that, for any reason, are
|
|
|
|
not performing as expected."
|
|
|
|
|
|
|
|
In a few words: It allows a vimscript programmer to concurrently spawn and
|
|
|
|
control multiple processes without blocking the current Nvim instance.
|
|
|
|
|
|
|
|
Nvim's job control was designed to be simple and familiar to vimscript
|
|
|
|
programmers, instead of being very powerful but complex. Unlike Vim's
|
2014-12-08 17:00:05 -07:00
|
|
|
facilities for calling with external commands, job control does not depend on
|
|
|
|
available shells, instead relying on OS functionality for process management.
|
2014-09-13 12:21:15 -07:00
|
|
|
|
|
|
|
Internally, Nvim job control is powered by libuv, which has a nice
|
2014-11-27 08:05:14 -07:00
|
|
|
cross-platform API for managing processes. See https://github.com/libuv/libuv
|
2014-09-13 12:21:15 -07:00
|
|
|
for details
|
|
|
|
|
|
|
|
==============================================================================
|
|
|
|
2. Usage *job-control-usage*
|
|
|
|
|
2015-01-13 23:35:40 -07:00
|
|
|
Here's a quick one-liner that creates a job which invokes the "ls" shell
|
|
|
|
command and prints the result:
|
|
|
|
>
|
|
|
|
call jobstart('', 'ls', ['-a'])|au JobActivity * echo v:job_data|au!
|
|
|
|
JobActivity
|
|
|
|
|
|
|
|
In the one-liner above, creating the JobActivity event handler immediately
|
|
|
|
after the call to jobstart() is not a race because the Nvim job system will
|
|
|
|
not publish the job result (even though it may receive it) until evaluation of
|
|
|
|
the chained user commands (`expr1|expr2|...|exprN`) has completed.
|
|
|
|
|
2014-09-13 12:21:15 -07:00
|
|
|
Job control is achieved by calling a combination of the |jobstart()|,
|
|
|
|
|jobsend()| and |jobstop()| functions, and by listening to the |JobActivity|
|
|
|
|
event. The best way to understand is with a complete example:
|
|
|
|
>
|
|
|
|
let job1 = jobstart('shell1', 'bash')
|
2014-12-08 17:00:05 -07:00
|
|
|
let job2 = jobstart('shell2', 'bash', ['-c', 'for ((i = 0; i < 10; i++)); do echo hello $i!; sleep 1; done'])
|
|
|
|
|
2014-09-13 12:21:15 -07:00
|
|
|
function JobHandler()
|
|
|
|
if v:job_data[1] == 'stdout'
|
2014-10-25 18:45:13 -07:00
|
|
|
let str = 'shell '. v:job_data[0].' stdout: '.join(v:job_data[2])
|
2014-09-13 12:21:15 -07:00
|
|
|
elseif v:job_data[1] == 'stderr'
|
2014-10-25 18:45:13 -07:00
|
|
|
let str = 'shell '.v:job_data[0].' stderr: '.join(v:job_data[2])
|
2014-09-13 12:21:15 -07:00
|
|
|
else
|
|
|
|
let str = 'shell '.v:job_data[0].' exited'
|
|
|
|
endif
|
2014-12-08 17:00:05 -07:00
|
|
|
|
2014-09-13 12:21:15 -07:00
|
|
|
call append(line('$'), str)
|
|
|
|
endfunction
|
2014-12-08 17:00:05 -07:00
|
|
|
|
2014-09-13 12:21:15 -07:00
|
|
|
au JobActivity shell* call JobHandler()
|
|
|
|
<
|
2014-12-08 17:00:05 -07:00
|
|
|
To test the above, copy it to the file ~/jobcontrol.vim and start with a clean
|
2014-09-13 12:21:15 -07:00
|
|
|
nvim instance:
|
2014-12-08 17:00:05 -07:00
|
|
|
>
|
|
|
|
nvim -u NONE -S ~/jobcontrol.vim
|
2014-09-13 12:21:15 -07:00
|
|
|
<
|
|
|
|
Here's what is happening:
|
|
|
|
|
2014-12-08 17:00:05 -07:00
|
|
|
- Two bash instances are spawned by |jobstart()| with their stdin/stdout/stderr
|
|
|
|
connected to nvim.
|
|
|
|
- The first shell is idle, waiting to read commands from its stdin.
|
|
|
|
- The second shell is started with the -c argument, causing it to execute a
|
|
|
|
command then exit. In this case, the command is a for loop that will print 0
|
|
|
|
through 9 then exit.
|
2015-02-16 23:28:37 -07:00
|
|
|
- The `JobHandler()` function is called by the `JobActivity` autocommand (notice
|
2014-12-08 17:00:05 -07:00
|
|
|
how the shell* pattern matches the names `shell1` and `shell2` passed to
|
2014-09-13 12:21:15 -07:00
|
|
|
|jobstart()|), and it takes care of displaying stdout/stderr received from
|
|
|
|
the shells.
|
|
|
|
- The v:job_data is an array set by the JobActivity event. It has the
|
|
|
|
following elements:
|
|
|
|
0: The job id
|
|
|
|
1: The kind of activity: one of "stdout", "stderr" or "exit"
|
2014-10-25 18:45:13 -07:00
|
|
|
2: When "activity" is "stdout" or "stderr", this will contain a list of
|
|
|
|
lines read from stdout or stderr
|
2014-09-13 12:21:15 -07:00
|
|
|
|
|
|
|
To send data to the job's stdin, one can use the |jobsend()| function, like
|
|
|
|
this:
|
|
|
|
>
|
2014-12-08 17:00:05 -07:00
|
|
|
:call jobsend(job1, "ls\n")
|
|
|
|
:call jobsend(job1, "invalid-command\n")
|
|
|
|
:call jobsend(job1, "exit\n")
|
2014-09-13 12:21:15 -07:00
|
|
|
<
|
|
|
|
A job may be killed at any time with the |jobstop()| function:
|
|
|
|
>
|
|
|
|
:call jobstop(job1)
|
|
|
|
<
|
2014-12-08 17:00:05 -07:00
|
|
|
When |jobstop()| is called, `SIGTERM` will be sent to the job. If a job does
|
|
|
|
not exit after 2 seconds, `SIGKILL` will be sent.
|
|
|
|
|
2014-09-13 12:21:15 -07:00
|
|
|
==============================================================================
|
|
|
|
vim:tw=78:ts=8:noet:ft=help:norl:
|