Merge pull request #88 from junegunn/improve-rtp-mgmt

Improve &runtimepath mgmt (fix #85)
This commit is contained in:
Junegunn Choi 2014-09-23 10:14:03 +09:00
commit 9d63fe6aeb
3 changed files with 155 additions and 55 deletions

105
plug.vim
View File

@ -142,17 +142,10 @@ function! plug#end()
let lod = {} let lod = {}
filetype off filetype off
" we want to make sure the plugin directories are added to rtp in the same for name in g:plugs_order
" order that they are registered with the Plug command. since the s:add_rtp
" function uses ^= to add plugin directories to the front of the rtp, we
" need to loop through the plugins in reverse
for name in reverse(copy(g:plugs_order))
let plug = g:plugs[name] let plug = g:plugs[name]
if get(s:loaded, plug.dir, 0) || !has_key(plug, 'on') && !has_key(plug, 'for') if get(s:loaded, name, 0) || !has_key(plug, 'on') && !has_key(plug, 'for')
let rtp = s:add_rtp(plug) let s:loaded[name] = 1
if reload
call s:source(rtp, 'plugin/**/*.vim', 'after/plugin/**/*.vim')
endif
continue continue
endif endif
@ -192,14 +185,28 @@ function! plug#end()
for [key, names] in items(lod) for [key, names] in items(lod)
augroup PlugLOD augroup PlugLOD
execute printf('autocmd FileType %s call <SID>lod_ft(%s, %s)', execute printf('autocmd FileType %s call <SID>lod_ft(%s, %s)',
\ key, string(key), string(reverse(names))) \ key, string(key), string(names))
augroup END augroup END
endfor endfor
if reload
call s:reload()
endif
call s:reorg_rtp() call s:reorg_rtp()
filetype plugin indent on filetype plugin indent on
syntax enable syntax enable
endfunction endfunction
function! s:loaded_names()
return filter(copy(g:plugs_order), 'get(s:loaded, v:val, 0)')
endfunction
function! s:reload()
for name in s:loaded_names()
call s:source(s:rtp(g:plugs[name]), 'plugin/**/*.vim', 'after/plugin/**/*.vim')
endfor
endfunction
function! s:trim(str) function! s:trim(str)
return substitute(a:str, '[\/]\+$', '', '') return substitute(a:str, '[\/]\+$', '', '')
endfunction endfunction
@ -246,27 +253,46 @@ function! s:err(msg)
endfunction endfunction
function! s:esc(path) function! s:esc(path)
return substitute(a:path, ' ', '\\ ', 'g') return escape(a:path, ' ')
endfunction endfunction
function! s:add_rtp(plug) function! s:escrtp(path)
let rtp = s:rtp(a:plug) return escape(a:path, ' ,')
execute 'set rtp^='.s:esc(rtp) endfunction
function! s:remove_rtp()
for name in s:loaded_names()
let rtp = s:rtp(g:plugs[name])
execute 'set rtp-='.s:escrtp(rtp)
let after = globpath(rtp, 'after') let after = globpath(rtp, 'after')
if isdirectory(after) if isdirectory(after)
execute 'set rtp+='.s:esc(after) execute 'set rtp-='.s:escrtp(after)
endif endif
let s:loaded[a:plug.dir] = 1 endfor
return rtp
endfunction endfunction
function! s:reorg_rtp() function! s:reorg_rtp()
if !empty(s:first_rtp) if !empty(s:first_rtp)
execute 'set rtp-='.s:first_rtp execute 'set rtp-='.s:first_rtp
execute 'set rtp^='.s:first_rtp
endif
if s:last_rtp !=# s:first_rtp
execute 'set rtp-='.s:last_rtp execute 'set rtp-='.s:last_rtp
endif
" &rtp is modified from outside
if exists('s:prtp') && s:prtp !=# &rtp
call s:remove_rtp()
unlet! s:middle
endif
let s:middle = get(s:, 'middle', &rtp)
let rtps = map(s:loaded_names(), 's:rtp(g:plugs[v:val])')
let afters = filter(map(copy(rtps), 'globpath(v:val, "after")'), 'isdirectory(v:val)')
let &rtp = join(map(rtps, 's:escrtp(v:val)'), ',')
\ . substitute(','.s:middle.',', '^,,$', ',', '')
\ . join(map(afters, 's:escrtp(v:val)'), ',')
let s:prtp = &rtp
if !empty(s:first_rtp)
execute 'set rtp^='.s:first_rtp
execute 'set rtp+='.s:last_rtp execute 'set rtp+='.s:last_rtp
endif endif
endfunction endfunction
@ -284,25 +310,28 @@ function! plug#load(...)
return s:err(printf('Unknown plugin%s: %s', s, join(unknowns, ', '))) return s:err(printf('Unknown plugin%s: %s', s, join(unknowns, ', ')))
end end
for name in a:000 for name in a:000
call s:lod(g:plugs[name], ['ftdetect', 'after/ftdetect', 'plugin', 'after/plugin']) call s:lod([name], ['ftdetect', 'after/ftdetect', 'plugin', 'after/plugin'])
endfor endfor
call s:reorg_rtp()
silent! doautocmd BufRead silent! doautocmd BufRead
return 1 return 1
endfunction endfunction
function! s:lod(plug, types) function! s:lod(names, types)
let rtp = s:add_rtp(a:plug) for name in a:names
let s:loaded[name] = 1
endfor
call s:reorg_rtp()
for name in a:names
let rtp = s:rtp(g:plugs[name])
for dir in a:types for dir in a:types
call s:source(rtp, dir.'/**/*.vim') call s:source(rtp, dir.'/**/*.vim')
endfor endfor
endfor
endfunction endfunction
function! s:lod_ft(pat, names) function! s:lod_ft(pat, names)
for name in a:names call s:lod(a:names, ['plugin', 'after/plugin'])
call s:lod(g:plugs[name], ['plugin', 'after/plugin'])
endfor
call s:reorg_rtp()
execute 'autocmd! PlugLOD FileType' a:pat execute 'autocmd! PlugLOD FileType' a:pat
silent! doautocmd filetypeplugin FileType silent! doautocmd filetypeplugin FileType
silent! doautocmd filetypeindent FileType silent! doautocmd filetypeindent FileType
@ -310,16 +339,14 @@ endfunction
function! s:lod_cmd(cmd, bang, l1, l2, args, name) function! s:lod_cmd(cmd, bang, l1, l2, args, name)
execute 'delc' a:cmd execute 'delc' a:cmd
call s:lod(g:plugs[a:name], ['ftdetect', 'after/ftdetect', 'plugin', 'after/plugin']) call s:lod([a:name], ['ftdetect', 'after/ftdetect', 'plugin', 'after/plugin'])
call s:reorg_rtp()
execute printf('%s%s%s %s', (a:l1 == a:l2 ? '' : (a:l1.','.a:l2)), a:cmd, a:bang, a:args) execute printf('%s%s%s %s', (a:l1 == a:l2 ? '' : (a:l1.','.a:l2)), a:cmd, a:bang, a:args)
endfunction endfunction
function! s:lod_map(map, name, prefix) function! s:lod_map(map, name, prefix)
execute 'unmap' a:map execute 'unmap' a:map
execute 'iunmap' a:map execute 'iunmap' a:map
call s:lod(g:plugs[a:name], ['ftdetect', 'after/ftdetect', 'plugin', 'after/plugin']) call s:lod([a:name], ['ftdetect', 'after/ftdetect', 'plugin', 'after/plugin'])
call s:reorg_rtp()
let extra = '' let extra = ''
while 1 while 1
let c = getchar(0) let c = getchar(0)
@ -343,7 +370,7 @@ function! s:add(repo, ...)
\ a:0 == 1 ? s:parse_options(a:1) : s:base_spec) \ a:0 == 1 ? s:parse_options(a:1) : s:base_spec)
let g:plugs[name] = spec let g:plugs[name] = spec
let g:plugs_order += [name] let g:plugs_order += [name]
let s:loaded[spec.dir] = 0 let s:loaded[name] = 0
catch catch
return s:err(v:exception) return s:err(v:exception)
endtry endtry
@ -1109,7 +1136,7 @@ function! s:status()
let cnt += 1 let cnt += 1
let ecnt += !valid let ecnt += !valid
" `s:loaded` entry can be missing if PlugUpgraded " `s:loaded` entry can be missing if PlugUpgraded
if valid && get(s:loaded, spec.dir, -1) == 0 if valid && get(s:loaded, name, -1) == 0
let unloaded = 1 let unloaded = 1
let msg .= ' (not loaded)' let msg .= ' (not loaded)'
endif endif
@ -1255,8 +1282,12 @@ function! s:revert()
echo 'Reverted.' echo 'Reverted.'
endfunction endfunction
let s:first_rtp = s:esc(get(split(&rtp, ','), 0, '')) function! s:split_rtp()
let s:last_rtp = s:esc(get(split(&rtp, ','), -1, '')) return split(&rtp, '\\\@<!,')
endfunction
let s:first_rtp = s:escrtp(get(s:split_rtp(), 0, ''))
let s:last_rtp = s:escrtp(get(s:split_rtp(), -1, ''))
if exists('g:plugs') if exists('g:plugs')
let g:plugs_order = get(g:, 'plugs_order', keys(g:plugs)) let g:plugs_order = get(g:, 'plugs_order', keys(g:plugs))

