43 Commits
0.3.2 ... 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
Junegunn Choi
f90afc9081 Remove images from repo 2014-06-23 23:39:48 +09:00
Junegunn Choi
612b9b3afd Fix test cases for travis-ci 2014-06-23 13:16:14 +09:00
Junegunn Choi
58891e05be Travis-CI integration 2014-06-23 12:57:46 +09:00
Junegunn Choi
baf7b18f73 Update test runner script 2014-06-23 12:53:51 +09:00
Junegunn Choi
cc37ed48be Improve PlugStatus message
Invalid branch/tag: %s (expected: %s). Try PlugUpdate.
2014-06-23 12:22:25 +09:00
Junegunn Choi
afe7dc6f8f Use case-sensitive match 2014-06-23 04:04:03 +09:00
Junegunn Choi
8863a3a53c Fix #28: False alarm from PlugStatus when tag used 2014-06-23 04:02:49 +09:00
Junegunn Choi
ee04a646d3 Fix: dependent plugins not loaded after initial installaion 2014-06-22 21:49:51 +09:00
Junegunn Choi
6ddee62977 Ensure ftplugin files are loaded (#24) 2014-06-22 13:09:18 +09:00
Junegunn Choi
8cf5fca9ca Revert "Ensure ftplugin files are loaded (#24)"
This reverts commit a026eb39c4.

Conflicts:
	plug.vim
2014-06-22 12:49:22 +09:00
Junegunn Choi
347fccb030 Revert "Remove FileType autocmd after loaded"
This reverts commit db3f5ad5c3.

Conflicts:
	plug.vim
2014-06-22 12:45:21 +09:00
Junegunn Choi
a026eb39c4 Ensure ftplugin files are loaded (#24)
If `filetype plugin on` is called before `plug#end()`, filetype
plugin handler is invoked before ODL autocmd from vim-plug which
updates runtimepath and ftplugin files are not loaded.
2014-06-22 10:27:15 +09:00
Junegunn Choi
4d352e1849 Revert "Clear #filetypeplugin for filetype-based ODL (#24)"
This reverts commit 1d477a1a01.
2014-06-22 10:21:58 +09:00
Junegunn Choi
db3f5ad5c3 Remove FileType autocmd after loaded 2014-06-22 09:58:14 +09:00
14 changed files with 643 additions and 211 deletions

12
.travis.yml Normal file
View File

@@ -0,0 +1,12 @@
language: vim
before_script: |
hg clone https://code.google.com/p/vim/
cd vim
./configure --with-features=huge --enable-rubyinterp
make
sudo make install
cd -
script: |
test/run !

View File

@@ -1,11 +1,12 @@
![vim-plug](https://raw.github.com/junegunn/vim-plug/master/plug.png) ![vim-plug](https://raw.github.com/junegunn/vim-plug/master/plug.png)
![travis-ci](https://travis-ci.org/junegunn/vim-plug.svg?branch=master)
A single-file Vim plugin manager. 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/vim-plug/master/gif/vim-plug.gif) ![](https://raw.github.com/junegunn/i/master/vim-plug/installer.gif)
### Pros. ### Pros.
@@ -36,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 |
@@ -69,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
@@ -172,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.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 528 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 306 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 922 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 247 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 650 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 521 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.3 MiB

437
plug.vim
View File

@@ -58,7 +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:loaded = {} 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')
@@ -123,17 +123,9 @@ function! plug#end()
augroup END augroup END
augroup! PlugLOD augroup! PlugLOD
endif endif
let lod = {}
filetype off filetype off
if exists('#filetypeplugin') &&
\ !empty(filter(values(g:plugs), 'has_key(v:val, "for")'))
unlet! g:did_load_ftplugin
augroup filetypeplugin
autocmd!
augroup END
augroup! filetypeplugin
endif
" we want to make sure the plugin directories are added to rtp in the same " we want to make sure the plugin directories are added to rtp in the same
" order that they are registered with the Plug command. since the s:add_rtp " 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 " function uses ^= to add plugin directories to the front of the rtp, we
@@ -150,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
@@ -168,23 +161,52 @@ function! plug#end()
for vim in split(globpath(s:rtp(plug), 'ftdetect/**/*.vim'), '\n') for vim in split(globpath(s:rtp(plug), 'ftdetect/**/*.vim'), '\n')
execute 'source '.vim execute 'source '.vim
endfor endfor
augroup PlugLOD for key in s:to_a(plug.for)
execute printf('autocmd FileType %s call <SID>lod_ft(%s, %s)', if !has_key(lod, key)
\ join(s:to_a(plug.for), ','), string(name), string(plug)) let lod[key] = []
augroup END endif
call add(lod[key], name)
endfor
endif endif
endfor endfor
for [key, names] in items(lod)
augroup PlugLOD
execute printf('autocmd FileType %s call <SID>lod_ft(%s, %s)',
\ key, string(key), string(reverse(names)))
augroup END
endfor
call s:reorg_rtp()
filetype plugin indent on filetype plugin indent on
syntax on syntax on
endfunction endfunction
function! s:rtp(spec) if s:is_win
let rtp = s:dirpath(a:spec.dir . get(a:spec, 'rtp', '')) function! s:rtp(spec)
if s:is_win let rtp = s:dirpath(a:spec.dir . get(a:spec, 'rtp', ''))
let rtp = substitute(rtp, '\\*$', '', '') return substitute(rtp, '\\*$', '', '')
endif endfunction
return rtp
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')
@@ -192,8 +214,20 @@ 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
@@ -207,24 +241,27 @@ function! s:lod(plug, types)
endfor endfor
endfunction endfunction
function! s:lod_ft(name, plug) function! s:lod_ft(pat, names)
if has_key(s:loaded, a:name) for name in a:names
return call s:lod(g:plugs[name], ['plugin', 'after'])
endif endfor
call s:lod(a:plug, ['plugin', 'after']) call s:reorg_rtp()
let s:loaded[a:name] = 1 execute 'autocmd! PlugLOD FileType ' . a:pat
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,21 +295,32 @@ function! s:add(...)
return return
endif endif
if plugin =~ ':' let plugin = substitute(plugin, '[/\\]*$', '', '')
let uri = plugin let name = substitute(split(plugin, '/')[-1], '\.git$', '', '')
else if !a:force && has_key(g:plugs, name)
if plugin !~ '/' let s:extended[name] = g:plugs[name]
let plugin = 'vim-scripts/'. plugin return
endif
let uri = 'https://git:@github.com/' . plugin . '.git'
endif endif
let name = substitute(split(plugin, '/')[-1], '\.git$', '', '') if plugin[0] =~ '[/$~]' || plugin =~? '^[a-z]:'
if !force && has_key(g:plugs, name) | return | endif let spec = extend(opts, { 'dir': s:dirpath(expand(plugin)) })
else
if plugin =~ ':'
let uri = plugin
else
if plugin !~ '/'
let plugin = 'vim-scripts/'. plugin
endif
let uri = 'https://git:@github.com/' . plugin . '.git'
endif
let dir = s:dirpath( fnamemodify(join([g:plug_home, name], '/'), ':p') )
let spec = extend(opts, { 'dir': dir, 'uri': uri })
endif
let dir = s:dirpath( fnamemodify(join([g:plug_home, name], '/'), ':p') )
let spec = extend(opts, { 'dir': dir, 'uri': uri })
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
@@ -406,20 +486,49 @@ function! s:update_impl(pull, args) abort
normal! 2G normal! 2G
redraw redraw
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
call s:update_parallel(a:pull, todo, threads) try
let imd = &imd
if s:mac_gui
set noimd
endif
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
if len(g:plugs) > len
call plug#end()
endif
call s:finish(a:pull) call s:finish(a:pull)
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
@@ -427,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)
@@ -462,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),
@@ -475,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
@@ -495,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 end
if lnum = where.call(name)
$curbuf.delete lnum
lnum = 4 if ing && lnum > maxy
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
else
fd = IO.popen(cmd)
data = fd.read.chomp
fd.close
end end
[$? == 0, data] else
fd = IO.popen(cmd).extend(PlugStream)
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
end end
[$? == 0, data.chomp]
rescue Timeout::Error, Interrupt => e rescue Timeout::Error, Interrupt => e
if fd && !fd.closed? if fd && !fd.closed?
pids = [fd.pid] pids = [fd.pid]
@@ -566,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
@@ -574,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
} }
@@ -590,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 {
@@ -600,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/
@@ -617,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
@@ -625,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
@@ -687,6 +853,11 @@ function! s:system(cmd)
return system(s:is_win ? '('.a:cmd.')' : a:cmd) return system(s:is_win ? '('.a:cmd.')' : a:cmd)
endfunction endfunction
function! s:system_chomp(str)
let ret = s:system(a:str)
return v:shell_error ? '' : substitute(ret, '\n$', '', '')
endfunction
function! s:git_valid(spec, check_branch, cd) function! s:git_valid(spec, check_branch, cd)
let ret = 1 let ret = 1
let msg = 'OK' let msg = 'OK'
@@ -694,7 +865,7 @@ function! s:git_valid(spec, check_branch, cd)
if a:cd | execute "cd " . s:esc(a:spec.dir) | endif 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 = split(s:system("git rev-parse --abbrev-ref HEAD 2>&1 && git config remote.origin.url"), '\n')
let remote = result[-1] let remote = result[-1]
if v:shell_error != 0 if v:shell_error
let msg = join([remote, "PlugClean required."], "\n") let msg = join([remote, "PlugClean required."], "\n")
let ret = 0 let ret = 0
elseif !s:compare_git_uri(remote, a:spec.uri) elseif !s:compare_git_uri(remote, a:spec.uri)
@@ -704,9 +875,13 @@ function! s:git_valid(spec, check_branch, cd)
let ret = 0 let ret = 0
elseif a:check_branch elseif a:check_branch
let branch = result[0] let branch = result[0]
if a:spec.branch != branch if a:spec.branch !=# branch
let msg = 'Invalid branch: '.branch.'. Try PlugUpdate.' let tag = s:system_chomp('git describe --exact-match --tags HEAD 2>&1')
let ret = 0 if a:spec.branch !=# tag
let msg = printf('Invalid branch/tag: %s (expected: %s). Try PlugUpdate.',
\ (empty(tag) ? branch : tag), a:spec.branch)
let ret = 0
endif
endif endif
endif endif
if a:cd | cd - | endif if a:cd | cd - | endif
@@ -724,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
@@ -826,10 +1002,18 @@ 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 isdirectory(spec.dir) if has_key(spec, 'uri')
let [valid, msg] = s:git_valid(spec, 1, 1) if isdirectory(spec.dir)
let [valid, msg] = s:git_valid(spec, 1, 1)
else
let [valid, msg] = [0, 'Not found. Try PlugInstall.']
endif
else else
let [valid, msg] = [0, 'Not found. Try PlugInstall.'] if isdirectory(spec.dir)
let [valid, msg] = [1, 'OK']
else
let [valid, msg] = [0, 'Not found.']
endif
endif endif
let cnt += 1 let cnt += 1
let ecnt += !valid let ecnt += !valid
@@ -893,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
@@ -915,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

@@ -7,8 +7,10 @@ Test cases for vim-plug
### Run ### Run
```vim ```
:e workflow.vader | Vader ./run
./run !
``` ```
### TODO ### TODO
@@ -18,7 +20,6 @@ Test cases for the following features are currently missing:
- Output formatting - Output formatting
- Timeout or interrupt cleaning up git processes - Timeout or interrupt cleaning up git processes
- User prompt in PlugClean command - User prompt in PlugClean command
- Automatic dependency resolution using Plugfile
- Single-threaded installer - Single-threaded installer
- Windows support - Windows support

View File

@@ -5,15 +5,24 @@ cd ..
PLUG_SRC=$(pwd)/plug.vim PLUG_SRC=$(pwd)/plug.vim
cd - > /dev/null cd - > /dev/null
export VADER_RTP=$TMPDIR/vader-rtp if [ ! -d vader.vim ]; then
vim -e +Vader -c ':call writefile([fnamemodify(globpath(&rtp, "autoload/vader.vim"), ":h:h")], $VADER_RTP)' +q git clone https://github.com/junegunn/vader.vim.git
fi
MINI_VIMRC=$TMPDIR/mini-vimrc rm -rf fzf
cat > $MINI_VIMRC << EOF if [ ! -d fzf-staged ]; then
let \$MYVIMRC = '$MINI_VIMRC' git clone https://github.com/junegunn/fzf.git fzf-staged
set nocompatible fi
set rtp=$(cat $VADER_RTP)
cat > /tmp/mini-vimrc << VIMRC
set rtp+=vader.vim
source $PLUG_SRC source $PLUG_SRC
EOF VIMRC
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 'let g:plug_threads = 1 | Vader! workflow.vader' > /dev/null
else
/usr/local/bin/vim -Nu /tmp/mini-vimrc -c 'Vader workflow.vader'
fi
vim -u $MINI_VIMRC +Vader*

View File

@@ -1,5 +1,8 @@
Execute (Initialize test environment): Execute (Initialize test environment):
Save &rtp, 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')
@@ -15,6 +18,21 @@ Execute (Initialize test environment):
colo default colo default
pclose pclose
function! PlugStatusSorted()
PlugStatus
%y
q
normal! P
%sort
g/^$/d
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)
@@ -59,14 +77,26 @@ 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
Plug 'junegunn/goyo.vim', '1.5.2'
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 '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
" Git URI " Git URI
Plug 'git@github.com:junegunn/vim-emoji.git' Plug 'https://bitbucket.org/junegunn/vim-emoji.git'
AssertEqual 'git@github.com:junegunn/vim-emoji.git', g:plugs['vim-emoji'].uri AssertEqual 'https://bitbucket.org/junegunn/vim-emoji.git', g:plugs['vim-emoji'].uri
AssertEqual 'master', g:plugs['vim-emoji'].branch AssertEqual 'master', g:plugs['vim-emoji'].branch
AssertEqual join([temp_plugged, 'vim-emoji/'], '/'), g:plugs['vim-emoji'].dir AssertEqual join([temp_plugged, 'vim-emoji/'], '/'), g:plugs['vim-emoji'].dir
@@ -75,28 +105,32 @@ Execute (Test Plug command):
AssertEqual 'https://git:@github.com/vim-scripts/beauty256.git', g:plugs.beauty256.uri AssertEqual 'https://git:@github.com/vim-scripts/beauty256.git', g:plugs.beauty256.uri
AssertEqual 'master', g:plugs.beauty256.branch AssertEqual 'master', g:plugs.beauty256.branch
AssertEqual 3, len(g:plugs) AssertEqual 4, len(g:plugs)
Execute (Plug command with dictionary option): Execute (Plug command with dictionary option):
Log string(g:plugs)
Plug 'junegunn/seoul256.vim', { 'branch': 'no-t_co', 'rtp': '././' } Plug 'junegunn/seoul256.vim', { 'branch': 'no-t_co', 'rtp': '././' }
AssertEqual join([temp_plugged, 'seoul256.vim/'], '/'), g:plugs['seoul256.vim'].dir AssertEqual join([temp_plugged, 'seoul256.vim/'], '/'), g:plugs['seoul256.vim'].dir
AssertEqual '././', g:plugs['seoul256.vim'].rtp AssertEqual '././', g:plugs['seoul256.vim'].rtp
AssertEqual 3, len(g:plugs) Log string(g:plugs)
AssertEqual 4, len(g:plugs)
Execute (PlugStatus before installation): Execute (PlugStatus before installation):
PlugStatus PlugStatus
AssertEqual 3, 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'))
@@ -111,30 +145,50 @@ 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 3, len(filter(getline(1, line('$')), 'v:val =~ "OK"')) Log getline(1, '$')
AssertExpect 'OK', 4
q q
Execute (Change tag of goyo.vim):
call plug#begin()
Plug 'junegunn/goyo.vim'
call plug#end()
Execute (PlugStatus):
call PlugStatusSorted()
Expect:
Invalid branch/tag: 1.5.3 (expected: master). Try PlugUpdate.
Finished. 1 error(s).
[=]
x goyo.vim:
Execute (PlugUpdate to set the right branch):
PlugUpdate
call PlugStatusSorted()
AssertEqual 2, g:vimrc_reloaded
Expect:
- goyo.vim: OK
Finished. 0 error(s).
[=]
Execute (Change branch of seoul256.vim): Execute (Change branch of seoul256.vim):
call plug#begin() call plug#begin()
Plug 'junegunn/seoul256.vim' Plug 'junegunn/seoul256.vim'
Plug 'git@github.com:junegunn/vim-emoji.git' Plug 'https://bitbucket.org/junegunn/vim-emoji.git'
call plug#end() call plug#end()
Execute (PlugStatus): Execute (PlugStatus):
PlugStatus call PlugStatusSorted()
%y
q
normal! P
%sort
g/^$/d
Expect: Expect:
Invalid branch: no-t_co. Try PlugUpdate. Invalid branch/tag: no-t_co (expected: master). Try PlugUpdate.
- vim-emoji: OK - vim-emoji: OK
Finished. 1 error(s). Finished. 1 error(s).
[==] [==]
@@ -143,16 +197,11 @@ Expect:
Execute (Change URI of seoul256.vim): Execute (Change URI of seoul256.vim):
call plug#begin() call plug#begin()
Plug 'junegunn.choi/seoul256.vim' Plug 'junegunn.choi/seoul256.vim'
Plug 'git@github.com:junegunn/vim-emoji.git' Plug 'https://bitbucket.org/junegunn/vim-emoji.git'
call plug#end() call plug#end()
Execute (PlugStatus): Execute (PlugStatus):
PlugStatus call PlugStatusSorted()
%y
q
normal! P
%sort
g/^$/d
Expect: Expect:
Expected: https://git:@github.com/junegunn.choi/seoul256.vim.git Expected: https://git:@github.com/junegunn.choi/seoul256.vim.git
@@ -172,7 +221,9 @@ Expect:
Execute (PlugClean! to remove seoul256.vim): Execute (PlugClean! to remove seoul256.vim):
PlugClean! PlugClean!
AssertEqual 1, len(filter(getline(1, line('$')), 'v:val =~ "Removed"')) " Three removed, emoji left
AssertExpect '^- ', 3
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
@@ -184,16 +235,11 @@ Execute (Change GIT URI of vim-emoji):
call plug#end() call plug#end()
Execute (PlugStatus): Execute (PlugStatus):
PlugStatus call PlugStatusSorted()
%y
q
normal! P
%sort
g/^$/d
Expect: Expect:
Expected: https://git:@github.com/junegunn/vim-emoji.git Expected: https://git:@github.com/junegunn/vim-emoji.git
Invalid URI: git@github.com:junegunn/vim-emoji.git Invalid URI: https://bitbucket.org/junegunn/vim-emoji.git
Not found. Try PlugInstall. Not found. Try PlugInstall.
PlugClean required. PlugClean required.
Finished. 2 error(s). Finished. 2 error(s).
@@ -203,23 +249,24 @@ Expect:
Execute (PlugClean! to remove vim-emoji): Execute (PlugClean! to remove vim-emoji):
PlugClean! PlugClean!
AssertEqual 1, len(filter(getline(1, line('$')), 'v:val =~ "Removed"')) AssertExpect '^- ', 1
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 2, 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'
q q
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 3, g:vimrc_reloaded AssertEqual 4, g:vimrc_reloaded
normal D normal D
AssertEqual 'No updates.', getline(1) AssertEqual 'No updates.', getline(1)
q q
@@ -325,15 +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 (TODO Check dependent plugin): Execute (Check dependent plugin):
^ It is a known issue that when a dependent plugin is installed, it is not
^ immediately added to runtimepath. It only becomes available when
^ plug#end() is called.
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
@@ -359,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 AssertExpect
delc AssertExpect
Restore Restore
source $MYVIMRC