51 Commits
0.6.2 ... 0.7.1

Author SHA1 Message Date
Junegunn Choi
d9b70554e3 Merge pull request #187 from junegunn/python-2.6
Python 2.6 compatibility
2015-03-08 02:40:28 +09:00
Junegunn Choi
3c6ac68947 Python 2.6 compatibility
Tested on
- Vim 7.2.330
- Python 2.6.5
- Ubuntu 10.04
- https://gist.github.com/junegunn/863dcbd78eadece788cd
2015-03-08 02:00:06 +09:00
Junegunn Choi
51dc024b2e Update README (markdown table) 2015-02-27 18:56:30 +09:00
Junegunn Choi
30a2c5cc14 Remove uniq() function from test code 2015-02-25 22:44:18 +09:00
Junegunn Choi
a34b745a21 Fix #184 - Avoid duplicate entries in g:plugs_order 2015-02-25 22:31:39 +09:00
Junegunn Choi
c759170ce2 Merge pull request #179 from starcraftman/master
Linking to wiki.
2015-02-22 22:36:18 +09:00
Jeremy Pallats/starcraft.man
44410a32e3 Linking to wiki. 2015-02-22 08:23:55 -05:00
Junegunn Choi
5698a055c3 Minor refactoring 2015-02-22 11:41:27 +09:00
Junegunn Choi
59748b0680 Fix error on windows when plug home contains spaces (#154)
Also fixes blank command output.
2015-02-22 03:53:24 +09:00
Junegunn Choi
95aa96a884 Interpret the second argument to Plug command as tag option
The older documentation of vim-plug suggested that the second string
parameter to Plug command was for both branches and tags. But we've
realized that tags and branches are not interchangeable (#174), and it
is now recommended that the user explicitly specify whether it's a
branch or a tag. The now-undocumented second parameter is currently for
branches, but I'd like to change it for tags, as the use of tags are
much more common.
2015-02-21 12:26:11 +09:00
Junegunn Choi
bb48508c3e Fix #177 - Check Python version >= 2.7 2015-02-21 03:47:58 +09:00
Junegunn Choi
8a525f165c Merge pull request #165 from starcraftman/new_pr_branch
Python parallel plugin management.
2015-02-19 00:26:40 +09:00
Jeremy Pallats/starcraft.man
e362fd5931 Python parallel plugin management.
* Main differences from ruby are inside Command class, notably it
poll/sleeps on the subprocess to check output & timeout.
* Another difference, interrupt is not instaneous due to checking var.
* Otherwise, I mainly just mirrored code into objects.
* Note that due to GVim freeze, disabling use on Windows
2015-02-18 10:07:35 -05:00
Junegunn Choi
74169f3761 Merge pull request #175 from junegunn/tag-vs-branch
Fix #174 - Error when updating tagged plugins
2015-02-18 17:27:14 +09:00
Junegunn Choi
7e4191baaf Fix update of tagged plugins (#174) 2015-02-18 16:47:32 +09:00
Junegunn Choi
753f7be798 Extend Travis CI build to use vim-nox on Ubuntu 12.04 2015-02-18 16:47:17 +09:00
Junegunn Choi
c74fae9f8e Revert "Use :pgroup option when starting subprocesses"
This reverts commit 308fb9bc94.
2015-02-17 20:59:22 +09:00
Junegunn Choi
fc200da975 Add o key binding for PlugDiff 2015-02-17 14:09:07 +09:00
Junegunn Choi
77f58a3793 Merge pull request #169 from junegunn/ruby-pgroup
Use :pgroup option when starting subprocesses
2015-02-17 11:52:46 +09:00
Junegunn Choi
308fb9bc94 Use :pgroup option when starting subprocesses
This makes it easier and faster to kill spawned git processes.
Repetitive `pgrep` command for collecting PIDs is no longer required.
Unfortunately, :pgroup option is not supported on Ruby 1.8 so we can't
remove the old implementation of `killall`.
2015-02-17 11:43:39 +09:00
Junegunn Choi
4a96db8971 Restore $GIT_TERMINAL_PROMPT in s:update_finish
Fix for asynchronous installer of Neovim
2015-02-15 21:24:33 +09:00
Junegunn Choi
925ec7b325 Merge pull request #168 from junegunn/git-no-prompt
Do not inject `git::` to url when git 2.3.0 or above found
2015-02-15 21:06:38 +09:00
Junegunn Choi
7fec10e088 Remove git::@ from URI if git 2.3.0 or above is found
Related: #161, #133, #109
2015-02-15 18:48:57 +09:00
Junegunn Choi
54fc8a4fc7 Add test case for unescaped spaces in &rtp 2015-02-14 23:18:57 +09:00
Junegunn Choi
9c1cca32f0 Do not escape spaces in &rtp
Related: https://github.com/SirVer/ultisnips/issues/445
2015-02-14 23:11:20 +09:00
Junegunn Choi
f6be60a9a5 Use v:version == 702 && has('patch374')
Thanks to @justinmk
2015-02-13 16:09:01 +09:00
Junegunn Choi
e81e761d43 Fix #166 - v:version >= 703 || has('patch-7.2.374') 2015-02-13 14:20:16 +09:00
Junegunn Choi
fb84e6b11c Fix typo 2015-02-12 11:38:48 +09:00
Junegunn Choi
ef784c17b1 Fix #154 - issues with paths containing spaces 2015-02-12 11:35:05 +09:00
Junegunn Choi
7aeff0ef0d Disable Ruby installer when without patch-7.2.374 (#162) 2015-02-10 12:09:46 +09:00
Junegunn Choi
773b3cadd0 Do not use --progress option on git 1.7.0 or below (#162) 2015-02-10 01:48:54 +09:00
Junegunn Choi
71542dd896 Do not use --progress option when not necessary
Patch suggested by @sangh. Fix #162 and #163.
2015-02-09 12:12:50 +09:00
Junegunn Choi
f825e4ef6e Ignore error when the buffer is not properly initialized (#162) 2015-02-09 12:09:27 +09:00
Junegunn Choi
6e7509e2ef Update PlugClean for Gist plugins
In order to install Gist as a plugin, you have to modify its `dir` to be
the `plugin` subdirectory of the normal path of the plugin if it were an
ordinary pathogen-compatible Vim plugin.

    Plug 'https://gist.github.com/952560a43601cd9898f1.git',
        \ { 'dir': g:plug_home.'/xxx/plugin', 'rtp': '..' }

PlugClean command was incompatible with the above trick, so it was
updated not to remove the parent directory of `dir` of each plugin.
2015-02-08 14:47:19 +09:00
Junegunn Choi
619e42a182 Merge pull request #160 from junegunn/fix-159
Fix #159 - Avoid errors on tcsh and fish
2015-02-08 01:15:49 +09:00
Junegunn Choi
48e8000b6a Use /bin/sh instead of /bin/bash (PlugSnapshot) 2015-02-08 01:08:18 +09:00
Junegunn Choi
79da5b2654 Fix #159 by temporarily setting &shell to sh 2015-02-07 13:36:45 +09:00
Junegunn Choi
61f010ffad Update README - curl --create-dirs 2015-02-01 03:19:00 +09:00
Junegunn Choi
4539bb8fb3 Update README - Pros. 2015-02-01 03:11:58 +09:00
Junegunn Choi
7d40f592af Fix #155 - cd /d on Windows 2015-01-29 19:08:03 +09:00
Junegunn Choi
1c61517164 Merge pull request #152 from michamos/patch-1
Clarify messages after 'PlugUpgrade'
2015-01-26 18:50:51 +09:00
Micha Moskovic
061b326b37 Clarify messages after 'PlugUpgrade' 2015-01-26 10:46:20 +01:00
Junegunn Choi
166426718e Merge pull request #147 from Pyrohh/simplify-nvim-check
Simplify neovim check
2015-01-18 11:38:49 +09:00
Michael Reed
b440603fa9 Simplify neovim check 2015-01-17 16:38:50 -05:00
Junegunn Choi
04fc8f9aba Fix #145 - Merge duplicate on-demand loading triggers 2015-01-17 17:20:37 +09:00
Junegunn Choi
ebe8635043 Merge pull request #143 from junegunn/fix-139
Fix #139 - Use git fetch+merge instead of pull
2015-01-09 09:53:36 +09:00
Junegunn Choi
334e820c4e Add more test cases for #139 2015-01-09 00:56:52 +09:00
Junegunn Choi
0e9fa672f8 Fix #139 - Use git fetch+merge instead of pull 2015-01-08 23:21:32 +09:00
Junegunn Choi
fdf1e53da5 Change test code to use local repositories 2015-01-07 20:14:48 +09:00
Junegunn Choi
470139cd86 Update README 2014-12-18 23:53:32 +09:00
Junegunn Choi
e8cd357060 Fix test failure 2014-12-13 11:51:37 +09:00
7 changed files with 1011 additions and 274 deletions

View File

@@ -1,15 +1,32 @@
language: ruby language: ruby
rvm: rvm:
- 1.8.7 - 1.8.7
- 1.9.2 # Test with vim-nox package on ubuntu
- 1.9.3 # Test against python installer
- 2.0.0 - 2.0.0
before_script: | before_script: |
hg clone https://code.google.com/p/vim/ if [ $(ruby -e 'puts RUBY_VERSION') = 1.9.2 ]; then
cd vim sudo apt-get update -y
./configure --with-features=huge --enable-rubyinterp sudo apt-get install -y vim-nox
make sudo ln -s /usr/bin/vim /usr/local/bin/vim
sudo make install else
cd - hg clone https://code.google.com/p/vim/
cd vim
if [ $(ruby -e 'puts RUBY_VERSION') = 1.9.3 ]; then
sudo apt-get update -y
sudo apt-get install -y python2.7-dev
./configure --with-features=huge --enable-pythoninterp
else
./configure --with-features=huge --enable-rubyinterp
fi
make
sudo make install
cd -
fi
git config --global user.email "you@example.com"
git config --global user.name "Your Name"
script: | script: |
test/run ! test/run !

View File

@@ -9,24 +9,27 @@ A minimalist Vim plugin manager.
- Easier to setup: Single file. No boilerplate code required. - Easier to setup: Single file. No boilerplate code required.
- Easier to use: Concise, intuitive syntax - Easier to use: Concise, intuitive syntax
- [Super-fast](https://raw.githubusercontent.com/junegunn/i/master/vim-plug/40-in-4.gif) - [Super-fast][40/4] parallel installation/update
parallel installation/update (requires (with [+python][py] or [+ruby][rb] or [Neovim][nv])
[+ruby](https://github.com/junegunn/vim-plug/wiki/ruby) or - On-demand loading for [faster startup time][startup-time]
[Neovim](http://neovim.org/)) - Can review and rollback updates
- On-demand loading to achieve - Branch/tag support
[fast startup time](http://junegunn.kr/images/vim-startup-time.png)
- Post-update hooks - Post-update hooks
- Can choose a specific branch or tag for each plugin
- Support for externally managed plugins - Support for externally managed plugins
[40/4]: https://raw.githubusercontent.com/junegunn/i/master/vim-plug/40-in-4.gif
[py]: https://github.com/junegunn/vim-plug/wiki/python
[rb]: https://github.com/junegunn/vim-plug/wiki/ruby
[nv]: http://neovim.org/
[startup-time]: http://junegunn.kr/images/vim-startup-time.png
### Usage ### Usage
[Download plug.vim](https://raw.githubusercontent.com/junegunn/vim-plug/master/plug.vim) [Download plug.vim](https://raw.githubusercontent.com/junegunn/vim-plug/master/plug.vim)
and put it in ~/.vim/autoload and put it in ~/.vim/autoload
```sh ```sh
mkdir -p ~/.vim/autoload curl -fLo ~/.vim/autoload/plug.vim --create-dirs \
curl -fLo ~/.vim/autoload/plug.vim \
https://raw.githubusercontent.com/junegunn/vim-plug/master/plug.vim https://raw.githubusercontent.com/junegunn/vim-plug/master/plug.vim
``` ```
@@ -86,13 +89,13 @@ Reload .vimrc and `:PlugInstall` to install plugins.
### Global options ### Global options
| 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 (*for Ruby installer*) | | `g:plug_timeout` | 60 | Time limit of each task in seconds (*Ruby & Python*) |
| `g:plug_retries` | 2 | Number of retries in case of timeout (*for Ruby installer*) | | `g:plug_retries` | 2 | Number of retries in case of timeout (*Ruby & Python*) |
| `g:plug_window` | `vertical topleft new` | Command to open plug window | | `g:plug_window` | `vertical topleft new` | Command to open plug window |
| `g:plug_url_format` | `https://git::@github.com/%s.git` | `printf` format to build repo URL | | `g:plug_url_format` | `https://git::@github.com/%s.git` | `printf` format to build repo URL |
### Keybindings ### Keybindings
@@ -143,6 +146,7 @@ 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. In that case, use `do` option to describe the task to be performed.
```vim ```vim
Plug 'Shougo/vimproc.vim', { 'do': 'make' }
Plug 'Valloric/YouCompleteMe', { 'do': './install.sh' } Plug 'Valloric/YouCompleteMe', { 'do': './install.sh' }
``` ```

614
plug.vim
View File

@@ -73,7 +73,9 @@ let s:plug_tab = get(s:, 'plug_tab', -1)
let s:plug_buf = get(s:, 'plug_buf', -1) let s:plug_buf = get(s:, 'plug_buf', -1)
let s:mac_gui = has('gui_macvim') && has('gui_running') 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:nvim = exists('##JobActivity') && !s:is_win let s:py2 = has('python') && !s:is_win
let s:ruby = has('ruby') && (v:version >= 703 || v:version == 702 && has('patch374'))
let s:nvim = has('nvim') && !s:is_win
let s:me = resolve(expand('<sfile>:p')) let s:me = resolve(expand('<sfile>:p'))
let s:base_spec = { 'branch': 'master', 'frozen': 0 } let s:base_spec = { 'branch': 'master', 'frozen': 0 }
let s:TYPE = { let s:TYPE = {
@@ -114,7 +116,7 @@ function! s:define_commands()
command! -nargs=* -bar -bang -complete=customlist,s:names PlugInstall call s:install('<bang>' == '!', [<f-args>]) command! -nargs=* -bar -bang -complete=customlist,s:names PlugInstall call s:install('<bang>' == '!', [<f-args>])
command! -nargs=* -bar -bang -complete=customlist,s:names PlugUpdate call s:update('<bang>' == '!', [<f-args>]) command! -nargs=* -bar -bang -complete=customlist,s:names PlugUpdate call s:update('<bang>' == '!', [<f-args>])
command! -nargs=0 -bar -bang PlugClean call s:clean('<bang>' == '!') command! -nargs=0 -bar -bang PlugClean call s:clean('<bang>' == '!')
command! -nargs=0 -bar PlugUpgrade if s:upgrade() | execute 'source' s:me | endif command! -nargs=0 -bar PlugUpgrade if s:upgrade() | execute 'source' s:esc(s:me) | endif
command! -nargs=0 -bar PlugStatus call s:status() command! -nargs=0 -bar PlugStatus call s:status()
command! -nargs=0 -bar PlugDiff call s:diff() command! -nargs=0 -bar PlugDiff call s:diff()
command! -nargs=? -bar PlugSnapshot call s:snapshot(<f-args>) command! -nargs=? -bar PlugSnapshot call s:snapshot(<f-args>)
@@ -131,11 +133,15 @@ endfunction
function! s:source(from, ...) function! s:source(from, ...)
for pattern in a:000 for pattern in a:000
for vim in s:lines(globpath(a:from, pattern)) for vim in s:lines(globpath(a:from, pattern))
execute 'source' vim execute 'source' s:esc(vim)
endfor endfor
endfor endfor
endfunction endfunction
function! s:assoc(dict, key, val)
let a:dict[a:key] = add(get(a:dict, a:key, []), a:val)
endfunction
function! plug#end() function! plug#end()
if !exists('g:plugs') if !exists('g:plugs')
return s:err('Call plug#begin() first') return s:err('Call plug#begin() first')
@@ -147,7 +153,7 @@ function! plug#end()
augroup END augroup END
augroup! PlugLOD augroup! PlugLOD
endif endif
let lod = {} let lod = { 'ft': {}, 'map': {}, 'cmd': {} }
filetype off filetype off
for name in g:plugs_order for name in g:plugs_order
@@ -162,19 +168,12 @@ function! plug#end()
for cmd in s:to_a(plug.on) for cmd in s:to_a(plug.on)
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 call s:assoc(lod.map, cmd, name)
\ [['i', '<C-O>', ''], ['n', '', ''], ['v', '', 'gv'], ['o', '', '']]
execute printf(
\ '%snoremap <silent> %s %s:<C-U>call <SID>lod_map(%s, %s, "%s")<CR>',
\ mode, cmd, map_prefix, string(cmd), string(name), key_prefix)
endfor
endif endif
call add(s:triggers[name].map, cmd) call add(s:triggers[name].map, cmd)
elseif cmd =~ '^[A-Z]' elseif cmd =~ '^[A-Z]'
if exists(':'.cmd) != 2 if exists(':'.cmd) != 2
execute printf( call s:assoc(lod.cmd, cmd, name)
\ 'command! -nargs=* -range -bang %s call s:lod_cmd(%s, "<bang>", <line1>, <line2>, <q-args>, %s)',
\ cmd, string(cmd), string(name))
endif endif
call add(s:triggers[name].cmd, cmd) call add(s:triggers[name].cmd, cmd)
endif endif
@@ -186,19 +185,31 @@ function! plug#end()
if !empty(types) if !empty(types)
call s:source(s:rtp(plug), 'ftdetect/**/*.vim', 'after/ftdetect/**/*.vim') call s:source(s:rtp(plug), 'ftdetect/**/*.vim', 'after/ftdetect/**/*.vim')
endif endif
for key in types for type in types
if !has_key(lod, key) call s:assoc(lod.ft, type, name)
let lod[key] = []
endif
call add(lod[key], name)
endfor endfor
endif endif
endfor endfor
for [key, names] in items(lod) for [cmd, names] in items(lod.cmd)
execute printf(
\ 'command! -nargs=* -range -bang %s call s:lod_cmd(%s, "<bang>", <line1>, <line2>, <q-args>, %s)',
\ cmd, string(cmd), string(names))
endfor
for [map, names] in items(lod.map)
for [mode, map_prefix, key_prefix] in
\ [['i', '<C-O>', ''], ['n', '', ''], ['v', '', 'gv'], ['o', '', '']]
execute printf(
\ '%snoremap <silent> %s %s:<C-U>call <SID>lod_map(%s, %s, "%s")<CR>',
\ mode, map, map_prefix, string(map), string(names), key_prefix)
endfor
endfor
for [ft, names] in items(lod.ft)
augroup PlugLOD augroup PlugLOD
execute printf('autocmd FileType %s call <SID>lod_ft(%s, %s)', execute printf('autocmd FileType %s call <SID>lod_ft(%s, %s)',
\ key, string(key), string(names)) \ ft, string(ft), string(names))
augroup END augroup END
endfor endfor
@@ -225,6 +236,27 @@ function! s:trim(str)
return substitute(a:str, '[\/]\+$', '', '') return substitute(a:str, '[\/]\+$', '', '')
endfunction endfunction
function! s:version_requirement(val, min)
for idx in range(0, len(a:min) - 1)
let v = get(a:val, idx, 0)
if v < a:min[idx] | return 0
elseif v > a:min[idx] | return 1
endif
endfor
return 1
endfunction
function! s:git_version_requirement(...)
let s:git_version = get(s:, 'git_version',
\ map(split(split(s:system('git --version'))[-1], '\.'), 'str2nr(v:val)'))
return s:version_requirement(s:git_version, a:000)
endfunction
function! s:progress_opt(base)
return a:base && !s:is_win &&
\ s:git_version_requirement(1, 7, 1) ? '--progress' : ''
endfunction
if s:is_win if s:is_win
function! s:rtp(spec) function! s:rtp(spec)
return s:path(a:spec.dir . get(a:spec, 'rtp', '')) return s:path(a:spec.dir . get(a:spec, 'rtp', ''))
@@ -300,9 +332,9 @@ function! s:reorg_rtp()
let s:middle = get(s:, 'middle', &rtp) let s:middle = get(s:, 'middle', &rtp)
let rtps = map(s:loaded_names(), 's:rtp(g:plugs[v:val])') let rtps = map(s:loaded_names(), 's:rtp(g:plugs[v:val])')
let afters = filter(map(copy(rtps), 'globpath(v:val, "after")'), 'isdirectory(v:val)') let afters = filter(map(copy(rtps), 'globpath(v:val, "after")'), 'isdirectory(v:val)')
let rtp = join(map(rtps, 's:escrtp(v:val)'), ',') let rtp = join(map(rtps, 'escape(v:val, ",")'), ',')
\ . ','.s:middle.',' \ . ','.s:middle.','
\ . join(map(afters, 's:escrtp(v:val)'), ',') \ . join(map(afters, 'escape(v:val, ",")'), ',')
let &rtp = substitute(substitute(rtp, ',,*', ',', 'g'), '^,\|,$', '', 'g') let &rtp = substitute(substitute(rtp, ',,*', ',', 'g'), '^,\|,$', '', 'g')
let s:prtp = &rtp let s:prtp = &rtp
@@ -336,11 +368,11 @@ function! s:remove_triggers(name)
return return
endif endif
for cmd in s:triggers[a:name].cmd for cmd in s:triggers[a:name].cmd
execute 'delc' cmd execute 'silent! delc' cmd
endfor endfor
for map in s:triggers[a:name].map for map in s:triggers[a:name].map
execute 'unmap' map execute 'silent! unmap' map
execute 'iunmap' map execute 'silent! iunmap' map
endfor endfor
call remove(s:triggers, a:name) call remove(s:triggers, a:name)
endfunction endfunction
@@ -367,13 +399,13 @@ function! s:lod_ft(pat, names)
doautocmd filetypeindent FileType doautocmd filetypeindent FileType
endfunction endfunction
function! s:lod_cmd(cmd, bang, l1, l2, args, name) function! s:lod_cmd(cmd, bang, l1, l2, args, names)
call s:lod([a:name], ['ftdetect', 'after/ftdetect', 'plugin', 'after/plugin']) call s:lod(a:names, ['ftdetect', 'after/ftdetect', 'plugin', 'after/plugin'])
execute printf('%s%s%s %s', (a:l1 == a:l2 ? '' : (a:l1.','.a:l2)), a:cmd, a:bang, a:args) 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, names, prefix)
call s:lod([a:name], ['ftdetect', 'after/ftdetect', 'plugin', 'after/plugin']) call s:lod(a:names, ['ftdetect', 'after/ftdetect', 'plugin', 'after/plugin'])
let extra = '' let extra = ''
while 1 while 1
let c = getchar(0) let c = getchar(0)
@@ -395,8 +427,10 @@ function! s:add(repo, ...)
let name = fnamemodify(repo, ':t:s?\.git$??') let name = fnamemodify(repo, ':t:s?\.git$??')
let spec = extend(s:infer_properties(name, repo), let spec = extend(s:infer_properties(name, repo),
\ a:0 == 1 ? s:parse_options(a:1) : s:base_spec) \ a:0 == 1 ? s:parse_options(a:1) : s:base_spec)
if !has_key(g:plugs, name)
call add(g:plugs_order, name)
endif
let g:plugs[name] = spec let g:plugs[name] = spec
let g:plugs_order += [name]
let s:loaded[name] = 0 let s:loaded[name] = 0
catch catch
return s:err(v:exception) return s:err(v:exception)
@@ -407,12 +441,9 @@ function! s:parse_options(arg)
let opts = copy(s:base_spec) let opts = copy(s:base_spec)
let type = type(a:arg) let type = type(a:arg)
if type == s:TYPE.string if type == s:TYPE.string
let opts.branch = a:arg let opts.tag = a:arg
elseif type == s:TYPE.dict elseif type == s:TYPE.dict
call extend(opts, a:arg) call extend(opts, a:arg)
if has_key(opts, 'tag')
let opts.branch = remove(opts, 'tag')
endif
if has_key(opts, 'dir') if has_key(opts, 'dir')
let opts.dir = s:dirpath(expand(opts.dir)) let opts.dir = s:dirpath(expand(opts.dir))
endif endif
@@ -579,6 +610,7 @@ function! s:prepare()
endif endif
silent! unmap <buffer> <cr> silent! unmap <buffer> <cr>
silent! unmap <buffer> L silent! unmap <buffer> L
silent! unmap <buffer> o
silent! unmap <buffer> X silent! unmap <buffer> X
setlocal buftype=nofile bufhidden=wipe nobuflisted noswapfile nowrap cursorline modifiable setlocal buftype=nofile bufhidden=wipe nobuflisted noswapfile nowrap cursorline modifiable
setf vim-plug setf vim-plug
@@ -691,6 +723,15 @@ function! s:update_impl(pull, force, args) abort
return return
endif endif
if !s:is_win && s:git_version_requirement(2, 3)
let s:git_terminal_prompt = exists('$GIT_TERMINAL_PROMPT') ? $GIT_TERMINAL_PROMPT : ''
let $GIT_TERMINAL_PROMPT = 0
for plug in values(todo)
let plug.uri = substitute(plug.uri,
\ '^https://git::@github\.com', 'https://github.com', '')
endfor
endif
if !isdirectory(g:plug_home) if !isdirectory(g:plug_home)
try try
call mkdir(g:plug_home, 'p') call mkdir(g:plug_home, 'p')
@@ -708,7 +749,7 @@ function! s:update_impl(pull, force, args) abort
\ 'pull': a:pull, \ 'pull': a:pull,
\ 'force': a:force, \ 'force': a:force,
\ 'new': {}, \ 'new': {},
\ 'threads': (has('ruby') || s:nvim) ? min([len(todo), threads]) : 1, \ 'threads': (s:py2 || s:ruby || s:nvim) ? min([len(todo), threads]) : 1,
\ 'bar': '', \ 'bar': '',
\ 'fin': 0 \ 'fin': 0
\ } \ }
@@ -717,17 +758,29 @@ function! s:update_impl(pull, force, args) abort
call append(0, ['', '']) call append(0, ['', ''])
normal! 2G normal! 2G
if has('ruby') && s:update.threads > 1 " Python version requirement (>= 2.7)
if s:py2 && !s:ruby && !s:nvim && s:update.threads > 1
redir => pyv
silent python import platform; print(platform.python_version())
redir END
let s:py2 = s:version_requirement(
\ map(split(split(pyv)[0], '\.'), 'str2nr(v:val)'), [2, 6])
endif
if (s:py2 || s:ruby) && !s:nvim && s:update.threads > 1
try try
let imd = &imd let imd = &imd
if s:mac_gui if s:mac_gui
set noimd set noimd
endif endif
call s:update_ruby() if s:ruby
call s:update_ruby()
else
call s:update_python()
endif
catch catch
let lines = getline(4, '$') let lines = getline(4, '$')
let printed = {} let printed = {}
silent 4,$d _ silent! 4,$d _
for line in lines for line in lines
let name = s:extract_name(line, '.', '') let name = s:extract_name(line, '.', '')
if empty(name) || !has_key(printed, name) if empty(name) || !has_key(printed, name)
@@ -750,6 +803,9 @@ function! s:update_impl(pull, force, args) abort
endfunction endfunction
function! s:update_finish() function! s:update_finish()
if exists('s:git_terminal_prompt')
let $GIT_TERMINAL_PROMPT = s:git_terminal_prompt
endif
if s:switch_in() if s:switch_in()
call s:do(s:update.pull, s:update.force, filter(copy(s:update.all), 'has_key(v:val, "do")')) call s:do(s:update.pull, s:update.force, filter(copy(s:update.all), 'has_key(v:val, "do")'))
call s:finish(s:update.pull) call s:finish(s:update.pull)
@@ -768,7 +824,7 @@ function! s:job_abort()
for [name, j] in items(s:jobs) for [name, j] in items(s:jobs)
silent! call jobstop(j.jobid) silent! call jobstop(j.jobid)
if j.new if j.new
call system('rm -rf ' . s:shellesc(g:plugs[name].dir)) call s:system('rm -rf ' . s:shellesc(g:plugs[name].dir))
endif endif
endfor endfor
let s:jobs = {} let s:jobs = {}
@@ -892,6 +948,8 @@ function! s:update_vim()
endfunction endfunction
function! s:tick() function! s:tick()
let pull = s:update.pull
let prog = s:progress_opt(s:nvim)
while 1 " Without TCO, Vim stack is bound to explode while 1 " Without TCO, Vim stack is bound to explode
if empty(s:update.todo) if empty(s:update.todo)
if empty(s:jobs) && !s:update.fin if empty(s:jobs) && !s:update.fin
@@ -903,19 +961,21 @@ while 1 " Without TCO, Vim stack is bound to explode
let name = keys(s:update.todo)[0] let name = keys(s:update.todo)[0]
let spec = remove(s:update.todo, name) let spec = remove(s:update.todo, name)
let pull = s:update.pull
let new = !isdirectory(spec.dir) let new = !isdirectory(spec.dir)
call s:log(new ? '+' : '*', name, pull ? 'Updating ...' : 'Installing ...') call s:log(new ? '+' : '*', name, pull ? 'Updating ...' : 'Installing ...')
redraw redraw
let checkout = s:shellesc(has_key(spec, 'tag') ? spec.tag : spec.branch)
let merge = s:shellesc(has_key(spec, 'tag') ? spec.tag : 'origin/'.spec.branch)
if !new if !new
let [valid, msg] = s:git_valid(spec, 0) let [valid, msg] = s:git_valid(spec, 0)
if valid if valid
if pull if pull
call s:spawn(name, call s:spawn(name,
\ printf('git checkout -q %s 2>&1 && git pull --progress --no-rebase origin %s 2>&1 && git submodule update --init --recursive 2>&1', \ printf('(git fetch %s 2>&1 && git checkout -q %s 2>&1 && git merge --ff-only %s 2>&1 && git submodule update --init --recursive 2>&1)',
\ s:shellesc(spec.branch), s:shellesc(spec.branch)), { 'dir': spec.dir }) \ prog, checkout, merge), { 'dir': spec.dir })
else else
let s:jobs[name] = { 'running': 0, 'result': 'Already installed', 'error': 0 } let s:jobs[name] = { 'running': 0, 'result': 'Already installed', 'error': 0 }
endif endif
@@ -924,9 +984,10 @@ while 1 " Without TCO, Vim stack is bound to explode
endif endif
else else
call s:spawn(name, call s:spawn(name,
\ printf('git clone --progress --recursive %s -b %s %s 2>&1', \ printf('git clone %s --recursive %s -b %s %s 2>&1',
\ prog,
\ s:shellesc(spec.uri), \ s:shellesc(spec.uri),
\ s:shellesc(spec.branch), \ checkout,
\ s:shellesc(s:trim(spec.dir))), { 'new': 1 }) \ s:shellesc(s:trim(spec.dir))), { 'new': 1 })
endif endif
@@ -939,6 +1000,386 @@ while 1 " Without TCO, Vim stack is bound to explode
endwhile endwhile
endfunction endfunction
function! s:update_python()
python << EOF
""" Due to use of signals this function is POSIX only. """
import datetime
import functools
import os
import Queue
import random
import re
import shutil
import signal
import subprocess
import tempfile
import threading as thr
import time
import traceback
import vim
G_PULL = vim.eval('s:update.pull') == '1'
G_RETRIES = int(vim.eval('get(g:, "plug_retries", 2)')) + 1
G_TIMEOUT = int(vim.eval('get(g:, "plug_timeout", 60)'))
G_PROGRESS = vim.eval('s:progress_opt(1)')
G_LOG_PROB = 1.0 / int(vim.eval('s:update.threads'))
G_STOP = thr.Event()
class CmdTimedOut(Exception):
pass
class CmdFailed(Exception):
pass
class InvalidURI(Exception):
pass
class Action(object):
INSTALL, UPDATE, ERROR, DONE = ['+', '*', 'x', '-']
class GLog(object):
ON = None
LOGDIR = None
@classmethod
def write(cls, msg):
if cls.ON is None:
cls.ON = int(vim.eval('get(g:, "plug_log_on", 0)'))
cls.LOGDIR = os.path.expanduser(vim.eval('get(g:, "plug_logs", "~/plug_logs")'))
if cls.ON:
if not os.path.exists(cls.LOGDIR):
os.makedirs(cls.LOGDIR)
cls._write(msg)
@classmethod
def _write(cls, msg):
name = thr.current_thread().name
fname = cls.LOGDIR + os.path.sep + name
with open(fname, 'ab') as flog:
ltime = datetime.datetime.now().strftime("%H:%M:%S.%f")
msg = '[{0},{1}] {2}{3}'.format(name, ltime, msg, '\n')
flog.write(msg)
class Buffer(object):
def __init__(self, lock, num_plugs):
self.bar = ''
self.event = 'Updating' if vim.eval('s:update.pull') == '1' else 'Installing'
self.is_win = vim.eval('s:is_win') == '1'
self.lock = lock
self.maxy = int(vim.eval('winheight(".")'))
self.num_plugs = num_plugs
def _where(self, name):
""" Find first line with name in current buffer. Return line num. """
found, lnum = False, 0
matcher = re.compile('^[-+x*] {0}:'.format(name))
for line in vim.current.buffer:
if matcher.search(line) is not None:
found = True
break
lnum += 1
if not found:
lnum = -1
return lnum
def header(self):
curbuf = vim.current.buffer
curbuf[0] = self.event + ' plugins ({0}/{1})'.format(len(self.bar), self.num_plugs)
num_spaces = self.num_plugs - len(self.bar)
curbuf[1] = '[{0}{1}]'.format(self.bar, num_spaces * ' ')
vim.command('normal! 2G')
if not self.is_win:
vim.command('redraw')
def write(self, *args, **kwargs):
with self.lock:
self._write(*args, **kwargs)
def _write(self, action, name, lines):
first, rest = lines[0], lines[1:]
msg = ['{0} {1}{2}{3}'.format(action, name, ': ' if first else '', first)]
padded_rest = [' ' + line for line in rest]
msg.extend(padded_rest)
try:
if action == Action.ERROR:
self.bar += 'x'
vim.command("call add(s:update.errors, '{0}')".format(name))
elif action == Action.DONE:
self.bar += '='
curbuf = vim.current.buffer
lnum = self._where(name)
if lnum != -1: # Found matching line num
del curbuf[lnum]
if lnum > self.maxy and action in set([Action.INSTALL, Action.UPDATE]):
lnum = 3
else:
lnum = 3
curbuf.append(msg, lnum)
self.header()
except vim.error:
GLog.write('Buffer Update FAILED.')
class Command(object):
def __init__(self, cmd, cmd_dir=None, timeout=60, ntries=3, cb=None, clean=None):
self.cmd = cmd
self.cmd_dir = cmd_dir
self.timeout = timeout
self.ntries = ntries
self.callback = cb if cb else (lambda msg: None)
self.clean = clean
def attempt_cmd(self):
""" Tries to run the command, returns result if no exceptions. """
attempt = 0
finished = False
limit = self.timeout
while not finished:
try:
attempt += 1
result = self.timeout_cmd()
finished = True
except CmdTimedOut:
if attempt != self.ntries:
for count in range(3, 0, -1):
if G_STOP.is_set():
raise KeyboardInterrupt
msg = 'Timeout. Will retry in {0} second{1} ...'.format(
count, 's' if count != 1 else '')
self.callback([msg])
time.sleep(1)
self.timeout += limit
self.callback(['Retrying ...'])
else:
raise
return result
def timeout_cmd(self):
""" Execute a cmd & poll for callback. Returns list of output.
Raises CmdFailed -> return code for Popen isn't 0
Raises CmdTimedOut -> command exceeded timeout without new output
"""
proc = None
first_line = True
try:
tfile = tempfile.NamedTemporaryFile()
proc = subprocess.Popen(self.cmd, cwd=self.cmd_dir, stdout=tfile,
stderr=subprocess.STDOUT, shell=True, preexec_fn=os.setsid)
while proc.poll() is None:
# Yield this thread
time.sleep(0.2)
if G_STOP.is_set():
raise KeyboardInterrupt
if first_line or random.random() < G_LOG_PROB:
first_line = False
line = nonblock_read(tfile.name)
if line:
self.callback([line])
time_diff = time.time() - os.path.getmtime(tfile.name)
if time_diff > self.timeout:
raise CmdTimedOut(['Timeout!'])
tfile.seek(0)
result = [line.rstrip() for line in tfile]
if proc.returncode != 0:
msg = ['']
msg.extend(result)
raise CmdFailed(msg)
except:
if proc and proc.poll() is None:
os.killpg(proc.pid, signal.SIGTERM)
if self.clean:
self.clean()
raise
return result
class Plugin(object):
def __init__(self, name, args, buf, lock):
self.name = name
self.args = args
self.buf = buf
self.lock = lock
tag = args.get('tag', 0)
self.checkout = esc(tag if tag else args['branch'])
self.merge = esc(tag if tag else 'origin/' + args['branch'])
def manage(self):
try:
if os.path.exists(self.args['dir']):
self.update()
else:
self.install()
with self.lock:
vim.command("let s:update.new['{0}'] = 1".format(self.name))
except (CmdTimedOut, CmdFailed, InvalidURI) as exc:
self.write(Action.ERROR, self.name, exc.message)
except KeyboardInterrupt:
G_STOP.set()
self.write(Action.ERROR, self.name, ['Interrupted!'])
except:
# Any exception except those above print stack trace
msg = 'Trace:\n{0}'.format(traceback.format_exc().rstrip())
self.write(Action.ERROR, self.name, msg.split('\n'))
raise
def install(self):
target = self.args['dir']
def clean(target):
def _clean():
try:
shutil.rmtree(target)
except OSError:
pass
return _clean
self.write(Action.INSTALL, self.name, ['Installing ...'])
callback = functools.partial(self.buf.write, Action.INSTALL, self.name)
cmd = 'git clone {0} --recursive {1} -b {2} {3} 2>&1'.format(
G_PROGRESS, self.args['uri'], self.checkout, esc(target))
com = Command(cmd, None, G_TIMEOUT, G_RETRIES, callback, clean(target))
result = com.attempt_cmd()
self.write(Action.DONE, self.name, result[-1:])
def update(self):
match = re.compile(r'git::?@')
actual_uri = re.sub(match, '', self.repo_uri())
expect_uri = re.sub(match, '', self.args['uri'])
if actual_uri != expect_uri:
msg = ['',
'Invalid URI: {0}'.format(actual_uri),
'Expected {0}'.format(expect_uri),
'PlugClean required.']
raise InvalidURI(msg)
if G_PULL:
self.write(Action.UPDATE, self.name, ['Updating ...'])
callback = functools.partial(self.buf.write, Action.UPDATE, self.name)
cmds = ['git fetch {0}'.format(G_PROGRESS),
'git checkout -q {0}'.format(self.checkout),
'git merge --ff-only {0}'.format(self.merge),
'git submodule update --init --recursive']
cmd = ' 2>&1 && '.join(cmds)
GLog.write(cmd)
com = Command(cmd, self.args['dir'], G_TIMEOUT, G_RETRIES, callback)
result = com.attempt_cmd()
GLog.write(result)
self.write(Action.DONE, self.name, result[-1:])
else:
self.write(Action.DONE, self.name, ['Already installed'])
def repo_uri(self):
cmd = 'git rev-parse --abbrev-ref HEAD 2>&1 && git config remote.origin.url'
command = Command(cmd, self.args['dir'], G_TIMEOUT, G_RETRIES)
result = command.attempt_cmd()
return result[-1]
def write(self, action, name, msg):
GLog.write('{0} {1}: {2}'.format(action, name, '\n'.join(msg)))
self.buf.write(action, name, msg)
class PlugThread(thr.Thread):
def __init__(self, tname, args):
super(PlugThread, self).__init__()
self.tname = tname
self.args = args
def run(self):
thr.current_thread().name = self.tname
work_q, lock, buf = self.args
try:
while not G_STOP.is_set():
name, args = work_q.get_nowait()
GLog.write('{0}: Dir {1}'.format(name, args['dir']))
plug = Plugin(name, args, buf, lock)
plug.manage()
work_q.task_done()
except Queue.Empty:
GLog.write('Queue now empty.')
class RefreshThread(thr.Thread):
def __init__(self, lock):
super(RefreshThread, self).__init__()
self.lock = lock
self.running = True
def run(self):
while self.running:
with self.lock:
vim.command('noautocmd normal! a')
time.sleep(0.2)
def stop(self):
self.running = False
def esc(name):
return '"' + name.replace('"', '\"') + '"'
def nonblock_read(fname):
""" Read a file with nonblock flag. Return the last line. """
fread = os.open(fname, os.O_RDONLY | os.O_NONBLOCK)
buf = os.read(fread, 100000)
os.close(fread)
line = buf.rstrip('\r\n')
left = max(line.rfind('\r'), line.rfind('\n'))
if left != -1:
left += 1
line = line[left:]
return line
def main():
thr.current_thread().name = 'main'
GLog.write('')
if GLog.ON and os.path.exists(GLog.LOGDIR):
shutil.rmtree(GLog.LOGDIR)
threads = []
nthreads = int(vim.eval('s:update.threads'))
plugs = vim.eval('s:update.todo')
mac_gui = vim.eval('s:mac_gui') == '1'
is_win = vim.eval('s:is_win') == '1'
GLog.write('Plugs: {0}'.format(plugs))
GLog.write('PULL: {0}, WIN: {1}, MAC: {2}'.format(G_PULL, is_win, mac_gui))
GLog.write('Num Threads: {0}'.format(nthreads))
lock = thr.Lock()
buf = Buffer(lock, len(plugs))
work_q = Queue.Queue()
for work in plugs.items():
work_q.put(work)
GLog.write('Starting Threads')
for num in range(nthreads):
tname = 'PlugT-{0:02}'.format(num)
thread = PlugThread(tname, (work_q, lock, buf))
thread.start()
threads.append(thread)
if mac_gui:
rthread = RefreshThread(lock)
rthread.start()
GLog.write('Joining Live Threads')
for thread in threads:
thread.join()
if mac_gui:
rthread.stop()
rthread.join()
GLog.write('Cleanly Exited Main')
main()
EOF
endfunction
function! s:update_ruby() function! s:update_ruby()
ruby << EOF ruby << EOF
module PlugStream module PlugStream
@@ -1040,7 +1481,7 @@ function! s:update_ruby()
if iswin if iswin
Timeout::timeout(timeout) 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
File.unlink tmp rescue nil File.unlink tmp rescue nil
end end
@@ -1097,19 +1538,20 @@ function! s:update_ruby()
end end
} if VIM::evaluate('s:mac_gui') == 1 } if VIM::evaluate('s:mac_gui') == 1
progress = iswin ? '' : '--progress' progress = VIM::evaluate('s:progress_opt(1)')
nthr.times do nthr.times do
mtx.synchronize do mtx.synchronize do
threads << Thread.new { threads << Thread.new {
while pair = take1.call while pair = take1.call
name = pair.first name = pair.first
dir, uri, branch = pair.last.values_at *%w[dir uri branch] dir, uri, branch, tag = pair.last.values_at *%w[dir uri branch tag]
branch = esc branch checkout = esc(tag ? tag : branch)
merge = esc(tag ? tag : "origin/#{branch}")
subm = "git submodule update --init --recursive 2>&1" subm = "git submodule update --init --recursive 2>&1"
exists = File.directory? dir exists = File.directory? dir
ok, result = ok, result =
if exists if exists
dir = esc dir dir = iswin ? dir : esc(dir)
ret, data = bt.call "#{cd} #{dir} && git rev-parse --abbrev-ref HEAD 2>&1 && git config remote.origin.url", nil, nil, nil ret, data = bt.call "#{cd} #{dir} && git rev-parse --abbrev-ref HEAD 2>&1 && git config remote.origin.url", nil, nil, nil
current_uri = data.lines.to_a.last current_uri = data.lines.to_a.last
if !ret if !ret
@@ -1125,7 +1567,7 @@ function! s:update_ruby()
else else
if pull if pull
log.call name, 'Updating ...', :update log.call name, 'Updating ...', :update
bt.call "#{cd} #{dir} && git checkout -q #{branch} 2>&1 && (git pull --no-rebase origin #{branch} #{progress} 2>&1 && #{subm})", name, :update, nil bt.call "#{cd} #{dir} && git fetch #{progress} 2>&1 && git checkout -q #{checkout} 2>&1 && git merge --ff-only #{merge} 2>&1 && #{subm}", name, :update, nil
else else
[true, skip] [true, skip]
end end
@@ -1133,7 +1575,7 @@ function! s:update_ruby()
else else
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", name, :install, proc { bt.call "git clone #{progress} --recursive #{uri} -b #{checkout} #{d} 2>&1", name, :install, proc {
FileUtils.rm_rf dir FileUtils.rm_rf dir
} }
end end
@@ -1151,7 +1593,7 @@ EOF
endfunction endfunction
function! s:shellesc(arg) function! s:shellesc(arg)
return '"'.substitute(a:arg, '"', '\\"', 'g').'"' return '"'.escape(a:arg, '"').'"'
endfunction endfunction
function! s:glob_dir(path) function! s:glob_dir(path)
@@ -1178,12 +1620,20 @@ function! s:format_message(bullet, name, message)
endfunction endfunction
function! s:with_cd(cmd, dir) function! s:with_cd(cmd, dir)
return 'cd '.s:esc(a:dir).' && '.a:cmd return printf('cd%s %s && %s', s:is_win ? ' /d' : '', s:shellesc(a:dir), a:cmd)
endfunction endfunction
function! s:system(cmd, ...) function! s:system(cmd, ...)
let cmd = a:0 > 0 ? s:with_cd(a:cmd, a:1) : a:cmd try
return system(s:is_win ? '('.cmd.')' : cmd) let sh = &shell
if !s:is_win
set shell=sh
endif
let cmd = a:0 > 0 ? s:with_cd(a:cmd, a:1) : a:cmd
return system(s:is_win ? '('.cmd.')' : cmd)
finally
let &shell = sh
endtry
endfunction endfunction
function! s:system_chomp(...) function! s:system_chomp(...)
@@ -1207,13 +1657,19 @@ function! s:git_valid(spec, check_branch)
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 " Check tag
if has_key(a:spec, 'tag')
let tag = s:system_chomp('git describe --exact-match --tags HEAD 2>&1', a:spec.dir) let tag = s:system_chomp('git describe --exact-match --tags HEAD 2>&1', a:spec.dir)
if a:spec.branch !=# tag if a:spec.tag !=# tag
let msg = printf('Invalid branch/tag: %s (expected: %s). Try PlugUpdate.', let msg = printf('Invalid tag: %s (expected: %s). Try PlugUpdate.',
\ (empty(tag) ? branch : tag), a:spec.branch) \ (empty(tag) ? 'N/A' : tag), a:spec.tag)
let ret = 0 let ret = 0
endif endif
" Check branch
elseif a:spec.branch !=# branch
let msg = printf('Invalid branch: %s (expected: %s). Try PlugUpdate.',
\ branch, a:spec.branch)
let ret = 0
endif endif
endif endif
else else
@@ -1243,6 +1699,7 @@ function! s:clean(force)
let allowed = {} let allowed = {}
for dir in dirs for dir in dirs
let allowed[s:dirpath(fnamemodify(dir, ':h:h'))] = 1
let allowed[dir] = 1 let allowed[dir] = 1
for child in s:glob_dir(dir) for child in s:glob_dir(dir)
let allowed[child] = 1 let allowed[child] = 1
@@ -1271,7 +1728,7 @@ function! s:clean(force)
if yes if yes
for dir in todo for dir in todo
if isdirectory(dir) if isdirectory(dir)
call system((s:is_win ? 'rmdir /S /Q ' : 'rm -rf ') . s:shellesc(dir)) call s:system((s:is_win ? 'rmdir /S /Q ' : 'rm -rf ') . s:shellesc(dir))
endif endif
endfor endfor
call append(line('$'), 'Removed.') call append(line('$'), 'Removed.')
@@ -1288,28 +1745,30 @@ function! s:upgrade()
redraw redraw
try try
if executable('curl') if executable('curl')
let output = system(printf('curl -fLo %s %s', s:shellesc(new), s:plug_src)) let output = s:system(printf('curl -fLo %s %s', s:shellesc(new), s:plug_src))
if v:shell_error if v:shell_error
throw get(s:lines(output), -1, v:shell_error) throw get(s:lines(output), -1, v:shell_error)
endif endif
elseif has('ruby') elseif s:ruby
call s:upgrade_using_ruby(new) call s:upgrade_using_ruby(new)
elseif s:py2
call s:upgrade_using_python(new)
else else
return s:err('curl executable or ruby support not found') return s:err('Missing: curl executable, ruby support or python support')
endif endif
catch catch
return s:err('Error upgrading vim-plug: '. v:exception) return s:err('Error upgrading vim-plug: '. v:exception)
endtry endtry
if readfile(s:me) ==# readfile(new) if readfile(s:me) ==# readfile(new)
echo 'vim-plug is up-to-date' echo 'vim-plug is already up-to-date'
silent! call delete(new) silent! call delete(new)
return 0 return 0
else else
call rename(s:me, s:me . '.old') call rename(s:me, s:me . '.old')
call rename(new, s:me) call rename(new, s:me)
unlet g:loaded_plug unlet g:loaded_plug
echo 'vim-plug is upgraded' echo 'vim-plug has been upgraded'
return 1 return 1
endif endif
endfunction endfunction
@@ -1323,6 +1782,15 @@ function! s:upgrade_using_ruby(new)
EOF EOF
endfunction endfunction
function! s:upgrade_using_python(new)
python << EOF
import urllib
import vim
psrc, dest = vim.eval('s:plug_src'), vim.eval('a:new')
urllib.urlretrieve(psrc, dest)
EOF
endfunction
function! s:upgrade_specs() function! s:upgrade_specs()
for spec in values(g:plugs) for spec in values(g:plugs)
let spec.frozen = get(spec, 'frozen', 0) let spec.frozen = get(spec, 'frozen', 0)
@@ -1438,7 +1906,7 @@ function! s:preview_commit()
execute 'pedit' sha execute 'pedit' sha
wincmd P wincmd P
setlocal filetype=git buftype=nofile nobuflisted setlocal filetype=git buftype=nofile nobuflisted
execute 'silent read !cd' s:esc(g:plugs[name].dir) '&& git show' sha execute 'silent read !cd' s:shellesc(g:plugs[name].dir) '&& git show' sha
normal! gg"_dd normal! gg"_dd
wincmd p wincmd p
endfunction endfunction
@@ -1472,6 +1940,7 @@ function! s:diff()
call setline(1, cnt == 0 ? 'No updates.' : 'Last update:') call setline(1, cnt == 0 ? 'No updates.' : 'Last update:')
nnoremap <silent> <buffer> <cr> :silent! call <SID>preview_commit()<cr> nnoremap <silent> <buffer> <cr> :silent! call <SID>preview_commit()<cr>
nnoremap <silent> <buffer> o :silent! call <SID>preview_commit()<cr>
nnoremap <silent> <buffer> X :call <SID>revert()<cr> nnoremap <silent> <buffer> X :call <SID>revert()<cr>
normal! gg normal! gg
setlocal nomodifiable setlocal nomodifiable
@@ -1499,9 +1968,9 @@ function! s:snapshot(...) abort
let [type, var, header] = s:is_win ? let [type, var, header] = s:is_win ?
\ ['dosbatch', '%PLUG_HOME%', \ ['dosbatch', '%PLUG_HOME%',
\ ['@echo off', ':: Generated by vim-plug', ':: '.strftime("%c"), '', \ ['@echo off', ':: Generated by vim-plug', ':: '.strftime("%c"), '',
\ ':: Make sure to PlugUpdate first', '', 'set PLUG_HOME='.s:esc(home)]] : \ ':: Make sure to PlugUpdate first', '', 'set PLUG_HOME='.home]] :
\ ['sh', '$PLUG_HOME', \ ['sh', '$PLUG_HOME',
\ ['#!/bin/bash', '# Generated by vim-plug', '# '.strftime("%c"), '', \ ['#!/bin/sh', '# Generated by vim-plug', '# '.strftime("%c"), '',
\ 'vim +PlugUpdate +qa', '', 'PLUG_HOME='.s:esc(home)]] \ 'vim +PlugUpdate +qa', '', 'PLUG_HOME='.s:esc(home)]]
call s:prepare() call s:prepare()
@@ -1518,17 +1987,18 @@ function! s:snapshot(...) abort
let sha = s:system_chomp('git rev-parse --short HEAD', dir) let sha = s:system_chomp('git rev-parse --short HEAD', dir)
if !empty(sha) if !empty(sha)
call append(anchor, printf('cd %s && git reset --hard %s', call append(anchor, printf('cd %s && git reset --hard %s',
\ substitute(dir, '^'.g:plug_home, var, ''), sha)) \ substitute(dir, '^\V'.escape(g:plug_home, '\'), var, ''), sha))
redraw redraw
endif endif
endfor endfor
if a:0 > 0 if a:0 > 0
let fn = s:esc(expand(a:1)) let fn = expand(a:1)
let fne = s:esc(fn)
call writefile(getline(1, '$'), fn) call writefile(getline(1, '$'), fn)
if !s:is_win | call system('chmod +x ' . fn) | endif if !s:is_win | call s:system('chmod +x ' . fne) | endif
echo 'Saved to '.a:1 echo 'Saved to '.a:1
silent execute 'e' fn silent execute 'e' fne
endif endif
endfunction endfunction

242
test/regressions.vader Normal file
View File

@@ -0,0 +1,242 @@
**********************************************************************
Execute (#112 On-demand loading should not suppress messages from ftplugin):
call plug#begin('$PLUG_FIXTURES')
Plug '$PLUG_FIXTURES/ftplugin-msg', { 'for': 'c' }
call plug#end()
redir => out
tabnew a.c
redir END
Assert stridx(out, 'ftplugin') >= 0
* The same applies to plug#load())
redir => out
call plug#load('ftplugin-msg')
redir END
Assert stridx(out, 'ftplugin') >= 0
q
**********************************************************************
Execute (#114 Should not contain empty path in &rtp):
call plug#begin('$TMPDIR/plugged')
call plug#end()
Log &rtp
Assert &rtp !~ ',,', 'Commas'
Assert &rtp !~ '^,', 'Comma prefix'
Assert &rtp !~ ',$', 'Comma suffix'
**********************************************************************
Execute (#130 Proper cleanup of on-demand loading triggers):
augroup PlugLOD
autocmd!
augroup END
" Cleared on command
call plug#begin('$TMPDIR/plugged')
Plug 'junegunn/vim-emoji', { 'on': ['EmojiCommand', 'EmojiCommand2', '<Plug>(EmojiMapping)'] }
call plug#end()
PlugInstall | q
Assert exists(':EmojiCommand'), 'EmojiCommand not defined'
Assert exists(':EmojiCommand2'), 'EmojiCommand2 not defined'
Assert !empty(mapcheck('<Plug>(EmojiMapping)')), '<Plug>(EmojiMapping) not defined'
silent! EmojiCommand
Assert !exists(':EmojiCommand'), 'EmojiCommand defined'
Assert !exists(':EmojiCommand2'), 'EmojiCommand2 defined'
Assert empty(mapcheck('<Plug>(EmojiMapping)')), '<Plug>(EmojiMapping) defined'
" Cleared on FileType
call plug#begin('$TMPDIR/plugged')
Plug 'junegunn/vim-emoji', { 'on': ['EmojiCommandExtra', '<Plug>(EmojiMappingExtra)'], 'for': ['emoji'] }
call plug#end()
Assert exists(':EmojiCommandExtra'), 'EmojiCommandExtra not defined'
Assert !empty(mapcheck('<Plug>(EmojiMappingExtra)')), '<Plug>(EmojiMappingExtra) not defined'
setf emoji
Assert !exists(':EmojiCommandExtra'), 'EmojiCommandExtra defined'
Assert empty(mapcheck('<Plug>(EmojiMappingExtra)')), '<Plug>(EmojiMappingExtra) defined'
**********************************************************************
Execute (#131 Syntax error):
call plug#begin('/no-permission')
Plug 'junegunn/vim-emoji'
call plug#end()
redir => out
silent PlugInstall
redir END
Assert out =~ 'Invalid plug directory: /no-permission'
**********************************************************************
Execute (#139-1 Using new remote branch):
" Make sure to remove the clone
call plug#begin('$TMPDIR/plugged')
call plug#end()
PlugClean!
" Install master branch
call plug#begin('$TMPDIR/plugged')
Plug expand('file:///$TMPDIR/new-branch')
call plug#end()
PlugUpdate
unlet! g:foo g:bar g:baz
call plug#load('new-branch')
Assert exists('g:foo'), 'g:foo should be found'
Assert !exists('g:bar'), 'g:bar should not be found'
Assert !exists('g:baz'), 'g:baz should not be found'
" Create a new branch on origin
call system('cd $TMPDIR/new-branch && git checkout -b new &&'
\. 'echo "let g:bar = 1" > plugin/bar.vim && git add plugin/bar.vim &&'
\. 'git commit -m second')
" We're setting up two plugins so that parallel installer is used
call plug#begin('$TMPDIR/plugged')
Plug 'junegunn/seoul256.vim'
Plug expand('file:///$TMPDIR/new-branch'), { 'branch': 'new' }
call plug#end()
PlugUpdate
silent %y
Log @"
Assert @" !~? 'error', 'Should be able to use new remote branch: ' . @"
unlet! g:foo g:bar g:baz
call plug#load('new-branch')
Assert exists('g:foo'), 'g:foo should be found'
Assert exists('g:bar'), 'g:bar should be found'
Assert !exists('g:baz'), 'g:baz should not be found'
call PlugStatusSorted()
Expect:
- new-branch: OK
- seoul256.vim: OK
Finished. 0 error(s).
[==]
Execute (#139-2 Using yet another new remote branch):
" Create another branch on origin
call system('cd $TMPDIR/new-branch && git checkout master &&'
\. 'git checkout -b brand-new &&'
\. 'echo "let g:baz = 1" > plugin/baz.vim && git add plugin/baz.vim &&'
\. 'git commit -m third')
" Test Vim installer here
call plug#begin('$TMPDIR/plugged')
Plug expand('file:///$TMPDIR/new-branch'), { 'branch': 'brand-new' }
call plug#end()
PlugUpdate
silent %y
Log @"
Assert @" !~? 'error', 'Should be able to use new remote branch: ' . @"
unlet! g:foo g:bar g:baz
call plug#load('new-branch')
Assert exists('g:foo'), 'g:foo should be found'
Assert !exists('g:bar'), 'g:bar should not be found'
Assert exists('g:baz'), 'g:baz should be found'
call PlugStatusSorted()
Expect:
- new-branch: OK
Finished. 0 error(s).
[=]
Execute (#139-3 Should fail when not possible to fast-forward):
" Commit on cloned repo
call system('cd $TMPDIR/plugged/new-branch && git checkout master &&'
\. 'touch foobar && git add foobar && git commit -m foobar')
" Different commit on remote
call system('cd $TMPDIR/new-branch && git checkout master &&'
\. 'touch foobaz && git add foobaz && git commit -m foobaz')
for multi in [0, 1]
call plug#begin('$TMPDIR/plugged')
if multi
Plug 'junegunn/seoul256.vim'
endif
Plug expand('file:///$TMPDIR/new-branch')
call plug#end()
PlugUpdate
silent %y
Assert @" =~ 'Not possible to fast-forward', @"
endfor
**********************************************************************
Execute (#145: Merging on-demand loading triggers - cmd):
unlet! g:xxx g:yyy
call plug#begin()
Plug '$PLUG_FIXTURES/xxx', { 'on': 'XXX' }
Plug '$PLUG_FIXTURES/yyy', { 'on': ['XXX', 'YYY'] }
call plug#end()
silent! XXX
Assert exists('g:xxx'), 'xxx is not loaded'
Assert exists('g:yyy'), 'yyy is not loaded'
Assert !exists(':YYY')
Execute (#145: Merging on-demand loading triggers - map):
unlet! g:xxx g:yyy
call plug#begin()
Plug '$PLUG_FIXTURES/xxx', { 'on': '<Plug>(xxx)' }
Plug '$PLUG_FIXTURES/yyy', { 'on': ['<Plug>(xxx)' ,'<Plug>(yyy)' ] }
call plug#end()
Assert !empty(mapcheck("<Plug>(xxx)"))
Assert !empty(mapcheck("<Plug>(yyy)"))
# FIXME feedkeys() cannot be tested with Vader
call plug#load('xxx', 'yyy')
Assert empty(mapcheck("<Plug>(xxx)"))
Assert empty(mapcheck("<Plug>(yyy)"))
**********************************************************************
Execute (#159: shell=/bin/tcsh):
let org = &shell
try
set shell=/bin/tcsh
call plug#begin('$TMPDIR/plugged')
Plug 'junegunn/seoul256.vim'
call plug#end()
PlugStatus
Log getline(1, '$')
q
AssertEqual '/bin/tcsh', &shell
finally
let &shell = org
endtry
**********************************************************************
Execute (#154: Spaces in &rtp should not be escaped):
call plug#begin('$TMPDIR/plug it')
Plug 'seoul256 vim'
call plug#end()
Log &rtp
Assert stridx(&rtp, 'plug it/seoul256 vim') >= 0
**********************************************************************
Execute (#184: Duplicate entries in &rtp):
call plug#begin('$TMPDIR/plugged')
Plug 'plugin1'
\| Plug 'plugin0'
Plug 'plugin2'
\| Plug 'plugin0'
\| Plug 'plugin1'
call plug#end()
Log &rtp
AssertEqual 3, len(filter(split(&rtp, ','), 'stridx(v:val, "plugged") >= 0'))

View File

@@ -7,14 +7,29 @@ cd - > /dev/null
export PLUG_FIXTURES=$(pwd)/fixtures export PLUG_FIXTURES=$(pwd)/fixtures
if [ ! -d vader.vim ]; then clone() {
git clone https://github.com/junegunn/vader.vim.git if [ ! -d $2 ]; then
fi git clone $1 $2
fi
}
# Clone
cd /tmp
mkdir -p junegunn vim-scripts jg
for repo in vader.vim goyo.vim rust.vim seoul256.vim vim-easy-align vim-fnr \
vim-oblique vim-pseudocl vim-redis vim-emoji; do
clone https://github.com/junegunn/${repo}.git junegunn/$repo &
done
clone https://github.com/vim-scripts/beauty256.git vim-scripts/beauty256 &
rm -rf $PLUG_FIXTURES/fzf rm -rf $PLUG_FIXTURES/fzf
if [ ! -d fzf-staged ]; then clone https://github.com/junegunn/fzf.git $PLUG_FIXTURES/fzf-staged &
git clone https://github.com/junegunn/fzf.git $PLUG_FIXTURES/fzf-staged wait
fi
(cd junegunn/seoul256.vim &&
git checkout no-t_co && git checkout master) > /dev/null 2>&1
clone junegunn/vim-emoji jg/vim-emoji
cd - > /dev/null
make_dirs() { make_dirs() {
mkdir -p "$PLUG_FIXTURES/$1" mkdir -p "$PLUG_FIXTURES/$1"
@@ -36,6 +51,7 @@ EOF
init() { init() {
rm -rf $PLUG_FIXTURES/{xxx,yyy,z1,z2} rm -rf $PLUG_FIXTURES/{xxx,yyy,z1,z2}
rm -rf $TMPDIR/new-branch
make_dirs xxx/ xxx make_dirs xxx/ xxx
make_dirs xxx/after xxx make_dirs xxx/after xxx
@@ -49,10 +65,20 @@ DOC
make_dirs z1/ z1 make_dirs z1/ z1
make_dirs z2/ z2 make_dirs z2/ z2
(
cd $TMPDIR
git init new-branch
cd new-branch
mkdir plugin
echo 'let g:foo = 1' > plugin/foo.vim
git add plugin/foo.vim
git commit -m initial
)
} }
cat > /tmp/mini-vimrc << VIMRC cat > /tmp/mini-vimrc << VIMRC
set rtp+=vader.vim set rtp+=/tmp/junegunn/vader.vim
set shell=/bin/bash set shell=/bin/bash
source $PLUG_SRC source $PLUG_SRC
VIMRC VIMRC
@@ -60,10 +86,10 @@ VIMRC
[ -z "$TMPDIR" ] && export TMPDIR=/tmp/ [ -z "$TMPDIR" ] && export TMPDIR=/tmp/
init init
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! test.vader' > /dev/null &&
init && init &&
/usr/local/bin/vim -Nu /tmp/mini-vimrc -c 'let g:plug_threads = 1 | Vader! workflow.vader' > /dev/null /usr/local/bin/vim -Nu /tmp/mini-vimrc -c 'let g:plug_threads = 1 | Vader! test.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 test.vader'
fi fi

72
test/test.vader Normal file
View File

@@ -0,0 +1,72 @@
Execute (Initialize test environment):
Save &rtp, g:plugs, g:plug_home, g:plug_window
let first_rtp = split(&rtp, ',')[0]
let last_rtp = split(&rtp, ',')[-1]
let vader = fnamemodify(globpath(&rtp, 'autoload/vader.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
execute 'set rtp^='.vader
execute 'set rtp^='.plug
let basertp = &rtp
unlet! g:plugs g:plug_home g:plug_window
let g:plug_url_format = 'file:///tmp/%s'
set t_Co=256
colo default
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>)
function! EnsureLoaded()
if has('vim_starting')
runtime! plugin/**/*.vim
endif
endfunction
Execute (Print Interpreter Version):
redir => out
if has('ruby')
silent ruby puts 'Ruby: ' + RUBY_VERSION
elseif has('python')
silent python import sys; svi = sys.version_info; print 'Python: {}.{}.{}'.format(svi[0], svi[1], svi[2])
endif
redir END
Log substitute(out, '\n', '', 'g')
Include: workflow.vader
Include: regressions.vader
Execute (Cleanup):
silent! call system('rm -rf '.temp_plugged)
silent! call system('rm -rf '.temp_plugged)
silent! call rename(fzf, expand('$PLUG_FIXTURES/fzf-staged'))
silent! unlet g:plugs
silent! unlet g:plug_home
silent! unlet g:plug_url_format
silent! unlet temp_plugged vader plug basertp save_rtp repo lnum fzf out tabnr found len
silent! delf PlugStatusSorted
silent! delf AssertExpect
silent! delf PlugUpdated
silent! delf EnsureLoaded
silent! delc AssertExpect
silent! unmap /
silent! unmap ?
Restore

View File

@@ -1,52 +1,6 @@
Execute (Initialize test environment):
Save &rtp, g:plugs, g:plug_home, g:plug_window
let first_rtp = split(&rtp, ',')[0]
let last_rtp = split(&rtp, ',')[-1]
let vader = fnamemodify(globpath(&rtp, 'autoload/vader.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
execute 'set rtp^='.vader
execute 'set rtp^='.plug
let basertp = &rtp
unlet! g:plugs g:plug_home g:plug_window
set t_Co=256
colo default
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>)
function! EnsureLoaded()
if has('vim_starting')
runtime! plugin/**/*.vim
endif
endfunction
Execute (Print Ruby version):
redir => out
silent ruby puts RUBY_VERSION
redir END
Log substitute(out, '\n', '', 'g')
Execute (plug#end() before plug#begin() should fail): Execute (plug#end() before plug#begin() should fail):
redir => out redir => out
AssertEqual 0, plug#end() silent! AssertEqual 0, plug#end()
redir END redir END
Assert stridx(out, 'Call plug#begin() first') >= 0 Assert stridx(out, 'Call plug#begin() first') >= 0
@@ -78,33 +32,33 @@ Execute (Subsequent plug#begin() calls will reuse g:plug_home):
AssertEqual temp_plugged, g:plug_home AssertEqual temp_plugged, g:plug_home
Execute (Test Plug command): Execute (Test Plug command):
" Git repo with branch ^ Git repo with branch (DEPRECATED. USE BRANCH OPTION)
Plug 'junegunn/seoul256.vim', 'yes-t_co' Plug 'junegunn/seoul256.vim', { 'branch': 'yes-t_co' }
AssertEqual 'https://git::@github.com/junegunn/seoul256.vim.git', g:plugs['seoul256.vim'].uri AssertEqual 'file:///tmp/junegunn/seoul256.vim', 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 AssertEqual 'yes-t_co', g:plugs['seoul256.vim'].branch
Plug 'junegunn/seoul256.vim', { 'branch': 'no-t_co' } " Using branch option 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 (DEPRECATED. USE TAG OPTION)
Plug 'junegunn/goyo.vim', '1.5.2' Plug 'junegunn/goyo.vim', '1.5.2'
AssertEqual 'https://git::@github.com/junegunn/goyo.vim.git', g:plugs['goyo.vim'].uri AssertEqual 'file:///tmp/junegunn/goyo.vim', 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 AssertEqual '1.5.2', g:plugs['goyo.vim'].tag
Plug 'junegunn/goyo.vim', { 'tag': '1.5.3' } " Using tag option 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'].tag
" Git URI " Git URI
Plug 'https://bitbucket.org/junegunn/vim-emoji.git' Plug 'file:///tmp/jg/vim-emoji'
AssertEqual 'https://bitbucket.org/junegunn/vim-emoji.git', g:plugs['vim-emoji'].uri AssertEqual 'file:///tmp/jg/vim-emoji', 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
" vim-scripts/ " vim-scripts/
Plug 'beauty256' Plug 'beauty256'
AssertEqual 'https://git::@github.com/vim-scripts/beauty256.git', g:plugs.beauty256.uri AssertEqual 'file:///tmp/vim-scripts/beauty256', g:plugs.beauty256.uri
AssertEqual 'master', g:plugs.beauty256.branch AssertEqual 'master', g:plugs.beauty256.branch
AssertEqual 4, len(g:plugs) AssertEqual 4, len(g:plugs)
@@ -155,7 +109,27 @@ Execute (PlugStatus after installation):
AssertExpect 'OK', 4 AssertExpect 'OK', 4
q q
Execute (PlugUpdate - tagged plugin should not fail (#174)):
PlugUpdate goyo.vim
Log getline(1, '$')
AssertExpect '^- goyo.vim', 1
q
Execute (Change tag of goyo.vim): Execute (Change tag of goyo.vim):
call plug#begin()
Plug 'junegunn/goyo.vim', { 'tag': '9.9.9' }
call plug#end()
Execute (PlugStatus):
call PlugStatusSorted()
Expect:
Invalid tag: 1.5.3 (expected: 9.9.9). Try PlugUpdate.
Finished. 1 error(s).
[=]
x goyo.vim:
Execute (Remove tag of goyo.vim):
call plug#begin() call plug#begin()
Plug 'junegunn/goyo.vim' Plug 'junegunn/goyo.vim'
call plug#end() call plug#end()
@@ -164,7 +138,7 @@ Execute (PlugStatus):
call PlugStatusSorted() call PlugStatusSorted()
Expect: Expect:
Invalid branch/tag: 1.5.3 (expected: master). Try PlugUpdate. Invalid branch: HEAD (expected: master). Try PlugUpdate.
Finished. 1 error(s). Finished. 1 error(s).
[=] [=]
x goyo.vim: x goyo.vim:
@@ -181,31 +155,53 @@ Expect:
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 'https://bitbucket.org/junegunn/vim-emoji.git' Plug 'file:///tmp/jg/vim-emoji'
call plug#end() call plug#end()
Execute (PlugStatus): Execute (PlugStatus):
call PlugStatusSorted() call PlugStatusSorted()
Expect: Expect:
Invalid branch/tag: no-t_co (expected: master). Try PlugUpdate. Invalid branch: no-t_co (expected: master). Try PlugUpdate.
- vim-emoji: OK - vim-emoji: OK
Finished. 1 error(s). Finished. 1 error(s).
[==] [==]
x seoul256.vim: x seoul256.vim:
Execute (PlugUpdate to switch branch, then PlugStatus):
PlugUpdate
call PlugStatusSorted()
Expect:
- seoul256.vim: OK
- vim-emoji: OK
Finished. 0 error(s).
[==]
Execute (Change tag of seoul256.vim):
call plug#begin()
Plug 'junegunn/seoul256.vim', { 'tag': 'no-such-tag' }
call plug#end()
call PlugStatusSorted()
Expect:
Invalid tag: N/A (expected: no-such-tag). Try PlugUpdate.
Finished. 1 error(s).
[=]
x seoul256.vim:
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 'https://bitbucket.org/junegunn/vim-emoji.git' Plug 'file:///tmp/jg/vim-emoji'
call plug#end() call plug#end()
Execute (PlugStatus): Execute (PlugStatus):
call PlugStatusSorted() call PlugStatusSorted()
Expect: Expect:
Expected: https://git::@github.com/junegunn.choi/seoul256.vim.git Expected: file:///tmp/junegunn.choi/seoul256.vim
Invalid URI: https://git::@github.com/junegunn/seoul256.vim.git Invalid URI: file:///tmp/junegunn/seoul256.vim
PlugClean required. PlugClean required.
- vim-emoji: OK - vim-emoji: OK
Finished. 1 error(s). Finished. 1 error(s).
@@ -238,8 +234,8 @@ Execute (PlugStatus):
call PlugStatusSorted() call PlugStatusSorted()
Expect: Expect:
Expected: https://git::@github.com/junegunn/vim-emoji.git Expected: file:///tmp/junegunn/vim-emoji
Invalid URI: https://bitbucket.org/junegunn/vim-emoji.git Invalid URI: file:///tmp/jg/vim-emoji
Not found. Try PlugInstall. Not found. Try PlugInstall.
PlugClean required. PlugClean required.
Finished. 2 error(s). Finished. 2 error(s).
@@ -304,8 +300,8 @@ Execute (Rollback recent updates, PlugUpdate, then PlugDiff):
" ]] motion " ]] motion
execute 'normal $]]' execute 'normal $]]'
Assert index([lnum + 4, lnum + 5], line('.')) >= 0 Assert line('.') >= 4
" +5 for merge commit " 5+ for merge commit
AssertEqual 3, col('.') AssertEqual 3, col('.')
" [[ motion " [[ motion
@@ -629,7 +625,7 @@ Execute (On install):
Plug 'junegunn/vim-pseudocl' Plug 'junegunn/vim-pseudocl'
call plug#end() call plug#end()
PlugInstall silent PlugInstall
q q
Assert filereadable(g:plugs['vim-easy-align'].dir.'/installed'), Assert filereadable(g:plugs['vim-easy-align'].dir.'/installed'),
@@ -646,7 +642,7 @@ Execute (On update):
" Reset for updates " Reset for updates
call system('cd '.g:plugs['vim-pseudocl'].dir.' && git reset --hard HEAD^') call system('cd '.g:plugs['vim-pseudocl'].dir.' && git reset --hard HEAD^')
PlugUpdate silent PlugUpdate
Log getline(1, '$') Log getline(1, '$')
q q
@@ -669,7 +665,7 @@ Execute (When already installed):
\ 'vim-pseudocl/installed2 should not exist' \ 'vim-pseudocl/installed2 should not exist'
Execute (PlugInstall!): Execute (PlugInstall!):
PlugInstall! silent PlugInstall!
q q
Assert filereadable(g:plugs['vim-easy-align'].dir.'/installed2'), Assert filereadable(g:plugs['vim-easy-align'].dir.'/installed2'),
\ 'vim-easy-align/installed2 should exist' \ 'vim-easy-align/installed2 should exist'
@@ -690,7 +686,7 @@ Execute (When already updated):
\ 'vim-pseudocl/updated2 should not exist' \ 'vim-pseudocl/updated2 should not exist'
Execute (PlugUpdate!): Execute (PlugUpdate!):
PlugUpdate! silent PlugUpdate!
q q
Assert filereadable(g:plugs['vim-easy-align'].dir.'/updated2'), Assert filereadable(g:plugs['vim-easy-align'].dir.'/updated2'),
\ 'vim-easy-align/updated2 should exist' \ 'vim-easy-align/updated2 should exist'
@@ -911,6 +907,7 @@ Execute (Open plug window in a new tab):
~ g:plug_url_format ~ g:plug_url_format
********************************************************************** **********************************************************************
Execute (Using g:plug_url_format): Execute (Using g:plug_url_format):
let prev_plug_url_format = g:plug_url_format
call plug#begin() call plug#begin()
let g:plug_url_format = 'git@bitbucket.org:%s.git' let g:plug_url_format = 'git@bitbucket.org:%s.git'
Plug 'junegunn/seoul256.vim' Plug 'junegunn/seoul256.vim'
@@ -918,7 +915,7 @@ Execute (Using g:plug_url_format):
Plug 'beauty256' Plug 'beauty256'
AssertEqual 'git@bitbucket.org:junegunn/seoul256.vim.git', g:plugs['seoul256.vim'].uri AssertEqual 'git@bitbucket.org:junegunn/seoul256.vim.git', g:plugs['seoul256.vim'].uri
AssertEqual 'git@bitsocket.org:vim-scripts/beauty256.git', g:plugs['beauty256'].uri AssertEqual 'git@bitsocket.org:vim-scripts/beauty256.git', g:plugs['beauty256'].uri
unlet g:plug_url_format let g:plug_url_format = prev_plug_url_format
********************************************************************** **********************************************************************
~ U ~ U
@@ -1053,39 +1050,22 @@ Execute (PlugClean should not try to remove unmanaged plugins inside g:plug_home
q q
********************************************************************** **********************************************************************
Execute (#112 On-demand loading should not suppress messages from ftplugin): Execute (PlugSnapshot / #154 issues with paths containing spaces):
call plug#begin('$PLUG_FIXTURES') call plug#begin('$TMPDIR/plug with spaces')
Plug '$PLUG_FIXTURES/ftplugin-msg', { 'for': 'c' } Plug 'junegunn/vim-easy-align'
call plug#end()
redir => out
tabnew a.c
redir END
Assert stridx(out, 'ftplugin') >= 0
* The same applies to plug#load())
redir => out
call plug#load('ftplugin-msg')
redir END
Assert stridx(out, 'ftplugin') >= 0
q
**********************************************************************
Execute (PlugSnapshot):
call plug#begin('$TMPDIR/plugged')
Plug 'junegunn/vim-emoji'
Plug 'junegunn/seoul256.vim' Plug 'junegunn/seoul256.vim'
call plug#end() call plug#end()
PlugClean! PlugClean!
PlugInstall PlugInstall
call plug#load('vim-easy-align') " Should properly handle paths with spaces
PlugSnapshot PlugSnapshot
AssertEqual '#!/bin/bash', getline(1) AssertEqual '#!/bin/sh', getline(1)
AssertEqual '# Generated by vim-plug', getline(2) AssertEqual '# Generated by vim-plug', getline(2)
AssertEqual 'vim +PlugUpdate +qa', getline(5) AssertEqual 'vim +PlugUpdate +qa', getline(5)
AssertEqual 'PLUG_HOME=$TMPDIR/plugged', getline(7) AssertEqual 'PLUG_HOME=$TMPDIR/plug\ with\ spaces', getline(7)
AssertEqual 0, stridx(getline(9), 'cd $PLUG_HOME/seoul256.vim/ && git reset --hard') AssertEqual 0, stridx(getline(9), 'cd $PLUG_HOME/seoul256.vim/ && git reset --hard')
AssertEqual 0, stridx(getline(10), 'cd $PLUG_HOME/vim-emoji/ && git reset --hard') AssertEqual 0, stridx(getline(10), 'cd $PLUG_HOME/vim-easy-align/ && git reset --hard')
AssertEqual 'sh', &filetype AssertEqual 'sh', &filetype
execute 'PlugSnapshot' g:plug_home.'/snapshot.sh' execute 'PlugSnapshot' g:plug_home.'/snapshot.sh'
@@ -1093,77 +1073,3 @@ Execute (PlugSnapshot):
AssertEqual 'snapshot.sh', fnamemodify(expand('%'), ':t') AssertEqual 'snapshot.sh', fnamemodify(expand('%'), ':t')
q q
**********************************************************************
Execute (#114 Should not contain empty path in &rtp):
call plug#begin('$TMPDIR/plugged')
call plug#end()
Log &rtp
Assert &rtp !~ ',,', 'Commas'
Assert &rtp !~ '^,', 'Comma prefix'
Assert &rtp !~ ',$', 'Comma suffix'
**********************************************************************
Execute (#130 Proper cleanup of on-demand loading triggers):
augroup PlugLOD
autocmd!
augroup END
" Cleared on command
call plug#begin('$TMPDIR/plugged')
Plug 'junegunn/vim-emoji', { 'on': ['EmojiCommand', 'EmojiCommand2', '<Plug>(EmojiMapping)'] }
call plug#end()
PlugInstall | q
Assert exists(':EmojiCommand'), 'EmojiCommand not defined'
Assert exists(':EmojiCommand2'), 'EmojiCommand2 not defined'
Assert !empty(mapcheck('<Plug>(EmojiMapping)')), '<Plug>(EmojiMapping) not defined'
silent! EmojiCommand
Assert !exists(':EmojiCommand'), 'EmojiCommand defined'
Assert !exists(':EmojiCommand2'), 'EmojiCommand2 defined'
Assert empty(mapcheck('<Plug>(EmojiMapping)')), '<Plug>(EmojiMapping) defined'
" Cleared on FileType
call plug#begin('$TMPDIR/plugged')
Plug 'junegunn/vim-emoji', { 'on': ['EmojiCommandExtra', '<Plug>(EmojiMappingExtra)'], 'for': ['emoji'] }
call plug#end()
Assert exists(':EmojiCommandExtra'), 'EmojiCommandExtra not defined'
Assert !empty(mapcheck('<Plug>(EmojiMappingExtra)')), '<Plug>(EmojiMappingExtra) not defined'
setf emoji
Assert !exists(':EmojiCommandExtra'), 'EmojiCommandExtra defined'
Assert empty(mapcheck('<Plug>(EmojiMappingExtra)')), '<Plug>(EmojiMappingExtra) defined'
**********************************************************************
Execute (#131 Syntax error):
call plug#begin('/no-permission')
Plug 'junegunn/vim-emoji'
call plug#end()
redir => out
silent PlugInstall
redir END
Assert out =~ 'Invalid plug directory: /no-permission'
Execute (Cleanup):
silent! call system('rm -rf '.temp_plugged)
silent! call system('rm -rf '.temp_plugged)
silent! call rename(fzf, expand('$PLUG_FIXTURES/fzf-staged'))
silent! unlet g:plugs
silent! unlet g:plug_home
silent! unlet g:plug_url_format
silent! unlet temp_plugged vader plug basertp save_rtp repo lnum fzf out tabnr found len
silent! delf PlugStatusSorted
silent! delf AssertExpect
silent! delf PlugUpdated
silent! delf EnsureLoaded
silent! delc AssertExpect
silent! unmap /
silent! unmap ?
Restore