aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJustin M. Keyes <justinkz@gmail.com>2017-11-06 01:23:32 +0100
committerJustin M. Keyes <justinkz@gmail.com>2017-11-06 01:56:04 +0100
commitfb3c21e09070b87b1ac734be14109c0e84cd9b4f (patch)
tree11728350e20b9cd8f77ed9b414c949b54948c672
parent5d2af7e45200c1e3337624449fe2be0906d1c7cf (diff)
downloadrneovim-fb3c21e09070b87b1ac734be14109c0e84cd9b4f.tar.gz
rneovim-fb3c21e09070b87b1ac734be14109c0e84cd9b4f.tar.bz2
rneovim-fb3c21e09070b87b1ac734be14109c0e84cd9b4f.zip
doc: job-control
closes #4266 closes #4746 ref https://github.com/neovim/neovim/issues/7058#issuecomment-317196803
-rw-r--r--runtime/doc/eval.txt131
-rw-r--r--runtime/doc/job_control.txt129
2 files changed, 130 insertions, 130 deletions
diff --git a/runtime/doc/eval.txt b/runtime/doc/eval.txt
index 300bdd061e..b0796b8c5d 100644
--- a/runtime/doc/eval.txt
+++ b/runtime/doc/eval.txt
@@ -1785,7 +1785,7 @@ v:scrollstart String describing the script or function that caused the
*v:servername* *servername-variable*
*$NVIM_LISTEN_ADDRESS*
-v:servername Default {Nvim} server address. Equivalent to
+v:servername Default Nvim server address. Equivalent to
|$NVIM_LISTEN_ADDRESS| on startup. |serverstop()|
Read-only.
@@ -4915,42 +4915,48 @@ items({dict}) *items()*
entry and the value of this entry. The |List| is in arbitrary
order.
-jobclose({job}[, {stream}]) {Nvim} *jobclose()*
- Close {job}'s {stream}, which can be one of "stdin", "stdout",
- "stderr" or "rpc" (closes the rpc channel for a job started
- with the "rpc" option.) If {stream} is omitted, all streams
- are closed. If the job is a pty job, this will then close the
- pty master, sending SIGHUP to the job process.
+jobclose({job}[, {stream}]) *jobclose()*
+ Close {stream} of |job-id| {job}, where {stream} is one of:
+ "stdin", "stdout", "stderr", "rpc" (RPC channel of a job
+ started with `"rpc":v:true`). If {stream} is omitted, all
+ streams are closed. If the job is a pty job, this will close
+ the pty master, sending SIGHUP to the job process.
-jobpid({job}) {Nvim} *jobpid()*
- Return the pid (process id) of {job}.
+jobpid({job}) *jobpid()*
+ Return the PID (process id) of |job-id| {job}.
-jobresize({job}, {width}, {height}) {Nvim} *jobresize()*
- Resize {job}'s pseudo terminal window to {width} and {height}.
- This function will fail if used on jobs started without the
- "pty" option.
+jobresize({job}, {width}, {height}) *jobresize()*
+ Resize the pseudo terminal window of |job-id| {job} to {width}
+ columns and {height} rows.
+ Fails if the job was not started with `"pty":v:true`.
-jobsend({job}, {data}) {Nvim} *jobsend()*
- Send data to {job} by writing it to the stdin of the process.
+jobsend({job}, {data}) *jobsend()*
+ Writes to stdin of the process associated with |job-id| {job}.
Returns 1 if the write succeeded, 0 otherwise.
- See |job-control| for more information.
+ See |job-control|.
{data} may be a string, string convertible, or a list. If
- {data} is a list, the items will be separated by newlines and
- any newlines in an item will be sent as a NUL. A final newline
- can be sent by adding a final empty string. For example: >
+ {data} is a list, the items will be joined by newlines; any
+ newlines in an item will be sent as NUL. To send a final
+ newline, include a final empty string. Example: >
:call jobsend(j, ["abc", "123\n456", ""])
< will send "abc<NL>123<NUL>456<NL>".
- If the job was started with the rpc option this function
- cannot be used, instead use |rpcnotify()| and |rpcrequest()|
- to communicate with the job.
+ jobsend() writes raw data, not RPC messages. If the job was
+ created with `"rpc":v:true` then the channel expects RPC
+ messages, use |rpcnotify()| and |rpcrequest()| instead.
-jobstart({cmd}[, {opts}]) {Nvim} *jobstart()*
- Spawns {cmd} as a job. If {cmd} is a |List| it is run
- directly. If {cmd} is a |String| it is processed like this: >
+jobstart({cmd}[, {opts}]) *jobstart()*
+ Spawns {cmd} as a job.
+ If {cmd} is a List it runs directly (no 'shell').
+ If {cmd} is a String it runs in the 'shell', like this: >
:call jobstart(split(&shell) + split(&shellcmdflag) + ['{cmd}'])
-< (Only shows the idea; see |shell-unquoting| for full details.)
+< (See |shell-unquoting| for details.)
+
+ Returns |job-id| on success, 0 on invalid arguments (or job
+ table is full), -1 if {cmd}[0] or 'shell' is not executable.
+
+ See |job-control| and |rpc|.
NOTE: on Windows if {cmd} is a List:
- cmd[0] must be an executable (not a "built-in"). If it is
@@ -4962,6 +4968,7 @@ jobstart({cmd}[, {opts}]) {Nvim} *jobstart()*
by CommandLineToArgvW https://msdn.microsoft.com/bb776391
unless cmd[0] is some form of "cmd.exe".
+ *jobstart-options*
{opts} is a dictionary with these keys:
|on_stdout|: stdout event handler (function name or |Funcref|)
|on_stderr|: stderr event handler (function name or |Funcref|)
@@ -4972,9 +4979,9 @@ jobstart({cmd}[, {opts}]) {Nvim} *jobstart()*
with the job over stdin and stdout. "on_stdout" is
then ignored, but "on_stderr" can still be used.
pty : If set, the job will be connected to a new pseudo
- terminal, and the job streams are connected to
- the master file descriptor. "on_stderr" is ignored
- as all output will be received on stdout.
+ terminal and the job streams are connected to the
+ master file descriptor. "on_stderr" is ignored,
+ "on_stdout" receives all output.
width : (pty only) Width of the terminal screen
height : (pty only) Height of the terminal screen
@@ -4982,43 +4989,31 @@ jobstart({cmd}[, {opts}]) {Nvim} *jobstart()*
detach : (non-pty only) Detach the job process from the
nvim process. The process will not get killed
when nvim exits. If the process dies before
- nvim exits, on_exit will still be invoked.
+ nvim exits, "on_exit" will still be invoked.
- {opts} is passed as |self| to the callback; the caller may
- pass arbitrary data by setting other keys.
- Returns:
- - The job ID on success, which is used by |jobsend()| (or
- |rpcnotify()| and |rpcrequest()| if "rpc" option was used)
- and |jobstop()|
- - 0 on invalid arguments or if the job table is full
- - -1 if {cmd}[0] is not executable.
- See |job-control| and |msgpack-rpc| for more information.
-
-jobstop({job}) {Nvim} *jobstop()*
- Stop a job created with |jobstart()| by sending a `SIGTERM`
- to the corresponding process. If the process doesn't exit
- cleanly soon, a `SIGKILL` will be sent. When the job is
- finally closed, the exit handler provided to |jobstart()| or
- |termopen()| will be run.
- See |job-control| for more information.
-
-jobwait({ids}[, {timeout}]) {Nvim} *jobwait()*
+ {opts} is passed as |self| dictionary to the callback; the
+ caller may set other keys to pass application-specific data.
+
+jobstop({job}) *jobstop()*
+ Stop |job-id| {job} by sending SIGTERM to the job process. If
+ the process does not terminate after a timeout then SIGKILL
+ will be sent. When the job terminates its |on_exit| handler
+ (if any) will be invoked.
+ See |job-control|.
+
+jobwait({ids}[, {timeout}]) *jobwait()*
Wait for a set of jobs to finish. The {ids} argument is a list
- of ids for jobs that will be waited for. If passed, {timeout}
- is the maximum number of milliseconds to wait. While this
- function is executing, callbacks for jobs not in the {ids}
- list can be executed. Also, the screen wont be updated unless
- |:redraw| is invoked by one of the callbacks.
-
- Returns a list of integers with the same length as {ids}, with
- each integer representing the wait result for the
- corresponding job id. The possible values for the resulting
- integers are:
-
- * the job return code if the job exited
- * -1 if the wait timed out for the job
- * -2 if the job was interrupted
- * -3 if the job id is invalid.
+ of |job-id|s to wait for. {timeout} is the maximum number of
+ milliseconds to wait. During jobwait(), callbacks for jobs not
+ in the {ids} list may be invoked. The screen will not redraw
+ unless |:redraw| is invoked by a callback.
+
+ Returns a list of len({ids}) integers, where each integer is
+ the wait-result of the corresponding job. Each wait-result is:
+ Job exit-code, if the job exited
+ -1 if the wait timed out for the job
+ -2 if the job was interrupted
+ -3 if the |job-id| is invalid.
join({list} [, {sep}]) *join()*
Join the items in {list} together into one String.
@@ -5652,7 +5647,7 @@ mode([expr]) Return a string that indicates the current mode.
i Insert
R Replace |R|
Rv Virtual Replace |gR|
- t Terminal {Nvim}
+ t Terminal
c Command-line
cv Vim Ex mode |gQ|
ce Normal Ex mode |Q|
@@ -8201,9 +8196,9 @@ There are four types of features:
Example: >
:if has("win32")
< *has-patch*
-3. {Nvim} version. The "nvim-1.2.3" feature means that the Nvim version is
- 1.2.3 or later. Example: >
- :if has("nvim-1.2.3")
+3. Nvim version. The "nvim-0.2.1" feature means that the Nvim version is
+ 0.2.1 or later. Example: >
+ :if has("nvim-0.2.1")
<
4. Included patches. The "patch123" feature means that patch 123 has been
included. Note that this form does not check the version of Vim, you need
diff --git a/runtime/doc/job_control.txt b/runtime/doc/job_control.txt
index 2cf48f0f4f..7ba0acff48 100644
--- a/runtime/doc/job_control.txt
+++ b/runtime/doc/job_control.txt
@@ -4,41 +4,30 @@
NVIM REFERENCE MANUAL by Thiago de Arruda
-Nvim's facilities for job control *job-control*
+Nvim job control *job-control*
+
+Job control is a way to perform multitasking in Nvim, so scripts can spawn and
+control multiple processes without blocking the current Nvim instance.
Type |gO| to see the table of contents.
==============================================================================
-1. Introduction *job-control-intro*
-
-Job control is a simple way to perform multitasking in vimscript. Wikipedia
-contains a more generic/detailed description:
+Concepts
-"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."
+Job Id *job-id*
-In a few words: It allows a vimscript programmer to concurrently spawn and
-control multiple processes without blocking the current Nvim instance.
+When a job starts it is assigned a number, unique for the life of the current
+Nvim session. Functions like |jobstart()| return job ids. Functions like
+|jobsend()|, |jobstop()|, |rpcnotify()|, and |rpcrequest()| take job ids.
-Nvim's job control was designed to be simple and familiar to vimscript
-programmers, instead of being very powerful but complex. Unlike Vim's
-facilities for calling with external commands, job control does not depend on
-available shells, instead relying on OS functionality for process management.
+==============================================================================
+Usage *job-control-usage*
-Internally, Nvim job control is powered by libuv, which has a nice
-cross-platform API for managing processes. See https://github.com/libuv/libuv
-for details.
+To control jobs, use the "job…" family of functions: |jobstart()|,
+|jobsend()|, |jobstop()|.
-==============================================================================
-2. Usage *job-control-usage*
+Example: >
-Job control is achieved by calling a combination of the |jobstart()|,
-|jobsend()| and |jobstop()| functions. Here's an example:
->
function! s:JobHandler(job_id, data, event) dict
if a:event == 'stdout'
let str = self.shell.' stdout: '.join(a:data)
@@ -58,35 +47,41 @@ Job control is achieved by calling a combination of the |jobstart()|,
let job1 = jobstart(['bash'], extend({'shell': 'shell 1'}, s:callbacks))
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: >
+ nvim -u ~/foo.vim
<
-To test the above, copy it to the file ~/jobcontrol.vim and start with a clean
-nvim instance:
->
- nvim -u NONE -S ~/jobcontrol.vim
-<
-Here's what is happening:
-
-- 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.
-- The `JobHandler()` function is a callback passed to |jobstart()| to handle
- various job events. It takes care of displaying stdout/stderr received from
- the shells.
- *on_stdout* *on_stderr* *on_exit*
-- The arguments passed to `JobHandler()` are:
-
- 0: The job id
- 1: If the event is "stdout" or "stderr", a list with lines read from the
- corresponding stream. For "exit", it is the status returned by the
- program.
- 2: The event type, which is "stdout", "stderr" or "exit".
+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.
+ - `JobHandler()` callback is passed to |jobstart()| to handle various job
+ events. It displays stdout/stderr data received from the shells.
+
+ *on_stdout*
+Arguments passed to on_stdout callback:
+ 0: |job-id|
+ 1: List of lines read from the stream. If the last item is not "" (empty
+ string), then it is an incomplete line that might be continued at the
+ next on_stdout invocation. See Note 2 below.
+ 2: Event type: "stdout"
+ *on_stderr*
+Arguments passed to on_stderr callback:
+ 0: |job-id|
+ 1: List of lines read from the stream. If the last item is not "" (empty
+ string), then it is an incomplete line that might be continued at the
+ next on_stderr invocation. See Note 2 below.
+ 2: Event type: "stderr"
+ *on_exit*
+Arguments passed to on_exit callback:
+ 0: |job-id|
+ 1: Exit-code of the process.
+ 2: Event type: "exit"
Note: Buffered stdout/stderr data which has not been flushed by the sender
- will not trigger the "stdout" callback (but if the process ends, the
- "exit" callback will be triggered).
+ 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. >
function! Receive(job_id, data, event)
@@ -97,9 +92,25 @@ Here's what is happening:
\ {'on_stdout': 'Receive'})
< https://github.com/neovim/neovim/issues/1592
-The options dictionary is passed as the "self" variable to the callback
-function. Here's a more object-oriented version of the above:
->
+ 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: >
+ 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: >
+
let Shell = {}
function Shell.on_stdout(_job_id, data, event)
@@ -126,19 +137,13 @@ function. Here's a more object-oriented version of the above:
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, one can use the |jobsend()| function, like
-this:
->
+To send data to the job's stdin, use |jobsend()|: >
:call jobsend(job1, "ls\n")
:call jobsend(job1, "invalid-command\n")
:call jobsend(job1, "exit\n")
<
-A job may be killed at any time with the |jobstop()| function:
->
+A job may be killed with |jobstop()|: >
:call jobstop(job1)
<
-When |jobstop()| is called, `SIGTERM` will be sent to the job. If a job does
-not exit after 2 seconds, `SIGKILL` will be sent.
-
==============================================================================
vim:tw=78:ts=8:noet:ft=help:norl: