Skip to content

Commit

Permalink
Merge pull request #344 from vim-denops/v7-pre
Browse files Browse the repository at this point in the history
🎉 Denops v7
  • Loading branch information
lambdalisue authored Jul 27, 2024
2 parents 09e6495 + 6eb990e commit 8c920ec
Show file tree
Hide file tree
Showing 69 changed files with 9,873 additions and 1,324 deletions.
38 changes: 21 additions & 17 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -41,58 +41,62 @@ jobs:
run: deno task check

test:
needs: check

strategy:
fail-fast: false
matrix:
runner:
- windows-latest
- macos-latest
- ubuntu-latest
version:
- "1.38.x"
- "1.45.x"
- "1.x"
host_version:
- vim: "v9.0.2189"
nvim: "v0.9.4"
- vim: "v9.1.0448"
nvim: "v0.10.0"

runs-on: ${{ matrix.runner }}

steps:
- run: git config --global core.autocrlf false
if: runner.os == 'Windows'

- uses: actions/checkout@v4

- uses: denoland/[email protected]
with:
deno-version: "${{ matrix.version }}"

- uses: rhysd/action-setup-vim@v1
id: vim
with:
version: "${{ matrix.host_version.vim }}"
- name: Check Vim
run: |
echo ${DENOPS_TEST_VIM}
${DENOPS_TEST_VIM} --version
env:
DENOPS_TEST_VIM: ${{ steps.vim.outputs.executable }}

- uses: rhysd/action-setup-vim@v1
id: nvim
with:
neovim: true
version: "${{ matrix.host_version.nvim }}"
- name: Check Neovim

- name: Export executables
run: |
echo ${DENOPS_TEST_NVIM}
${DENOPS_TEST_NVIM} --version
env:
DENOPS_TEST_NVIM: ${{ steps.nvim.outputs.executable }}
echo "DENOPS_TEST_VIM_EXECUTABLE=${{ steps.vim.outputs.executable }}" >> "$GITHUB_ENV"
echo "DENOPS_TEST_NVIM_EXECUTABLE=${{ steps.nvim.outputs.executable }}" >> "$GITHUB_ENV"
- name: Perform pre-cache
run: deno cache ./denops/@denops-private/mod.ts

- name: Test
run: deno task test:coverage
env:
DENOPS_TEST_DENOPS_PATH: "./"
DENOPS_TEST_VIM_EXECUTABLE: ${{ steps.vim.outputs.executable }}
DENOPS_TEST_NVIM_EXECUTABLE: ${{ steps.nvim.outputs.executable }}
timeout-minutes: 5
timeout-minutes: 10

- run: |
deno task coverage --lcov > coverage.lcov
- uses: codecov/codecov-action@v4
with:
os: ${{ runner.os }}
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/update.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ jobs:
git config user.name github-actions[bot]
git config user.email github-actions[bot]@users.noreply.github.com
- name: Update dependencies and commit changes
run: deno task -q upgrade:commit --summary ../title.txt --report ../body.md
run: deno task -q update:commit --summary ../title.txt --report ../body.md
- name: Check result
id: result
uses: andstor/file-existence-action@v2
Expand Down
8 changes: 3 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,17 +3,15 @@
<strong>Denops</strong><br>
<sup>An ecosystem for Vim/Neovim enabling developers to write plugins in Deno.</sup>