View File

@ -19,10 +19,14 @@ make_dirs() {
cd "$1" cd "$1"
mkdir -p autoload colors ftdetect ftplugin indent plugin syntax mkdir -p autoload colors ftdetect ftplugin indent plugin syntax
for d in *; do for d in *; do
[ -d $d ] || continue
cat > $d/xxx.vim << EOF cat > $d/xxx.vim << EOF
" echom expand('<sfile>') " echom expand('<sfile>')
let g:total_order = get(g:, 'total_order', [])
let g:$2 = get(g:, '$2', []) let g:$2 = get(g:, '$2', [])
call add(g:$2, '${1:4}/$d') let s:name = join(filter(['$2', '${1:4}', '$d'], '!empty(v:val)'), '/')
call add(g:$2, s:name)
call add(g:total_order, s:name)
EOF EOF
done done
cd - > /dev/null cd - > /dev/null
@ -30,12 +34,14 @@ EOF
make_dirs xxx/ xxx make_dirs xxx/ xxx
make_dirs xxx/after xxx make_dirs xxx/after xxx
mkdir xxx/doc mkdir -p xxx/doc
cat > xxx/doc/xxx.txt << DOC cat > xxx/doc/xxx.txt << DOC
hello *xxx* hello *xxx*
DOC DOC
make_dirs yyy/ yyy make_dirs yyy/ yyy
make_dirs yyy/after yyy
make_dirs z1/ z1 make_dirs z1/ z1
make_dirs z2/ z2 make_dirs z2/ z2

View File

@ -32,6 +32,12 @@ Execute (Initialize test environment):
endfunction endfunction
command! -nargs=+ -bang AssertExpect call AssertExpect('<bang>' == '!', <args>) command! -nargs=+ -bang AssertExpect call AssertExpect('<bang>' == '!', <args>)
function! EnsureLoaded()
if has('vim_starting')
runtime! plugin/**/*.vim
endif
endfunction
Execute (Print Ruby version): Execute (Print Ruby version):
redir => out redir => out
silent ruby puts RUBY_VERSION silent ruby puts RUBY_VERSION
@ -388,10 +394,7 @@ Given (Unaligned code):
aa=2 aa=2
Execute (Check installed plugins): Execute (Check installed plugins):
if has('vim_starting') call EnsureLoaded()
Log 'Vader is run from commandline'
runtime! plugin/**/*.vim
endif
Assert exists(':FNR'), 'FNR command should be found' Assert exists(':FNR'), 'FNR command should be found'
Assert !exists(':RedisExecute'), 'RedisExecute command still should not be found' Assert !exists(':RedisExecute'), 'RedisExecute command still should not be found'
@ -740,9 +743,9 @@ Execute (Immediate loading):
" Different result when Vader is run from commandline with `-c` option " Different result when Vader is run from commandline with `-c` option
Log g:xxx Log g:xxx
if has('vim_starting') if has('vim_starting')
AssertEqual ['/ftdetect', 'after/ftdetect'], g:xxx AssertEqual ['xxx/ftdetect', 'xxx/after/ftdetect'], g:xxx
else else
AssertEqual ['/plugin', 'after/plugin', '/ftdetect', 'after/ftdetect'], g:xxx AssertEqual ['xxx/plugin', 'xxx/after/plugin', 'xxx/ftdetect', 'xxx/after/ftdetect'], g:xxx
endif endif
Execute (Command-based on-demand loading): Execute (Command-based on-demand loading):
@ -753,20 +756,20 @@ Execute (Command-based on-demand loading):
AssertEqual [], g:xxx AssertEqual [], g:xxx
silent! XXX silent! XXX
AssertEqual ['/ftdetect', 'after/ftdetect', '/plugin', 'after/plugin'], g:xxx AssertEqual ['xxx/ftdetect', 'xxx/after/ftdetect', 'xxx/plugin', 'xxx/after/plugin'], g:xxx
setf xxx setf xxx
AssertEqual ['/ftdetect', 'after/ftdetect', '/plugin', 'after/plugin', '/ftplugin', 'after/ftplugin', '/indent', 'after/indent', '/syntax', 'after/syntax'], g:xxx AssertEqual ['xxx/ftdetect', 'xxx/after/ftdetect', 'xxx/plugin', 'xxx/after/plugin', 'xxx/ftplugin', 'xxx/after/ftplugin', 'xxx/indent', 'xxx/after/indent', 'xxx/syntax', 'xxx/after/syntax'], g:xxx
Execute (Filetype-based on-demand loading): Execute (Filetype-based on-demand loading):
call plug#begin() call plug#begin()
Plug '$PWD/xxx', { 'for': 'xxx' } Plug '$PWD/xxx', { 'for': 'xxx' }
call plug#end() call plug#end()
AssertEqual ['/ftdetect', 'after/ftdetect'], g:xxx AssertEqual ['xxx/ftdetect', 'xxx/after/ftdetect'], g:xxx
setf xxx setf xxx
AssertEqual ['/ftdetect', 'after/ftdetect', '/plugin', 'after/plugin', '/ftplugin', 'after/ftplugin', '/indent', 'after/indent', '/syntax', 'after/syntax'], g:xxx AssertEqual ['xxx/ftdetect', 'xxx/after/ftdetect', 'xxx/plugin', 'xxx/after/plugin', 'xxx/ftplugin', 'xxx/after/ftplugin', 'xxx/indent', 'xxx/after/indent', 'xxx/syntax', 'xxx/after/syntax'], g:xxx
Before: Before:
@ -937,21 +940,81 @@ Execute (Update plugins with U key in visual mode):
AssertExpect! '[==]', 1 AssertExpect! '[==]', 1
q q
**********************************************************************
Execute (plug#begin should expand env vars): Execute (plug#begin should expand env vars):
AssertNotEqual '$HOME/.emacs/plugged', expand('$HOME/.emacs/plugged') AssertNotEqual '$HOME/.emacs/plugged', expand('$HOME/.emacs/plugged')
call plug#begin('$HOME/.emacs/plugged') call plug#begin('$HOME/.emacs/plugged')
AssertEqual expand('$HOME/.emacs/plugged'), g:plug_home AssertEqual expand('$HOME/.emacs/plugged'), g:plug_home
**********************************************************************
Execute (Plug directory with comma):
call plug#begin(temp_plugged . '/p,l,u,g,g,e,d')
Plug 'junegunn/vim-emoji'
call plug#end()
Log &rtp
PlugInstall
q
let found = filter(split(globpath(&rtp, 'README.md'), '\n'), 'v:val =~ ","')
Log found
AssertEqual 1, len(found)
**********************************************************************
Execute (Strict load order):
let g:total_order = []
call plug#begin()
Plug '$PWD/xxx'
Plug '$PWD/yyy', { 'for': ['xxx'] }
call plug#end()
call EnsureLoaded()
setf xxx
Log 'Case 1: ' . &rtp
AssertEqual ['yyy/ftdetect', 'yyy/after/ftdetect', 'xxx/ftdetect', 'xxx/after/ftdetect'], g:total_order[0:3]
Assert index(g:total_order, 'xxx/plugin') < index(g:total_order, 'yyy/plugin')
Assert index(g:total_order, 'xxx/after/plugin') < index(g:total_order, 'yyy/after/plugin')
let len = len(split(&rtp, ','))
let g:total_order = []
call plug#begin()
Plug '$PWD/xxx', { 'for': ['xxx'] }
Plug '$PWD/yyy'
call plug#end()
call EnsureLoaded()
set rtp^=manually-prepended
set rtp+=manually-appended
setf xxx
Log 'Case 2: ' . &rtp
AssertEqual 'manually-prepended', split(&rtp, ',')[3]
AssertEqual 'manually-appended', split(&rtp, ',')[-4]
AssertEqual ['xxx/ftdetect', 'xxx/after/ftdetect', 'yyy/ftdetect', 'yyy/after/ftdetect'], g:total_order[0:3]
Assert index(g:total_order, 'yyy/plugin') < index(g:total_order, 'xxx/plugin')
Assert index(g:total_order, 'yyy/after/plugin') < index(g:total_order, 'xxx/after/plugin')
AssertEqual len + 2, len(split(&rtp, ','))
let g:total_order = []
call plug#begin()
Plug '$PWD/xxx', { 'for': ['xxx'] }
Plug '$PWD/yyy', { 'for': ['xxx'] }
call plug#end()
call EnsureLoaded()
setf xxx
Log 'Case 3: ' . &rtp
AssertEqual ['xxx/ftdetect', 'xxx/after/ftdetect', 'yyy/ftdetect', 'yyy/after/ftdetect'], g:total_order[0:3]
Assert index(g:total_order, 'xxx/plugin') < index(g:total_order, 'yyy/plugin')
Assert index(g:total_order, 'xxx/after/plugin') < index(g:total_order, 'yyy/after/plugin')
AssertEqual len + 2, len(split(&rtp, ','))
Execute (Cleanup): Execute (Cleanup):
silent! call system('rm -rf '.temp_plugged) silent! call system('rm -rf '.temp_plugged)
silent! call rename('fzf', 'fzf-staged') silent! call rename('fzf', 'fzf-staged')
silent! unlet g:plugs silent! unlet g:plugs
silent! unlet g:plug_home silent! unlet g:plug_home
silent! unlet g:plug_url_format silent! unlet g:plug_url_format
silent! unlet temp_plugged vader plug basertp save_rtp repo lnum fzf out tabnr silent! unlet temp_plugged vader plug basertp save_rtp repo lnum fzf out tabnr found len
silent! delf PlugStatusSorted silent! delf PlugStatusSorted
silent! delf AssertExpect silent! delf AssertExpect
silent! delf PlugUpdated silent! delf PlugUpdated
silent! delf EnsureLoaded
silent! delc AssertExpect silent! delc AssertExpect
silent! unmap / silent! unmap /
silent! unmap ? silent! unmap ?