diff options
Diffstat (limited to 'runtime/doc/job_control.txt')
-rw-r--r-- | runtime/doc/job_control.txt | 88 |
1 files changed, 57 insertions, 31 deletions
diff --git a/runtime/doc/job_control.txt b/runtime/doc/job_control.txt index 1faf9bcd94..dc746bbe99 100644 --- a/runtime/doc/job_control.txt +++ b/runtime/doc/job_control.txt @@ -37,37 +37,28 @@ for details ============================================================================== 2. Usage *job-control-usage* -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. - 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: +|jobsend()| and |jobstop()| functions. Here's an example: > - let job1 = jobstart('shell1', 'bash') - let job2 = jobstart('shell2', 'bash', ['-c', 'for ((i = 0; i < 10; i++)); do echo hello $i!; sleep 1; done']) - - function JobHandler() - if v:job_data[1] == 'stdout' - let str = 'shell '. v:job_data[0].' stdout: '.join(v:job_data[2]) - elseif v:job_data[1] == 'stderr' - let str = 'shell '.v:job_data[0].' stderr: '.join(v:job_data[2]) + function s:JobHandler(job_id, data, event) + if a:event == 'stdout' + let str = self.shell.' stdout: '.join(a:data) + elseif a:event == 'stderr' + let str = self.shell.' stderr: '.join(a:data) else - let str = 'shell '.v:job_data[0].' exited' + let str = self.shell.' exited' endif call append(line('$'), str) endfunction + let s:callbacks = { + \ 'on_stdout': function('s:JobHandler'), + \ 'on_stderr': function('s:JobHandler'), + \ 'on_exit': function('s:JobHandler') + \ } + 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)) - au JobActivity shell* call JobHandler() < To test the above, copy it to the file ~/jobcontrol.vim and start with a clean nvim instance: @@ -82,16 +73,51 @@ Here's what is happening: - 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 called by the `JobActivity` autocommand (notice - how the shell* pattern matches the names `shell1` and `shell2` passed to - |jobstart()|), and it takes care of displaying stdout/stderr received from +- 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. -- The v:job_data is an array set by the JobActivity event. It has the - following elements: +- The arguments passed to `JobHandler()` are: + 0: The job id - 1: The kind of activity: one of "stdout", "stderr" or "exit" - 2: When "activity" is "stdout" or "stderr", this will contain a list of - lines read from stdout or stderr + 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". + +The options dictionary is passed as the "self" variable to the callback +function. Here's a more object-oriented version of the above: +> + let Shell = {} + + function Shell.on_stdout(job_id, data) + call append(line('$'), self.get_name().' stdout: '.join(a:data)) + endfunction + + function Shell.on_stderr(job_id, data) + call append(line('$'), self.get_name().' stderr: '.join(a:data)) + endfunction + + function Shell.on_exit(job_id, data) + call append(line('$'), self.get_name().' exited') + endfunction + + function Shell.get_name() + return 'shell '.self.name + endfunction + + function Shell.new(name, ...) + let instance = extend(copy(g:Shell), {'name': a:name}) + let argv = ['bash'] + if a:0 > 0 + let argv += ['-c', a:1] + endif + let instance.id = jobstart(argv, instance) + return instance + endfunction + + let s1 = Shell.new('1') + let s2 = Shell.new('2', 'for i in {1..10}; do echo hello $i!; sleep 1; done') + To send data to the job's stdin, one can use the |jobsend()| function, like this: |