46 Commits
0.3.6 ... 0.4.1

Author SHA1 Message Date
Junegunn Choi
f58d090bb2 Add dir option: managed plugins outside g:plug_home 2014-07-30 19:20:51 +09:00
Junegunn Choi
eeef77e9c8 Merge branch 'vheon-refactoring' into refactoring 2014-07-29 23:37:47 +09:00
Andrea Cedraro
6af2cd8946 Inline substitute inside s:dirpath() 2014-07-29 14:21:11 +02:00
Junegunn Choi
878cdd5309 Unmap / and ? from vim-oblique after test 2014-07-29 19:18:33 +09:00
Junegunn Choi
9bb2da53a0 Replace s:extract_name with a single fnamemodify call 2014-07-29 19:17:12 +09:00
Junegunn Choi
58c06ed77e Use single-quotes whenever possible for consistency 2014-07-29 19:07:09 +09:00
Junegunn Choi
2e691c6feb Define a separate version of s:is_local_plug for Windows 2014-07-29 10:09:05 +09:00
Junegunn Choi
a18087610a Use fnamemodify instead of split hackery
Simpler and faster
2014-07-29 02:42:53 +09:00
Junegunn Choi
276106d987 Performance tuning: reduce the number of s:parse_options calls 2014-07-29 02:11:59 +09:00
Junegunn Choi
d499fc311a Use dot operator instead of get()
The reason I used get() instead of concise dot operator when accessing
`frozen` and `local` properties of plugin spec was to avoid errors when
a user "PlugUpgrade" from an old version of vim-plug whose g:plugs does
not have those properties. Added the code to patch the old version of
g:plugs so that we can safely use dot operators.
2014-07-29 01:51:32 +09:00
Junegunn Choi
c4b4aa8f07 Code cleanup: reuse s:trim() when possible 2014-07-29 00:19:29 +09:00
Junegunn Choi
d690f8d576 Change error reporting method
As suggested by @vheon:
https://github.com/junegunn/vim-plug/pull/40#issuecomment-50278543
2014-07-28 19:56:59 +09:00
Junegunn Choi
8738341ad0 Performance tuning: reduce the number of globpath calls 2014-07-28 19:45:40 +09:00
Junegunn Choi
5ab2024fbb Performace tuning: inlining some function calls 2014-07-28 19:41:05 +09:00
Junegunn Choi
300176ba9f Avoid echoerr inside catch block 2014-07-28 01:27:30 +09:00
Andrea Cedraro
da7d6bd58b Refactor s:add function 2014-07-27 17:38:57 +02:00
Junegunn Choi
b651558c63 Update README 2014-07-27 12:00:36 +09:00
Junegunn Choi
2d815ad2f0 Escape angle brackets in README 2014-07-27 11:58:12 +09:00
Junegunn Choi
3af4079179 Fix typo 2014-07-27 11:55:06 +09:00
Junegunn Choi
e6a594f1ad Change post-hook function to take a dictionary for more control 2014-07-27 11:28:53 +09:00
Junegunn Choi
e741d02ad0 Fix elapsed time to include the time spent in post-update hook 2014-07-27 11:15:13 +09:00
Junegunn Choi
b2208640d4 Update documentation 2014-07-27 11:06:47 +09:00
Junegunn Choi
aa49c38586 Don't need <Plug> map (#38) 2014-07-27 03:16:44 +09:00
Junegunn Choi
b6b10ac17e Print progress of post-update hooks using :! (#38) 2014-07-27 03:07:37 +09:00
Junegunn Choi
706f7e00ea Merge pull request #39 from vheon/fix-type-parameter-clarity
Replace return value of type() with call to the function
2014-07-27 02:22:31 +09:00
Andrea Cedraro
6ff1031339 Replace return value of type() with named values 2014-07-26 19:14:46 +02:00
Junegunn Choi
0936877399 Don't check for the need for post-update hook when interrupted 2014-07-27 00:42:23 +09:00
Junegunn Choi
d956e16f15 Minor refactoring 2014-07-26 22:58:34 +09:00
Junegunn Choi
f98c8456fa Post-update hook (do option) 2014-07-26 22:49:18 +09:00
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
4 changed files with 748 additions and 174 deletions

108
README.md
View File

@@ -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,31 @@ 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 |
| `dir` | Custom directory for the plugin |
| `do` | Post-update hook (string or funcref) |
| `on` | On-demand loading: Commands or `<Plug>`-mappings |
| `for` | On-demand loading: File types |
| `frozen` | Do not install/update plugin unless explicitly given as the argument |
### 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
@@ -107,6 +121,48 @@ Plug 'tpope/vim-fireplace', { 'for': 'clojure' }
Plug 'junegunn/vader.vim', { 'on': 'Vader', 'for': 'vader' } Plug 'junegunn/vader.vim', { 'on': 'Vader', 'for': 'vader' }
``` ```
### Post-installation/update hooks
There are some plugins that require extra steps after installation or update.
In that case, use `do` option to describe the task to be performed.
```vim
Plug 'Valloric/YouCompleteMe', { 'do': './install.sh' }
```
If you need more control, you can pass a reference to a Vim function that
takes a single argument.
```vim
function! BuildYCM(info)
" info is a dictionary with two fields
" - name: name of the plugin
" - status: 'installed' or 'updated'
if a:info.status == 'installed'
!./install.sh
endif
endfunction
Plug 'Valloric/YouCompleteMe', { 'do': function('BuildYCM') }
```
Both forms of post-update hook are executed inside the directory of the plugin.
Make sure to escape BARs when you write `do` option inline as they are
mistakenly recognized as command separator for Plug command.
```vim
Plug 'junegunn/fzf', { 'do': 'yes \| ./install' }
```
But you can avoid the escaping if you extract the inline specification using a
variable (or any Vimscript expression) as follows:
```vim
let g:fzf_install = 'yes | ./install'
Plug 'junegunn/fzf', { 'do': g:fzf_install }
```
### Dependency resolution ### Dependency resolution
See [Dependency See [Dependency
@@ -116,6 +172,7 @@ Resolution](https://github.com/junegunn/vim-plug/wiki/Dependency-Resolution).
- [Writing my own Vim plugin manager](http://junegunn.kr/2013/09/writing-my-own-vim-plugin-manager) - [Writing my own Vim plugin manager](http://junegunn.kr/2013/09/writing-my-own-vim-plugin-manager)
- [Thoughts on Vim plugin dependency](http://junegunn.kr/2013/09/thoughts-on-vim-plugin-dependency) - [Thoughts on Vim plugin dependency](http://junegunn.kr/2013/09/thoughts-on-vim-plugin-dependency)
- [Vim plugins and startup time](http://junegunn.kr/2014/07/vim-plugins-and-startup-time)
### FAQ/Troubleshooting ### FAQ/Troubleshooting
@@ -173,17 +230,14 @@ 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 #### Migrating from other plugin managers
You may submit a request for a new feature by [creating an vim-plug does not require any extra statement other than `plug#begin()` and
issue](https://github.com/junegunn/vim-plug/issues). However, please be minded `plug#end()`. You can remove `filetype off`, `filetype plugin indent on` and
that this is an opinionated software and I want to keep the feature set as small `syntax on` from your .vimrc as they are automatically handled by
as possible. So I may not agree with you on the necessity of the suggested `plug#end()`.
feature. If that happens, I suggest the following options.
1. Check out [Vundle](https://github.com/gmarik/vundle) or ### License
[NeoBundle](https://github.com/Shougo/neobundle.vim).
They offer broader feature sets. MIT
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.

451
plug.vim
View File

@@ -9,19 +9,29 @@
" "
" Edit your .vimrc " Edit your .vimrc
" "
" call plug#begin() " 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'
" Plug 'junegunn/goyo.vim', { 'on': 'Goyo' } "
" " Plug 'user/repo1', 'branch_or_tag' " " On-demand loading
" " Plug 'user/repo2', { 'rtp': 'vim/plugin/dir', 'branch': 'branch_or_tag' } " Plug 'scrooloose/nerdtree', { 'on': 'NERDTreeToggle' }
" " ... " Plug 'tpope/vim-fireplace', { 'for': 'clojure' }
"
" " Using git URL
" 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()
" "
" Then :PlugInstall to install plugins. (default: ~/.vim/plugged) " Then reload .vimrc and :PlugInstall to install plugins.
" You can change the location of the plugins with plug#begin(path) call. " Visit https://github.com/junegunn/vim-plug for more information.
" "
" "
" Copyright (c) 2014 Junegunn Choi " Copyright (c) 2014 Junegunn Choi
@@ -58,8 +68,16 @@ 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')
let s:base_spec = { 'branch': 'master', 'frozen': 0, 'local': 0 }
let s:TYPE = {
\ 'string': type(''),
\ 'list': type([]),
\ 'dict': type({}),
\ 'funcref': type(function('call'))
\ }
function! plug#begin(...) function! plug#begin(...)
if a:0 > 0 if a:0 > 0
@@ -69,21 +87,18 @@ function! plug#begin(...)
elseif !empty(&rtp) elseif !empty(&rtp)
let home = s:path(split(&rtp, ',')[0]) . '/plugged' let home = s:path(split(&rtp, ',')[0]) . '/plugged'
else else
echoerr "Unable to determine plug home. Try calling plug#begin() with a path argument." return s:err('Unable to determine plug home. Try calling plug#begin() with a path argument.')
return 0
endif endif
if !isdirectory(home) if !isdirectory(home)
try try
call mkdir(home, 'p') call mkdir(home, 'p')
catch catch
echoerr 'Invalid plug directory: '. home return s:err('Invalid plug directory: '. home)
return 0
endtry endtry
endif endif
if !executable('git') if !executable('git')
echoerr "`git' executable not found. vim-plug requires git." return s:err('`git` executable not found. vim-plug requires git.')
return 0
endif endif
let g:plug_home = home let g:plug_home = home
@@ -95,7 +110,7 @@ function! plug#begin(...)
command! -nargs=* -complete=customlist,s:names PlugInstall call s:install(<f-args>) command! -nargs=* -complete=customlist,s:names PlugInstall call s:install(<f-args>)
command! -nargs=* -complete=customlist,s:names PlugUpdate call s:update(<f-args>) command! -nargs=* -complete=customlist,s:names PlugUpdate call s:update(<f-args>)
command! -nargs=0 -bang PlugClean call s:clean('<bang>' == '!') command! -nargs=0 -bang PlugClean call s:clean('<bang>' == '!')
command! -nargs=0 PlugUpgrade if s:upgrade() | execute "source ". s:me | endif command! -nargs=0 PlugUpgrade if s:upgrade() | call s:upgrade_specs() | execute 'source '. s:me | endif
command! -nargs=0 PlugStatus call s:status() command! -nargs=0 PlugStatus call s:status()
command! -nargs=0 PlugDiff call s:diff() command! -nargs=0 PlugDiff call s:diff()
@@ -103,17 +118,18 @@ function! plug#begin(...)
endfunction endfunction
function! s:to_a(v) function! s:to_a(v)
return type(a:v) == 3 ? a:v : [a:v] return type(a:v) == s:TYPE.list ? a:v : [a:v]
endfunction endfunction
function! plug#end() function! plug#end()
if !exists('g:plugs') if !exists('g:plugs')
echoerr 'Call plug#begin() first' return s:err('Call plug#begin() first')
return
endif endif
let keys = keys(g:plugs) let keys = keys(g:plugs)
let plugfiles = s:find_plugfiles()
while !empty(keys) while !empty(keys)
let keys = keys(s:extend(keys)) " No need to look for Plugfiles more than once
let keys = keys(s:extend(keys, plugfiles))
endwhile endwhile
if exists('#PlugLOD') if exists('#PlugLOD')
@@ -142,15 +158,15 @@ function! plug#end()
if cmd =~ '^<Plug>.\+' if cmd =~ '^<Plug>.\+'
if empty(mapcheck(cmd)) && empty(mapcheck(cmd, 'i')) if empty(mapcheck(cmd)) && empty(mapcheck(cmd, 'i'))
for [mode, map_prefix, key_prefix] in for [mode, map_prefix, key_prefix] in
\ [['i', "<C-O>", ''], ['n', '', ''], ['v', '', 'gv'], ['o', '', '']] \ [['i', '<C-O>', ''], ['n', '', ''], ['v', '', 'gv'], ['o', '', '']]
execute printf( execute printf(
\ "%snoremap <silent> %s %s:<C-U>call <SID>lod_map(%s, %s, '%s')<CR>", \ '%snoremap <silent> %s %s:<C-U>call <SID>lod_map(%s, %s, "%s")<CR>',
\ mode, cmd, map_prefix, string(cmd), string(name), key_prefix) \ 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(name)) \ cmd, string(cmd), string(name))
endif endif
endfor endfor
@@ -175,46 +191,76 @@ 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
function! s:trim(str)
return substitute(a:str, '[\/]\+$', '', '')
endfunction
if s:is_win if s:is_win
function! s:rtp(spec) function! s:rtp(spec)
let rtp = s:dirpath(a:spec.dir . get(a:spec, 'rtp', '')) return s:path(a:spec.dir . get(a:spec, 'rtp', ''))
return substitute(rtp, '\\*$', '', '')
endfunction endfunction
function! s:path(path) function! s:path(path)
return substitute(substitute(a:path, '/', '\', 'g'), '[/\\]*$', '', '') return s:trim(substitute(a:path, '/', '\', 'g'))
endfunction endfunction
function! s:dirpath(path) function! s:dirpath(path)
return s:path(a:path) . '\' return s:path(a:path) . '\'
endfunction endfunction
function! s:is_local_plug(repo)
return a:repo =~? '^[a-z]:'
endfunction
else else
function! s:rtp(spec) function! s:rtp(spec)
return s:dirpath(a:spec.dir . get(a:spec, 'rtp', '')) return s:dirpath(a:spec.dir . get(a:spec, 'rtp', ''))
endfunction endfunction
function! s:path(path) function! s:path(path)
return substitute(a:path, '[/\\]*$', '', '') return s:trim(a:path)
endfunction endfunction
function! s:dirpath(path) function! s:dirpath(path)
return s:path(a:path) . '/' return substitute(a:path, '[/\\]*$', '/', '')
endfunction
function! s:is_local_plug(repo)
return a:repo[0] =~ '[/$~]'
endfunction endfunction
endif endif
function! s:err(msg)
echohl ErrorMsg
echom a:msg
echohl None
return 0
endfunction
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)
let after = globpath(a:rtp, 'after') let after = globpath(a:rtp, 'after')
if isdirectory(after) if isdirectory(after)
execute "set rtp+=".s:esc(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
@@ -232,6 +278,7 @@ 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
silent! doautocmd filetypeplugin FileType silent! doautocmd filetypeplugin FileType
endfunction endfunction
@@ -239,13 +286,15 @@ endfunction
function! s:lod_cmd(cmd, bang, l1, l2, args, name) function! s:lod_cmd(cmd, bang, l1, l2, args, name)
execute 'delc '.a:cmd execute 'delc '.a:cmd
call s:lod(g:plugs[a:name], ['plugin', 'ftdetect', 'after']) call s:lod(g:plugs[a:name], ['plugin', 'ftdetect', 'after'])
execute printf("%s%s%s %s", (a:l1 == a:l2 ? '' : (a:l1.','.a:l2)), a:cmd, a:bang, a:args) call s:reorg_rtp()
execute printf('%s%s%s %s', (a:l1 == a:l2 ? '' : (a:l1.','.a:l2)), a:cmd, a:bang, a:args)
endfunction endfunction
function! s:lod_map(map, name, prefix) function! s:lod_map(map, name, prefix)
execute 'unmap '.a:map execute 'unmap '.a:map
execute 'iunmap '.a:map execute 'iunmap '.a:map
call s:lod(g:plugs[a:name], ['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)
@@ -257,42 +306,68 @@ function! s:lod_map(map, name, prefix)
call feedkeys(a:prefix . 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, repo, ...)
let force = a:1 if a:0 > 1
let opts = { 'branch': 'master' } return s:err('Invalid number of arguments (1..2)')
if a:0 == 2 endif
let plugin = a:2
elseif a:0 == 3 try
let plugin = a:2 let repo = s:trim(a:repo)
if type(a:3) == 1 let name = fnamemodify(repo, ':t:s?\.git$??')
let opts.branch = a:3 if !a:force && has_key(g:plugs, name)
elseif type(a:3) == 4 let s:extended[name] = g:plugs[name]
call extend(opts, a:3)
else
echoerr "Invalid argument type (expected: string or dictionary)"
return return
endif endif
else
echoerr "Invalid number of arguments (1..2)"
return
endif
let name = substitute(split(plugin, '/')[-1], '\.git$', '', '') let spec = extend(s:infer_properties(name, repo),
if !force && has_key(g:plugs, name) | return | endif \ a:0 == 1 ? s:parse_options(a:1) : copy(s:base_spec))
if !a:force
if plugin =~ ':' let s:extended[name] = spec
let uri = plugin
else
if plugin !~ '/'
let plugin = 'vim-scripts/'. plugin
endif endif
let uri = 'https://git:@github.com/' . plugin . '.git'
endif
let dir = s:dirpath( fnamemodify(join([g:plug_home, name], '/'), ':p') ) let g:plugs[name] = spec
let spec = extend(opts, { 'dir': dir, 'uri': uri }) let g:plugs_order += [name]
let g:plugs[name] = spec catch
let g:plugs_order += [name] return s:err(v:exception)
endtry
endfunction
function! s:parse_options(arg)
let opts = copy(s:base_spec)
let type = type(a:arg)
if type == s:TYPE.string
let opts.branch = a:arg
elseif type == s:TYPE.dict
call extend(opts, a:arg)
if has_key(opts, 'tag')
let opts.branch = remove(opts, 'tag')
endif
if has_key(opts, 'dir')
let opts.dir = s:dirpath(expand(opts.dir))
endif
else
throw 'Invalid argument type (expected: string or dictionary)'
endif
return opts
endfunction
function! s:infer_properties(name, repo)
let repo = a:repo
if s:is_local_plug(repo)
let properties = { 'dir': s:dirpath(expand(repo)), 'local': 1 }
else
if repo =~ ':'
let uri = repo
else
if repo !~ '/'
let repo = 'vim-scripts/'. repo
endif
let uri = 'https://git:@github.com/' . repo . '.git'
endif
let dir = s:dirpath( fnamemodify(join([g:plug_home, a:name], '/'), ':p') )
let properties = { 'dir': dir, 'uri': uri }
endif
return properties
endfunction endfunction
function! s:install(...) function! s:install(...)
@@ -307,7 +382,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
@@ -325,7 +400,8 @@ function! s:syntax()
syn match plugDash /^-/ syn match plugDash /^-/
syn match plugPlus /^+/ syn match plugPlus /^+/
syn match plugStar /^*/ syn match plugStar /^*/
syn match plugName /\(^- \)\@<=[^:]*/ syn match plugMessage /\(^- \)\@<=.*/
syn match plugName /\(^- \)\@<=[^ ]*:/
syn match plugInstall /\(^+ \)\@<=[^:]*/ syn match plugInstall /\(^+ \)\@<=[^:]*/
syn match plugUpdate /\(^* \)\@<=[^:]*/ syn match plugUpdate /\(^* \)\@<=[^:]*/
syn match plugCommit /^ [0-9a-z]\{7} .*/ contains=plugRelDate,plugSha syn match plugCommit /^ [0-9a-z]\{7} .*/ contains=plugRelDate,plugSha
@@ -343,6 +419,7 @@ function! s:syntax()
hi def link plugPlus Constant hi def link plugPlus Constant
hi def link plugStar Boolean hi def link plugStar Boolean
hi def link plugMessage Function
hi def link plugName Label hi def link plugName Label
hi def link plugInstall Function hi def link plugInstall Function
hi def link plugUpdate Type hi def link plugUpdate Type
@@ -374,6 +451,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>
@@ -394,10 +472,47 @@ function! s:assign_name()
let name = prefix let name = prefix
let idx = 2 let idx = 2
while bufexists(name) while bufexists(name)
let name = printf("%s (%s)", prefix, idx) let name = printf('%s (%s)', prefix, idx)
let idx = idx + 1 let idx = idx + 1
endwhile endwhile
silent! execute "f ".fnameescape(name) silent! execute 'f '.fnameescape(name)
endfunction
function! s:do(pull, todo)
for [name, spec] in items(a:todo)
if !isdirectory(spec.dir)
continue
endif
execute 'cd '.s:esc(spec.dir)
let installed = has_key(s:prev_update.new, name)
if installed || (a:pull &&
\ !empty(s:system_chomp('git log --pretty=format:"%h" "HEAD...HEAD@{1}"')))
call append(3, '- Post-update hook for '. name .' ... ')
let type = type(spec.do)
if type == s:TYPE.string
try
" FIXME: Escaping is incomplete. We could use shellescape with eval,
" but it won't work on Windows.
let g:_plug_do = '!'.escape(spec.do, '#!%')
execute "normal! :execute g:_plug_do\<cr>\<cr>"
finally
let result = v:shell_error ? ('Exit status: '.v:shell_error) : 'Done!'
unlet g:_plug_do
endtry
elseif type == s:TYPE.funcref
try
call spec.do({ 'name': name, 'status': (installed ? 'installed' : 'updated') })
let result = 'Done!'
catch
let result = 'Error: ' . v:exception
endtry
else
let result = 'Error: Invalid type!'
endif
call setline(4, getline(4) . result)
endif
cd -
endfor
endfunction endfunction
function! s:finish(pull) function! s:finish(pull)
@@ -408,22 +523,41 @@ 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
let st = reltime()
let args = copy(a:args) let args = copy(a:args)
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, '!v:val.frozen') :
\ filter(managed, 'index(args, v:key) >= 0')
if empty(todo) if empty(todo)
echohl WarningMsg echohl WarningMsg
@@ -438,9 +572,17 @@ function! s:update_impl(pull, args) abort
normal! 2G normal! 2G
redraw redraw
if !isdirectory(g:plug_home)
call mkdir(g:plug_home, 'p')
endif
let len = len(g:plugs) let len = len(g:plugs)
let s:prev_update = { 'errors': [], 'pull': a:pull, 'new': {}, 'threads': threads }
if has('ruby') && threads > 1 if has('ruby') && threads > 1
try 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 catch
let lines = getline(4, '$') let lines = getline(4, '$')
@@ -449,47 +591,68 @@ function! s:update_impl(pull, args) abort
for line in lines for line in lines
let name = get(matchlist(line, '^. \([^:]\+\):'), 1, '') let name = get(matchlist(line, '^. \([^:]\+\):'), 1, '')
if empty(name) || !has_key(printed, name) if empty(name) || !has_key(printed, name)
let printed[name] = 1
call append('$', line) 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 endif
endfor endfor
echoerr v:exception finally
let &imd = imd
endtry endtry
else else
call s:update_serial(a:pull, todo) call s:update_serial(a:pull, todo)
endif endif
call s:do(a:pull, filter(copy(todo), 'has_key(v:val, "do")'))
if len(g:plugs) > len if len(g:plugs) > len
call plug#end() call plug#end()
endif endif
call s:finish(a:pull) call s:finish(a:pull)
call setline(1, 'Updated. Elapsed time: ' . split(reltimestr(reltime(st)))[0] . ' sec.')
endfunction endfunction
function! s:extend(names) function! s:find_plugfiles()
let prev = copy(g:plugs) let plugfiles = {}
for pf in split(globpath(g:plug_home, '*/'.s:plug_file), '\n')
let plugfiles[fnamemodify(pf, ':h:t')] = pf
endfor
return plugfiles
endfunction
function! s:extend(names, ...)
let s:extended = {}
let plugfiles = a:0 > 0 ? a:1 : s:find_plugfiles()
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 = globpath(s:rtp(g:plugs[name]), s:plug_file) let spec = g:plugs[name]
if filereadable(plugfile) if spec.local
execute "source ". s:esc(plugfile) let plugfile = globpath(s:rtp(spec), s:plug_file)
if filereadable(plugfile)
execute 'source '. s:esc(plugfile)
endif
elseif has_key(plugfiles, name)
execute 'source '. s:esc(plugfiles[name])
endif endif
endfor endfor
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)
call setline(1, (a:pull ? 'Updating' : 'Installing'). call setline(1, (a:pull ? 'Updating' : 'Installing').
\ " plugins (".a:cnt."/".a:total.")") \ ' plugins ('.a:cnt.'/'.a:total.')')
call s:progress_bar(2, a:bar, a:total) call s:progress_bar(2, a:bar, a:total)
normal! 2G normal! 2G
redraw redraw
endfunction endfunction
function! s:update_serial(pull, todo) function! s:update_serial(pull, todo)
let st = reltime()
let base = g:plug_home let base = g:plug_home
let todo = copy(a:todo) let todo = copy(a:todo)
let total = len(todo) let total = len(todo)
@@ -512,34 +675,34 @@ 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)
call mkdir(base, 'p')
endif
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),
\ s:shellesc(spec.branch), \ s:shellesc(spec.branch),
\ s:shellesc(substitute(spec.dir, '[\/]\+$', '', '')), \ s:shellesc(s:trim(spec.dir)),
\ s:shellesc(spec.dir))) \ s:shellesc(spec.dir)))
let error = v:shell_error != 0 let error = v:shell_error != 0
if !error | let s:prev_update.new[name] = 1 | endif
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
break break
endif endif
endwhile endwhile
call setline(1, "Updated. Elapsed time: " . split(reltimestr(reltime(st)))[0] . ' sec.')
endfunction endfunction
function! s:update_parallel(pull, todo, threads) function! s:update_parallel(pull, todo, threads)
@@ -565,7 +728,7 @@ function! s:update_parallel(pull, todo, threads)
%["#{arg.gsub('"', '\"')}"] %["#{arg.gsub('"', '\"')}"]
end end
st = Time.now require 'set'
require 'thread' require 'thread'
require 'fileutils' require 'fileutils'
require 'timeout' require 'timeout'
@@ -575,17 +738,17 @@ function! s:update_parallel(pull, todo, threads)
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 maxy = VIM::evaluate('winheight(".")').to_i
cd = iswin ? 'cd /d' : 'cd' cd = iswin ? 'cd /d' : 'cd'
tot = 0 tot = VIM::evaluate('len(a:todo)') || 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 = $curbuf[2][1...-1].strip.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')
@@ -598,7 +761,10 @@ function! s:update_parallel(pull, todo, threads)
bar += type ? '=' : 'x' unless ing bar += type ? '=' : 'x' unless ing
b = case type b = case type
when :install then '+' when :update then '*' when :install then '+' when :update then '*'
when true, nil then '-' else 'x' end when true, nil then '-' else
VIM::command("call add(s:prev_update.errors, '#{name}')")
'x'
end
result = result =
if type || type.nil? if type || type.nil?
["#{b} #{name}: #{result.lines.to_a.last}"] ["#{b} #{name}: #{result.lines.to_a.last}"]
@@ -618,11 +784,14 @@ function! s:update_parallel(pull, todo, threads)
end end
} }
bt = proc { |cmd, name, type| bt = proc { |cmd, name, type|
tried = timeout = 0
begin begin
tried += 1
timeout += limit
fd = nil fd = nil
data = '' data = ''
if iswin if iswin
Timeout::timeout(limit) do 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
@@ -632,7 +801,7 @@ function! s:update_parallel(pull, todo, threads)
fd = IO.popen(cmd).extend(PlugStream) fd = IO.popen(cmd).extend(PlugStream)
first_line = true first_line = true
log_prob = 1.0 / nthr log_prob = 1.0 / nthr
while line = Timeout::timeout(limit) { fd.get_line } while line = Timeout::timeout(timeout) { fd.get_line }
data << line data << line
log.call name, line.chomp, type if name && (first_line || rand < log_prob) log.call name, line.chomp, type if name && (first_line || rand < log_prob)
first_line = false first_line = false
@@ -655,6 +824,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
} }
@@ -671,10 +849,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' 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 {
@@ -683,8 +872,9 @@ function! s:update_parallel(pull, todo, threads)
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" subm = "git submodule update --init --recursive 2>&1"
exists = File.directory? dir
ok, result = ok, result =
if File.directory? dir if exists
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", nil, nil 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
@@ -707,11 +897,11 @@ function! s:update_parallel(pull, todo, threads)
end end
end end
else else
FileUtils.mkdir_p(base)
d = esc dir.sub(%r{[\\/]+$}, '') d = esc dir.sub(%r{[\\/]+$}, '')
log.call name, 'Installing ...', :install log.call name, 'Installing ...', :install
bt.call "(git clone #{progress} --recursive #{uri} -b #{branch} #{d} 2>&1 && cd #{esc dir} && #{subm})", name, :install bt.call "(git clone #{progress} --recursive #{uri} -b #{branch} #{d} 2>&1 && cd #{esc dir} && #{subm})", name, :install
end end
mtx.synchronize { VIM::command("let s:prev_update.new['#{name}'] = 1") } if !exists && ok
log.call name, result, ok log.call name, result, ok
end end
} if running } if running
@@ -719,11 +909,15 @@ function! s:update_parallel(pull, todo, threads)
end end
threads.each { |t| t.join rescue nil } 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."
EOF EOF
endfunction endfunction
@@ -767,16 +961,16 @@ function! s:git_valid(spec, check_branch, cd)
let ret = 1 let ret = 1
let msg = 'OK' let msg = 'OK'
if isdirectory(a:spec.dir) if isdirectory(a:spec.dir)
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 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)
let msg = join(['Invalid URI: '.remote, let msg = join(['Invalid URI: '.remote,
\ 'Expected: '.a:spec.uri, \ 'Expected: '.a:spec.uri,
\ "PlugClean required."], "\n") \ 'PlugClean required.'], "\n")
let ret = 0 let ret = 0
elseif a:check_branch elseif a:check_branch
let branch = result[0] let branch = result[0]
@@ -804,8 +998,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
@@ -840,7 +1035,7 @@ function! s:clean(force)
call append(line('$'), 'Already clean.') call append(line('$'), 'Already clean.')
else else
call inputsave() call inputsave()
let yes = a:force || (input("Proceed? (Y/N) ") =~? '^y') let yes = a:force || (input('Proceed? (Y/N) ') =~? '^y')
call inputrestore() call inputrestore()
if yes if yes
for dir in todo for dir in todo
@@ -860,23 +1055,22 @@ function! s:upgrade()
if executable('curl') if executable('curl')
let mee = s:shellesc(s:me) let mee = s:shellesc(s:me)
let new = s:shellesc(s:me . '.new') let new = s:shellesc(s:me . '.new')
echo "Downloading ". s:plug_source echo 'Downloading '. s:plug_source
redraw redraw
let mv = s:is_win ? 'move /Y' : 'mv -f' let mv = s:is_win ? 'move /Y' : 'mv -f'
let cp = s:is_win ? 'copy /Y' : 'cp -f' let cp = s:is_win ? 'copy /Y' : 'cp -f'
call system(printf( call system(printf(
\ "curl -fLo %s %s && ".cp." %s %s.old && ".mv." %s %s", \ 'curl -fLo %s %s && '.cp.' %s %s.old && '.mv.' %s %s',
\ new, s:plug_source, mee, mee, new, mee)) \ new, s:plug_source, mee, mee, new, mee))
if v:shell_error == 0 if v:shell_error == 0
unlet g:loaded_plug unlet g:loaded_plug
echo "Downloaded ". s:plug_source echo 'Downloaded '. s:plug_source
return 1 return 1
else else
echoerr "Error upgrading vim-plug" return s:err('Error upgrading vim-plug')
return 0
endif endif
elseif has('ruby') elseif has('ruby')
echo "Downloading ". s:plug_source echo 'Downloading '. s:plug_source
ruby << EOF ruby << EOF
require 'open-uri' require 'open-uri'
require 'fileutils' require 'fileutils'
@@ -890,14 +1084,20 @@ function! s:upgrade()
File.rename new, me File.rename new, me
EOF EOF
unlet g:loaded_plug unlet g:loaded_plug
echo "Downloaded ". s:plug_source echo 'Downloaded '. s:plug_source
return 1 return 1
else else
echoerr "curl executable or ruby support not found" return s:err('curl executable or ruby support not found')
return 0
endif endif
endfunction endfunction
function! s:upgrade_specs()
for spec in values(g:plugs)
let spec.frozen = get(spec, 'frozen', 0)
let spec.local = get(spec, 'local', 0)
endfor
endfunction
function! s:status() function! s:status()
call s:prepare() call s:prepare()
call append(0, 'Checking plugins') call append(0, 'Checking plugins')
@@ -906,10 +1106,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
@@ -973,12 +1181,12 @@ 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
execute 'cd '.s:esc(v.dir) execute 'cd '.s:esc(v.dir)
let diff = system('git log --pretty=format:"%h %s (%cr)" "HEAD@{0}...HEAD@{1}"') let diff = system('git log --pretty=format:"%h %s (%cr)" "HEAD...HEAD@{1}"')
if !v:shell_error && !empty(diff) if !v:shell_error && !empty(diff)
call append(1, '') call append(1, '')
call append(2, '- '.k.':') call append(2, '- '.k.':')
@@ -995,6 +1203,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,18 +27,22 @@ 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)
let $MYVIMRC = vimrc let $MYVIMRC = vimrc
Execute (plug#end() before plug#begin() should fail): Execute (plug#end() before plug#begin() should fail):
try redir => out
call plug#end() AssertEqual 0, plug#end()
Assert 0, 'should not reach here' redir END
catch Assert stridx(out, 'Call plug#begin() first') >= 0
Assert stridx(v:exception, 'Call plug#begin() first') >= 0
endtry
Execute (plug#begin() without path argument): Execute (plug#begin() without path argument):
call plug#begin() call plug#begin()
@@ -45,12 +52,10 @@ Execute (plug#begin() without path argument):
Execute (plug#begin() without path argument with empty &rtp): Execute (plug#begin() without path argument with empty &rtp):
let save_rtp = &rtp let save_rtp = &rtp
set rtp= set rtp=
try redir => out
call plug#begin() AssertEqual 0, plug#begin()
Assert 0, 'should not reach here' redir END
catch Assert stridx(out, 'Unable to determine plug home') >= 0
Assert stridx(v:exception, 'Unable to determine plug home') >= 0, 'Got: '.v:exception
endtry
let &rtp = save_rtp let &rtp = save_rtp
Execute (plug#begin(path)): Execute (plug#begin(path)):
@@ -68,15 +73,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 +114,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 +141,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 +218,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 +245,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 =~ "^- [^:]*:"')) 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 +261,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 +368,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
@@ -374,7 +392,7 @@ Expect (Aligned code):
a = 1 a = 1
aa = 2 aa = 2
Given (nothing): Given:
Execute (Partial PlugUpdate): Execute (Partial PlugUpdate):
PlugUpdate vim-redis PlugUpdate vim-redis
q q
@@ -384,13 +402,298 @@ 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
**********************************************************************
~ Post-update hook (`do` option)
**********************************************************************
Execute (Cleanup):
call plug#begin()
call plug#end()
PlugClean!
Execute (On install):
call plug#begin()
Plug 'junegunn/vim-easy-align', { 'do': 'touch installed' }
Plug 'junegunn/vim-pseudocl'
call plug#end()
PlugInstall
q
Assert filereadable(g:plugs['vim-easy-align'].dir.'/installed'),
\ 'vim-easy-align/installed should exist'
Assert !filereadable(g:plugs['vim-pseudocl'].dir.'/installed'),
\ 'vim-pseudocl/installed should not exist'
Execute (On update):
call plug#begin()
Plug 'junegunn/vim-easy-align', { 'do': 'touch updated' }
Plug 'junegunn/vim-pseudocl', { 'do': 'touch updated' }
call plug#end()
" Reset for updates
call system('cd '.g:plugs['vim-pseudocl'].dir.' && git reset --hard HEAD^')
PlugUpdate
Log getline(1, '$')
q
Assert !filereadable(g:plugs['vim-easy-align'].dir.'/updated'),
\ 'vim-easy-align/updated should not exist'
Assert filereadable(g:plugs['vim-pseudocl'].dir.'/updated'),
\ 'vim-pseudocl/updated should exist'
Execute (When already installed):
call plug#begin()
Plug 'junegunn/vim-easy-align', { 'do': 'touch installed2' }
Plug 'junegunn/vim-pseudocl', { 'do': 'touch installed2' }
call plug#end()
PlugInstall
q
Assert !filereadable(g:plugs['vim-easy-align'].dir.'/installed2'),
\ 'vim-easy-align/installed2 should not exist'
Assert !filereadable(g:plugs['vim-pseudocl'].dir.'/installed2'),
\ 'vim-pseudocl/installed2 should exist'
Execute (When already updated):
call plug#begin()
Plug 'junegunn/vim-easy-align', { 'do': 'touch updated2' }
Plug 'junegunn/vim-pseudocl', { 'do': 'touch updated2' }
call plug#end()
PlugUpdate
q
Assert !filereadable(g:plugs['vim-easy-align'].dir.'/updated2'),
\ 'vim-easy-align/updated2 should not exist'
Assert !filereadable(g:plugs['vim-pseudocl'].dir.'/updated2'),
\ 'vim-pseudocl/updated2 should exist'
Execute (Using Funcref):
function! PlugUpdated(info)
call system('touch '. a:info.name . a:info.status . len(a:info))
endfunction
call plug#begin()
Plug 'junegunn/vim-easy-align', { 'do': function('PlugUpdated') }
Plug 'junegunn/vim-pseudocl', { 'do': function('PlugUpdated') }
call plug#end()
call system('cd '.g:plugs['vim-easy-align'].dir.' && git reset --hard HEAD^')
call system('rm -rf '.g:plugs['vim-pseudocl'].dir)
PlugUpdate
Log getline(1, '$')
q
Assert filereadable(g:plugs['vim-easy-align'].dir.'/vim-easy-alignupdated2'),
\ 'vim-easy-align/vim-easy-alignupdated2 should exist'
Assert filereadable(g:plugs['vim-pseudocl'].dir.'/vim-pseudoclinstalled2'),
\ 'vim-pseudocl/vim-pseudoclinstalled2 should exist'
**********************************************************************
~ Overriding `dir`
**********************************************************************
Execute (Using custom dir):
Assert isdirectory(g:plugs['vim-easy-align'].dir)
call plug#begin()
Plug 'junegunn/vim-easy-align', { 'dir': $TMPDIR.'easy-align' }
call plug#end()
AssertEqual $TMPDIR.'easy-align/', g:plugs['vim-easy-align'].dir
PlugClean!
Assert !isdirectory(g:plugs['vim-easy-align'].dir)
q
PlugInstall
q
Assert isdirectory(g:plugs['vim-easy-align'].dir)
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 out
delf PlugStatusSorted delf PlugStatusSorted
delf AssertExpect
delf PlugUpdated
delc AssertExpect
unmap /
unmap ?
Restore Restore