[![Deno 1.38.5 or above](https://img.shields.io/badge/Deno-Support%201.38.5-yellowgreen.svg?logo=deno)](https://github.com/denoland/deno/tree/v1.38.5)
[![Vim 9.0.2189 or above](https://img.shields.io/badge/Vim-Support%209.0.2189-yellowgreen.svg?logo=vim)](https://github.com/vim/vim/tree/v9.0.2189)
[![Neovim 0.9.4 or above](https://img.shields.io/badge/Neovim-Support%200.9.4-yellowgreen.svg?logo=neovim&logoColor=white)](https://github.com/neovim/neovim/tree/v0.9.4)
[![Deno 1.45.0 or above](https://img.shields.io/badge/Deno-Support%201.45.0-yellowgreen.svg?logo=deno)](https://github.com/denoland/deno/tree/v1.45.0)
[![Vim 9.1.0448 or above](https://img.shields.io/badge/Vim-Support%209.1.0448-yellowgreen.svg?logo=vim)](https://github.com/vim/vim/tree/v9.1.0448)
[![Neovim 0.10.0 or above](https://img.shields.io/badge/Neovim-Support%200.10.0-yellowgreen.svg?logo=neovim&logoColor=white)](https://github.com/neovim/neovim/tree/v0.10.0)

[![MIT License](https://img.shields.io/badge/license-MIT-blue.svg)](LICENSE)
[![deno land](http://img.shields.io/badge/available%20on-deno.land/x/denops__core-lightgrey.svg?logo=deno)](https://deno.land/x/denops_core)
[![test](https://github.com/vim-denops/denops.vim/actions/workflows/test.yml/badge.svg)](https://github.com/vim-denops/denops.vim/actions/workflows/test.yml)
[![codecov](https://codecov.io/github/vim-denops/denops.vim/branch/main/graph/badge.svg?token=k50SaoYUp0)](https://codecov.io/github/vim-denops/denops.vim)

[![vim help](https://img.shields.io/badge/vim-%3Ah%20denops-orange.svg)](doc/denops.txt)
[![deno doc](https://doc.deno.land/badge.svg)](https://doc.deno.land/https/deno.land/x/denops_core/mod.ts)
[![Documentation](https://img.shields.io/badge/denops-Documentation-yellow.svg)](https://vim-denops.github.io/denops-documentation/)

</div>
Expand Down
8 changes: 8 additions & 0 deletions autoload/denops.vim
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,14 @@ function! denops#request_async(name, method, params, success, failure) abort
\)
endfunction

function! denops#interrupt(...) abort
let l:args = a:0 ? [a:1] : []
call denops#server#wait_async({ -> denops#_internal#server#chan#notify(
\ 'invoke',
\ ['interrupt', l:args],
\)})
endfunction

" Configuration
call denops#_internal#conf#define('denops#disabled', 0)
call denops#_internal#conf#define('denops#deno', 'deno')
Expand Down
4 changes: 3 additions & 1 deletion autoload/denops/_internal/echo.vim
Original file line number Diff line number Diff line change
Expand Up @@ -56,5 +56,7 @@ function! s:echomsg_batch() abort
let s:delayed_timer = 0
let s:delayed_messages = []
" Forcibly show the messages to the user
call feedkeys(printf("\<Cmd>%dmessages\<CR>", l:counter), 'n')
if l:counter > 1 && !g:denops#_test
call feedkeys(printf("\<Cmd>%dmessages\<CR>", l:counter), 'n')
endif
endfunction
3 changes: 3 additions & 0 deletions autoload/denops/_internal/event.vim
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
function denops#_internal#event#emit(name) abort
execute 'doautocmd <nomodeline> User' a:name
endfunction
31 changes: 19 additions & 12 deletions autoload/denops/_internal/job.vim
Original file line number Diff line number Diff line change
Expand Up @@ -24,13 +24,17 @@ if has('nvim')
\ 'on_stderr': funcref('s:on_recv', [a:options.on_stderr]),
\ 'on_exit': funcref('s:on_exit', [a:options.on_exit]),
\}
return jobstart(a:args, l:options)
try
return jobstart(a:args, l:options)
catch
" NOTE: Call `on_exit` when cmd (args[0]) is not executable.
call timer_start(0, { -> l:options.on_exit(-1, -1, 'exit') })
endtry
endfunction

function! s:stop(job) abort
try
call jobstop(a:job)
call jobwait([a:job])
catch /^Vim\%((\a\+)\)\=:E900/
" NOTE:
" Vim does not raise exception even the job has already closed so fail
Expand Down Expand Up @@ -58,24 +62,27 @@ else
\ 'err_cb': funcref('s:out_cb', [a:options.on_stderr, 'stderr']),
\ 'exit_cb': funcref('s:exit_cb', [a:options.on_exit, 'exit']),
\}
return job_start(a:args, l:options)
let l:job = job_start(a:args, l:options)
if l:job->job_status() ==# "fail"
" NOTE:
" On Windows call `on_exit` when cmd (args[0]) is not executable.
" On Unix a non-existing command results in "dead" instead of "fail",
" and `on_exit` is called by `job_start()`.
call timer_start(0, { -> l:options.exit_cb(-1, -1) })
endif
return l:job
endfunction

function! s:stop(job) abort
call job_stop(a:job)
call timer_start(s:KILL_TIMEOUT_MS, { -> job_stop(a:job, 'kill') })
" Wait until the job is actually closed
while job_status(a:job) ==# 'run'
sleep 10m
endwhile
redraw
endfunction

function! s:out_cb(callback, event, ch, msg) abort
call a:callback(a:ch, a:msg, a:event)
function! s:out_cb(callback, event, job, msg) abort
call a:callback(a:job, a:msg, a:event)
endfunction

function! s:exit_cb(callback, event, ch, status) abort
call a:callback(a:ch, a:status, a:event)
function! s:exit_cb(callback, event, job, status) abort
call a:callback(a:job, a:status, a:event)
endfunction
endif
62 changes: 57 additions & 5 deletions autoload/denops/_internal/plugin.vim
Original file line number Diff line number Diff line change
@@ -1,12 +1,22 @@
const s:STATE_RESERVED = 'reserved'
const s:STATE_LOADING = 'loading'
const s:STATE_LOADED = 'loaded'
const s:STATE_UNLOADING = 'unloading'
const s:STATE_FAILED = 'failed'

const s:VALID_NAME_PATTERN = '^[-_0-9a-zA-Z]\+$'

let s:plugins = {}

function! denops#_internal#plugin#is_valid_name(name) abort
return a:name =~# s:VALID_NAME_PATTERN
endfunction

function! denops#_internal#plugin#get(name) abort
if !has_key(s:plugins, a:name)
if !denops#_internal#plugin#is_valid_name(a:name)
throw printf('[denops] Invalid plugin name: %s', a:name)
endif
let s:plugins[a:name] = #{name: a:name, script: '', state: s:STATE_RESERVED, callbacks: []}
endif
return s:plugins[a:name]
Expand All @@ -20,24 +30,41 @@ function! denops#_internal#plugin#load(name, script) abort
const l:script = denops#_internal#path#norm(a:script)
const l:args = [a:name, l:script]
let l:plugin = denops#_internal#plugin#get(a:name)
if l:plugin.state !=# s:STATE_RESERVED && l:plugin.state !=# s:STATE_FAILED
call denops#_internal#echo#debug(printf('already loaded. skip: %s', l:args))
return
endif
let l:plugin.state = s:STATE_LOADING
let l:plugin.script = l:script
let s:plugins[a:name] = l:plugin
call denops#_internal#echo#debug(printf('load plugin: %s', l:args))
call denops#_internal#server#chan#notify('invoke', ['load', l:args])
endfunction

function! denops#_internal#plugin#unload(name) abort
const l:args = [a:name]
let l:plugin = denops#_internal#plugin#get(a:name)
if l:plugin.state ==# s:STATE_LOADED
let l:plugin.state = s:STATE_UNLOADING
endif
call denops#_internal#echo#debug(printf('unload plugin: %s', l:args))
call denops#_internal#server#chan#notify('invoke', ['unload', l:args])
endfunction

function! denops#_internal#plugin#reload(name) abort
const l:args = [a:name]
let l:plugin = denops#_internal#plugin#get(a:name)
let l:plugin.state = s:STATE_LOADING
if l:plugin.state ==# s:STATE_LOADED
let l:plugin.state = s:STATE_UNLOADING
endif
call denops#_internal#echo#debug(printf('reload plugin: %s', l:args))
call denops#_internal#server#chan#notify('invoke', ['reload', l:args])
endfunction

function! s:DenopsSystemPluginPre() abort
const l:name = matchstr(expand('<amatch>'), 'DenopsSystemPluginPre:\zs.*')
execute printf('doautocmd <nomodeline> User DenopsPluginPre:%s', l:name)
let l:plugin = denops#_internal#plugin#get(l:name)
let l:plugin.state = s:STATE_LOADING
call denops#_internal#event#emit(printf('DenopsPluginPre:%s', l:name))
endfunction

function! s:DenopsSystemPluginPost() abort
Expand All @@ -49,21 +76,46 @@ function! s:DenopsSystemPluginPost() abort
for l:Callback in l:callbacks
call l:Callback()
endfor
execute printf('doautocmd <nomodeline> User DenopsPluginPost:%s', l:name)
call denops#_internal#event#emit(printf('DenopsPluginPost:%s', l:name))
endfunction

function! s:DenopsSystemPluginFail() abort
const l:name = matchstr(expand('<amatch>'), 'DenopsSystemPluginFail:\zs.*')
let l:plugin = denops#_internal#plugin#get(l:name)
let l:plugin.state = s:STATE_FAILED
let l:plugin.callbacks = []
execute printf('doautocmd <nomodeline> User DenopsPluginFail:%s', l:name)
call denops#_internal#event#emit(printf('DenopsPluginFail:%s', l:name))
endfunction

function! s:DenopsSystemPluginUnloadPre() abort
const l:name = matchstr(expand('<amatch>'), 'DenopsSystemPluginUnloadPre:\zs.*')
let l:plugin = denops#_internal#plugin#get(l:name)
let l:plugin.state = s:STATE_UNLOADING
call denops#_internal#event#emit(printf('DenopsPluginUnloadPre:%s', l:name))
endfunction

function! s:DenopsSystemPluginUnloadPost() abort
const l:name = matchstr(expand('<amatch>'), 'DenopsSystemPluginUnloadPost:\zs.*')
let l:plugin = denops#_internal#plugin#get(l:name)
let l:plugin.state = s:STATE_RESERVED
call denops#_internal#event#emit(printf('DenopsPluginUnloadPost:%s', l:name))
endfunction

function! s:DenopsSystemPluginUnloadFail() abort
const l:name = matchstr(expand('<amatch>'), 'DenopsSystemPluginUnloadFail:\zs.*')
let l:plugin = denops#_internal#plugin#get(l:name)
let l:plugin.state = s:STATE_RESERVED
let l:plugin.callbacks = []
call denops#_internal#event#emit(printf('DenopsPluginUnloadFail:%s', l:name))
endfunction

augroup denops_autoload_plugin_internal
autocmd!
autocmd User DenopsSystemPluginPre:* ++nested call s:DenopsSystemPluginPre()
autocmd User DenopsSystemPluginPost:* ++nested call s:DenopsSystemPluginPost()
autocmd User DenopsSystemPluginFail:* ++nested call s:DenopsSystemPluginFail()
autocmd User DenopsSystemPluginUnloadPre:* ++nested call s:DenopsSystemPluginUnloadPre()
autocmd User DenopsSystemPluginUnloadPost:* ++nested call s:DenopsSystemPluginUnloadPost()
autocmd User DenopsSystemPluginUnloadFail:* ++nested call s:DenopsSystemPluginUnloadFail()
autocmd User DenopsClosed let s:plugins = {}
augroup END
2 changes: 1 addition & 1 deletion autoload/denops/_internal/rpc/nvim.vim
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ endfunction
function! denops#_internal#rpc#nvim#close(chan) abort
call timer_stop(a:chan._healthcheck_timer)
call chanclose(a:chan._id)
call a:chan._on_close(a:chan)
call timer_start(0, { -> a:chan._on_close(a:chan) })
endfunction

function! denops#_internal#rpc#nvim#notify(chan, method, params) abort
Expand Down
17 changes: 11 additions & 6 deletions autoload/denops/_internal/rpc/vim.vim
Original file line number Diff line number Diff line change
Expand Up @@ -3,29 +3,34 @@ function! denops#_internal#rpc#vim#connect(addr, ...) abort
\ 'on_close': { -> 0 },
\}, a:0 ? a:1 : {},
\)
let l:chan = ch_open(a:addr, {
let l:chan = {
\ '_on_close': l:options.on_close,
\}
let l:chan._handle = ch_open(a:addr, {
\ 'mode': 'json',
\ 'drop': 'auto',
\ 'noblock': 1,
\ 'timeout': g:denops#_internal#rpc#vim#timeout,
\ 'close_cb': l:options.on_close,
\ 'close_cb': { -> l:chan._on_close(l:chan) },
\})
if ch_status(l:chan) !=# 'open'
if ch_status(l:chan._handle) !=# 'open'
throw printf('Failed to connect `%s`', a:addr)
endif
return l:chan
endfunction

function! denops#_internal#rpc#vim#close(chan) abort
return ch_close(a:chan)
" NOTE: 'close_cb' specified on `ch_open` is not invoked when `ch_close` called.
call ch_close(a:chan._handle)
call timer_start(0, { -> a:chan._on_close(a:chan) })
endfunction

function! denops#_internal#rpc#vim#notify(chan, method, params) abort
return ch_sendraw(a:chan, json_encode([0, [a:method] + a:params]) . "\n")
return ch_sendraw(a:chan._handle, json_encode([0, [a:method] + a:params]) . "\n")
endfunction

function! denops#_internal#rpc#vim#request(chan, method, params) abort
let [l:ok, l:err] = ch_evalexpr(a:chan, [a:method] + a:params)
let [l:ok, l:err] = ch_evalexpr(a:chan._handle, [a:method] + a:params)
if l:err isnot# v:null
throw l:err
endif
Expand Down
Loading

0 comments on commit 8c920ec

Please sign in to comment.