Skip to content

Commit 669f05d

Browse files
committed
💪 Refactor denops#plugin module
1. Move most of core functions of `denops#plugin` into the internal module 2. Track plugin state in `denops#_internal#plugin` before it is loaded
1 parent f1d29ba commit 669f05d

File tree

2 files changed

+104
-81
lines changed

2 files changed

+104
-81
lines changed

autoload/denops/_internal/plugin.vim

Lines changed: 67 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,10 @@
1+
const s:STATE_RESERVED = 'reserved'
2+
const s:STATE_LOADING = 'loading'
3+
const s:STATE_LOADED = 'loaded'
4+
const s:STATE_FAILED = 'failed'
5+
6+
let s:plugins = {}
7+
18
function! denops#_internal#plugin#collect() abort
29
const l:pattern = denops#_internal#path#join(['denops', '*', 'main.ts'])
310
let l:plugins = []
@@ -20,5 +27,64 @@ function! denops#_internal#plugin#find(name) abort
2027
endif
2128
return #{ name: l:name, script: l:script }
2229
endfor
23-
throw printf('No denops plugin for "%s" exists', a:name)
30+
throw printf('Denops plugin "%s" does not exist in the runtimepath', a:name)
31+
endfunction
32+
33+
function! denops#_internal#plugin#get(name) abort
34+
if !has_key(s:plugins, a:name)
35+
let s:plugins[a:name] = #{name: a:name, script: '', state: s:STATE_RESERVED, callbacks: []}
36+
endif
37+
return s:plugins[a:name]
38+
endfunction
39+
40+
function! denops#_internal#plugin#load(name, script) abort
41+
const l:script = denops#_internal#path#norm(a:script)
42+
const l:args = [a:name, l:script]
43+
let l:plugin = denops#_internal#plugin#get(a:name)
44+
let l:plugin.state = s:STATE_LOADING
45+
let l:plugin.script = l:script
46+
let s:plugins[a:name] = l:plugin
47+
call denops#_internal#echo#debug(printf('load plugin: %s', l:args))
48+
call denops#_internal#server#chan#notify('invoke', ['load', l:args])
49+
endfunction
50+
51+
function! denops#_internal#plugin#reload(name) abort
52+
const l:args = [a:name]
53+
let l:plugin = denops#_internal#plugin#get(a:name)
54+
let l:plugin.state = s:STATE_LOADING
55+
call denops#_internal#echo#debug(printf('reload plugin: %s', l:args))
56+
call denops#_internal#server#chan#notify('invoke', ['reload', l:args])
57+
endfunction
58+
59+
function! s:DenopsSystemPluginPre() abort
60+
const l:name = matchstr(expand('<amatch>'), 'DenopsSystemPluginPre:\zs.*')
61+
execute printf('doautocmd <nomodeline> User DenopsPluginPre:%s', l:name)
62+
endfunction
63+
64+
function! s:DenopsSystemPluginPost() abort
65+
const l:name = matchstr(expand('<amatch>'), 'DenopsSystemPluginPost:\zs.*')
66+
let l:plugin = denops#_internal#plugin#get(l:name)
67+
const l:callbacks = l:plugin.callbacks
68+
let l:plugin.state = s:STATE_LOADED
69+
let l:plugin.callbacks = []
70+
for l:Callback in l:callbacks
71+
call l:Callback()
72+
endfor
73+
execute printf('doautocmd <nomodeline> User DenopsPluginPost:%s', l:name)
74+
endfunction
75+
76+
function! s:DenopsSystemPluginFail() abort
77+
const l:name = matchstr(expand('<amatch>'), 'DenopsSystemPluginFail:\zs.*')
78+
let l:plugin = denops#_internal#plugin#get(a:name)
79+
let l:plugin.state = s:STATE_FAILED
80+
let l:plugin.callbacks = []
81+
execute printf('doautocmd <nomodeline> User DenopsPluginFail:%s', l:name)
2482
endfunction
83+
84+
augroup denops_autoload_plugin_internal
85+
autocmd!
86+
autocmd User DenopsSystemPluginPre:* ++nested call s:DenopsSystemPluginPre()
87+
autocmd User DenopsSystemPluginPost:* ++nested call s:DenopsSystemPluginPost()
88+
autocmd User DenopsSystemPluginFail:* ++nested call s:DenopsSystemPluginFail()
89+
autocmd User DenopsClosed let s:plugins = {}
90+
augroup END

autoload/denops/plugin.vim

Lines changed: 37 additions & 80 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,5 @@
1-
let s:loaded_plugins = {}
2-
let s:load_callbacks = {}
3-
41
function! denops#plugin#is_loaded(name) abort
5-
return has_key(s:loaded_plugins, a:name)
2+
return denops#_internal#plugin#get(a:name).state =~# '^\%(loaded\|failed\)$'
63
endfunction
74

85
function! denops#plugin#wait(name, ...) abort
@@ -21,66 +18,43 @@ function! denops#plugin#wait(name, ...) abort
2118
endif
2219
return -2
2320
endif
24-
if has_key(s:loaded_plugins, a:name)
25-
return s:loaded_plugins[a:name]
26-
endif
27-
let l:ret = denops#_internal#wait#for(
28-
\ l:options.timeout,
29-
\ { -> has_key(s:loaded_plugins, a:name) },
30-
\ l:options.interval,
31-
\)
32-
if l:ret is# -1
33-
if !l:options.silent
34-
call denops#_internal#echo#error(printf(
35-
\ 'Failed to wait for "%s" to start. It took more than %d milliseconds and timed out.',
36-
\ a:name,
37-
\ l:options.timeout,
38-
\))
21+
if !denops#plugin#is_loaded(a:name)
22+
let l:ret = denops#_internal#wait#for(
23+
\ l:options.timeout,
24+
\ { -> denops#plugin#is_loaded(a:name) },
25+
\ l:options.interval,
26+
\)
27+
if l:ret is# -1
28+
if !l:options.silent
29+
call denops#_internal#echo#error(printf(
30+
\ 'Failed to wait for "%s" to start. It took more than %d milliseconds and timed out.',
31+
\ a:name,
32+
\ l:options.timeout,
33+
\))
34+
endif
35+
return -1
3936
endif
40-
return -1
4137
endif
38+
return denops#_internal#plugin#get(a:name).state ==# 'loaded' ? 0 : -3
4239
endfunction
4340

