42 Commits
0.5.7 ... 0.6.2

Author SHA1 Message Date
Junegunn Choi
3606c294de Merge pull request #135 from threeifbywhiskey/confirmation-convention
Downcase opt-in confirmation options
2014-12-08 23:58:05 +09:00
Dorien Snake
06f903d8af Downcase opt-in confirmation options
There's a fairly widespread convention which recommends indicating the default
confirmation option in uppercase. Granted, the number of applicable instances
in vim-plug is currently only two, but perhaps this'll save users with such an
inclination having to hit Enter just to sate their curiosities.
2014-12-08 08:49:45 -05:00
Junegunn Choi
1f704deb76 Merge branch 'master' of github.com:junegunn/vim-plug 2014-12-08 17:37:46 +09:00
Junegunn Choi
3ebf6361bf Update README 2014-12-08 17:37:26 +09:00
Junegunn Choi
9b99c1f885 Merge pull request #134 from wilywampa/master
Check for full match of command name
2014-12-08 10:02:09 +09:00
Jacob Niehus
53cc8a53d9 Check for full match of command name 2014-12-07 13:19:09 -07:00
Junegunn Choi
2ee153d610 Define s:triggers by default to avoid error after upgrade (#132) 2014-12-05 12:05:57 +09:00
Junegunn Choi
7019171737 Fix #131 - Syntax error 2014-12-04 15:13:37 +09:00
Junegunn Choi
044c3a67c4 Fix #130 - Proper cleanup of on-demand loading triggers 2014-12-04 13:06:13 +09:00
Junegunn Choi
48514768c2 Fix missing progress update (#127)
In the recent versions of NeoVim, jobstart() does not return
monotonically increasing numbers, this caused vim-plug to miss updating
the progress of a task when the job ID for the task is already
reassigned to a new task.
2014-12-02 02:48:25 +09:00
Junegunn Choi
68ad02c5c3 Display "Press 'D'" message only when existing plugins are updated
Fix #123
2014-11-24 03:32:01 +09:00
Junegunn Choi
12bc2ea1da Fix some test code 2014-11-21 01:06:17 +09:00
Junegunn Choi
ade7fb95b1 Fix failing test case 2014-11-08 11:33:11 +09:00
Junegunn Choi
9c55223869 Merge pull request #118 from splinterofchaos/job_data-list
Update: job_data[2] as a list.
2014-11-08 10:28:53 +09:00
Scott Prager
495becf442 Update: job_data[2] is a list. 2014-10-29 01:03:58 -04:00
Junegunn Choi
425ef39db2 Fix #114 - &rtp should not contain empty path 2014-10-22 13:36:57 +09:00
Junegunn Choi
bd2cb9d2de Install frozen plugin if it's not found (#113) 2014-10-22 13:05:10 +09:00
Junegunn Choi
0263370bd1 Fix #112: Do not suppress messages from ftplugin 2014-10-19 14:45:19 +09:00
Junegunn Choi
4b3fbd1592 Workaround for PlugUpgrade error on Neovim (#111) 2014-10-18 11:26:05 +09:00
Junegunn Choi
396a534a0a Update README
g:plug_timeout and g:plug_retries are only for Ruby installer
2014-10-10 23:18:40 +09:00
Junegunn Choi
a45c3834f8 Merge pull request #103 from junegunn/neuevim
Parallel installer for Neovim
2014-10-10 23:11:40 +09:00
Junegunn Choi
a5c3952380 Sort auto-completion candidates 2014-10-10 17:36:54 +09:00
Junegunn Choi
60bda7322f Improve ]]/[[ movement 2014-10-10 17:35:07 +09:00
Junegunn Choi
05008e7a82 Use s:extract_name instead of matchstr 2014-10-10 17:34:39 +09:00
Junegunn Choi
2889cb4739 Minor refactoring 2014-10-10 15:50:43 +09:00
Junegunn Choi
61b21068ee Update test case (related: #8c915a5) 2014-10-10 10:54:00 +09:00
Junegunn Choi
15da7eb78a Code cleanup 2014-10-10 10:39:49 +09:00
Junegunn Choi
385a1eb350 Detect abnormal process exit using 'Error' line 2014-10-10 10:28:15 +09:00
Junegunn Choi
8c915a5271 Reuse plug window even if it's in another tab 2014-10-10 10:23:00 +09:00
Junegunn Choi
ee9f0e55b8 Use s:lines instead of split 2014-10-10 10:10:52 +09:00
Junegunn Choi
018adb2aef Disable NVim parallel installer on Windows 2014-10-10 10:06:29 +09:00
Junegunn Choi
da47e6ee56 Avoid unnecessary tab/window switch 2014-10-10 04:39:38 +09:00
Junegunn Choi
662274e617 Stabilize Neovim installer
- Abort running jobs when plug windows is reset
- Multi-line error report
- Retain window view
2014-10-10 01:10:34 +09:00
Junegunn Choi
4eeff535fa Parallel installer for Neovim 2014-10-09 19:55:36 +09:00
Junegunn Choi
c3669836d3 Fix Travis CI build 2014-10-02 01:32:23 +09:00
Junegunn Choi
eb38fe3d32 Fix Travis CI build 2014-10-02 01:21:52 +09:00
Junegunn Choi
e7704e6cb3 PlugSnapshot to use unexpanded plug home
/cc @andreicristianpetcu

plug#begin expands its path argument and converts it to the absolute
path by default. However, it makes sense to use the unexpanded form in
case of PlugSnapshot as described in
https://github.com/junegunn/vim-plug/issues/97#issuecomment-57421483

For example, for the following cases,

- call plug#begin('~/.vim/plugged')
- call plug#begin('$HOME/.vim/plugged')

PlugSnapshot will use the exact arguments, `~/.vim/plugged` or
`$HOME/.vim/plugged`, instead of the absolute paths such as
`/home/jg/.vim/plugged`.
2014-10-01 23:14:27 +09:00
Junegunn Choi
e1e04cabd5 Minor refactoring
/cc @vheon
2014-10-01 11:37:58 +09:00
Junegunn Choi
afc20ecff3 Implement PlugSnapshot (#97)
Known issue: After running the script, PlugDiff will show "future"
commits.
2014-10-01 03:10:24 +09:00
Junegunn Choi
38510a8788 Remove unnecessary submodule command after recursive clone 2014-09-29 02:12:33 +09:00
Junegunn Choi
a34b06dd54 Fix Travis-CI build 2014-09-27 15:30:58 +09:00
Junegunn Choi
5d910fc9ea Allow unmanaged plugins inside g:plug_home (#95) 2014-09-27 14:41:57 +09:00
6 changed files with 623 additions and 210 deletions

View File

@@ -1,9 +1,9 @@
![vim-plug](https://raw.githubusercontent.com/junegunn/vim-plug/master/plug.png)
<img src="https://raw.githubusercontent.com/junegunn/vim-plug/master/plug.png" height="56" alt="vim-plug">
[![travis-ci](https://travis-ci.org/junegunn/vim-plug.svg?branch=master)](https://travis-ci.org/junegunn/vim-plug)
A minimalist Vim plugin manager.
![](https://raw.githubusercontent.com/junegunn/i/master/vim-plug/installer.gif)
<img src="https://raw.githubusercontent.com/junegunn/i/master/vim-plug/installer.gif" height="450">
### Pros.
@@ -11,7 +11,8 @@ A minimalist Vim plugin manager.
- Easier to use: Concise, intuitive syntax
- [Super-fast](https://raw.githubusercontent.com/junegunn/i/master/vim-plug/40-in-4.gif)
parallel installation/update (requires
[+ruby](https://github.com/junegunn/vim-plug/wiki/ruby))
[+ruby](https://github.com/junegunn/vim-plug/wiki/ruby) or
[Neovim](http://neovim.org/))
- On-demand loading to achieve
[fast startup time](http://junegunn.kr/images/vim-startup-time.png)
- Post-update hooks
@@ -69,28 +70,29 @@ Reload .vimrc and `:PlugInstall` to install plugins.
| `PlugUpgrade` | Upgrade vim-plug itself |
| `PlugStatus` | Check the status of plugins |
| `PlugDiff` | See the updated changes from the previous PlugUpdate |
| `PlugSnapshot [output path]` | Generate script for restoring the current snapshot of the plugins |
### `Plug` options
| Option | Description |
| -------------- | -------------------------------------------------------------------- |
| `branch`/`tag` | Branch or tag of the repository to use |
| `rtp` | Subdirectory that contains Vim plugin |
| `dir` | Custom directory for the plugin |
| `do` | Post-update hook (string or funcref) |
| `on` | On-demand loading: Commands or `<Plug>`-mappings |
| `for` | On-demand loading: File types |
| `frozen` | Do not install/update plugin unless explicitly given as the argument |
| Option | Description |
| -------------- | ------------------------------------------------ |
| `branch`/`tag` | Branch or tag of the repository to use |
| `rtp` | Subdirectory that contains Vim plugin |
| `dir` | Custom directory for the plugin |
| `do` | Post-update hook (string or funcref) |
| `on` | On-demand loading: Commands or `<Plug>`-mappings |
| `for` | On-demand loading: File types |
| `frozen` | Do not update unless explicitly specified |
### Global options
| Flag | Default | Description |
| ------------------- | --------------------------------- | ------------------------------------ |
| `g:plug_threads` | 16 | Default number of threads to use |
| `g:plug_timeout` | 60 | Time limit of each task in seconds |
| `g:plug_retries` | 2 | Number of retries in case of timeout |
| `g:plug_window` | `vertical topleft new` | Command to open plug window |
| `g:plug_url_format` | `https://git::@github.com/%s.git` | `printf` format to build repo URL |
| Flag | Default | Description |
| ------------------- | --------------------------------- | ----------------------------------------------------------- |
| `g:plug_threads` | 16 | Default number of threads to use |
| `g:plug_timeout` | 60 | Time limit of each task in seconds (*for Ruby installer*) |
| `g:plug_retries` | 2 | Number of retries in case of timeout (*for Ruby installer*) |
| `g:plug_window` | `vertical topleft new` | Command to open plug window |
| `g:plug_url_format` | `https://git::@github.com/%s.git` | `printf` format to build repo URL |
### Keybindings

558
plug.vim
View File

@@ -68,10 +68,12 @@ let g:loaded_plug = 1
let s:cpo_save = &cpo
set cpo&vim
let s:plug_source = 'https://raw.githubusercontent.com/junegunn/vim-plug/master/plug.vim'
let s:plug_src = 'https://raw.githubusercontent.com/junegunn/vim-plug/master/plug.vim'
let s:plug_tab = get(s:, 'plug_tab', -1)
let s:plug_buf = get(s:, 'plug_buf', -1)
let s:mac_gui = has('gui_macvim') && has('gui_running')
let s:is_win = has('win32') || has('win64')
let s:nvim = exists('##JobActivity') && !s:is_win
let s:me = resolve(expand('<sfile>:p'))
let s:base_spec = { 'branch': 'master', 'frozen': 0 }
let s:TYPE = {
@@ -81,9 +83,11 @@ let s:TYPE = {
\ 'funcref': type(function('call'))
\ }
let s:loaded = get(s:, 'loaded', {})
let s:triggers = get(s:, 'triggers', {})
function! plug#begin(...)
if a:0 > 0
let s:plug_home_org = a:1
let home = s:path(fnamemodify(expand(a:1), ':p'))
elseif exists('g:plug_home')
let home = s:path(g:plug_home)
@@ -95,8 +99,8 @@ function! plug#begin(...)
let g:plug_home = home
let g:plugs = {}
" we want to keep track of the order plugins where registered.
let g:plugs_order = []
let s:triggers = {}
call s:define_commands()
return 1
@@ -113,15 +117,20 @@ function! s:define_commands()
command! -nargs=0 -bar PlugUpgrade if s:upgrade() | execute 'source' s:me | endif
command! -nargs=0 -bar PlugStatus call s:status()
command! -nargs=0 -bar PlugDiff call s:diff()
command! -nargs=? -bar PlugSnapshot call s:snapshot(<f-args>)
endfunction
function! s:to_a(v)
return type(a:v) == s:TYPE.list ? a:v : [a:v]
endfunction
function! s:to_s(v)
return type(a:v) == s:TYPE.string ? a:v : join(a:v, "\n") . "\n"
endfunction
function! s:source(from, ...)
for pattern in a:000
for vim in split(globpath(a:from, pattern), '\n')
for vim in s:lines(globpath(a:from, pattern))
execute 'source' vim
endfor
endfor
@@ -149,6 +158,7 @@ function! plug#end()
endif
if has_key(plug, 'on')
let s:triggers[name] = { 'map': [], 'cmd': [] }
for cmd in s:to_a(plug.on)
if cmd =~ '^<Plug>.\+'
if empty(mapcheck(cmd)) && empty(mapcheck(cmd, 'i'))
@@ -159,10 +169,14 @@ function! plug#end()
\ mode, cmd, map_prefix, string(cmd), string(name), key_prefix)
endfor
endif
elseif !exists(':'.cmd)
execute printf(
\ 'command! -nargs=* -range -bang %s call s:lod_cmd(%s, "<bang>", <line1>, <line2>, <q-args>, %s)',
\ cmd, string(cmd), string(name))
call add(s:triggers[name].map, cmd)
elseif cmd =~ '^[A-Z]'
if exists(':'.cmd) != 2
execute printf(
\ 'command! -nargs=* -range -bang %s call s:lod_cmd(%s, "<bang>", <line1>, <line2>, <q-args>, %s)',
\ cmd, string(cmd), string(name))
endif
call add(s:triggers[name].cmd, cmd)
endif
endfor
endif
@@ -286,9 +300,10 @@ function! s:reorg_rtp()
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.',', '^,,$', ',', '')
let rtp = join(map(rtps, 's:escrtp(v:val)'), ',')
\ . ','.s:middle.','
\ . join(map(afters, 's:escrtp(v:val)'), ',')
let &rtp = substitute(substitute(rtp, ',,*', ',', 'g'), '^,\|,$', '', 'g')
let s:prtp = &rtp
if !empty(s:first_rtp)
@@ -312,12 +327,27 @@ function! plug#load(...)
for name in a:000
call s:lod([name], ['ftdetect', 'after/ftdetect', 'plugin', 'after/plugin'])
endfor
silent! doautocmd BufRead
doautocmd BufRead
return 1
endfunction
function! s:remove_triggers(name)
if !has_key(s:triggers, a:name)
return
endif
for cmd in s:triggers[a:name].cmd
execute 'delc' cmd
endfor
for map in s:triggers[a:name].map
execute 'unmap' map
execute 'iunmap' map
endfor
call remove(s:triggers, a:name)
endfunction
function! s:lod(names, types)
for name in a:names
call s:remove_triggers(name)
let s:loaded[name] = 1
endfor
call s:reorg_rtp()
@@ -333,19 +363,16 @@ endfunction
function! s:lod_ft(pat, names)
call s:lod(a:names, ['plugin', 'after/plugin'])
execute 'autocmd! PlugLOD FileType' a:pat
silent! doautocmd filetypeplugin FileType
silent! doautocmd filetypeindent FileType
doautocmd filetypeplugin FileType
doautocmd filetypeindent FileType
endfunction
function! s:lod_cmd(cmd, bang, l1, l2, args, name)
execute 'delc' a:cmd
call s:lod([a:name], ['ftdetect', 'after/ftdetect', 'plugin', 'after/plugin'])
execute printf('%s%s%s %s', (a:l1 == a:l2 ? '' : (a:l1.','.a:l2)), a:cmd, a:bang, a:args)
endfunction
function! s:lod_map(map, name, prefix)
execute 'unmap' a:map
execute 'iunmap' a:map
call s:lod([a:name], ['ftdetect', 'after/ftdetect', 'plugin', 'after/plugin'])
let extra = ''
while 1
@@ -481,25 +508,59 @@ function! s:lpad(str, len)
return a:str . repeat(' ', a:len - len(a:str))
endfunction
function! s:lines(msg)
return split(a:msg, "[\r\n]")
endfunction
function! s:lastline(msg)
let lines = split(a:msg, '\n')
return get(lines, -1, '')
return get(s:lines(a:msg), -1, '')
endfunction
function! s:new_window()
execute get(g:, 'plug_window', 'vertical topleft new')
endfunction
function! s:prepare()
if bufexists(s:plug_buf)
function! s:plug_window_exists()
let buflist = tabpagebuflist(s:plug_tab)
return !empty(buflist) && index(buflist, s:plug_buf) >= 0
endfunction
function! s:switch_in()
if !s:plug_window_exists()
return 0
endif
if winbufnr(0) != s:plug_buf
let s:pos = [tabpagenr(), winnr(), winsaveview()]
execute 'normal!' s:plug_tab.'gt'
let winnr = bufwinnr(s:plug_buf)
if winnr < 0
call s:new_window()
execute 'buffer' s:plug_buf
else
execute winnr . 'wincmd w'
endif
setlocal modifiable
execute winnr.'wincmd w'
call add(s:pos, winsaveview())
else
let s:pos = [winsaveview()]
endif
setlocal modifiable
return 1
endfunction
function! s:switch_out(...)
call winrestview(s:pos[-1])
setlocal nomodifiable
if a:0 > 0
execute a:1
endif
if len(s:pos) > 1
execute 'normal!' s:pos[0].'gt'
execute s:pos[1] 'wincmd w'
call winrestview(s:pos[2])
endif
endfunction
function! s:prepare()
call s:job_abort()
if s:switch_in()
silent %d _
else
call s:new_window()
@@ -512,6 +573,7 @@ function! s:prepare()
nnoremap <silent> <buffer> ]] :silent! call <SID>section('')<cr>
nnoremap <silent> <buffer> [[ :silent! call <SID>section('b')<cr>
let b:plug_preview = -1
let s:plug_tab = tabpagenr()
let s:plug_buf = winbufnr(0)
call s:assign_name()
endif
@@ -540,11 +602,11 @@ function! s:do(pull, force, todo)
if !isdirectory(spec.dir)
continue
endif
execute 'cd' s:esc(spec.dir)
let installed = has_key(s:prev_update.new, name)
let installed = has_key(s:update.new, name)
let updated = installed ? 0 :
\ (a:pull && !empty(s:system_chomp('git log --pretty=format:"%h" "HEAD...HEAD@{1}"')))
\ (a:pull && !empty(s:system_chomp('git log --pretty=format:"%h" "HEAD...HEAD@{1}"', spec.dir)))
if a:force || installed || updated
execute 'cd' s:esc(spec.dir)
call append(3, '- Post-update hook for '. name .' ... ')
let type = type(spec.do)
if type == s:TYPE.string
@@ -569,25 +631,28 @@ function! s:do(pull, force, todo)
let result = 'Error: Invalid type!'
endif
call setline(4, getline(4) . result)
cd -
endif
cd -
endfor
endfunction
function! s:finish(pull)
let new_frozen = len(filter(keys(s:update.new), 'g:plugs[v:val].frozen'))
if new_frozen
let s = new_frozen > 1 ? 's' : ''
call append(3, printf('- Installed %d frozen plugin%s', new_frozen, s))
endif
call append(3, '- Finishing ... ')
redraw
call plug#helptags()
call plug#end()
call setline(4, getline(4) . 'Done!')
normal! gg
call s:syntax()
redraw
let msgs = []
if !empty(s:prev_update.errors)
if !empty(s:update.errors)
call add(msgs, "Press 'R' to retry.")
endif
if a:pull && !empty(filter(getline(5, '$'),
if a:pull && len(s:update.new) < len(filter(getline(5, '$'),
\ "v:val =~ '^- ' && stridx(v:val, 'Already up-to-date') < 0"))
call add(msgs, "Press 'D' to see the updated changes.")
endif
@@ -595,11 +660,11 @@ function! s:finish(pull)
endfunction
function! s:retry()
if empty(s:prev_update.errors)
if empty(s:update.errors)
return
endif
call s:update_impl(s:prev_update.pull, s:prev_update.force,
\ extend(copy(s:prev_update.errors), [s:prev_update.threads]))
call s:update_impl(s:update.pull, s:update.force,
\ extend(copy(s:update.errors), [s:update.threads]))
endfunction
function! s:is_managed(name)
@@ -607,17 +672,16 @@ function! s:is_managed(name)
endfunction
function! s:names(...)
return filter(keys(g:plugs), 'stridx(v:val, a:1) == 0 && s:is_managed(v:val)')
return sort(filter(keys(g:plugs), 'stridx(v:val, a:1) == 0 && s:is_managed(v:val)'))
endfunction
function! s:update_impl(pull, force, args) abort
let st = reltime()
let args = copy(a:args)
let threads = (len(args) > 0 && args[-1] =~ '^[1-9][0-9]*$') ?
\ remove(args, -1) : get(g:, 'plug_threads', 16)
let managed = filter(copy(g:plugs), 's:is_managed(v:key)')
let todo = empty(args) ? filter(managed, '!v:val.frozen') :
let todo = empty(args) ? filter(managed, '!v:val.frozen || !isdirectory(v:val.dir)') :
\ filter(managed, 'index(args, v:key) >= 0')
if empty(todo)
@@ -631,103 +695,251 @@ function! s:update_impl(pull, force, args) abort
try
call mkdir(g:plug_home, 'p')
catch
return s:err(printf('Invalid plug directory: %s.'
\ 'Try to call plug#begin with a valid directory', g:plug_home))
return s:err(printf('Invalid plug directory: %s. '.
\ 'Try to call plug#begin with a valid directory', g:plug_home))
endtry
endif
call s:prepare()
call append(0, a:pull ? 'Updating plugins' : 'Installing plugins')
call append(1, '['. s:lpad('', len(todo)) .']')
normal! 2G
redraw
let s:update = {
\ 'start': reltime(),
\ 'all': todo,
\ 'todo': copy(todo),
\ 'errors': [],
\ 'pull': a:pull,
\ 'force': a:force,
\ 'new': {},
\ 'threads': (has('ruby') || s:nvim) ? min([len(todo), threads]) : 1,
\ 'bar': '',
\ 'fin': 0
\ }
let s:prev_update = { 'errors': [], 'pull': a:pull, 'force': a:force, 'new': {}, 'threads': threads }
if has('ruby') && threads > 1
call s:prepare()
call append(0, ['', ''])
normal! 2G
if has('ruby') && s:update.threads > 1
try
let imd = &imd
if s:mac_gui
set noimd
endif
call s:update_parallel(a:pull, todo, threads)
call s:update_ruby()
catch
let lines = getline(4, '$')
let printed = {}
silent 4,$d _
for line in lines
let name = matchstr(line, '^. \zs[^:]\+\ze:')
let name = s:extract_name(line, '.', '')
if empty(name) || !has_key(printed, name)
call append('$', line)
if !empty(name)
let printed[name] = 1
if line[0] == 'x' && index(s:prev_update.errors, name) < 0
call add(s:prev_update.errors, name)
if line[0] == 'x' && index(s:update.errors, name) < 0
call add(s:update.errors, name)
end
endif
endif
endfor
finally
let &imd = imd
call s:update_finish()
endtry
else
call s:update_serial(a:pull, todo)
call s:update_vim()
endif
call s:do(a:pull, a:force, filter(copy(todo), 'has_key(v:val, "do")'))
call s:finish(a:pull)
call setline(1, 'Updated. Elapsed time: ' . split(reltimestr(reltime(st)))[0] . ' sec.')
endfunction
function! s:update_progress(pull, cnt, bar, total)
call setline(1, (a:pull ? 'Updating' : 'Installing').
\ ' plugins ('.a:cnt.'/'.a:total.')')
call s:progress_bar(2, a:bar, a:total)
normal! 2G
redraw
function! s:update_finish()
if s:switch_in()
call s:do(s:update.pull, s:update.force, filter(copy(s:update.all), 'has_key(v:val, "do")'))
call s:finish(s:update.pull)
call setline(1, 'Updated. Elapsed time: ' . split(reltimestr(reltime(s:update.start)))[0] . ' sec.')
call s:switch_out('normal! gg')
endif
endfunction
function! s:update_serial(pull, todo)
let base = g:plug_home
let todo = copy(a:todo)
let total = len(todo)
let done = {}
let bar = ''
for [name, spec] in items(todo)
let done[name] = 1
if isdirectory(spec.dir)
execute 'cd' s:esc(spec.dir)
let [valid, msg] = s:git_valid(spec, 0, 0)
if valid
let result = a:pull ?
\ s:system(
\ printf('git checkout -q %s 2>&1 && git pull --no-rebase origin %s 2>&1 && git submodule update --init --recursive 2>&1',
\ s:shellesc(spec.branch), s:shellesc(spec.branch))) : 'Already installed'
let error = a:pull ? v:shell_error != 0 : 0
else
let result = msg
let error = 1
endif
cd -
else
let result = s:system(
\ printf('git clone --recursive %s -b %s %s 2>&1 && cd %s && git submodule update --init --recursive 2>&1',
\ s:shellesc(spec.uri),
\ s:shellesc(spec.branch),
\ s:shellesc(s:trim(spec.dir)),
\ s:shellesc(spec.dir)))
let error = v:shell_error != 0
if !error | let s:prev_update.new[name] = 1 | endif
function! s:job_abort()
if !s:nvim || !exists('s:jobs')
return
endif
augroup PlugJobControl
autocmd!
augroup END
for [name, j] in items(s:jobs)
silent! call jobstop(j.jobid)
if j.new
call system('rm -rf ' . s:shellesc(g:plugs[name].dir))
endif
let bar .= error ? 'x' : '='
if error
call add(s:prev_update.errors, name)
endif
call append(3, s:format_message(!error, name, result))
call s:update_progress(a:pull, len(done), bar, total)
endfor
let s:jobs = {}
endfunction
function! s:update_parallel(pull, todo, threads)
function! s:job_handler(name) abort
if !s:plug_window_exists() " plug window closed
return s:job_abort()
endif
if !has_key(s:jobs, a:name)
return
endif
let job = s:jobs[a:name]
if v:job_data[1] == 'exit'
let job.running = 0
if s:lastline(job.result) ==# 'Error'
let job.error = 1
let job.result = substitute(job.result, "Error[\r\n]$", '', '')
endif
call s:reap(a:name)
call s:tick()
else
let job.result .= s:to_s(v:job_data[2])
" To reduce the number of buffer updates
let job.tick = get(job, 'tick', -1) + 1
if job.tick % len(s:jobs) == 0
call s:log(job.new ? '+' : '*', a:name, job.result)
endif
endif
endfunction
function! s:spawn(name, cmd, opts)
let job = { 'running': 1, 'new': get(a:opts, 'new', 0),
\ 'error': 0, 'result': '' }
let s:jobs[a:name] = job
if s:nvim
let x = jobstart(a:name, 'sh', ['-c',
\ (has_key(a:opts, 'dir') ? s:with_cd(a:cmd, a:opts.dir) : a:cmd)
\ . ' || echo Error'])
if x > 0
let job.jobid = x
augroup PlugJobControl
execute 'autocmd JobActivity' a:name printf('call s:job_handler(%s)', string(a:name))
augroup END
else
let job.running = 0
let job.error = 1
let job.result = x < 0 ? 'sh is not executable' :
\ 'Invalid arguments (or job table is full)'
endif
else
let params = has_key(a:opts, 'dir') ? [a:cmd, a:opts.dir] : [a:cmd]
let job.result = call('s:system', params)
let job.error = v:shell_error != 0
let job.running = 0
endif
endfunction
function! s:reap(name)
if s:nvim
silent! execute 'autocmd! PlugJobControl JobActivity' a:name
endif
let job = s:jobs[a:name]
if job.error
call add(s:update.errors, a:name)
elseif get(job, 'new', 0)
let s:update.new[a:name] = 1
endif
let s:update.bar .= job.error ? 'x' : '='
call s:log(job.error ? 'x' : '-', a:name, job.result)
call s:bar()
call remove(s:jobs, a:name)
endfunction
function! s:bar()
if s:switch_in()
let total = len(s:update.all)
call setline(1, (s:update.pull ? 'Updating' : 'Installing').
\ ' plugins ('.len(s:update.bar).'/'.total.')')
call s:progress_bar(2, s:update.bar, total)
call s:switch_out()
endif
endfunction
function! s:logpos(name)
for i in range(1, line('$'))
if getline(i) =~# '^[-+x*] '.a:name.':'
return i
endif
endfor
return 0
endfunction
function! s:log(bullet, name, lines)
if s:switch_in()
let pos = s:logpos(a:name)
if pos > 0
execute pos 'd _'
if pos > winheight('.')
let pos = 4
endif
else
let pos = 4
endif
call append(pos - 1, s:format_message(a:bullet, a:name, a:lines))
call s:switch_out()
endif
endfunction
function! s:update_vim()
let s:jobs = {}
call s:bar()
call s:tick()
endfunction
function! s:tick()
while 1 " Without TCO, Vim stack is bound to explode
if empty(s:update.todo)
if empty(s:jobs) && !s:update.fin
let s:update.fin = 1
call s:update_finish()
endif
return
endif
let name = keys(s:update.todo)[0]
let spec = remove(s:update.todo, name)
let pull = s:update.pull
let new = !isdirectory(spec.dir)
call s:log(new ? '+' : '*', name, pull ? 'Updating ...' : 'Installing ...')
redraw
if !new
let [valid, msg] = s:git_valid(spec, 0)
if valid
if pull
call s:spawn(name,
\ printf('git checkout -q %s 2>&1 && git pull --progress --no-rebase origin %s 2>&1 && git submodule update --init --recursive 2>&1',
\ s:shellesc(spec.branch), s:shellesc(spec.branch)), { 'dir': spec.dir })
else
let s:jobs[name] = { 'running': 0, 'result': 'Already installed', 'error': 0 }
endif
else
let s:jobs[name] = { 'running': 0, 'result': msg, 'error': 1 }
endif
else
call s:spawn(name,
\ printf('git clone --progress --recursive %s -b %s %s 2>&1',
\ s:shellesc(spec.uri),
\ s:shellesc(spec.branch),
\ s:shellesc(s:trim(spec.dir))), { 'new': 1 })
endif
if !s:jobs[name].running
call s:reap(name)
endif
if len(s:jobs) >= s:update.threads
break
endif
endwhile
endfunction
function! s:update_ruby()
ruby << EOF
module PlugStream
SEP = ["\r", "\n", nil]
@@ -769,15 +981,15 @@ function! s:update_parallel(pull, todo, threads)
require 'timeout'
running = true
iswin = VIM::evaluate('s:is_win').to_i == 1
pull = VIM::evaluate('a:pull').to_i == 1
pull = VIM::evaluate('s:update.pull').to_i == 1
base = VIM::evaluate('g:plug_home')
all = VIM::evaluate('a:todo')
all = VIM::evaluate('s:update.todo')
limit = VIM::evaluate('get(g:, "plug_timeout", 60)')
tries = VIM::evaluate('get(g:, "plug_retries", 2)') + 1
nthr = VIM::evaluate('a:threads').to_i
nthr = VIM::evaluate('s:update.threads').to_i
maxy = VIM::evaluate('winheight(".")').to_i
cd = iswin ? 'cd /d' : 'cd'
tot = VIM::evaluate('len(a:todo)') || 0
tot = VIM::evaluate('len(s:update.todo)') || 0
bar = ''
skip = 'Already installed'
mtx = Mutex.new
@@ -797,7 +1009,7 @@ function! s:update_parallel(pull, todo, threads)
b = case type
when :install then '+' when :update then '*'
when true, nil then '-' else
VIM::command("call add(s:prev_update.errors, '#{name}')")
VIM::command("call add(s:update.errors, '#{name}')")
'x'
end
result =
@@ -886,7 +1098,7 @@ function! s:update_parallel(pull, todo, threads)
} if VIM::evaluate('s:mac_gui') == 1
progress = iswin ? '' : '--progress'
[all.length, nthr].min.times do
nthr.times do
mtx.synchronize do
threads << Thread.new {
while pair = take1.call
@@ -921,11 +1133,11 @@ function! s:update_parallel(pull, todo, threads)
else
d = esc dir.sub(%r{[\\/]+$}, '')
log.call name, 'Installing ...', :install
bt.call "(git clone #{progress} --recursive #{uri} -b #{branch} #{d} 2>&1 && cd #{esc dir} && #{subm})", name, :install, proc {
bt.call "git clone #{progress} --recursive #{uri} -b #{branch} #{d} 2>&1", name, :install, proc {
FileUtils.rm_rf dir
}
end
mtx.synchronize { VIM::command("let s:prev_update.new['#{name}'] = 1") } if !exists && ok
mtx.synchronize { VIM::command("let s:update.new['#{name}'] = 1") } if !exists && ok
log.call name, result, ok
end
} if running
@@ -943,7 +1155,7 @@ function! s:shellesc(arg)
endfunction
function! s:glob_dir(path)
return map(filter(split(globpath(a:path, '**'), '\n'), 'isdirectory(v:val)'), 's:dirpath(v:val)')
return map(filter(s:lines(globpath(a:path, '**')), 'isdirectory(v:val)'), 's:dirpath(v:val)')
endfunction
function! s:progress_bar(line, bar, total)
@@ -956,30 +1168,34 @@ function! s:compare_git_uri(a, b)
return a ==# b
endfunction
function! s:format_message(ok, name, message)
if a:ok
return [printf('- %s: %s', a:name, s:lastline(a:message))]
function! s:format_message(bullet, name, message)
if a:bullet != 'x'
return [printf('%s %s: %s', a:bullet, a:name, s:lastline(a:message))]
else
let lines = map(split(a:message, '\n'), '" ".v:val')
let lines = map(s:lines(a:message), '" ".v:val')
return extend([printf('x %s:', a:name)], lines)
endif
endfunction
function! s:system(cmd)
return system(s:is_win ? '('.a:cmd.')' : a:cmd)
function! s:with_cd(cmd, dir)
return 'cd '.s:esc(a:dir).' && '.a:cmd
endfunction
function! s:system_chomp(str)
let ret = s:system(a:str)
function! s:system(cmd, ...)
let cmd = a:0 > 0 ? s:with_cd(a:cmd, a:1) : a:cmd
return system(s:is_win ? '('.cmd.')' : cmd)
endfunction
function! s:system_chomp(...)
let ret = call('s:system', a:000)
return v:shell_error ? '' : substitute(ret, '\n$', '', '')
endfunction
function! s:git_valid(spec, check_branch, cd)
function! s:git_valid(spec, check_branch)
let ret = 1
let msg = 'OK'
if isdirectory(a:spec.dir)
if a:cd | execute 'cd' s:esc(a:spec.dir) | endif
let result = split(s:system('git rev-parse --abbrev-ref HEAD 2>&1 && git config remote.origin.url'), '\n')
let result = s:lines(s:system('git rev-parse --abbrev-ref HEAD 2>&1 && git config remote.origin.url', a:spec.dir))
let remote = result[-1]
if v:shell_error
let msg = join([remote, 'PlugClean required.'], "\n")
@@ -992,7 +1208,7 @@ function! s:git_valid(spec, check_branch, cd)
elseif a:check_branch
let branch = result[0]
if a:spec.branch !=# branch
let tag = s:system_chomp('git describe --exact-match --tags HEAD 2>&1')
let tag = s:system_chomp('git describe --exact-match --tags HEAD 2>&1', a:spec.dir)
if a:spec.branch !=# tag
let msg = printf('Invalid branch/tag: %s (expected: %s). Try PlugUpdate.',
\ (empty(tag) ? branch : tag), a:spec.branch)
@@ -1000,7 +1216,6 @@ function! s:git_valid(spec, check_branch, cd)
endif
endif
endif
if a:cd | cd - | endif
else
let msg = 'Not found'
let ret = 0
@@ -1015,10 +1230,9 @@ function! s:clean(force)
" List of valid directories
let dirs = []
let managed = filter(copy(g:plugs), 's:is_managed(v:key)')
let [cnt, total] = [0, len(managed)]
for spec in values(managed)
if s:git_valid(spec, 0, 1)[0]
let [cnt, total] = [0, len(g:plugs)]
for [name, spec] in items(g:plugs)
if !s:is_managed(name) || s:git_valid(spec, 0)[0]
call add(dirs, spec.dir)
endif
let cnt += 1
@@ -1052,7 +1266,7 @@ function! s:clean(force)
call append(line('$'), 'Already clean.')
else
call inputsave()
let yes = a:force || (input('Proceed? (Y/N) ') =~? '^y')
let yes = a:force || (input('Proceed? (y/N) ') =~? '^y')
call inputrestore()
if yes
for dir in todo
@@ -1070,21 +1284,16 @@ endfunction
function! s:upgrade()
let new = s:me . '.new'
echo 'Downloading '. s:plug_source
echo 'Downloading '. s:plug_src
redraw
try
if executable('curl')
let output = system(printf('curl -fLo %s %s', s:shellesc(new), s:plug_source))
let output = system(printf('curl -fLo %s %s', s:shellesc(new), s:plug_src))
if v:shell_error
throw get(split(output, '\n'), -1, v:shell_error)
throw get(s:lines(output), -1, v:shell_error)
endif
elseif has('ruby')
ruby << EOF
require 'open-uri'
File.open(VIM::evaluate('new'), 'w') do |f|
f << open(VIM::evaluate('s:plug_source')).read
end
EOF
call s:upgrade_using_ruby(new)
else
return s:err('curl executable or ruby support not found')
endif
@@ -1105,6 +1314,15 @@ EOF
endif
endfunction
function! s:upgrade_using_ruby(new)
ruby << EOF
require 'open-uri'
File.open(VIM::evaluate('a:new'), 'w') do |f|
f << open(VIM::evaluate('s:plug_src')).read
end
EOF
endfunction
function! s:upgrade_specs()
for spec in values(g:plugs)
let spec.frozen = get(spec, 'frozen', 0)
@@ -1122,7 +1340,7 @@ function! s:status()
for [name, spec] in items(g:plugs)
if has_key(spec, 'uri')
if isdirectory(spec.dir)
let [valid, msg] = s:git_valid(spec, 1, 1)
let [valid, msg] = s:git_valid(spec, 1)
else
let [valid, msg] = [0, 'Not found. Try PlugInstall.']
endif
@@ -1141,7 +1359,7 @@ function! s:status()
let msg .= ' (not loaded)'
endif
call s:progress_bar(2, repeat('=', cnt), total)
call append(3, s:format_message(valid, name, msg))
call append(3, s:format_message(valid ? '-' : 'x', name, msg))
normal! 2G
redraw
endfor
@@ -1194,7 +1412,7 @@ function! s:find_name(lnum)
if empty(line)
return ''
endif
let name = matchstr(line, '\(^- \)\@<=[^:]\+')
let name = s:extract_name(line, '-', '')
if !empty(name)
return name
endif
@@ -1220,15 +1438,13 @@ function! s:preview_commit()
execute 'pedit' sha
wincmd P
setlocal filetype=git buftype=nofile nobuflisted
execute 'cd' s:esc(g:plugs[name].dir)
execute 'silent read !git show' sha
cd -
execute 'silent read !cd' s:esc(g:plugs[name].dir) '&& git show' sha
normal! gg"_dd
wincmd p
endfunction
function! s:section(flags)
call search('\(^- \)\@<=.', a:flags)
call search('\(^[x-] \)\@<=[^:]\+:', a:flags)
endfunction
function! s:diff()
@@ -1243,17 +1459,15 @@ function! s:diff()
continue
endif
execute 'cd' s:esc(v.dir)
let diff = system('git log --pretty=format:"%h %s (%cr)" "HEAD...HEAD@{1}"')
if !v:shell_error && !empty(diff)
let diff = s:system_chomp('git log --pretty=format:"%h %s (%cr)" "HEAD...HEAD@{1}"', v.dir)
if !empty(diff)
call append(1, '')
call append(2, '- '.k.':')
call append(3, map(split(diff, '\n'), '" ". v:val'))
call append(3, map(s:lines(diff), '" ". v:val'))
let cnt += 1
normal! gg
redraw
endif
cd -
endfor
call setline(1, cnt == 0 ? 'No updates.' : 'Last update:')
@@ -1269,19 +1483,55 @@ endfunction
function! s:revert()
let name = s:find_name(line('.'))
if empty(name) || !has_key(g:plugs, name) ||
\ input(printf('Revert the update of %s? (Y/N) ', name)) !~? '^y'
\ input(printf('Revert the update of %s? (y/N) ', name)) !~? '^y'
return
endif
execute 'cd' s:esc(g:plugs[name].dir)
call system('git reset --hard HEAD@{1} && git checkout '.s:esc(g:plugs[name].branch))
cd -
call s:system('git reset --hard HEAD@{1} && git checkout '.s:esc(g:plugs[name].branch), g:plugs[name].dir)
setlocal modifiable
normal! "_dap
setlocal nomodifiable
echo 'Reverted.'
endfunction
function! s:snapshot(...) abort
let home = get(s:, 'plug_home_org', g:plug_home)
let [type, var, header] = s:is_win ?
\ ['dosbatch', '%PLUG_HOME%',
\ ['@echo off', ':: Generated by vim-plug', ':: '.strftime("%c"), '',
\ ':: Make sure to PlugUpdate first', '', 'set PLUG_HOME='.s:esc(home)]] :
\ ['sh', '$PLUG_HOME',
\ ['#!/bin/bash', '# Generated by vim-plug', '# '.strftime("%c"), '',
\ 'vim +PlugUpdate +qa', '', 'PLUG_HOME='.s:esc(home)]]
call s:prepare()
execute 'setf' type
call append(0, header)
call append('$', '')
1
redraw
let dirs = sort(map(values(filter(copy(g:plugs),
\'has_key(v:val, "uri") && isdirectory(v:val.dir)')), 'v:val.dir'))
let anchor = line('$') - 1
for dir in reverse(dirs)
let sha = s:system_chomp('git rev-parse --short HEAD', dir)
if !empty(sha)
call append(anchor, printf('cd %s && git reset --hard %s',
\ substitute(dir, '^'.g:plug_home, var, ''), sha))
redraw
endif
endfor
if a:0 > 0
let fn = s:esc(expand(a:1))
call writefile(getline(1, '$'), fn)
if !s:is_win | call system('chmod +x ' . fn) | endif
echo 'Saved to '.a:1
silent execute 'e' fn
endif
endfunction
function! s:split_rtp()
return split(&rtp, '\\\@<!,')
endfunction

5
test/fixtures/.gitignore vendored Normal file
View File

@@ -0,0 +1,5 @@
fzf*
xxx
yyy
z1
z2

View File

@@ -0,0 +1 @@
echomsg 'ftplugin'

View File

@@ -5,18 +5,20 @@ cd ..
PLUG_SRC=$(pwd)/plug.vim
cd - > /dev/null
export PLUG_FIXTURES=$(pwd)/fixtures
if [ ! -d vader.vim ]; then
git clone https://github.com/junegunn/vader.vim.git
fi
rm -rf fzf
rm -rf $PLUG_FIXTURES/fzf
if [ ! -d fzf-staged ]; then
git clone https://github.com/junegunn/fzf.git fzf-staged
git clone https://github.com/junegunn/fzf.git $PLUG_FIXTURES/fzf-staged
fi
make_dirs() {
mkdir -p "$1"
cd "$1"
mkdir -p "$PLUG_FIXTURES/$1"
cd "$PLUG_FIXTURES/$1"
mkdir -p autoload colors ftdetect ftplugin indent plugin syntax
for d in *; do
[ -d $d ] || continue
@@ -32,18 +34,22 @@ EOF
cd - > /dev/null
}
make_dirs xxx/ xxx
make_dirs xxx/after xxx
mkdir -p xxx/doc
cat > xxx/doc/xxx.txt << DOC
init() {
rm -rf $PLUG_FIXTURES/{xxx,yyy,z1,z2}
make_dirs xxx/ xxx
make_dirs xxx/after xxx
mkdir -p $PLUG_FIXTURES/xxx/doc
cat > $PLUG_FIXTURES/xxx/doc/xxx.txt << DOC
hello *xxx*
DOC
make_dirs yyy/ yyy
make_dirs yyy/after yyy
make_dirs yyy/ yyy
make_dirs yyy/after yyy
make_dirs z1/ z1
make_dirs z2/ z2
make_dirs z1/ z1
make_dirs z2/ z2
}
cat > /tmp/mini-vimrc << VIMRC
set rtp+=vader.vim
@@ -51,8 +57,11 @@ set shell=/bin/bash
source $PLUG_SRC
VIMRC
[ -z "$TMPDIR" ] && export TMPDIR=/tmp/
init
if [ "$1" = '!' ]; then
/usr/local/bin/vim -Nu /tmp/mini-vimrc -c 'Vader! workflow.vader' > /dev/null &&
init &&
/usr/local/bin/vim -Nu /tmp/mini-vimrc -c 'let g:plug_threads = 1 | Vader! workflow.vader' > /dev/null
else
/usr/local/bin/vim -Nu /tmp/mini-vimrc -c 'Vader workflow.vader'

View File

@@ -304,7 +304,8 @@ Execute (Rollback recent updates, PlugUpdate, then PlugDiff):
" ]] motion
execute 'normal $]]'
AssertEqual lnum + 4, line('.')
Assert index([lnum + 4, lnum + 5], line('.')) >= 0
" +5 for merge commit
AssertEqual 3, col('.')
" [[ motion
@@ -337,7 +338,8 @@ Execute (Rollback recent updates, PlugUpdate, then PlugDiff):
AssertEqual 1, &previewwindow
pclose
Execute (Plug window in a new tab):
Execute (Reuse Plug window in another tab):
let tabnr = tabpagenr()
PlugDiff
tab new new-tab
set buftype=nofile
@@ -345,8 +347,8 @@ Execute (Plug window in a new tab):
normal D
AssertExpect '^- ', 1
normal q
AssertEqual 'new-tab', expand('%')
q
AssertEqual tabnr, tabpagenr()
normal! gt
q
**********************************************************************
@@ -420,7 +422,7 @@ Execute (On-demand loading based on filetypes):
**********************************************************************
Execute (Add unmanaged plugin):
let fzf = fnamemodify(g:vader_file, ':h') . '/fzf'
let fzf = expand('$PLUG_FIXTURES/fzf')
Log fzf
call plug#begin()
@@ -450,6 +452,7 @@ Execute (Plug block for following tests):
call plug#end()
" Remove plugins from previous tests
PlugClean!
q
Execute (PlugInstall will only install vim-easy-align):
PlugInstall
@@ -478,7 +481,7 @@ Execute (PlugStatus should point out that the plugin is missing):
Execute (Deploy unmanaged plugin):
Assert !exists(':FZF'), ':FZF command should not exist'
call rename('fzf-staged', 'fzf')
call rename(expand('$PLUG_FIXTURES/fzf-staged'), fzf)
Execute (PlugUpdate still should not care):
PlugUpdate
@@ -516,12 +519,37 @@ Execute (Common parent):
**********************************************************************
~ Frozen plugins
**********************************************************************
- We've decided to install plugins that are frozen: see #113
Execute (Frozen plugin are not ~~installed nor~~ updated):
" Remove plugins
call plug#begin()
call plug#end()
PlugClean!
q
Execute (Frozen plugin are not installed nor updated):
" vim-easy-align is not found, so it will be installed even though it's frozen
call plug#begin()
Plug 'junegunn/vim-easy-align', { 'frozen': 1 }
call plug#end()
PlugInstall
AssertEqual 1, len(filter(getline(1, '$'), 'v:val =~ "vim-easy-align"'))
q
" Remove plugins again
call plug#begin()
call plug#end()
PlugClean!
q
" PlugUpdate will do the same
call plug#begin()
Plug 'junegunn/vim-easy-align', { 'frozen': 1 }
call plug#end()
PlugInstall
AssertEqual 1, len(filter(getline(1, '$'), 'v:val =~ "vim-easy-align"'))
q
" Since vim-easy-align already exists, PlugInstall or PlugUpdate will skip it
redir => out
silent PlugInstall
redir END
@@ -593,6 +621,7 @@ Execute (Cleanup):
call plug#begin()
call plug#end()
PlugClean!
q
Execute (On install):
call plug#begin()
@@ -731,12 +760,12 @@ Execute (Using custom dir):
**********************************************************************
Before (Clear global vars):
let g:xxx = []
set rtp-=$PWD/xxx/
set rtp-=$PWD/xxx/after
set rtp-=$PLUG_FIXTURES/xxx/
set rtp-=$PLUG_FIXTURES/xxx/after
Execute (Immediate loading):
call plug#begin()
Plug '$PWD/xxx'
Plug '$PLUG_FIXTURES/xxx'
call plug#end()
" FIXME:
@@ -750,7 +779,7 @@ Execute (Immediate loading):
Execute (Command-based on-demand loading):
call plug#begin()
Plug '$PWD/xxx', { 'on': 'XXX' }
Plug '$PLUG_FIXTURES/xxx', { 'on': 'XXX' }
call plug#end()
AssertEqual [], g:xxx
@@ -763,7 +792,7 @@ Execute (Command-based on-demand loading):
Execute (Filetype-based on-demand loading):
call plug#begin()
Plug '$PWD/xxx', { 'for': 'xxx' }
Plug '$PLUG_FIXTURES/xxx', { 'for': 'xxx' }
call plug#end()
AssertEqual ['xxx/ftdetect', 'xxx/after/ftdetect'], g:xxx
@@ -778,10 +807,10 @@ Before:
**********************************************************************
Execute (plug#helptags):
silent! call delete(expand('$PWD/xxx/doc/tags'))
Assert !filereadable(expand('$PWD/xxx/doc/tags'))
silent! call delete(expand('$PLUG_FIXTURES/xxx/doc/tags'))
Assert !filereadable(expand('$PLUG_FIXTURES/xxx/doc/tags'))
AssertEqual 1, plug#helptags()
Assert filereadable(expand('$PWD/xxx/doc/tags'))
Assert filereadable(expand('$PLUG_FIXTURES/xxx/doc/tags'))
**********************************************************************
~ Manual loading
@@ -822,7 +851,7 @@ Execute (PlugStatus should not contain (not loaded)):
Execute (Load plugin from PlugStatus screen with L key in normal mode):
call plug#begin()
Plug '$PWD/yyy', { 'on': [] }
Plug '$PLUG_FIXTURES/yyy', { 'on': [] }
call plug#end()
PlugStatus
@@ -836,8 +865,8 @@ Execute (Load plugin from PlugStatus screen with L key in normal mode):
Execute (Load plugin from PlugStatus screen with L key in visual mode):
call plug#begin()
Plug '$PWD/z1', { 'on': [] }
Plug '$PWD/z2', { 'for': [] }
Plug '$PLUG_FIXTURES/z1', { 'on': [] }
Plug '$PLUG_FIXTURES/z2', { 'for': [] }
call plug#end()
PlugStatus
@@ -963,8 +992,8 @@ Execute (Plug directory with comma):
Execute (Strict load order):
let g:total_order = []
call plug#begin()
Plug '$PWD/xxx'
Plug '$PWD/yyy', { 'for': ['xxx'] }
Plug '$PLUG_FIXTURES/xxx'
Plug '$PLUG_FIXTURES/yyy', { 'for': ['xxx'] }
call plug#end()
call EnsureLoaded()
setf xxx
@@ -976,8 +1005,8 @@ Execute (Strict load order):
let g:total_order = []
call plug#begin()
Plug '$PWD/xxx', { 'for': ['xxx'] }
Plug '$PWD/yyy'
Plug '$PLUG_FIXTURES/xxx', { 'for': ['xxx'] }
Plug '$PLUG_FIXTURES/yyy'
call plug#end()
call EnsureLoaded()
set rtp^=manually-prepended
@@ -993,8 +1022,8 @@ Execute (Strict load order):
let g:total_order = []
call plug#begin()
Plug '$PWD/xxx', { 'for': ['xxx'] }
Plug '$PWD/yyy', { 'for': ['xxx'] }
Plug '$PLUG_FIXTURES/xxx', { 'for': ['xxx'] }
Plug '$PLUG_FIXTURES/yyy', { 'for': ['xxx'] }
call plug#end()
call EnsureLoaded()
setf xxx
@@ -1004,9 +1033,126 @@ Execute (Strict load order):
Assert index(g:total_order, 'xxx/after/plugin') < index(g:total_order, 'yyy/after/plugin')
AssertEqual len + 2, len(split(&rtp, ','))
**********************************************************************
Execute (PlugClean should not try to remove unmanaged plugins inside g:plug_home):
call plug#begin('$PLUG_FIXTURES')
Plug '$PLUG_FIXTURES/ftplugin-msg', { 'for': [] }
Plug '$PLUG_FIXTURES/fzf'
Plug '$PLUG_FIXTURES/xxx'
Plug '$PLUG_FIXTURES/yyy'
call plug#end()
" Remove z1, z2
PlugClean!
AssertExpect '^- ', 2
AssertExpect 'Already clean', 0
PlugClean!
AssertExpect '^- ', 0
AssertExpect 'Already clean', 1
q
**********************************************************************
Execute (#112 On-demand loading should not suppress messages from ftplugin):
call plug#begin('$PLUG_FIXTURES')
Plug '$PLUG_FIXTURES/ftplugin-msg', { 'for': 'c' }
call plug#end()
redir => out
tabnew a.c
redir END
Assert stridx(out, 'ftplugin') >= 0
* The same applies to plug#load())
redir => out
call plug#load('ftplugin-msg')
redir END
Assert stridx(out, 'ftplugin') >= 0
q
**********************************************************************
Execute (PlugSnapshot):
call plug#begin('$TMPDIR/plugged')
Plug 'junegunn/vim-emoji'
Plug 'junegunn/seoul256.vim'
call plug#end()
PlugClean!
PlugInstall
PlugSnapshot
AssertEqual '#!/bin/bash', getline(1)
AssertEqual '# Generated by vim-plug', getline(2)
AssertEqual 'vim +PlugUpdate +qa', getline(5)
AssertEqual 'PLUG_HOME=$TMPDIR/plugged', getline(7)
AssertEqual 0, stridx(getline(9), 'cd $PLUG_HOME/seoul256.vim/ && git reset --hard')
AssertEqual 0, stridx(getline(10), 'cd $PLUG_HOME/vim-emoji/ && git reset --hard')
AssertEqual 'sh', &filetype
execute 'PlugSnapshot' g:plug_home.'/snapshot.sh'
AssertEqual 'sh', &filetype
AssertEqual 'snapshot.sh', fnamemodify(expand('%'), ':t')
q
**********************************************************************
Execute (#114 Should not contain empty path in &rtp):
call plug#begin('$TMPDIR/plugged')
call plug#end()
Log &rtp
Assert &rtp !~ ',,', 'Commas'
Assert &rtp !~ '^,', 'Comma prefix'
Assert &rtp !~ ',$', 'Comma suffix'
**********************************************************************
Execute (#130 Proper cleanup of on-demand loading triggers):
augroup PlugLOD
autocmd!
augroup END
" Cleared on command
call plug#begin('$TMPDIR/plugged')
Plug 'junegunn/vim-emoji', { 'on': ['EmojiCommand', 'EmojiCommand2', '<Plug>(EmojiMapping)'] }
call plug#end()
PlugInstall | q
Assert exists(':EmojiCommand'), 'EmojiCommand not defined'
Assert exists(':EmojiCommand2'), 'EmojiCommand2 not defined'
Assert !empty(mapcheck('<Plug>(EmojiMapping)')), '<Plug>(EmojiMapping) not defined'
silent! EmojiCommand
Assert !exists(':EmojiCommand'), 'EmojiCommand defined'
Assert !exists(':EmojiCommand2'), 'EmojiCommand2 defined'
Assert empty(mapcheck('<Plug>(EmojiMapping)')), '<Plug>(EmojiMapping) defined'
" Cleared on FileType
call plug#begin('$TMPDIR/plugged')
Plug 'junegunn/vim-emoji', { 'on': ['EmojiCommandExtra', '<Plug>(EmojiMappingExtra)'], 'for': ['emoji'] }
call plug#end()
Assert exists(':EmojiCommandExtra'), 'EmojiCommandExtra not defined'
Assert !empty(mapcheck('<Plug>(EmojiMappingExtra)')), '<Plug>(EmojiMappingExtra) not defined'
setf emoji
Assert !exists(':EmojiCommandExtra'), 'EmojiCommandExtra defined'
Assert empty(mapcheck('<Plug>(EmojiMappingExtra)')), '<Plug>(EmojiMappingExtra) defined'
**********************************************************************
Execute (#131 Syntax error):
call plug#begin('/no-permission')
Plug 'junegunn/vim-emoji'
call plug#end()
redir => out
silent PlugInstall
redir END
Assert out =~ 'Invalid plug directory: /no-permission'
Execute (Cleanup):
silent! call system('rm -rf '.temp_plugged)
silent! call rename('fzf', 'fzf-staged')
silent! call system('rm -rf '.temp_plugged)
silent! call rename(fzf, expand('$PLUG_FIXTURES/fzf-staged'))
silent! unlet g:plugs
silent! unlet g:plug_home
silent! unlet g:plug_url_format