From cab599dff5920e10854e2f9262240a167becf269 Mon Sep 17 00:00:00 2001 From: "K.Takata" Date: Thu, 6 May 2021 08:10:19 +0900 Subject: [PATCH 1/2] Squashed 'autoload/minpac/' changes from 8eae0c4..0fb846e 0fb846e avoid has_key check for on_stdout 236debf Merge pull request #43 from prabirshrestha/fix-retry c4d6144 Set waittime 8fc5956 Increment l:retry f6b87c1 Trim null 69a4a5c Merge pull request #42 from mattn/fix-null 35b369f Trim null 36e97f0 Merge pull request #41 from mattn/tcp 2addfc3 Skip neovim 625cd40 Add test for async#job#connect fa1b82d Retry a4f4005 Add async#job#connect 6102020 Add :AsyncEmbed d15123a Add default value when reading 'close_stdin' from input options bb3aceb Make `opts` argument of `async#job#send`, optional 732cf48 Pass `close_stdin` as a Dictionary rather than bool argument ab499e8 Better / safer management of non-blocking channels a0f4e4e Wait for transmit buffer to be empty, before calling `ch_close_in` ada658f Add support for sending data and closing stdin at the same time 42371b5 fix not restoring cpoptions f67ecb5 Support 'cwd' option in jobstart 627a8c4 Do NOT remove job in job_stop but on_exit 8998efb Add tests for Neovim 91c3f2b Do NOT raise E900 on invalid jobid f301455 doc: Update Embedding section 8da445b default to noblock if supported by vim 8 to avoid deadlocks causing vim to hang (#31) 4bde72e Don't use workaround (#30) ff9177c add async#job#pid() (#28) 0521409 Fix variable name in example (#19) d721851 Merge pull request #25 from prabirshrestha/add-test 633414e Use partial argument 79d54f4 Merge pull request #27 from prabirshrestha/revert-22 c980166 Revert #22 d7c52bc Fix test d5e8819 Install vim 2a883ee Fix test 519430b Add tests 7627c81 Merge pull request #24 from prabirshrestha/fix-heavy ca41dab Buffer size must be more large 300493e Merge pull request #22 from mattn/fix-block 017c6a8 Fix .travis.yml 7b1dfec Fix .travis.yml d10fdb9 Start timer to read lazy 89bec95 Add "sleep 1m" to read blocked channel git-subtree-dir: autoload/minpac git-subtree-split: 0fb846e1eb3c2bf04d52a57f41088afb3395212e --- .travis.yml | 12 ++- README.md | 30 ++---- autoload/async/embedder.vim | 48 ++++++++++ autoload/async/job.vim | 179 ++++++++++++++++++++++++++++-------- plugin/async.vim | 7 ++ test/.themisrc | 2 + test/async.vimspec | 93 +++++++++++++++++++ test/install-vim.sh | 27 ++++++ 8 files changed, 336 insertions(+), 62 deletions(-) create mode 100644 autoload/async/embedder.vim create mode 100644 plugin/async.vim create mode 100644 test/.themisrc create mode 100644 test/async.vimspec create mode 100644 test/install-vim.sh diff --git a/.travis.yml b/.travis.yml index 227f9dd..5d3dfd4 100644 --- a/.travis.yml +++ b/.travis.yml @@ -2,9 +2,17 @@ language: viml sudo: required dist: trusty +install: + - export VIM_VERSION=master + - bash test/install-vim.sh + - export PATH=$HOME/vim/bin:$PATH + +before_script: + - git clone --depth 1 --branch v1.5.4 --single-branch https://github.com/thinca/vim-themis /tmp/vim-themis + script: - - pip install --user --upgrade vim-vint + - pip install --user --upgrade vim-vint pathlib enum34 typing - python --version - vim --version - - vint --version - vint autoload + - /tmp/vim-themis/bin/themis --reporter dot diff --git a/README.md b/README.md index a0b2c85..ac208e2 100644 --- a/README.md +++ b/README.md @@ -27,11 +27,14 @@ else echom 'job failed to start' endif +" If you want to get the process id of the job +let pid = async#job#pid(jobid) + " If you want to wait the job: -call async#job#wait([job], 5000) " timeout: 5 sec +call async#job#wait([jobid], 5000) " timeout: 5 sec " If you want to stop the job: -call async#job#stop(job) +call async#job#stop(jobid) ``` ## APIs @@ -43,31 +46,15 @@ APIs are based on neovim's job control APIs. * [jobstart()](https://neovim.io/doc/user/eval.html#jobstart%28%29) * [jobstop()](https://neovim.io/doc/user/eval.html#jobstop%28%29) * [jobwait()](https://neovim.io/doc/user/eval.html#jobwait%28%29) +* [jobpid()](https://neovim.io/doc/user/eval.html#jobpid%28%29) ## Embedding Async.vim can be either embedded with other plugins or be used as an external plugin. -If you want to embed all you need is to change these 4 function names async#job# to what ever you want. E.g.: +If you want to embed run the following vim command. ```vim -" public apis {{{ -function! yourplugin#job#start(cmd, opts) abort - return s:job_start(a:cmd, a:opts) -endfunction - -function! yourplugin#job#stop(jobid) abort - call s:job_stop(a:jobid) -endfunction - -function! yourplugin#job#send(jobid, data) abort - call s:job_send(a:jobid, a:data) -endfunction - -function! yourplugin#job#wait(jobids, ...) abort - let l:timeout = get(a:000, 0, -1) - return s:job_wait(a:jobids, l:timeout) -endfunction -" }}} +:AsyncEmbed path=./autoload/myplugin/job.vim namespace=myplugin#job ``` ## Todos @@ -75,4 +62,3 @@ endfunction * `job_stop` and `job_send` is treated as noop when using `system()` * `on_stderr` doesn't work when using `system()` * Fallback to python/ruby threads and vimproc instead of using `system()` for better compatibility (PRs welcome!!!) - diff --git a/autoload/async/embedder.vim b/autoload/async/embedder.vim new file mode 100644 index 0000000..7965d75 --- /dev/null +++ b/autoload/async/embedder.vim @@ -0,0 +1,48 @@ +let s:autoload_root = expand(':p:h:h') +let s:git_dir = simplify(expand(':p:h:h:h') . '/.git') + +function! s:get_git_commit() abort + if !executable('git') || !isdirectory(s:git_dir) + return 'UNKNOWN' + endif + + let l:git = 'git --git-dir=' . shellescape(s:git_dir) . ' ' + let l:commit = trim(system(l:git . 'rev-parse HEAD')) + let l:is_dirty = system(l:git . 'status --porcelain') =~? '\S' + + return l:commit . (l:is_dirty ? ' (dirty)' : '') +endfunction + +function! async#embedder#embed(...) abort + let l:args = {} + + for l:arg in a:000 + let l:idx = stridx(l:arg, '=') + let l:key = l:arg[:l:idx - 1] + let l:value = l:arg[l:idx + 1:] + let l:args[l:key] = l:value + endfor + + if !has_key(l:args, 'path') + echom 'path required' + return + endif + + if !has_key(l:args, 'namespace') + echom 'namespace required' + endif + + + let l:lines = readfile(s:autoload_root . '/async/job.vim') + let l:lines = map(l:lines, {_, l -> substitute(l, '\V\C\) diff --git a/test/.themisrc b/test/.themisrc new file mode 100644 index 0000000..70fef82 --- /dev/null +++ b/test/.themisrc @@ -0,0 +1,2 @@ +call themis#option('recursive', 1) +call themis#helper('command').with(themis#helper('assert')) diff --git a/test/async.vimspec b/test/async.vimspec new file mode 100644 index 0000000..cfc2a98 --- /dev/null +++ b/test/async.vimspec @@ -0,0 +1,93 @@ +function! s:on_stdout(ctx, id, data, event) abort + call add(a:ctx.output, join(a:data, '')) + call async#job#stop(a:id) +endfunction + +Describe async + Before + let scope = themis#helper('scope') + let vars = scope.vars('autoload/async/job.vim') + End + + Describe async#job#start + It can start cmmand and return numbered job-id + let job = async#job#start('vim --version', {}) + Assert Equals(type(job), v:t_number) + End + End + + Describe async#job#stop + It can stop the job specified + let job = async#job#start('bash -c "sleep 2 && touch i-love-vim"', {}) + sleep 3 + call async#job#stop(job) + Assert filereadable('i-love-vim') + call delete('i-love-vim') + + let job = async#job#start('bash -c "sleep 2 && touch i-love-vim"', {}) + sleep 1 + call async#job#stop(job) + Assert !filereadable('i-love-vim') + End + + It invokes 'on_exit' callback + let ns = { 'called': 0 } + let job = async#job#start('bash -c "sleep 2 && touch i-love-vim"', { + \ 'on_exit': { -> extend(ns, { 'called': 1 }) }, + \}) + call async#job#stop(job) + sleep 1m + Assert Equals(ns, {'called': 1}) + End + + It removes a corresponding job from an internal variable + let job1 = async#job#start('bash -c "sleep 2 && touch i-love-vim"', {}) + let job2 = async#job#start('bash -c "sleep 2 && touch i-love-vim"', {}) + Assert Equals(sort(keys(vars.jobs)), sort([string(job1), string(job2)])) + call async#job#stop(job1) + sleep 1m + Assert Equals(sort(keys(vars.jobs)), sort([string(job2)])) + sleep 3 + Assert Equals(sort(keys(vars.jobs)), []) + End + End + + Describe async#job#wait + It can wait the job specified + let job = async#job#start('bash -c "sleep 2"', {}) + let start = reltime() + call async#job#wait([job]) + let seconds = reltimefloat(reltime(start)) + call async#job#stop(job) + Assert seconds > 2 + End + End + + Describe async#job#send + It can send input text to the job + let ctx = { 'output': [] } + let job = async#job#start('cat', {'on_stdout': function('s:on_stdout', [ctx])}) + call async#job#send(job, "i-love-vim\n") + call async#job#wait([job]) + let out = join(ctx.output, '') + Assert Equals(out, 'i-love-vim') + End + End + + Describe async#job#connect + It can connect tcp-server and return numbered job-id + if has('nvim') + Skip nvim is not supported + endif + let ctx = { 'output': [] } + let job = async#job#connect('google.com:80', {'on_stdout': function('s:on_stdout', [ctx])}) + Assert Equals(type(job), v:t_number) + call async#job#send(job, "GET / HTTP/1.0\r\n\r\n") + sleep 4 + let out = join(ctx.output, '') + let firstline = trim(split(out, '[\r\n]')[0]) + Assert Equals(firstline, 'HTTP/1.0 200 OK') + End + End + +End diff --git a/test/install-vim.sh b/test/install-vim.sh new file mode 100644 index 0000000..abcc0f0 --- /dev/null +++ b/test/install-vim.sh @@ -0,0 +1,27 @@ +#!/bin/bash + +set -ev + +case "${TRAVIS_OS_NAME}" in + linux) + if [[ "${VIM_VERSION}" == "" ]]; then + exit + fi + git clone --depth 1 --branch "${VIM_VERSION}" https://github.com/vim/vim /tmp/vim + cd /tmp/vim + ./configure --prefix="${HOME}/vim" --with-features=huge --enable-pythoninterp \ + --enable-python3interp --enable-fail-if-missing + make -j2 + make install + ;; + osx) + brew install macvim + # Instead of --with-override-system-vim, manually link the executable because + # it prevents MacVim installation with a bottle. + ln -fs "$(brew --prefix macvim)/bin/mvim" "/usr/local/bin/vim" + ;; + *) + echo "Unknown value of \${TRAVIS_OS_NAME}: ${TRAVIS_OS_NAME}" + exit 65 + ;; +esac From 5351955003b07a747e700c119ff9483c84b248f4 Mon Sep 17 00:00:00 2001 From: "K.Takata" Date: Mon, 19 Apr 2021 14:18:10 +0900 Subject: [PATCH 2/2] async.vim: Remove some files from async.vim These files are not needed in minpac. --- autoload/minpac/plugin/async.vim | 7 --- autoload/minpac/test/.themisrc | 2 - autoload/minpac/test/async.vimspec | 93 ----------------------------- autoload/minpac/test/install-vim.sh | 27 --------- 4 files changed, 129 deletions(-) delete mode 100644 autoload/minpac/plugin/async.vim delete mode 100644 autoload/minpac/test/.themisrc delete mode 100644 autoload/minpac/test/async.vimspec delete mode 100644 autoload/minpac/test/install-vim.sh diff --git a/autoload/minpac/plugin/async.vim b/autoload/minpac/plugin/async.vim deleted file mode 100644 index 6d56bdc..0000000 --- a/autoload/minpac/plugin/async.vim +++ /dev/null @@ -1,7 +0,0 @@ -if exists('g:async_vim') - finish -endif -let g:async_vim = 1 - -" :AsyncEmbed path=./autoload/myplugin/job.vim namespace=myplugin#job -command! -nargs=+ AsyncEmbed :call async#embedder#embed() diff --git a/autoload/minpac/test/.themisrc b/autoload/minpac/test/.themisrc deleted file mode 100644 index 70fef82..0000000 --- a/autoload/minpac/test/.themisrc +++ /dev/null @@ -1,2 +0,0 @@ -call themis#option('recursive', 1) -call themis#helper('command').with(themis#helper('assert')) diff --git a/autoload/minpac/test/async.vimspec b/autoload/minpac/test/async.vimspec deleted file mode 100644 index cfc2a98..0000000 --- a/autoload/minpac/test/async.vimspec +++ /dev/null @@ -1,93 +0,0 @@ -function! s:on_stdout(ctx, id, data, event) abort - call add(a:ctx.output, join(a:data, '')) - call async#job#stop(a:id) -endfunction - -Describe async - Before - let scope = themis#helper('scope') - let vars = scope.vars('autoload/async/job.vim') - End - - Describe async#job#start - It can start cmmand and return numbered job-id - let job = async#job#start('vim --version', {}) - Assert Equals(type(job), v:t_number) - End - End - - Describe async#job#stop - It can stop the job specified - let job = async#job#start('bash -c "sleep 2 && touch i-love-vim"', {}) - sleep 3 - call async#job#stop(job) - Assert filereadable('i-love-vim') - call delete('i-love-vim') - - let job = async#job#start('bash -c "sleep 2 && touch i-love-vim"', {}) - sleep 1 - call async#job#stop(job) - Assert !filereadable('i-love-vim') - End - - It invokes 'on_exit' callback - let ns = { 'called': 0 } - let job = async#job#start('bash -c "sleep 2 && touch i-love-vim"', { - \ 'on_exit': { -> extend(ns, { 'called': 1 }) }, - \}) - call async#job#stop(job) - sleep 1m - Assert Equals(ns, {'called': 1}) - End - - It removes a corresponding job from an internal variable - let job1 = async#job#start('bash -c "sleep 2 && touch i-love-vim"', {}) - let job2 = async#job#start('bash -c "sleep 2 && touch i-love-vim"', {}) - Assert Equals(sort(keys(vars.jobs)), sort([string(job1), string(job2)])) - call async#job#stop(job1) - sleep 1m - Assert Equals(sort(keys(vars.jobs)), sort([string(job2)])) - sleep 3 - Assert Equals(sort(keys(vars.jobs)), []) - End - End - - Describe async#job#wait - It can wait the job specified - let job = async#job#start('bash -c "sleep 2"', {}) - let start = reltime() - call async#job#wait([job]) - let seconds = reltimefloat(reltime(start)) - call async#job#stop(job) - Assert seconds > 2 - End - End - - Describe async#job#send - It can send input text to the job - let ctx = { 'output': [] } - let job = async#job#start('cat', {'on_stdout': function('s:on_stdout', [ctx])}) - call async#job#send(job, "i-love-vim\n") - call async#job#wait([job]) - let out = join(ctx.output, '') - Assert Equals(out, 'i-love-vim') - End - End - - Describe async#job#connect - It can connect tcp-server and return numbered job-id - if has('nvim') - Skip nvim is not supported - endif - let ctx = { 'output': [] } - let job = async#job#connect('google.com:80', {'on_stdout': function('s:on_stdout', [ctx])}) - Assert Equals(type(job), v:t_number) - call async#job#send(job, "GET / HTTP/1.0\r\n\r\n") - sleep 4 - let out = join(ctx.output, '') - let firstline = trim(split(out, '[\r\n]')[0]) - Assert Equals(firstline, 'HTTP/1.0 200 OK') - End - End - -End diff --git a/autoload/minpac/test/install-vim.sh b/autoload/minpac/test/install-vim.sh deleted file mode 100644 index abcc0f0..0000000 --- a/autoload/minpac/test/install-vim.sh +++ /dev/null @@ -1,27 +0,0 @@ -#!/bin/bash - -set -ev - -case "${TRAVIS_OS_NAME}" in - linux) - if [[ "${VIM_VERSION}" == "" ]]; then - exit - fi - git clone --depth 1 --branch "${VIM_VERSION}" https://github.com/vim/vim /tmp/vim - cd /tmp/vim - ./configure --prefix="${HOME}/vim" --with-features=huge --enable-pythoninterp \ - --enable-python3interp --enable-fail-if-missing - make -j2 - make install - ;; - osx) - brew install macvim - # Instead of --with-override-system-vim, manually link the executable because - # it prevents MacVim installation with a bottle. - ln -fs "$(brew --prefix macvim)/bin/mvim" "/usr/local/bin/vim" - ;; - *) - echo "Unknown value of \${TRAVIS_OS_NAME}: ${TRAVIS_OS_NAME}" - exit 65 - ;; -esac