4441
function! denops#plugin#wait_async(name, callback) abort
45-
if has_key(s:loaded_plugins, a:name)
46-
if s:loaded_plugins[a:name] isnot# 0
47-
return
48-
endif
42+
let l:plugin = denops#_internal#plugin#get(a:name)
43+
if l:plugin.state ==# 'loaded'
4944
call a:callback()
5045
return
46+
elseif l:plugin.state ==# 'failed'
47+
return
5148
endif
52-
let l:callbacks = get(s:load_callbacks, a:name, [])
53-
call add(l:callbacks, a:callback)
54-
let s:load_callbacks[a:name] = l:callbacks
55-
endfunction
56-
57-
" DEPRECATED
58-
" Some plugins (e.g. dein.vim) use this function with options thus we cannot
59-
" change the interface of this function.
60-
" That's why we introduce 'load' function that replaces this function.
61-
function! denops#plugin#register(name, ...) abort
62-
call denops#_internal#echo#deprecate(
63-
\ 'denops#plugin#register() is deprecated. Use denops#plugin#load() instead.',
64-
\)
65-
if a:0 is# 0 || type(a:1) is# v:t_dict
66-
let l:script = denops#_internal#plugin#find(a:name).script
67-
else
68-
let l:script = a:1
69-
endif
70-
return denops#plugin#load(a:name, l:script)
49+
call add(l:plugin.callbacks, a:callback)
7150
endfunction
7251

7352
function! denops#plugin#load(name, script) abort
74-
let l:script = denops#_internal#path#norm(a:script)
75-
let l:args = [a:name, l:script]
76-
call denops#_internal#echo#debug(printf('load plugin: %s', l:args))
77-
call denops#_internal#server#chan#notify('invoke', ['load', l:args])
53+
call denops#_internal#plugin#load(a:name, a:script)
7854
endfunction
7955

8056
function! denops#plugin#reload(name) abort
81-
let l:args = [a:name]
82-
call denops#_internal#echo#debug(printf('reload plugin: %s', l:args))
83-
call denops#_internal#server#chan#notify('invoke', ['reload', l:args])
57+
call denops#_internal#plugin#reload(a:name)
8458
endfunction
8559

8660
function! denops#plugin#discover() abort
@@ -110,38 +84,21 @@ function! denops#plugin#check_type(...) abort
11084
\ })
11185
endfunction
11286

113-
function! s:relay_autocmd(name) abort
114-
let l:plugin = matchstr(expand('<amatch>'), '^[^:]\+:\zs.*')
115-
execute printf('doautocmd <nomodeline> User %s:%s', a:name, l:plugin)
116-
endfunction
117-
118-
function! s:DenopsSystemPluginPost() abort
119-
let l:plugin = matchstr(expand('<amatch>'), 'DenopsSystemPluginPost:\zs.*')
120-
let s:loaded_plugins[l:plugin] = 0
121-
if has_key(s:load_callbacks, l:plugin)
122-
for l:Callback in remove(s:load_callbacks, l:plugin)
123-
call l:Callback()
124-
endfor
125-
endif
126-
execute printf('doautocmd <nomodeline> User DenopsPluginPost:%s', l:plugin)
127-
endfunction
128-
129-
function! s:DenopsSystemPluginFail() abort
130-
let l:plugin = matchstr(expand('<amatch>'), 'DenopsSystemPluginFail:\zs.*')
131-
let s:loaded_plugins[l:plugin] = -3
132-
if has_key(s:load_callbacks, l:plugin)
133-
call remove(s:load_callbacks, l:plugin)
87+
" DEPRECATED
88+
" Some plugins (e.g. dein.vim) use this function with options thus we cannot
89+
" change the interface of this function.
90+
" That's why we introduce 'load' function that replaces this function.
91+
function! denops#plugin#register(name, ...) abort
92+
call denops#_internal#echo#deprecate(
93+
\ 'denops#plugin#register() is deprecated. Use denops#plugin#load() instead.',
94+
\)
95+
if a:0 is# 0 || type(a:1) is# v:t_dict
96+
let l:script = denops#_internal#plugin#find(a:name).script
97+
else
98+
let l:script = a:1
13499
endif
135-
execute printf('doautocmd <nomodeline> User DenopsPluginFail:%s', l:plugin)
100+
return denops#plugin#load(a:name, l:script)
136101
endfunction
137102

138-
augroup denops_autoload_plugin_internal
139-
autocmd!
140-
autocmd User DenopsSystemPluginPre:* call s:relay_autocmd('DenopsPluginPre')
141-
autocmd User DenopsSystemPluginPost:* ++nested call s:DenopsSystemPluginPost()
142-
autocmd User DenopsSystemPluginFail:* call s:DenopsSystemPluginFail()
143-
autocmd User DenopsClosed let s:loaded_plugins = {}
144-
augroup END
145-
146103
call denops#_internal#conf#define('denops#plugin#wait_interval', 200)
147104
call denops#_internal#conf#define('denops#plugin#wait_timeout', 30000)

0 commit comments

Comments
 (0)