29 Commits
0.3.4 ... 0.4.0

Author SHA1 Message Date
Junegunn Choi
5b2c03d3a8 R to retry interrupted tasks as well 2014-07-23 11:46:29 +09:00
Junegunn Choi
0b31be49cf Update README 2014-07-22 12:47:34 +09:00
Junegunn Choi
74fa6ab9df 'R' to retry failed update/installation tasks 2014-07-22 12:46:59 +09:00
Junegunn Choi
0d7e20c984 Merge pull request #37 from junegunn/retries
Retry in case of timeout
2014-07-21 23:13:43 +09:00
Junegunn Choi
e2714fb56e Retry in 3 seconds 2014-07-21 23:09:16 +09:00
Junegunn Choi
3b83a22ea4 Avoid InsertEnter/InsertLeave events in GUI MacVim workaround 2014-07-21 14:27:38 +09:00
Junegunn Choi
cd418369bc Use gui_macvim instead of mac (#36) 2014-07-21 11:42:27 +09:00
Junegunn Choi
279a334c8b Temporarily disable &imd on GUI MacVim (#36) 2014-07-21 11:35:48 +09:00
Junegunn Choi
9132e9d50d Workaround for screen freeze in MacVim GUI (#36) 2014-07-21 02:49:47 +09:00
Junegunn Choi
3323163e04 Retry in case of timeout (#35)
while gradually increasing the time limit
2014-07-20 02:14:15 +09:00
Junegunn Choi
e4671eaf9e Do not assume that frozen key exists
To avoid possible error after PlugUpgrade
2014-07-18 01:27:41 +09:00
Junegunn Choi
9afa356fb3 Exclude unmanaged plugins from PlugDiff output 2014-07-17 10:28:59 +09:00
Junegunn Choi
e04f696682 Ignore errors during :helptags
https://github.com/junegunn/vim-plug/issues/31#issuecomment-49058031
2014-07-17 02:20:00 +09:00
Junegunn Choi
4cb5fd04a6 Note on single quotes (#33) 2014-07-16 20:40:49 +09:00
Junegunn Choi
c16743e8fc License 2014-07-16 20:39:39 +09:00
Junegunn Choi
46a6e8441f Pin first and last path in &rtp (#34) 2014-07-16 20:26:42 +09:00
Junegunn Choi
466d1839b3 Add support for local plugins. Add frozen option (#32) 2014-07-16 19:52:58 +09:00
Junegunn Choi
c3cf35abb5 Ignore occasional error from Ruby 1.8.7
Related: https://bugs.ruby-lang.org/issues/1471
2014-07-13 22:02:11 +09:00
Junegunn Choi
344f80aedb Fix Ruby installer for Ruby 1.8.7 (#31) 2014-07-13 20:18:56 +09:00
Junegunn Choi
dae0540a11 Change gif 2014-07-13 17:39:19 +09:00
Junegunn Choi
af89938633 Real-time progress report
This commit is almost identical to the reverted
60b907c87f, but it tries to avoid high CPU load
by not printing every line.
2014-07-13 03:58:16 +09:00
Junegunn Choi
35c5f2830b Revert "Real-time progress report"
This reverts commit 60b907c87f.
2014-07-13 03:22:25 +09:00
Junegunn Choi
60b907c87f Real-time progress report 2014-07-13 03:05:54 +09:00
Junegunn Choi
9ceb9caa09 Minor refactoring 2014-07-10 00:44:09 +09:00
Junegunn Choi
42a42e7e71 Fix after directory and Plugfile on Windows 2014-07-10 00:13:32 +09:00
Junegunn Choi
8885b1086f Minor refactoring in ODL: no need to pass full dict 2014-07-09 01:14:03 +09:00
Junegunn Choi
90c07f269c Fix <Plug>-based ODL on visual range spanning multiple lines 2014-07-07 22:55:44 +09:00
Junegunn Choi
f1c5157e35 Fix <Plug>-based on-demand-loading on visual mode 2014-07-07 19:06:20 +09:00
Junegunn Choi
7f1ec7b12b Load ftplugins while avoiding extraneous FileType events (#24, #25) 2014-07-04 14:20:48 +09:00
4 changed files with 522 additions and 145 deletions

View File

@@ -6,7 +6,7 @@ A single-file Vim plugin manager.
Somewhere between [Pathogen](https://github.com/tpope/vim-pathogen) and Somewhere between [Pathogen](https://github.com/tpope/vim-pathogen) and
[Vundle](https://github.com/gmarik/vundle), but with faster parallel installer. [Vundle](https://github.com/gmarik/vundle), but with faster parallel installer.
![](https://raw.github.com/junegunn/i/master/vim-plug/vim-plug.gif) ![](https://raw.github.com/junegunn/i/master/vim-plug/installer.gif)
### Pros. ### Pros.
@@ -37,28 +37,28 @@ Edit your .vimrc
```vim ```vim
call plug#begin('~/.vim/plugged') call plug#begin('~/.vim/plugged')
" Make sure you use single quotes
Plug 'junegunn/seoul256.vim' Plug 'junegunn/seoul256.vim'
Plug 'junegunn/vim-easy-align' Plug 'junegunn/vim-easy-align'
" On-demand loading
Plug 'scrooloose/nerdtree', { 'on': 'NERDTreeToggle' } Plug 'scrooloose/nerdtree', { 'on': 'NERDTreeToggle' }
Plug 'tpope/vim-fireplace', { 'for': 'clojure' } Plug 'tpope/vim-fireplace', { 'for': 'clojure' }
" Plug 'user/repo1', 'branch_or_tag'
" Plug 'user/repo2', { 'rtp': 'vim/plugin/dir', 'branch': 'devel' } " Using git URL
" Plug 'git@github.com:junegunn/vim-github-dashboard.git' Plug 'https://github.com/junegunn/vim-github-dashboard.git'
" ...
" Plugin options
Plug 'nsf/gocode', { 'tag': 'go.weekly.2012-03-13', 'rtp': 'vim' }
" Locally-managed plugin
Plug '~/.fzf'
call plug#end() call plug#end()
``` ```
Reload .vimrc and `:PlugInstall` to install plugins. Reload .vimrc and `:PlugInstall` to install plugins.
### Plugin directory
If you omit the path argument to `plug#begin()`, plugins are installed in
`plugged` directory under the first path in `runtimepath` at the point when
`plug#begin()` is called. This is usually `~/.vim/plugged` (or
`$HOME/vimfiles/plugged` on Windows) given that you didn't touch runtimepath
before the call.
### Commands ### Commands
| Command | Description | | Command | Description |
@@ -70,17 +70,29 @@ before the call.
| PlugStatus | Check the status of plugins | | PlugStatus | Check the status of plugins |
| PlugDiff | See the updated changes from the previous PlugUpdate | | PlugDiff | See the updated changes from the previous PlugUpdate |
### `Plug` options
| Option | Description |
| -------------- | -------------------------------------------------------------------- |
| `branch`/`tag` | Branch or tag of the repository to use |
| `rtp` | Subdirectory that contains Vim plugin |
| `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 |
### Options for parallel installer ### Options for parallel installer
| Flag | Default | Description | | Flag | Default | Description |
| ---------------- | ------- | --------------------------------- | | ---------------- | ------- | ------------------------------------ |
| `g:plug_threads` | 16 | Default number of threads to use | | `g:plug_threads` | 16 | Default number of threads to use |
| `g:plug_timeout` | 60 | Time limit of each task in seconds | | `g:plug_timeout` | 60 | Time limit of each task in seconds |
| `g:plug_retries` | 2 | Number of retries in case of timeout |
### Keybindings ### Keybindings
- `D` - `PlugDiff` - `D` - `PlugDiff`
- `S` - `PlugStatus` - `S` - `PlugStatus`
- `R` - Retry failed update or installation tasks
- `q` - Close the window - `q` - Close the window
### Example: A small [sensible](https://github.com/tpope/vim-sensible) Vim configuration ### Example: A small [sensible](https://github.com/tpope/vim-sensible) Vim configuration
@@ -173,17 +185,7 @@ it as "unstable" or "in development", and always use its latest revision.
If you really must choose a certain untagged revision, consider forking the If you really must choose a certain untagged revision, consider forking the
repository. repository.
### Regarding feature request ### License
You may submit a request for a new feature by [creating an MIT
issue](https://github.com/junegunn/vim-plug/issues). However, please be minded
that this is an opinionated software and I want to keep the feature set as small
as possible. So I may not agree with you on the necessity of the suggested
feature. If that happens, I suggest the following options.
1. Check out [Vundle](https://github.com/gmarik/vundle) or
[NeoBundle](https://github.com/Shougo/neobundle.vim).
They offer broader feature sets.
2. Create a fork of this project and let it be your own plugin manager.
There's no need for us to have a single canonical branch.

346
plug.vim
View File

@@ -58,6 +58,7 @@ set cpo&vim
let s:plug_source = 'https://raw.github.com/junegunn/vim-plug/master/plug.vim' let s:plug_source = 'https://raw.github.com/junegunn/vim-plug/master/plug.vim'
let s:plug_file = 'Plugfile' let s:plug_file = 'Plugfile'
let s:plug_buf = -1 let s:plug_buf = -1
let s:mac_gui = has('gui_macvim') && has('gui_running')
let s:is_win = has('win32') || has('win64') let s:is_win = has('win32') || has('win64')
let s:me = expand('<sfile>:p') let s:me = expand('<sfile>:p')
@@ -141,16 +142,17 @@ function! plug#end()
for cmd in commands for cmd in commands
if cmd =~ '^<Plug>.\+' if cmd =~ '^<Plug>.\+'
if empty(mapcheck(cmd)) && empty(mapcheck(cmd, 'i')) if empty(mapcheck(cmd)) && empty(mapcheck(cmd, 'i'))
for [mode, prefix] in [['i', "<C-O>"], ['', '']] for [mode, map_prefix, key_prefix] in
\ [['i', "<C-O>", ''], ['n', '', ''], ['v', '', 'gv'], ['o', '', '']]
execute printf( execute printf(
\ "%snoremap <silent> %s %s:call <SID>lod_map(%s, %s)<CR>", \ "%snoremap <silent> %s %s:<C-U>call <SID>lod_map(%s, %s, '%s')<CR>",
\ mode, cmd, prefix, string(cmd), string(plug)) \ mode, cmd, map_prefix, string(cmd), string(name), key_prefix)
endfor endfor
endif endif
elseif !exists(':'.cmd) elseif !exists(':'.cmd)
execute printf( execute printf(
\ "command! -nargs=* -range -bang %s call s:lod_cmd(%s, '<bang>', <line1>, <line2>, <q-args>, %s)", \ "command! -nargs=* -range -bang %s call s:lod_cmd(%s, '<bang>', <line1>, <line2>, <q-args>, %s)",
\ cmd, string(cmd), string(plug)) \ cmd, string(cmd), string(name))
endif endif
endfor endfor
endif endif
@@ -174,26 +176,58 @@ function! plug#end()
\ key, string(key), string(reverse(names))) \ key, string(key), string(reverse(names)))
augroup END augroup END
endfor endfor
call s:reorg_rtp()
filetype plugin indent on filetype plugin indent on
syntax on syntax on
endfunction endfunction
if s:is_win
function! s:rtp(spec) function! s:rtp(spec)
let rtp = s:dirpath(a:spec.dir . get(a:spec, 'rtp', '')) let rtp = s:dirpath(a:spec.dir . get(a:spec, 'rtp', ''))
if s:is_win return substitute(rtp, '\\*$', '', '')
let rtp = substitute(rtp, '\\*$', '', '')
endif
return rtp
endfunction endfunction
function! s:path(path)
return substitute(substitute(a:path, '/', '\', 'g'), '[/\\]*$', '', '')
endfunction
function! s:dirpath(path)
return s:path(a:path) . '\'
endfunction
else
function! s:rtp(spec)
return s:dirpath(a:spec.dir . get(a:spec, 'rtp', ''))
endfunction
function! s:path(path)
return substitute(a:path, '[/\\]*$', '', '')
endfunction
function! s:dirpath(path)
return s:path(a:path) . '/'
endfunction
endif
function! s:esc(path) function! s:esc(path)
return substitute(a:path, ' ', '\\ ', 'g') return substitute(a:path, ' ', '\\ ', 'g')
endfunction endfunction
function! s:add_rtp(rtp) function! s:add_rtp(rtp)
execute "set rtp^=".s:esc(a:rtp) execute "set rtp^=".s:esc(a:rtp)
if isdirectory(a:rtp.'after') let after = globpath(a:rtp, 'after')
execute "set rtp+=".s:esc(a:rtp.'after') if isdirectory(after)
execute "set rtp+=".s:esc(after)
endif
endfunction
function! s:reorg_rtp()
if !empty(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 endif
endfunction endfunction
@@ -211,20 +245,23 @@ function! s:lod_ft(pat, names)
for name in a:names for name in a:names
call s:lod(g:plugs[name], ['plugin', 'after']) call s:lod(g:plugs[name], ['plugin', 'after'])
endfor endfor
call s:reorg_rtp()
execute 'autocmd! PlugLOD FileType ' . a:pat execute 'autocmd! PlugLOD FileType ' . a:pat
let &l:filetype = &l:filetype silent! doautocmd filetypeplugin FileType
endfunction endfunction
function! s:lod_cmd(cmd, bang, l1, l2, args, plug) function! s:lod_cmd(cmd, bang, l1, l2, args, name)
execute 'delc '.a:cmd execute 'delc '.a:cmd
call s:lod(a:plug, ['plugin', 'ftdetect', 'after']) call s:lod(g:plugs[a:name], ['plugin', 'ftdetect', 'after'])
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, plug) 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(a:plug, ['plugin', 'ftdetect', 'after']) call s:lod(g:plugs[a:name], ['plugin', 'ftdetect', 'after'])
call s:reorg_rtp()
let extra = '' let extra = ''
while 1 while 1
let c = getchar(0) let c = getchar(0)
@@ -233,20 +270,22 @@ function! s:lod_map(map, plug)
endif endif
let extra .= nr2char(c) let extra .= nr2char(c)
endwhile endwhile
call feedkeys(substitute(a:map, '^<Plug>', "\<Plug>", '') . extra) call feedkeys(a:prefix . substitute(a:map, '^<Plug>', "\<Plug>", '') . extra)
endfunction endfunction
function! s:add(...) function! s:add(force, ...)
let force = a:1 let opts = { 'branch': 'master', 'frozen': 0 }
let opts = { 'branch': 'master' } if a:0 == 1
if a:0 == 2 let plugin = a:1
let plugin = a:2 elseif a:0 == 2
elseif a:0 == 3 let plugin = a:1
let plugin = a:2 if type(a:2) == 1
if type(a:3) == 1 let opts.branch = a:2
let opts.branch = a:3 elseif type(a:2) == 4
elseif type(a:3) == 4 call extend(opts, a:2)
call extend(opts, a:3) if has_key(opts, 'tag')
let opts.branch = remove(opts, 'tag')
endif
else else
echoerr "Invalid argument type (expected: string or dictionary)" echoerr "Invalid argument type (expected: string or dictionary)"
return return
@@ -256,6 +295,16 @@ function! s:add(...)
return return
endif endif
let plugin = substitute(plugin, '[/\\]*$', '', '')
let name = substitute(split(plugin, '/')[-1], '\.git$', '', '')
if !a:force && has_key(g:plugs, name)
let s:extended[name] = g:plugs[name]
return
endif
if plugin[0] =~ '[/$~]' || plugin =~? '^[a-z]:'
let spec = extend(opts, { 'dir': s:dirpath(expand(plugin)) })
else
if plugin =~ ':' if plugin =~ ':'
let uri = plugin let uri = plugin
else else
@@ -264,13 +313,14 @@ function! s:add(...)
endif endif
let uri = 'https://git:@github.com/' . plugin . '.git' let uri = 'https://git:@github.com/' . plugin . '.git'
endif endif
let name = substitute(split(plugin, '/')[-1], '\.git$', '', '')
if !force && has_key(g:plugs, name) | return | endif
let dir = s:dirpath( fnamemodify(join([g:plug_home, name], '/'), ':p') ) let dir = s:dirpath( fnamemodify(join([g:plug_home, name], '/'), ':p') )
let spec = extend(opts, { 'dir': dir, 'uri': uri }) let spec = extend(opts, { 'dir': dir, 'uri': uri })
endif
let g:plugs[name] = spec let g:plugs[name] = spec
if !a:force
let s:extended[name] = spec
endif
let g:plugs_order += [name] let g:plugs_order += [name]
endfunction endfunction
@@ -286,7 +336,7 @@ function! s:apply()
for spec in values(g:plugs) for spec in values(g:plugs)
let docd = join([spec.dir, 'doc'], '/') let docd = join([spec.dir, 'doc'], '/')
if isdirectory(docd) if isdirectory(docd)
execute "helptags ". join([spec.dir, 'doc'], '/') silent! execute "helptags ". join([spec.dir, 'doc'], '/')
endif endif
endfor endfor
runtime! plugin/*.vim runtime! plugin/*.vim
@@ -302,7 +352,11 @@ function! s:syntax()
syn match plugBracket /[[\]]/ contained syn match plugBracket /[[\]]/ contained
syn match plugX /x/ contained syn match plugX /x/ contained
syn match plugDash /^-/ syn match plugDash /^-/
syn match plugPlus /^+/
syn match plugStar /^*/
syn match plugName /\(^- \)\@<=[^:]*/ syn match plugName /\(^- \)\@<=[^:]*/
syn match plugInstall /\(^+ \)\@<=[^:]*/
syn match plugUpdate /\(^* \)\@<=[^:]*/
syn match plugCommit /^ [0-9a-z]\{7} .*/ contains=plugRelDate,plugSha syn match plugCommit /^ [0-9a-z]\{7} .*/ contains=plugRelDate,plugSha
syn match plugSha /\(^ \)\@<=[0-9a-z]\{7}/ contained syn match plugSha /\(^ \)\@<=[0-9a-z]\{7}/ contained
syn match plugRelDate /([^)]*)$/ contained syn match plugRelDate /([^)]*)$/ contained
@@ -313,8 +367,15 @@ function! s:syntax()
hi def link plugX Exception hi def link plugX Exception
hi def link plugBracket Structure hi def link plugBracket Structure
hi def link plugNumber Number hi def link plugNumber Number
hi def link plugDash Special hi def link plugDash Special
hi def link plugPlus Constant
hi def link plugStar Boolean
hi def link plugName Label hi def link plugName Label
hi def link plugInstall Function
hi def link plugUpdate Type
hi def link plugError Error hi def link plugError Error
hi def link plugRelDate Comment hi def link plugRelDate Comment
hi def link plugSha Identifier hi def link plugSha Identifier
@@ -342,6 +403,7 @@ function! s:prepare()
else else
vertical topleft new vertical topleft new
nnoremap <silent> <buffer> q :if b:plug_preview==1<bar>pc<bar>endif<bar>q<cr> nnoremap <silent> <buffer> q :if b:plug_preview==1<bar>pc<bar>endif<bar>q<cr>
nnoremap <silent> <buffer> R :silent! call <SID>retry()<cr>
nnoremap <silent> <buffer> D :PlugDiff<cr> nnoremap <silent> <buffer> D :PlugDiff<cr>
nnoremap <silent> <buffer> S :PlugStatus<cr> nnoremap <silent> <buffer> S :PlugStatus<cr>
nnoremap <silent> <buffer> ]] :silent! call <SID>section('')<cr> nnoremap <silent> <buffer> ]] :silent! call <SID>section('')<cr>
@@ -376,13 +438,30 @@ function! s:finish(pull)
call setline(4, getline(4) . 'Done!') call setline(4, getline(4) . 'Done!')
normal! gg normal! gg
redraw redraw
if a:pull let msgs = []
echo "Press 'D' to see the updated changes." if !empty(s:prev_update.errors)
call add(msgs, "Press 'R' to retry.")
endif endif
if a:pull
call add(msgs, "Press 'D' to see the updated changes.")
endif
echo join(msgs, ' ')
endfunction
function! s:retry()
if empty(s:prev_update.errors)
return
endif
call s:update_impl(s:prev_update.pull,
\ extend(copy(s:prev_update.errors), [s:prev_update.threads]))
endfunction
function! s:is_managed(name)
return has_key(g:plugs[a:name], 'uri')
endfunction endfunction
function! s:names(...) function! s:names(...)
return filter(keys(g:plugs), 'stridx(v:val, a:1) == 0') return filter(keys(g:plugs), 'stridx(v:val, a:1) == 0 && s:is_managed(v:val)')
endfunction endfunction
function! s:update_impl(pull, args) abort function! s:update_impl(pull, args) abort
@@ -390,8 +469,9 @@ function! s:update_impl(pull, args) abort
let threads = (len(args) > 0 && args[-1] =~ '^[1-9][0-9]*$') ? let threads = (len(args) > 0 && args[-1] =~ '^[1-9][0-9]*$') ?
\ remove(args, -1) : get(g:, 'plug_threads', 16) \ remove(args, -1) : get(g:, 'plug_threads', 16)
let todo = empty(args) ? g:plugs : let managed = filter(copy(g:plugs), 's:is_managed(v:key)')
\ filter(copy(g:plugs), 'index(args, v:key) >= 0') let todo = empty(args) ? filter(managed, '!get(v:val, "frozen", 0)') :
\ filter(managed, 'index(args, v:key) >= 0')
if empty(todo) if empty(todo)
echohl WarningMsg echohl WarningMsg
@@ -407,8 +487,33 @@ function! s:update_impl(pull, args) abort
redraw redraw
let len = len(g:plugs) let len = len(g:plugs)
let s:prev_update = { 'errors': [], 'pull': a:pull, 'threads': threads }
if has('ruby') && threads > 1 if has('ruby') && threads > 1
try
let imd = &imd
if s:mac_gui
set noimd
endif
call s:update_parallel(a:pull, todo, threads) call s:update_parallel(a:pull, todo, threads)
catch
let lines = getline(4, '$')
let printed = {}
silent 4,$d
for line in lines
let name = get(matchlist(line, '^. \([^:]\+\):'), 1, '')
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)
end
endif
endif
endfor
finally
let &imd = imd
endtry
else else
call s:update_serial(a:pull, todo) call s:update_serial(a:pull, todo)
endif endif
@@ -419,11 +524,11 @@ function! s:update_impl(pull, args) abort
endfunction endfunction
function! s:extend(names) function! s:extend(names)
let prev = copy(g:plugs) let s:extended = {}
try try
command! -nargs=+ Plug call s:add(0, <args>) command! -nargs=+ Plug call s:add(0, <args>)
for name in a:names for name in a:names
let plugfile = s:rtp(g:plugs[name]) . s:plug_file let plugfile = globpath(s:rtp(g:plugs[name]), s:plug_file)
if filereadable(plugfile) if filereadable(plugfile)
execute "source ". s:esc(plugfile) execute "source ". s:esc(plugfile)
endif endif
@@ -431,7 +536,7 @@ function! s:extend(names)
finally finally
command! -nargs=+ Plug call s:add(1, <args>) command! -nargs=+ Plug call s:add(1, <args>)
endtry endtry
return filter(copy(g:plugs), '!has_key(prev, v:key)') return s:extended
endfunction endfunction
function! s:update_progress(pull, cnt, bar, total) function! s:update_progress(pull, cnt, bar, total)
@@ -466,11 +571,11 @@ function! s:update_serial(pull, todo)
let result = msg let result = msg
let error = 1 let error = 1
endif endif
cd -
else else
if !isdirectory(base) if !isdirectory(base)
call mkdir(base, 'p') call mkdir(base, 'p')
endif endif
execute 'cd '.base
let result = s:system( let result = s:system(
\ printf('git clone --recursive %s -b %s %s 2>&1 && cd %s && git submodule update --init --recursive 2>&1', \ 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.uri),
@@ -479,14 +584,17 @@ function! s:update_serial(pull, todo)
\ s:shellesc(spec.dir))) \ s:shellesc(spec.dir)))
let error = v:shell_error != 0 let error = v:shell_error != 0
endif endif
cd -
let bar .= error ? 'x' : '=' let bar .= error ? 'x' : '='
if error
call add(s:prev_update.errors, name)
endif
call append(3, s:format_message(!error, name, result)) call append(3, s:format_message(!error, name, result))
call s:update_progress(a:pull, len(done), bar, total) call s:update_progress(a:pull, len(done), bar, total)
endfor endfor
if !empty(s:extend(keys(todo))) let extended = s:extend(keys(todo))
let todo = filter(copy(g:plugs), '!has_key(done, v:key)') if !empty(extended)
let todo = filter(extended, '!has_key(done, v:key)')
let total += len(todo) let total += len(todo)
call s:update_progress(a:pull, len(done), bar, total) call s:update_progress(a:pull, len(done), bar, total)
else else
@@ -499,70 +607,109 @@ endfunction
function! s:update_parallel(pull, todo, threads) function! s:update_parallel(pull, todo, threads)
ruby << EOF ruby << EOF
module PlugStream
SEP = ["\r", "\n", nil]
def get_line
buffer = ''
loop do
char = readchar rescue return
if SEP.include? char.chr
buffer << $/
break
else
buffer << char
end
end
buffer
end
end unless defined?(PlugStream)
def esc arg def esc arg
%["#{arg.gsub('"', '\"')}"] %["#{arg.gsub('"', '\"')}"]
end end
st = Time.now require 'set'
require 'thread' require 'thread'
require 'fileutils' require 'fileutils'
require 'timeout' require 'timeout'
running = true running = true
st = Time.now
iswin = VIM::evaluate('s:is_win').to_i == 1 iswin = VIM::evaluate('s:is_win').to_i == 1
pull = VIM::evaluate('a:pull').to_i == 1 pull = VIM::evaluate('a:pull').to_i == 1
base = VIM::evaluate('g:plug_home') base = VIM::evaluate('g:plug_home')
all = VIM::evaluate('copy(a:todo)') all = VIM::evaluate('copy(a:todo)')
limit = VIM::evaluate('get(g:, "plug_timeout", 60)') 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('a:threads').to_i
maxy = VIM::evaluate('winheight(".")').to_i
cd = iswin ? 'cd /d' : 'cd' cd = iswin ? 'cd /d' : 'cd'
done = {} tot = VIM::evaluate('len(a:todo)') || 0
tot = 0
bar = '' bar = ''
skip = 'Already installed' skip = 'Already installed'
mtx = Mutex.new mtx = Mutex.new
take1 = proc { mtx.synchronize { running && all.shift } } take1 = proc { mtx.synchronize { running && all.shift } }
logh = proc { logh = proc {
cnt = done.length cnt = bar.length
tot = VIM::evaluate('len(a:todo)') || tot
$curbuf[1] = "#{pull ? 'Updating' : 'Installing'} plugins (#{cnt}/#{tot})" $curbuf[1] = "#{pull ? 'Updating' : 'Installing'} plugins (#{cnt}/#{tot})"
$curbuf[2] = '[' + bar.ljust(tot) + ']' $curbuf[2] = '[' + bar.ljust(tot) + ']'
VIM::command('normal! 2G') VIM::command('normal! 2G')
VIM::command('redraw') unless iswin VIM::command('redraw') unless iswin
} }
log = proc { |name, result, ok| where = proc { |name| (1..($curbuf.length)).find { |l| $curbuf[l] =~ /^[-+x*] #{name}:/ } }
log = proc { |name, result, type|
mtx.synchronize do mtx.synchronize do
bar += ok ? '=' : 'x' ing = ![true, false].include?(type)
done[name] = true bar += type ? '=' : 'x' unless ing
b = case type
when :install then '+' when :update then '*'
when true, nil then '-' else
VIM::command("call add(s:prev_update.errors, '#{name}')")
'x'
end
result = result =
if ok if type || type.nil?
["- #{name}: #{result.lines.to_a.last.strip}"] ["#{b} #{name}: #{result.lines.to_a.last}"]
elsif result =~ /^Interrupted|^Timeout/ elsif result =~ /^Interrupted|^Timeout/
["x #{name}: #{result}"] ["#{b} #{name}: #{result}"]
else else
["x #{name}"] + result.lines.map { |l| " " << l } ["#{b} #{name}"] + result.lines.map { |l| " " << l }
end
if lnum = where.call(name)
$curbuf.delete lnum
lnum = 4 if ing && lnum > maxy
end end
result.each_with_index do |line, offset| result.each_with_index do |line, offset|
$curbuf.append 3 + offset, line.chomp $curbuf.append((lnum || 4) - 1 + offset, line.gsub(/\e\[./, '').chomp)
end end
logh.call logh.call
end end
} }
bt = proc { |cmd| bt = proc { |cmd, name, type|
tried = timeout = 0
begin begin
tried += 1
timeout += limit
fd = nil fd = nil
Timeout::timeout(limit) do data = ''
if iswin if iswin
Timeout::timeout(timeout) do
tmp = VIM::evaluate('tempname()') tmp = VIM::evaluate('tempname()')
system("#{cmd} > #{tmp}") system("#{cmd} > #{tmp}")
data = File.read(tmp).chomp data = File.read(tmp).chomp
File.unlink tmp rescue nil File.unlink tmp rescue nil
end
else else
fd = IO.popen(cmd) fd = IO.popen(cmd).extend(PlugStream)
data = fd.read.chomp first_line = true
log_prob = 1.0 / nthr
while line = Timeout::timeout(timeout) { fd.get_line }
data << line
log.call name, line.chomp, type if name && (first_line || rand < log_prob)
first_line = false
end
fd.close fd.close
end end
[$? == 0, data] [$? == 0, data.chomp]
end
rescue Timeout::Error, Interrupt => e rescue Timeout::Error, Interrupt => e
if fd && !fd.closed? if fd && !fd.closed?
pids = [fd.pid] pids = [fd.pid]
@@ -570,7 +717,7 @@ function! s:update_parallel(pull, todo, threads)
children = pids children = pids
until children.empty? until children.empty?
children = children.map { |pid| children = children.map { |pid|
`pgrep -P #{pid}`.lines.map(&:chomp) `pgrep -P #{pid}`.lines.map { |l| l.chomp }
}.flatten }.flatten
pids += children pids += children
end end
@@ -578,6 +725,15 @@ function! s:update_parallel(pull, todo, threads)
pids.each { |pid| Process.kill 'TERM', pid.to_i rescue nil } pids.each { |pid| Process.kill 'TERM', pid.to_i rescue nil }
fd.close fd.close
end end
if e.is_a?(Timeout::Error) && tried < tries
3.downto(1) do |countdown|
s = countdown > 1 ? 's' : ''
log.call name, "Timeout. Will retry in #{countdown} second#{s} ...", type
sleep 1
end
log.call name, 'Retrying ...', type
retry
end
[false, e.is_a?(Interrupt) ? "Interrupted!" : "Timeout!"] [false, e.is_a?(Interrupt) ? "Interrupted!" : "Timeout!"]
end end
} }
@@ -594,9 +750,21 @@ function! s:update_parallel(pull, todo, threads)
threads.each { |t| t.join rescue nil } threads.each { |t| t.join rescue nil }
main.kill main.kill
} }
refresh = Thread.new {
while true
mtx.synchronize do
break unless running
VIM::command('noautocmd normal! a')
end
sleep 0.2
end
} if VIM::evaluate('s:mac_gui') == 1
processed = Set.new
progress = iswin ? '' : '--progress'
until all.empty? until all.empty?
names = all.keys names = all.keys
processed.merge names
[names.length, nthr].min.times do [names.length, nthr].min.times do
mtx.synchronize do mtx.synchronize do
threads << Thread.new { threads << Thread.new {
@@ -604,10 +772,11 @@ function! s:update_parallel(pull, todo, threads)
name = pair.first name = pair.first
dir, uri, branch = pair.last.values_at *%w[dir uri branch] dir, uri, branch = pair.last.values_at *%w[dir uri branch]
branch = esc branch branch = esc branch
subm = "git submodule update --init --recursive 2>&1"
ok, result = ok, result =
if File.directory? dir if File.directory? dir
dir = esc dir dir = esc dir
ret, data = bt.call "#{cd} #{dir} && git rev-parse --abbrev-ref HEAD 2>&1 && git config remote.origin.url" ret, data = bt.call "#{cd} #{dir} && git rev-parse --abbrev-ref HEAD 2>&1 && git config remote.origin.url", nil, nil
current_uri = data.lines.to_a.last current_uri = data.lines.to_a.last
if !ret if !ret
if data =~ /^Interrupted|^Timeout/ if data =~ /^Interrupted|^Timeout/
@@ -621,7 +790,8 @@ function! s:update_parallel(pull, todo, threads)
"PlugClean required."].join($/)] "PlugClean required."].join($/)]
else else
if pull if pull
bt.call "#{cd} #{dir} && git checkout -q #{branch} 2>&1 && git pull origin #{branch} 2>&1 && git submodule update --init --recursive 2>&1" log.call name, 'Updating ...', :update
bt.call "#{cd} #{dir} && git checkout -q #{branch} 2>&1 && (git pull origin #{branch} #{progress} 2>&1 && #{subm})", name, :update
else else
[true, skip] [true, skip]
end end
@@ -629,37 +799,29 @@ function! s:update_parallel(pull, todo, threads)
else else
FileUtils.mkdir_p(base) FileUtils.mkdir_p(base)
d = esc dir.sub(%r{[\\/]+$}, '') d = esc dir.sub(%r{[\\/]+$}, '')
bt.call "#{cd} #{base} && git clone --recursive #{uri} -b #{branch} #{d} 2>&1 && cd #{esc dir} && git submodule update --init --recursive 2>&1" log.call name, 'Installing ...', :install
bt.call "(git clone #{progress} --recursive #{uri} -b #{branch} #{d} 2>&1 && cd #{esc dir} && #{subm})", name, :install
end end
log.call name, result, ok log.call name, result, ok
end end
} if running } if running
end end
end end
threads.each(&:join) threads.each { |t| t.join rescue nil }
mtx.synchronize { threads.clear } mtx.synchronize { threads.clear }
all.merge!(VIM::evaluate("s:extend(#{names.inspect})") || {}) extended = Hash[(VIM::evaluate("s:extend(#{names.inspect})") || {}).reject { |k, _|
processed.include? k
}]
tot += extended.length
all.merge!(extended)
logh.call logh.call
end end
refresh.kill if refresh
watcher.kill watcher.kill
$curbuf[1] = "Updated. Elapsed time: #{"%.6f" % (Time.now - st)} sec." $curbuf[1] = "Updated. Elapsed time: #{"%.6f" % (Time.now - st)} sec."
EOF EOF
endfunction endfunction
function! s:path(path)
return substitute(s:is_win ? substitute(a:path, '/', '\', 'g') : a:path,
\ '[/\\]*$', '', '')
endfunction
function! s:dirpath(path)
let path = s:path(a:path)
if s:is_win
return path !~ '\\$' ? path.'\' : path
else
return path !~ '/$' ? path.'/' : path
endif
endfunction
function! s:shellesc(arg) function! s:shellesc(arg)
return '"'.substitute(a:arg, '"', '\\"', 'g').'"' return '"'.substitute(a:arg, '"', '\\"', 'g').'"'
endfunction endfunction
@@ -737,8 +899,9 @@ function! s:clean(force)
" List of valid directories " List of valid directories
let dirs = [] let dirs = []
let [cnt, total] = [0, len(g:plugs)] let managed = filter(copy(g:plugs), 's:is_managed(v:key)')
for spec in values(g:plugs) let [cnt, total] = [0, len(managed)]
for spec in values(managed)
if s:git_valid(spec, 0, 1)[0] if s:git_valid(spec, 0, 1)[0]
call add(dirs, spec.dir) call add(dirs, spec.dir)
endif endif
@@ -839,11 +1002,19 @@ function! s:status()
let ecnt = 0 let ecnt = 0
let [cnt, total] = [0, len(g:plugs)] let [cnt, total] = [0, len(g:plugs)]
for [name, spec] in items(g:plugs) for [name, spec] in items(g:plugs)
if has_key(spec, 'uri')
if isdirectory(spec.dir) if isdirectory(spec.dir)
let [valid, msg] = s:git_valid(spec, 1, 1) let [valid, msg] = s:git_valid(spec, 1, 1)
else else
let [valid, msg] = [0, 'Not found. Try PlugInstall.'] let [valid, msg] = [0, 'Not found. Try PlugInstall.']
endif endif
else
if isdirectory(spec.dir)
let [valid, msg] = [1, 'OK']
else
let [valid, msg] = [0, 'Not found.']
endif
endif
let cnt += 1 let cnt += 1
let ecnt += !valid let ecnt += !valid
call s:progress_bar(2, repeat('=', cnt), total) call s:progress_bar(2, repeat('=', cnt), total)
@@ -906,7 +1077,7 @@ function! s:diff()
let cnt = 0 let cnt = 0
for [k, v] in items(g:plugs) for [k, v] in items(g:plugs)
if !isdirectory(v.dir) if !isdirectory(v.dir) || !s:is_managed(k)
continue continue
endif endif
@@ -928,6 +1099,9 @@ function! s:diff()
normal! gg normal! gg
endfunction endfunction
let s:first_rtp = s:esc(get(split(&rtp, ','), 0, ''))
let s:last_rtp = s:esc(get(split(&rtp, ','), -1, ''))
let &cpo = s:cpo_save let &cpo = s:cpo_save
unlet s:cpo_save unlet s:cpo_save

View File

@@ -9,13 +9,19 @@ if [ ! -d vader.vim ]; then
git clone https://github.com/junegunn/vader.vim.git git clone https://github.com/junegunn/vader.vim.git
fi fi
rm -rf fzf
if [ ! -d fzf-staged ]; then
git clone https://github.com/junegunn/fzf.git fzf-staged
fi
cat > /tmp/mini-vimrc << VIMRC cat > /tmp/mini-vimrc << VIMRC
set rtp+=vader.vim set rtp+=vader.vim
source $PLUG_SRC source $PLUG_SRC
VIMRC VIMRC
if [ "$1" = '!' ]; then if [ "$1" = '!' ]; then
/usr/local/bin/vim -Nu /tmp/mini-vimrc -c 'Vader! workflow.vader' > /dev/null /usr/local/bin/vim -Nu /tmp/mini-vimrc -c 'Vader! workflow.vader' > /dev/null &&
/usr/local/bin/vim -Nu /tmp/mini-vimrc -c 'let g:plug_threads = 1 | Vader! workflow.vader' > /dev/null
else else
/usr/local/bin/vim -Nu /tmp/mini-vimrc -c 'Vader workflow.vader' /usr/local/bin/vim -Nu /tmp/mini-vimrc -c 'Vader workflow.vader'
fi fi

View File

@@ -1,6 +1,9 @@
Execute (Initialize test environment): Execute (Initialize test environment):
Save &rtp, g:plugs, g:plug_home, $MYVIMRC Save &rtp, g:plugs, g:plug_home, $MYVIMRC
let first_rtp = split(&rtp, ',')[0]
let last_rtp = split(&rtp, ',')[-1]
let vader = fnamemodify(globpath(&rtp, 'autoload/vader.vim'), ':h:h') let vader = fnamemodify(globpath(&rtp, 'autoload/vader.vim'), ':h:h')
let plug = fnamemodify(globpath(&rtp, 'autoload/plug.vim'), ':h:h') let plug = fnamemodify(globpath(&rtp, 'autoload/plug.vim'), ':h:h')
set rtp=$HOME/.vim,$VIM/vimfiles,$VIMRUNTIME,$VIM/vimfiles/after,$HOME/.vim/after set rtp=$HOME/.vim,$VIM/vimfiles,$VIMRUNTIME,$VIM/vimfiles/after,$HOME/.vim/after
@@ -24,6 +27,12 @@ Execute (Initialize test environment):
g/^$/d g/^$/d
endfunction endfunction
function! AssertExpect(bang, pat, cnt)
let op = a:bang ? '==' : '=~'
AssertEqual a:cnt, len(filter(getline(1, '$'), "v:val ".op." '".a:pat."'"))
endfunction
command! -nargs=+ -bang AssertExpect call AssertExpect('<bang>' == '!', <args>)
let g:vimrc_reloaded = 0 let g:vimrc_reloaded = 0
let vimrc = tempname() let vimrc = tempname()
call writefile(['let g:vimrc_reloaded += 1'], vimrc) call writefile(['let g:vimrc_reloaded += 1'], vimrc)
@@ -68,15 +77,21 @@ Execute (Subsequent plug#begin() calls will reuse g:plug_home):
Execute (Test Plug command): Execute (Test Plug command):
" Git repo with branch " Git repo with branch
Plug 'junegunn/seoul256.vim', 'no-t_co' Plug 'junegunn/seoul256.vim', 'yes-t_co'
AssertEqual 'https://git:@github.com/junegunn/seoul256.vim.git', g:plugs['seoul256.vim'].uri AssertEqual 'https://git:@github.com/junegunn/seoul256.vim.git', g:plugs['seoul256.vim'].uri
AssertEqual join([temp_plugged, 'seoul256.vim/'], '/'), g:plugs['seoul256.vim'].dir AssertEqual join([temp_plugged, 'seoul256.vim/'], '/'), g:plugs['seoul256.vim'].dir
AssertEqual 'yes-t_co', g:plugs['seoul256.vim'].branch
Plug 'junegunn/seoul256.vim', { 'branch': 'no-t_co' } " Using branch option
AssertEqual 'no-t_co', g:plugs['seoul256.vim'].branch AssertEqual 'no-t_co', g:plugs['seoul256.vim'].branch
" Git repo with tag " Git repo with tag
Plug 'junegunn/goyo.vim', '1.5.3' Plug 'junegunn/goyo.vim', '1.5.2'
AssertEqual 'https://git:@github.com/junegunn/goyo.vim.git', g:plugs['goyo.vim'].uri AssertEqual 'https://git:@github.com/junegunn/goyo.vim.git', g:plugs['goyo.vim'].uri
AssertEqual join([temp_plugged, 'goyo.vim/'], '/'), g:plugs['goyo.vim'].dir AssertEqual join([temp_plugged, 'goyo.vim/'], '/'), g:plugs['goyo.vim'].dir
AssertEqual '1.5.2', g:plugs['goyo.vim'].branch
Plug 'junegunn/goyo.vim', { 'tag': '1.5.3' } " Using tag option
AssertEqual '1.5.3', g:plugs['goyo.vim'].branch AssertEqual '1.5.3', g:plugs['goyo.vim'].branch
" Git URI " Git URI
@@ -103,17 +118,19 @@ Execute (Plug command with dictionary option):
Execute (PlugStatus before installation): Execute (PlugStatus before installation):
PlugStatus PlugStatus
AssertEqual 4, len(filter(getline(1, line('$')), 'v:val =~ "Not found"')) AssertExpect 'Not found', 4
q q
Execute (PlugClean before installation): Execute (PlugClean before installation):
PlugClean PlugClean
AssertEqual 1, len(filter(getline(1, line('$')), 'v:val =~ "Already clean"')) AssertExpect 'Already clean', 1
q q
Execute (plug#end() updates &rtp): Execute (plug#end() updates &rtp):
call plug#end() call plug#end()
Assert len(&rtp) > len(basertp) Assert len(&rtp) > len(basertp)
AssertEqual first_rtp, split(&rtp, ',')[0]
AssertEqual last_rtp, split(&rtp, ',')[-1]
Execute (Yet, plugins are not available): Execute (Yet, plugins are not available):
Assert empty(globpath(&rtp, 'autoload/emoji.vim')) Assert empty(globpath(&rtp, 'autoload/emoji.vim'))
@@ -128,12 +145,13 @@ Execute (Plugin available after installation):
Execute (PlugClean after installation): Execute (PlugClean after installation):
PlugClean PlugClean
AssertEqual 1, len(filter(getline(1, line('$')), 'v:val =~ "Already clean"')) AssertExpect 'Already clean', 1
q q
Execute (PlugStatus after installation): Execute (PlugStatus after installation):
PlugStatus PlugStatus
AssertEqual 4, len(filter(getline(1, line('$')), 'v:val =~ "OK"')) Log getline(1, '$')
AssertExpect 'OK', 4
q q
Execute (Change tag of goyo.vim): Execute (Change tag of goyo.vim):
@@ -204,8 +222,8 @@ Expect:
Execute (PlugClean! to remove seoul256.vim): Execute (PlugClean! to remove seoul256.vim):
PlugClean! PlugClean!
" Three removed, emoji left " Three removed, emoji left
AssertEqual 3, len(filter(getline(1, line('$')), 'v:val =~ "^- "')) AssertExpect '^- ', 3
AssertEqual 1, len(filter(getline(1, line('$')), 'v:val =~ "Removed"')) AssertExpect 'Removed', 1
Assert empty(globpath(&rtp, 'colors/seoul256.vim')) Assert empty(globpath(&rtp, 'colors/seoul256.vim'))
Assert !empty(globpath(&rtp, 'autoload/emoji.vim')) Assert !empty(globpath(&rtp, 'autoload/emoji.vim'))
q q
@@ -231,15 +249,15 @@ Expect:
Execute (PlugClean! to remove vim-emoji): Execute (PlugClean! to remove vim-emoji):
PlugClean! PlugClean!
AssertEqual 1, len(filter(getline(1, line('$')), 'v:val =~ "^- "')) AssertExpect '^- ', 1
AssertEqual 1, len(filter(getline(1, line('$')), 'v:val =~ "Removed"')) AssertExpect 'Removed', 1
Assert empty(globpath(&rtp, 'colors/seoul256.vim')) Assert empty(globpath(&rtp, 'colors/seoul256.vim'))
Assert empty(globpath(&rtp, 'autoload/emoji.vim')) Assert empty(globpath(&rtp, 'autoload/emoji.vim'))
q q
Execute (PlugUpdate to install both again): Execute (PlugUpdate to install both again):
PlugUpdate PlugUpdate
AssertEqual 2, len(filter(getline(1, line('$')), 'v:val =~ "Cloning into"')) AssertExpect '^- [^:]*:', 2
AssertEqual 3, g:vimrc_reloaded AssertEqual 3, g:vimrc_reloaded
Assert !empty(globpath(&rtp, 'colors/seoul256.vim')), 'seoul256.vim should be found' Assert !empty(globpath(&rtp, 'colors/seoul256.vim')), 'seoul256.vim should be found'
Assert !empty(globpath(&rtp, 'autoload/emoji.vim')), 'vim-emoji should be found' Assert !empty(globpath(&rtp, 'autoload/emoji.vim')), 'vim-emoji should be found'
@@ -247,7 +265,7 @@ Execute (PlugUpdate to install both again):
Execute (PlugUpdate only to find out plugins are up-to-date, D key to check): Execute (PlugUpdate only to find out plugins are up-to-date, D key to check):
PlugUpdate PlugUpdate
AssertEqual 2, len(filter(getline(1, line('$')), 'v:val =~ "Already up-to-date"')) AssertExpect 'Already up-to-date', 2
AssertEqual 4, g:vimrc_reloaded AssertEqual 4, g:vimrc_reloaded
normal D normal D
AssertEqual 'No updates.', getline(1) AssertEqual 'No updates.', getline(1)
@@ -354,11 +372,15 @@ Execute (Check commands):
Execute (Partial PlugInstall): Execute (Partial PlugInstall):
PlugInstall vim-fnr vim-easy-align PlugInstall vim-fnr vim-easy-align
AssertExpect 'vim-pseudocl', 1
PlugInstall vim-fnr vim-easy-align 1 PlugInstall vim-fnr vim-easy-align 1
AssertExpect 'vim-pseudocl', 1
q q
Execute (Check dependent plugin): Execute (Check dependent plugin):
Assert &rtp =~ 'pseudocl', &rtp Assert &rtp =~ 'pseudocl', &rtp
AssertEqual first_rtp, split(&rtp, ',')[0]
AssertEqual last_rtp, split(&rtp, ',')[-1]
Given (Unaligned code): Given (Unaligned code):
a=1 a=1
@@ -384,13 +406,186 @@ Execute (On-demand loading based on filetypes):
set ft=redis set ft=redis
Assert exists(':RedisExecute'), 'RedisExecute command is now found' Assert exists(':RedisExecute'), 'RedisExecute command is now found'
**********************************************************************
~ Local (unmanaged) plugins
**********************************************************************
Execute (Add unmanaged plugin):
let fzf = fnamemodify(g:vader_file, ':h') . '/fzf'
Log fzf
call plug#begin()
Plug fzf, { 'on': 'SomeCommand' }
call plug#end()
" Check uri field
Assert !has_key(g:plugs.fzf, 'uri'), 'Should not have uri field'
" Check dir field
AssertEqual fzf.'/', g:plugs.fzf.dir
" Trailing slashes and backslashes should be stripped
for suffix in ['///', '/\/\/']
call plug#begin()
Plug fzf.suffix, { 'on': 'SomeCommand' }
call plug#end()
" Check dir field
AssertEqual fzf.'/', g:plugs.fzf.dir
endfor
Execute (Plug block for following tests):
call plug#begin()
Plug 'junegunn/vim-easy-align'
Plug fzf, { 'on': 'SomeCommand' }
call plug#end()
" Remove plugins from previous tests
PlugClean!
Execute (PlugInstall will only install vim-easy-align):
PlugInstall
Log getline(1, '$')
AssertExpect 'fzf', 0
q
Execute (PlugUpdate will only update vim-easy-align):
PlugUpdate
Log getline(1, '$')
AssertExpect 'fzf', 0
q
Execute (PlugClean should not care about unmanaged plugins):
PlugClean
Log getline(1, '$')
AssertExpect 'fzf', 0
q
Execute (PlugStatus should point out that the plugin is missing):
PlugStatus
Log getline(1, '$')
AssertExpect 'x fzf', 1
AssertExpect 'Not found', 1
q
Execute (Deploy unmanaged plugin):
Assert !exists(':FZF'), ':FZF command should not exist'
call rename('fzf-staged', 'fzf')
Execute (PlugUpdate still should not care):
PlugUpdate
Log getline(1, '$')
AssertExpect 'fzf', 0
q
Execute (PlugStatus with no error):
PlugStatus
Log getline(1, '$')
AssertExpect 'x fzf', 0
AssertExpect 'Not found', 0
q
Execute (Check &rtp after SomeCommand):
Log &rtp
Assert &rtp !~ 'fzf'
silent! SomeCommand
Assert &rtp =~ 'fzf'
AssertEqual first_rtp, split(&rtp, ',')[0]
AssertEqual last_rtp, split(&rtp, ',')[-1]
Execute (Common parent):
call plug#begin()
Plug 'junegunn/vim-pseudocl'
Plug 'junegunn/vim-fnr'
Plug 'junegunn/vim-oblique'
call plug#end()
PlugInstall
Log getline(1, '$')
AssertExpect! '[===]', 1
q
**********************************************************************
~ Frozen plugins
**********************************************************************
Execute (Frozen plugin are not installed nor updated):
call plug#begin()
Plug 'junegunn/vim-easy-align', { 'frozen': 1 }
call plug#end()
redir => output
silent PlugInstall
redir END
Assert output =~ 'No plugin to install'
redir => output
silent PlugUpdate
redir END
Assert output =~ 'No plugin to update'
Execute (But you can still install it if the name is given as the argument):
PlugInstall vim-easy-align
Log getline(1, '$')
AssertEqual 1, len(filter(getline(1, '$'), 'v:val =~ "vim-easy-align"'))
q
PlugUpdate vim-easy-align
Log getline(1, '$')
AssertEqual 1, len(filter(getline(1, '$'), 'v:val =~ "vim-easy-align"'))
q
**********************************************************************
~ Retry
**********************************************************************
Execute (Retry failed tasks):
call plug#begin()
Plug 'junegunn/vim-easy-align'
Plug 'junegunn/aaaaaaaaaaaaaa'
call plug#end()
PlugInstall
Log getline(1, '$')
AssertExpect 'x aaa', 1
AssertExpect '- vim-easy-align', 1
normal R
Log getline(1, '$')
AssertExpect 'x aaa', 1
AssertExpect '- vim-easy-align', 0
AssertExpect! '[x]', 1
q
call plug#begin()
Plug 'junegunn/vim-easy-align'
Plug 'junegunn/aaaaaaaaaaaaaa'
Plug 'junegunn/bbbbbbbbbbbbbb'
Plug 'junegunn/cccccccccccccc'
call plug#end()
" Ruby installer
PlugUpdate
normal R
AssertExpect '- vim-easy-align', 0
AssertExpect! '[xxx]', 1
q
" Vim installer
PlugUpdate 1
normal R
AssertExpect '- vim-easy-align', 0
AssertExpect! '[xxx]', 1
q
Execute (Cleanup): Execute (Cleanup):
call system('rm -rf '.temp_plugged) call system('rm -rf '.temp_plugged)
call rename('fzf', 'fzf-staged')
unlet g:plugs unlet g:plugs
unlet g:plug_home unlet g:plug_home
unlet g:vimrc_reloaded unlet g:vimrc_reloaded
unlet temp_plugged vader plug basertp save_rtp repo lnum unlet temp_plugged vader plug basertp save_rtp repo lnum fzf
delf PlugStatusSorted delf PlugStatusSorted
delf AssertExpect
delc AssertExpect
Restore Restore