mirror of
https://github.com/junegunn/vim-plug.git
synced 2025-12-06 17:14:26 +08:00
Compare commits
42 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
3606c294de | ||
|
|
06f903d8af | ||
|
|
1f704deb76 | ||
|
|
3ebf6361bf | ||
|
|
9b99c1f885 | ||
|
|
53cc8a53d9 | ||
|
|
2ee153d610 | ||
|
|
7019171737 | ||
|
|
044c3a67c4 | ||
|
|
48514768c2 | ||
|
|
68ad02c5c3 | ||
|
|
12bc2ea1da | ||
|
|
ade7fb95b1 | ||
|
|
9c55223869 | ||
|
|
495becf442 | ||
|
|
425ef39db2 | ||
|
|
bd2cb9d2de | ||
|
|
0263370bd1 | ||
|
|
4b3fbd1592 | ||
|
|
396a534a0a | ||
|
|
a45c3834f8 | ||
|
|
a5c3952380 | ||
|
|
60bda7322f | ||
|
|
05008e7a82 | ||
|
|
2889cb4739 | ||
|
|
61b21068ee | ||
|
|
15da7eb78a | ||
|
|
385a1eb350 | ||
|
|
8c915a5271 | ||
|
|
ee9f0e55b8 | ||
|
|
018adb2aef | ||
|
|
da47e6ee56 | ||
|
|
662274e617 | ||
|
|
4eeff535fa | ||
|
|
c3669836d3 | ||
|
|
eb38fe3d32 | ||
|
|
e7704e6cb3 | ||
|
|
e1e04cabd5 | ||
|
|
afc20ecff3 | ||
|
|
38510a8788 | ||
|
|
a34b06dd54 | ||
|
|
5d910fc9ea |
40
README.md
40
README.md
@@ -1,9 +1,9 @@
|
||||

|
||||
<img src="https://raw.githubusercontent.com/junegunn/vim-plug/master/plug.png" height="56" alt="vim-plug">
|
||||
[](https://travis-ci.org/junegunn/vim-plug)
|
||||
|
||||
A minimalist Vim plugin manager.
|
||||
|
||||

|
||||
<img src="https://raw.githubusercontent.com/junegunn/i/master/vim-plug/installer.gif" height="450">
|
||||
|
||||
### Pros.
|
||||
|
||||
@@ -11,7 +11,8 @@ A minimalist Vim plugin manager.
|
||||
- Easier to use: Concise, intuitive syntax
|
||||
- [Super-fast](https://raw.githubusercontent.com/junegunn/i/master/vim-plug/40-in-4.gif)
|
||||
parallel installation/update (requires
|
||||
[+ruby](https://github.com/junegunn/vim-plug/wiki/ruby))
|
||||
[+ruby](https://github.com/junegunn/vim-plug/wiki/ruby) or
|
||||
[Neovim](http://neovim.org/))
|
||||
- On-demand loading to achieve
|
||||
[fast startup time](http://junegunn.kr/images/vim-startup-time.png)
|
||||
- Post-update hooks
|
||||
@@ -69,28 +70,29 @@ Reload .vimrc and `:PlugInstall` to install plugins.
|
||||
| `PlugUpgrade` | Upgrade vim-plug itself |
|
||||
| `PlugStatus` | Check the status of plugins |
|
||||
| `PlugDiff` | See the updated changes from the previous PlugUpdate |
|
||||
| `PlugSnapshot [output path]` | Generate script for restoring the current snapshot of the plugins |
|
||||
|
||||
### `Plug` options
|
||||
|
||||
| Option | Description |
|
||||
| -------------- | -------------------------------------------------------------------- |
|
||||
| `branch`/`tag` | Branch or tag of the repository to use |
|
||||
| `rtp` | Subdirectory that contains Vim plugin |
|
||||
| `dir` | Custom directory for the plugin |
|
||||
| `do` | Post-update hook (string or funcref) |
|
||||
| `on` | On-demand loading: Commands or `<Plug>`-mappings |
|
||||
| `for` | On-demand loading: File types |
|
||||
| `frozen` | Do not install/update plugin unless explicitly given as the argument |
|
||||
| Option | Description |
|
||||
| -------------- | ------------------------------------------------ |
|
||||
| `branch`/`tag` | Branch or tag of the repository to use |
|
||||
| `rtp` | Subdirectory that contains Vim plugin |
|
||||
| `dir` | Custom directory for the plugin |
|
||||
| `do` | Post-update hook (string or funcref) |
|
||||
| `on` | On-demand loading: Commands or `<Plug>`-mappings |
|
||||
| `for` | On-demand loading: File types |
|
||||
| `frozen` | Do not update unless explicitly specified |
|
||||
|
||||
### Global options
|
||||
|
||||
| Flag | Default | Description |
|
||||
| ------------------- | --------------------------------- | ------------------------------------ |
|
||||
| `g:plug_threads` | 16 | Default number of threads to use |
|
||||
| `g:plug_timeout` | 60 | Time limit of each task in seconds |
|
||||
| `g:plug_retries` | 2 | Number of retries in case of timeout |
|
||||
| `g:plug_window` | `vertical topleft new` | Command to open plug window |
|
||||
| `g:plug_url_format` | `https://git::@github.com/%s.git` | `printf` format to build repo URL |
|
||||
| Flag | Default | Description |
|
||||
| ------------------- | --------------------------------- | ----------------------------------------------------------- |
|
||||
| `g:plug_threads` | 16 | Default number of threads to use |
|
||||
| `g:plug_timeout` | 60 | Time limit of each task in seconds (*for Ruby installer*) |
|
||||
| `g:plug_retries` | 2 | Number of retries in case of timeout (*for Ruby installer*) |
|
||||
| `g:plug_window` | `vertical topleft new` | Command to open plug window |
|
||||
| `g:plug_url_format` | `https://git::@github.com/%s.git` | `printf` format to build repo URL |
|
||||
|
||||
### Keybindings
|
||||
|
||||
|
||||
558
plug.vim
558
plug.vim
@@ -68,10 +68,12 @@ let g:loaded_plug = 1
|
||||
let s:cpo_save = &cpo
|
||||
set cpo&vim
|
||||
|
||||
let s:plug_source = 'https://raw.githubusercontent.com/junegunn/vim-plug/master/plug.vim'
|
||||
let s:plug_src = 'https://raw.githubusercontent.com/junegunn/vim-plug/master/plug.vim'
|
||||
let s:plug_tab = get(s:, 'plug_tab', -1)
|
||||
let s:plug_buf = get(s:, 'plug_buf', -1)
|
||||
let s:mac_gui = has('gui_macvim') && has('gui_running')
|
||||
let s:is_win = has('win32') || has('win64')
|
||||
let s:nvim = exists('##JobActivity') && !s:is_win
|
||||
let s:me = resolve(expand('<sfile>:p'))
|
||||
let s:base_spec = { 'branch': 'master', 'frozen': 0 }
|
||||
let s:TYPE = {
|
||||
@@ -81,9 +83,11 @@ let s:TYPE = {
|
||||
\ 'funcref': type(function('call'))
|
||||
\ }
|
||||
let s:loaded = get(s:, 'loaded', {})
|
||||
let s:triggers = get(s:, 'triggers', {})
|
||||
|
||||
function! plug#begin(...)
|
||||
if a:0 > 0
|
||||
let s:plug_home_org = a:1
|
||||
let home = s:path(fnamemodify(expand(a:1), ':p'))
|
||||
elseif exists('g:plug_home')
|
||||
let home = s:path(g:plug_home)
|
||||
@@ -95,8 +99,8 @@ function! plug#begin(...)
|
||||
|
||||
let g:plug_home = home
|
||||
let g:plugs = {}
|
||||
" we want to keep track of the order plugins where registered.
|
||||
let g:plugs_order = []
|
||||
let s:triggers = {}
|
||||
|
||||
call s:define_commands()
|
||||
return 1
|
||||
@@ -113,15 +117,20 @@ function! s:define_commands()
|
||||
command! -nargs=0 -bar PlugUpgrade if s:upgrade() | execute 'source' s:me | endif
|
||||
command! -nargs=0 -bar PlugStatus call s:status()
|
||||
command! -nargs=0 -bar PlugDiff call s:diff()
|
||||
command! -nargs=? -bar PlugSnapshot call s:snapshot(<f-args>)
|
||||
endfunction
|
||||
|
||||
function! s:to_a(v)
|
||||
return type(a:v) == s:TYPE.list ? a:v : [a:v]
|
||||
endfunction
|
||||
|
||||
function! s:to_s(v)
|
||||
return type(a:v) == s:TYPE.string ? a:v : join(a:v, "\n") . "\n"
|
||||
endfunction
|
||||
|
||||
function! s:source(from, ...)
|
||||
for pattern in a:000
|
||||
for vim in split(globpath(a:from, pattern), '\n')
|
||||
for vim in s:lines(globpath(a:from, pattern))
|
||||
execute 'source' vim
|
||||
endfor
|
||||
endfor
|
||||
@@ -149,6 +158,7 @@ function! plug#end()
|
||||
endif
|
||||
|
||||
if has_key(plug, 'on')
|
||||
let s:triggers[name] = { 'map': [], 'cmd': [] }
|
||||
for cmd in s:to_a(plug.on)
|
||||
if cmd =~ '^<Plug>.\+'
|
||||
if empty(mapcheck(cmd)) && empty(mapcheck(cmd, 'i'))
|
||||
@@ -159,10 +169,14 @@ function! plug#end()
|
||||
\ mode, cmd, map_prefix, string(cmd), string(name), key_prefix)
|
||||
endfor
|
||||
endif
|
||||
elseif !exists(':'.cmd)
|
||||
execute printf(
|
||||
\ 'command! -nargs=* -range -bang %s call s:lod_cmd(%s, "<bang>", <line1>, <line2>, <q-args>, %s)',
|
||||
\ cmd, string(cmd), string(name))
|
||||
call add(s:triggers[name].map, cmd)
|
||||
elseif cmd =~ '^[A-Z]'
|
||||
if exists(':'.cmd) != 2
|
||||
execute printf(
|
||||
\ 'command! -nargs=* -range -bang %s call s:lod_cmd(%s, "<bang>", <line1>, <line2>, <q-args>, %s)',
|
||||
\ cmd, string(cmd), string(name))
|
||||
endif
|
||||
call add(s:triggers[name].cmd, cmd)
|
||||
endif
|
||||
endfor
|
||||
endif
|
||||
@@ -286,9 +300,10 @@ function! s:reorg_rtp()
|
||||
let s:middle = get(s:, 'middle', &rtp)
|
||||
let rtps = map(s:loaded_names(), 's:rtp(g:plugs[v:val])')
|
||||
let afters = filter(map(copy(rtps), 'globpath(v:val, "after")'), 'isdirectory(v:val)')
|
||||
let &rtp = join(map(rtps, 's:escrtp(v:val)'), ',')
|
||||
\ . substitute(','.s:middle.',', '^,,$', ',', '')
|
||||
let rtp = join(map(rtps, 's:escrtp(v:val)'), ',')
|
||||
\ . ','.s:middle.','
|
||||
\ . join(map(afters, 's:escrtp(v:val)'), ',')
|
||||
let &rtp = substitute(substitute(rtp, ',,*', ',', 'g'), '^,\|,$', '', 'g')
|
||||
let s:prtp = &rtp
|
||||
|
||||
if !empty(s:first_rtp)
|
||||
@@ -312,12 +327,27 @@ function! plug#load(...)
|
||||
for name in a:000
|
||||
call s:lod([name], ['ftdetect', 'after/ftdetect', 'plugin', 'after/plugin'])
|
||||
endfor
|
||||
silent! doautocmd BufRead
|
||||
doautocmd BufRead
|
||||
return 1
|
||||
endfunction
|
||||
|
||||
function! s:remove_triggers(name)
|
||||
if !has_key(s:triggers, a:name)
|
||||
return
|
||||
endif
|
||||
for cmd in s:triggers[a:name].cmd
|
||||
execute 'delc' cmd
|
||||
endfor
|
||||
for map in s:triggers[a:name].map
|
||||
execute 'unmap' map
|
||||
execute 'iunmap' map
|
||||
endfor
|
||||
call remove(s:triggers, a:name)
|
||||
endfunction
|
||||
|
||||
function! s:lod(names, types)
|
||||
for name in a:names
|
||||
call s:remove_triggers(name)
|
||||
let s:loaded[name] = 1
|
||||
endfor
|
||||
call s:reorg_rtp()
|
||||
@@ -333,19 +363,16 @@ endfunction
|
||||
function! s:lod_ft(pat, names)
|
||||
call s:lod(a:names, ['plugin', 'after/plugin'])
|
||||
execute 'autocmd! PlugLOD FileType' a:pat
|
||||
silent! doautocmd filetypeplugin FileType
|
||||
silent! doautocmd filetypeindent FileType
|
||||
doautocmd filetypeplugin FileType
|
||||
doautocmd filetypeindent FileType
|
||||
endfunction
|
||||
|
||||
function! s:lod_cmd(cmd, bang, l1, l2, args, name)
|
||||
execute 'delc' a:cmd
|
||||
call s:lod([a:name], ['ftdetect', 'after/ftdetect', 'plugin', 'after/plugin'])
|
||||
execute printf('%s%s%s %s', (a:l1 == a:l2 ? '' : (a:l1.','.a:l2)), a:cmd, a:bang, a:args)
|
||||
endfunction
|
||||
|
||||
function! s:lod_map(map, name, prefix)
|
||||
execute 'unmap' a:map
|
||||
execute 'iunmap' a:map
|
||||
call s:lod([a:name], ['ftdetect', 'after/ftdetect', 'plugin', 'after/plugin'])
|
||||
let extra = ''
|
||||
while 1
|
||||
@@ -481,25 +508,59 @@ function! s:lpad(str, len)
|
||||
return a:str . repeat(' ', a:len - len(a:str))
|
||||
endfunction
|
||||
|
||||
function! s:lines(msg)
|
||||
return split(a:msg, "[\r\n]")
|
||||
endfunction
|
||||
|
||||
function! s:lastline(msg)
|
||||
let lines = split(a:msg, '\n')
|
||||
return get(lines, -1, '')
|
||||
return get(s:lines(a:msg), -1, '')
|
||||
endfunction
|
||||
|
||||
function! s:new_window()
|
||||
execute get(g:, 'plug_window', 'vertical topleft new')
|
||||
endfunction
|
||||
|
||||
function! s:prepare()
|
||||
if bufexists(s:plug_buf)
|
||||
function! s:plug_window_exists()
|
||||
let buflist = tabpagebuflist(s:plug_tab)
|
||||
return !empty(buflist) && index(buflist, s:plug_buf) >= 0
|
||||
endfunction
|
||||
|
||||
function! s:switch_in()
|
||||
if !s:plug_window_exists()
|
||||
return 0
|
||||
endif
|
||||
|
||||
if winbufnr(0) != s:plug_buf
|
||||
let s:pos = [tabpagenr(), winnr(), winsaveview()]
|
||||
execute 'normal!' s:plug_tab.'gt'
|
||||
let winnr = bufwinnr(s:plug_buf)
|
||||
if winnr < 0
|
||||
call s:new_window()
|
||||
execute 'buffer' s:plug_buf
|
||||
else
|
||||
execute winnr . 'wincmd w'
|
||||
endif
|
||||
setlocal modifiable
|
||||
execute winnr.'wincmd w'
|
||||
call add(s:pos, winsaveview())
|
||||
else
|
||||
let s:pos = [winsaveview()]
|
||||
endif
|
||||
|
||||
setlocal modifiable
|
||||
return 1
|
||||
endfunction
|
||||
|
||||
function! s:switch_out(...)
|
||||
call winrestview(s:pos[-1])
|
||||
setlocal nomodifiable
|
||||
if a:0 > 0
|
||||
execute a:1
|
||||
endif
|
||||
|
||||
if len(s:pos) > 1
|
||||
execute 'normal!' s:pos[0].'gt'
|
||||
execute s:pos[1] 'wincmd w'
|
||||
call winrestview(s:pos[2])
|
||||
endif
|
||||
endfunction
|
||||
|
||||
function! s:prepare()
|
||||
call s:job_abort()
|
||||
if s:switch_in()
|
||||
silent %d _
|
||||
else
|
||||
call s:new_window()
|
||||
@@ -512,6 +573,7 @@ function! s:prepare()
|
||||
nnoremap <silent> <buffer> ]] :silent! call <SID>section('')<cr>
|
||||
nnoremap <silent> <buffer> [[ :silent! call <SID>section('b')<cr>
|
||||
let b:plug_preview = -1
|
||||
let s:plug_tab = tabpagenr()
|
||||
let s:plug_buf = winbufnr(0)
|
||||
call s:assign_name()
|
||||
endif
|
||||
@@ -540,11 +602,11 @@ function! s:do(pull, force, todo)
|
||||
if !isdirectory(spec.dir)
|
||||
continue
|
||||
endif
|
||||
execute 'cd' s:esc(spec.dir)
|
||||
let installed = has_key(s:prev_update.new, name)
|
||||
let installed = has_key(s:update.new, name)
|
||||
let updated = installed ? 0 :
|
||||
\ (a:pull && !empty(s:system_chomp('git log --pretty=format:"%h" "HEAD...HEAD@{1}"')))
|
||||
\ (a:pull && !empty(s:system_chomp('git log --pretty=format:"%h" "HEAD...HEAD@{1}"', spec.dir)))
|
||||
if a:force || installed || updated
|
||||
execute 'cd' s:esc(spec.dir)
|
||||
call append(3, '- Post-update hook for '. name .' ... ')
|
||||
let type = type(spec.do)
|
||||
if type == s:TYPE.string
|
||||
@@ -569,25 +631,28 @@ function! s:do(pull, force, todo)
|
||||
let result = 'Error: Invalid type!'
|
||||
endif
|
||||
call setline(4, getline(4) . result)
|
||||
cd -
|
||||
endif
|
||||
cd -
|
||||
endfor
|
||||
endfunction
|
||||
|
||||
function! s:finish(pull)
|
||||
let new_frozen = len(filter(keys(s:update.new), 'g:plugs[v:val].frozen'))
|
||||
if new_frozen
|
||||
let s = new_frozen > 1 ? 's' : ''
|
||||
call append(3, printf('- Installed %d frozen plugin%s', new_frozen, s))
|
||||
endif
|
||||
call append(3, '- Finishing ... ')
|
||||
redraw
|
||||
call plug#helptags()
|
||||
call plug#end()
|
||||
call setline(4, getline(4) . 'Done!')
|
||||
normal! gg
|
||||
call s:syntax()
|
||||
redraw
|
||||
let msgs = []
|
||||
if !empty(s:prev_update.errors)
|
||||
if !empty(s:update.errors)
|
||||
call add(msgs, "Press 'R' to retry.")
|
||||
endif
|
||||
if a:pull && !empty(filter(getline(5, '$'),
|
||||
if a:pull && len(s:update.new) < len(filter(getline(5, '$'),
|
||||
\ "v:val =~ '^- ' && stridx(v:val, 'Already up-to-date') < 0"))
|
||||
call add(msgs, "Press 'D' to see the updated changes.")
|
||||
endif
|
||||
@@ -595,11 +660,11 @@ function! s:finish(pull)
|
||||
endfunction
|
||||
|
||||
function! s:retry()
|
||||
if empty(s:prev_update.errors)
|
||||
if empty(s:update.errors)
|
||||
return
|
||||
endif
|
||||
call s:update_impl(s:prev_update.pull, s:prev_update.force,
|
||||
\ extend(copy(s:prev_update.errors), [s:prev_update.threads]))
|
||||
call s:update_impl(s:update.pull, s:update.force,
|
||||
\ extend(copy(s:update.errors), [s:update.threads]))
|
||||
endfunction
|
||||
|
||||
function! s:is_managed(name)
|
||||
@@ -607,17 +672,16 @@ function! s:is_managed(name)
|
||||
endfunction
|
||||
|
||||
function! s:names(...)
|
||||
return filter(keys(g:plugs), 'stridx(v:val, a:1) == 0 && s:is_managed(v:val)')
|
||||
return sort(filter(keys(g:plugs), 'stridx(v:val, a:1) == 0 && s:is_managed(v:val)'))
|
||||
endfunction
|
||||
|
||||
function! s:update_impl(pull, force, args) abort
|
||||
let st = reltime()
|
||||
let args = copy(a:args)
|
||||
let threads = (len(args) > 0 && args[-1] =~ '^[1-9][0-9]*$') ?
|
||||
\ remove(args, -1) : get(g:, 'plug_threads', 16)
|
||||
|
||||
let managed = filter(copy(g:plugs), 's:is_managed(v:key)')
|
||||
let todo = empty(args) ? filter(managed, '!v:val.frozen') :
|
||||
let todo = empty(args) ? filter(managed, '!v:val.frozen || !isdirectory(v:val.dir)') :
|
||||
\ filter(managed, 'index(args, v:key) >= 0')
|
||||
|
||||
if empty(todo)
|
||||
@@ -631,103 +695,251 @@ function! s:update_impl(pull, force, args) abort
|
||||
try
|
||||
call mkdir(g:plug_home, 'p')
|
||||
catch
|
||||
return s:err(printf('Invalid plug directory: %s.'
|
||||
\ 'Try to call plug#begin with a valid directory', g:plug_home))
|
||||
return s:err(printf('Invalid plug directory: %s. '.
|
||||
\ 'Try to call plug#begin with a valid directory', g:plug_home))
|
||||
endtry
|
||||
endif
|
||||
|
||||
call s:prepare()
|
||||
call append(0, a:pull ? 'Updating plugins' : 'Installing plugins')
|
||||
call append(1, '['. s:lpad('', len(todo)) .']')
|
||||
normal! 2G
|
||||
redraw
|
||||
let s:update = {
|
||||
\ 'start': reltime(),
|
||||
\ 'all': todo,
|
||||
\ 'todo': copy(todo),
|
||||
\ 'errors': [],
|
||||
\ 'pull': a:pull,
|
||||
\ 'force': a:force,
|
||||
\ 'new': {},
|
||||
\ 'threads': (has('ruby') || s:nvim) ? min([len(todo), threads]) : 1,
|
||||
\ 'bar': '',
|
||||
\ 'fin': 0
|
||||
\ }
|
||||
|
||||
let s:prev_update = { 'errors': [], 'pull': a:pull, 'force': a:force, 'new': {}, 'threads': threads }
|
||||
if has('ruby') && threads > 1
|
||||
call s:prepare()
|
||||
call append(0, ['', ''])
|
||||
normal! 2G
|
||||
|
||||
if has('ruby') && s:update.threads > 1
|
||||
try
|
||||
let imd = &imd
|
||||
if s:mac_gui
|
||||
set noimd
|
||||
endif
|
||||
call s:update_parallel(a:pull, todo, threads)
|
||||
call s:update_ruby()
|
||||
catch
|
||||
let lines = getline(4, '$')
|
||||
let printed = {}
|
||||
silent 4,$d _
|
||||
for line in lines
|
||||
let name = matchstr(line, '^. \zs[^:]\+\ze:')
|
||||
let name = s:extract_name(line, '.', '')
|
||||
if empty(name) || !has_key(printed, name)
|
||||
call append('$', line)
|
||||
if !empty(name)
|
||||
let printed[name] = 1
|
||||
if line[0] == 'x' && index(s:prev_update.errors, name) < 0
|
||||
call add(s:prev_update.errors, name)
|
||||
if line[0] == 'x' && index(s:update.errors, name) < 0
|
||||
call add(s:update.errors, name)
|
||||
end
|
||||
endif
|
||||
endif
|
||||
endfor
|
||||
finally
|
||||
let &imd = imd
|
||||
call s:update_finish()
|
||||
endtry
|
||||
else
|
||||
call s:update_serial(a:pull, todo)
|
||||
call s:update_vim()
|
||||
endif
|
||||
call s:do(a:pull, a:force, filter(copy(todo), 'has_key(v:val, "do")'))
|
||||
call s:finish(a:pull)
|
||||
call setline(1, 'Updated. Elapsed time: ' . split(reltimestr(reltime(st)))[0] . ' sec.')
|
||||
endfunction
|
||||
|
||||
function! s:update_progress(pull, cnt, bar, total)
|
||||
call setline(1, (a:pull ? 'Updating' : 'Installing').
|
||||
\ ' plugins ('.a:cnt.'/'.a:total.')')
|
||||
call s:progress_bar(2, a:bar, a:total)
|
||||
normal! 2G
|
||||
redraw
|
||||
function! s:update_finish()
|
||||
if s:switch_in()
|
||||
call s:do(s:update.pull, s:update.force, filter(copy(s:update.all), 'has_key(v:val, "do")'))
|
||||
call s:finish(s:update.pull)
|
||||
call setline(1, 'Updated. Elapsed time: ' . split(reltimestr(reltime(s:update.start)))[0] . ' sec.')
|
||||
call s:switch_out('normal! gg')
|
||||
endif
|
||||
endfunction
|
||||
|
||||
function! s:update_serial(pull, todo)
|
||||
let base = g:plug_home
|
||||
let todo = copy(a:todo)
|
||||
let total = len(todo)
|
||||
let done = {}
|
||||
let bar = ''
|
||||
|
||||
for [name, spec] in items(todo)
|
||||
let done[name] = 1
|
||||
if isdirectory(spec.dir)
|
||||
execute 'cd' s:esc(spec.dir)
|
||||
let [valid, msg] = s:git_valid(spec, 0, 0)
|
||||
if valid
|
||||
let result = a:pull ?
|
||||
\ s:system(
|
||||
\ printf('git checkout -q %s 2>&1 && git pull --no-rebase origin %s 2>&1 && git submodule update --init --recursive 2>&1',
|
||||
\ s:shellesc(spec.branch), s:shellesc(spec.branch))) : 'Already installed'
|
||||
let error = a:pull ? v:shell_error != 0 : 0
|
||||
else
|
||||
let result = msg
|
||||
let error = 1
|
||||
endif
|
||||
cd -
|
||||
else
|
||||
let result = s:system(
|
||||
\ printf('git clone --recursive %s -b %s %s 2>&1 && cd %s && git submodule update --init --recursive 2>&1',
|
||||
\ s:shellesc(spec.uri),
|
||||
\ s:shellesc(spec.branch),
|
||||
\ s:shellesc(s:trim(spec.dir)),
|
||||
\ s:shellesc(spec.dir)))
|
||||
let error = v:shell_error != 0
|
||||
if !error | let s:prev_update.new[name] = 1 | endif
|
||||
function! s:job_abort()
|
||||
if !s:nvim || !exists('s:jobs')
|
||||
return
|
||||
endif
|
||||
augroup PlugJobControl
|
||||
autocmd!
|
||||
augroup END
|
||||
for [name, j] in items(s:jobs)
|
||||
silent! call jobstop(j.jobid)
|
||||
if j.new
|
||||
call system('rm -rf ' . s:shellesc(g:plugs[name].dir))
|
||||
endif
|
||||
let bar .= error ? 'x' : '='
|
||||
if error
|
||||
call add(s:prev_update.errors, name)
|
||||
endif
|
||||
call append(3, s:format_message(!error, name, result))
|
||||
call s:update_progress(a:pull, len(done), bar, total)
|
||||
endfor
|
||||
let s:jobs = {}
|
||||
endfunction
|
||||
|
||||
function! s:update_parallel(pull, todo, threads)
|
||||
function! s:job_handler(name) abort
|
||||
if !s:plug_window_exists() " plug window closed
|
||||
return s:job_abort()
|
||||
endif
|
||||
|
||||
if !has_key(s:jobs, a:name)
|
||||
return
|
||||
endif
|
||||
let job = s:jobs[a:name]
|
||||
|
||||
if v:job_data[1] == 'exit'
|
||||
let job.running = 0
|
||||
if s:lastline(job.result) ==# 'Error'
|
||||
let job.error = 1
|
||||
let job.result = substitute(job.result, "Error[\r\n]$", '', '')
|
||||
endif
|
||||
call s:reap(a:name)
|
||||
call s:tick()
|
||||
else
|
||||
let job.result .= s:to_s(v:job_data[2])
|
||||
" To reduce the number of buffer updates
|
||||
let job.tick = get(job, 'tick', -1) + 1
|
||||
if job.tick % len(s:jobs) == 0
|
||||
call s:log(job.new ? '+' : '*', a:name, job.result)
|
||||
endif
|
||||
endif
|
||||
endfunction
|
||||
|
||||
function! s:spawn(name, cmd, opts)
|
||||
let job = { 'running': 1, 'new': get(a:opts, 'new', 0),
|
||||
\ 'error': 0, 'result': '' }
|
||||
let s:jobs[a:name] = job
|
||||
|
||||
if s:nvim
|
||||
let x = jobstart(a:name, 'sh', ['-c',
|
||||
\ (has_key(a:opts, 'dir') ? s:with_cd(a:cmd, a:opts.dir) : a:cmd)
|
||||
\ . ' || echo Error'])
|
||||
if x > 0
|
||||
let job.jobid = x
|
||||
augroup PlugJobControl
|
||||
execute 'autocmd JobActivity' a:name printf('call s:job_handler(%s)', string(a:name))
|
||||
augroup END
|
||||
else
|
||||
let job.running = 0
|
||||
let job.error = 1
|
||||
let job.result = x < 0 ? 'sh is not executable' :
|
||||
\ 'Invalid arguments (or job table is full)'
|
||||
endif
|
||||
else
|
||||
let params = has_key(a:opts, 'dir') ? [a:cmd, a:opts.dir] : [a:cmd]
|
||||
let job.result = call('s:system', params)
|
||||
let job.error = v:shell_error != 0
|
||||
let job.running = 0
|
||||
endif
|
||||
endfunction
|
||||
|
||||
function! s:reap(name)
|
||||
if s:nvim
|
||||
silent! execute 'autocmd! PlugJobControl JobActivity' a:name
|
||||
endif
|
||||
|
||||
let job = s:jobs[a:name]
|
||||
if job.error
|
||||
call add(s:update.errors, a:name)
|
||||
elseif get(job, 'new', 0)
|
||||
let s:update.new[a:name] = 1
|
||||
endif
|
||||
let s:update.bar .= job.error ? 'x' : '='
|
||||
|
||||
call s:log(job.error ? 'x' : '-', a:name, job.result)
|
||||
call s:bar()
|
||||
|
||||
call remove(s:jobs, a:name)
|
||||
endfunction
|
||||
|
||||
function! s:bar()
|
||||
if s:switch_in()
|
||||
let total = len(s:update.all)
|
||||
call setline(1, (s:update.pull ? 'Updating' : 'Installing').
|
||||
\ ' plugins ('.len(s:update.bar).'/'.total.')')
|
||||
call s:progress_bar(2, s:update.bar, total)
|
||||
call s:switch_out()
|
||||
endif
|
||||
endfunction
|
||||
|
||||
function! s:logpos(name)
|
||||
for i in range(1, line('$'))
|
||||
if getline(i) =~# '^[-+x*] '.a:name.':'
|
||||
return i
|
||||
endif
|
||||
endfor
|
||||
return 0
|
||||
endfunction
|
||||
|
||||
function! s:log(bullet, name, lines)
|
||||
if s:switch_in()
|
||||
let pos = s:logpos(a:name)
|
||||
if pos > 0
|
||||
execute pos 'd _'
|
||||
if pos > winheight('.')
|
||||
let pos = 4
|
||||
endif
|
||||
else
|
||||
let pos = 4
|
||||
endif
|
||||
call append(pos - 1, s:format_message(a:bullet, a:name, a:lines))
|
||||
call s:switch_out()
|
||||
endif
|
||||
endfunction
|
||||
|
||||
function! s:update_vim()
|
||||
let s:jobs = {}
|
||||
|
||||
call s:bar()
|
||||
call s:tick()
|
||||
endfunction
|
||||
|
||||
function! s:tick()
|
||||
while 1 " Without TCO, Vim stack is bound to explode
|
||||
if empty(s:update.todo)
|
||||
if empty(s:jobs) && !s:update.fin
|
||||
let s:update.fin = 1
|
||||
call s:update_finish()
|
||||
endif
|
||||
return
|
||||
endif
|
||||
|
||||
let name = keys(s:update.todo)[0]
|
||||
let spec = remove(s:update.todo, name)
|
||||
let pull = s:update.pull
|
||||
let new = !isdirectory(spec.dir)
|
||||
|
||||
call s:log(new ? '+' : '*', name, pull ? 'Updating ...' : 'Installing ...')
|
||||
redraw
|
||||
|
||||
if !new
|
||||
let [valid, msg] = s:git_valid(spec, 0)
|
||||
if valid
|
||||
if pull
|
||||
call s:spawn(name,
|
||||
\ printf('git checkout -q %s 2>&1 && git pull --progress --no-rebase origin %s 2>&1 && git submodule update --init --recursive 2>&1',
|
||||
\ s:shellesc(spec.branch), s:shellesc(spec.branch)), { 'dir': spec.dir })
|
||||
else
|
||||
let s:jobs[name] = { 'running': 0, 'result': 'Already installed', 'error': 0 }
|
||||
endif
|
||||
else
|
||||
let s:jobs[name] = { 'running': 0, 'result': msg, 'error': 1 }
|
||||
endif
|
||||
else
|
||||
call s:spawn(name,
|
||||
\ printf('git clone --progress --recursive %s -b %s %s 2>&1',
|
||||
\ s:shellesc(spec.uri),
|
||||
\ s:shellesc(spec.branch),
|
||||
\ s:shellesc(s:trim(spec.dir))), { 'new': 1 })
|
||||
endif
|
||||
|
||||
if !s:jobs[name].running
|
||||
call s:reap(name)
|
||||
endif
|
||||
if len(s:jobs) >= s:update.threads
|
||||
break
|
||||
endif
|
||||
endwhile
|
||||
endfunction
|
||||
|
||||
function! s:update_ruby()
|
||||
ruby << EOF
|
||||
module PlugStream
|
||||
SEP = ["\r", "\n", nil]
|
||||
@@ -769,15 +981,15 @@ function! s:update_parallel(pull, todo, threads)
|
||||
require 'timeout'
|
||||
running = true
|
||||
iswin = VIM::evaluate('s:is_win').to_i == 1
|
||||
pull = VIM::evaluate('a:pull').to_i == 1
|
||||
pull = VIM::evaluate('s:update.pull').to_i == 1
|
||||
base = VIM::evaluate('g:plug_home')
|
||||
all = VIM::evaluate('a:todo')
|
||||
all = VIM::evaluate('s:update.todo')
|
||||
limit = VIM::evaluate('get(g:, "plug_timeout", 60)')
|
||||
tries = VIM::evaluate('get(g:, "plug_retries", 2)') + 1
|
||||
nthr = VIM::evaluate('a:threads').to_i
|
||||
nthr = VIM::evaluate('s:update.threads').to_i
|
||||
maxy = VIM::evaluate('winheight(".")').to_i
|
||||
cd = iswin ? 'cd /d' : 'cd'
|
||||
tot = VIM::evaluate('len(a:todo)') || 0
|
||||
tot = VIM::evaluate('len(s:update.todo)') || 0
|
||||
bar = ''
|
||||
skip = 'Already installed'
|
||||
mtx = Mutex.new
|
||||
@@ -797,7 +1009,7 @@ function! s:update_parallel(pull, todo, threads)
|
||||
b = case type
|
||||
when :install then '+' when :update then '*'
|
||||
when true, nil then '-' else
|
||||
VIM::command("call add(s:prev_update.errors, '#{name}')")
|
||||
VIM::command("call add(s:update.errors, '#{name}')")
|
||||
'x'
|
||||
end
|
||||
result =
|
||||
@@ -886,7 +1098,7 @@ function! s:update_parallel(pull, todo, threads)
|
||||
} if VIM::evaluate('s:mac_gui') == 1
|
||||
|
||||
progress = iswin ? '' : '--progress'
|
||||
[all.length, nthr].min.times do
|
||||
nthr.times do
|
||||
mtx.synchronize do
|
||||
threads << Thread.new {
|
||||
while pair = take1.call
|
||||
@@ -921,11 +1133,11 @@ function! s:update_parallel(pull, todo, threads)
|
||||
else
|
||||
d = esc dir.sub(%r{[\\/]+$}, '')
|
||||
log.call name, 'Installing ...', :install
|
||||
bt.call "(git clone #{progress} --recursive #{uri} -b #{branch} #{d} 2>&1 && cd #{esc dir} && #{subm})", name, :install, proc {
|
||||
bt.call "git clone #{progress} --recursive #{uri} -b #{branch} #{d} 2>&1", name, :install, proc {
|
||||
FileUtils.rm_rf dir
|
||||
}
|
||||
end
|
||||
mtx.synchronize { VIM::command("let s:prev_update.new['#{name}'] = 1") } if !exists && ok
|
||||
mtx.synchronize { VIM::command("let s:update.new['#{name}'] = 1") } if !exists && ok
|
||||
log.call name, result, ok
|
||||
end
|
||||
} if running
|
||||
@@ -943,7 +1155,7 @@ function! s:shellesc(arg)
|
||||
endfunction
|
||||
|
||||
function! s:glob_dir(path)
|
||||
return map(filter(split(globpath(a:path, '**'), '\n'), 'isdirectory(v:val)'), 's:dirpath(v:val)')
|
||||
return map(filter(s:lines(globpath(a:path, '**')), 'isdirectory(v:val)'), 's:dirpath(v:val)')
|
||||
endfunction
|
||||
|
||||
function! s:progress_bar(line, bar, total)
|
||||
@@ -956,30 +1168,34 @@ function! s:compare_git_uri(a, b)
|
||||
return a ==# b
|
||||
endfunction
|
||||
|
||||
function! s:format_message(ok, name, message)
|
||||
if a:ok
|
||||
return [printf('- %s: %s', a:name, s:lastline(a:message))]
|
||||
function! s:format_message(bullet, name, message)
|
||||
if a:bullet != 'x'
|
||||
return [printf('%s %s: %s', a:bullet, a:name, s:lastline(a:message))]
|
||||
else
|
||||
let lines = map(split(a:message, '\n'), '" ".v:val')
|
||||
let lines = map(s:lines(a:message), '" ".v:val')
|
||||
return extend([printf('x %s:', a:name)], lines)
|
||||
endif
|
||||
endfunction
|
||||
|
||||
function! s:system(cmd)
|
||||
return system(s:is_win ? '('.a:cmd.')' : a:cmd)
|
||||
function! s:with_cd(cmd, dir)
|
||||
return 'cd '.s:esc(a:dir).' && '.a:cmd
|
||||
endfunction
|
||||
|
||||
function! s:system_chomp(str)
|
||||
let ret = s:system(a:str)
|
||||
function! s:system(cmd, ...)
|
||||
let cmd = a:0 > 0 ? s:with_cd(a:cmd, a:1) : a:cmd
|
||||
return system(s:is_win ? '('.cmd.')' : cmd)
|
||||
endfunction
|
||||
|
||||
function! s:system_chomp(...)
|
||||
let ret = call('s:system', a:000)
|
||||
return v:shell_error ? '' : substitute(ret, '\n$', '', '')
|
||||
endfunction
|
||||
|
||||
function! s:git_valid(spec, check_branch, cd)
|
||||
function! s:git_valid(spec, check_branch)
|
||||
let ret = 1
|
||||
let msg = 'OK'
|
||||
if isdirectory(a:spec.dir)
|
||||
if a:cd | execute 'cd' s:esc(a:spec.dir) | endif
|
||||
let result = split(s:system('git rev-parse --abbrev-ref HEAD 2>&1 && git config remote.origin.url'), '\n')
|
||||
let result = s:lines(s:system('git rev-parse --abbrev-ref HEAD 2>&1 && git config remote.origin.url', a:spec.dir))
|
||||
let remote = result[-1]
|
||||
if v:shell_error
|
||||
let msg = join([remote, 'PlugClean required.'], "\n")
|
||||
@@ -992,7 +1208,7 @@ function! s:git_valid(spec, check_branch, cd)
|
||||
elseif a:check_branch
|
||||
let branch = result[0]
|
||||
if a:spec.branch !=# branch
|
||||
let tag = s:system_chomp('git describe --exact-match --tags HEAD 2>&1')
|
||||
let tag = s:system_chomp('git describe --exact-match --tags HEAD 2>&1', a:spec.dir)
|
||||
if a:spec.branch !=# tag
|
||||
let msg = printf('Invalid branch/tag: %s (expected: %s). Try PlugUpdate.',
|
||||
\ (empty(tag) ? branch : tag), a:spec.branch)
|
||||
@@ -1000,7 +1216,6 @@ function! s:git_valid(spec, check_branch, cd)
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
if a:cd | cd - | endif
|
||||
else
|
||||
let msg = 'Not found'
|
||||
let ret = 0
|
||||
@@ -1015,10 +1230,9 @@ function! s:clean(force)
|
||||
|
||||
" List of valid directories
|
||||
let dirs = []
|
||||
let managed = filter(copy(g:plugs), 's:is_managed(v:key)')
|
||||
let [cnt, total] = [0, len(managed)]
|
||||
for spec in values(managed)
|
||||
if s:git_valid(spec, 0, 1)[0]
|
||||
let [cnt, total] = [0, len(g:plugs)]
|
||||
for [name, spec] in items(g:plugs)
|
||||
if !s:is_managed(name) || s:git_valid(spec, 0)[0]
|
||||
call add(dirs, spec.dir)
|
||||
endif
|
||||
let cnt += 1
|
||||
@@ -1052,7 +1266,7 @@ function! s:clean(force)
|
||||
call append(line('$'), 'Already clean.')
|
||||
else
|
||||
call inputsave()
|
||||
let yes = a:force || (input('Proceed? (Y/N) ') =~? '^y')
|
||||
let yes = a:force || (input('Proceed? (y/N) ') =~? '^y')
|
||||
call inputrestore()
|
||||
if yes
|
||||
for dir in todo
|
||||
@@ -1070,21 +1284,16 @@ endfunction
|
||||
|
||||
function! s:upgrade()
|
||||
let new = s:me . '.new'
|
||||
echo 'Downloading '. s:plug_source
|
||||
echo 'Downloading '. s:plug_src
|
||||
redraw
|
||||
try
|
||||
if executable('curl')
|
||||
let output = system(printf('curl -fLo %s %s', s:shellesc(new), s:plug_source))
|
||||
let output = system(printf('curl -fLo %s %s', s:shellesc(new), s:plug_src))
|
||||
if v:shell_error
|
||||
throw get(split(output, '\n'), -1, v:shell_error)
|
||||
throw get(s:lines(output), -1, v:shell_error)
|
||||
endif
|
||||
elseif has('ruby')
|
||||
ruby << EOF
|
||||
require 'open-uri'
|
||||
File.open(VIM::evaluate('new'), 'w') do |f|
|
||||
f << open(VIM::evaluate('s:plug_source')).read
|
||||
end
|
||||
EOF
|
||||
call s:upgrade_using_ruby(new)
|
||||
else
|
||||
return s:err('curl executable or ruby support not found')
|
||||
endif
|
||||
@@ -1105,6 +1314,15 @@ EOF
|
||||
endif
|
||||
endfunction
|
||||
|
||||
function! s:upgrade_using_ruby(new)
|
||||
ruby << EOF
|
||||
require 'open-uri'
|
||||
File.open(VIM::evaluate('a:new'), 'w') do |f|
|
||||
f << open(VIM::evaluate('s:plug_src')).read
|
||||
end
|
||||
EOF
|
||||
endfunction
|
||||
|
||||
function! s:upgrade_specs()
|
||||
for spec in values(g:plugs)
|
||||
let spec.frozen = get(spec, 'frozen', 0)
|
||||
@@ -1122,7 +1340,7 @@ function! s:status()
|
||||
for [name, spec] in items(g:plugs)
|
||||
if has_key(spec, 'uri')
|
||||
if isdirectory(spec.dir)
|
||||
let [valid, msg] = s:git_valid(spec, 1, 1)
|
||||
let [valid, msg] = s:git_valid(spec, 1)
|
||||
else
|
||||
let [valid, msg] = [0, 'Not found. Try PlugInstall.']
|
||||
endif
|
||||
@@ -1141,7 +1359,7 @@ function! s:status()
|
||||
let msg .= ' (not loaded)'
|
||||
endif
|
||||
call s:progress_bar(2, repeat('=', cnt), total)
|
||||
call append(3, s:format_message(valid, name, msg))
|
||||
call append(3, s:format_message(valid ? '-' : 'x', name, msg))
|
||||
normal! 2G
|
||||
redraw
|
||||
endfor
|
||||
@@ -1194,7 +1412,7 @@ function! s:find_name(lnum)
|
||||
if empty(line)
|
||||
return ''
|
||||
endif
|
||||
let name = matchstr(line, '\(^- \)\@<=[^:]\+')
|
||||
let name = s:extract_name(line, '-', '')
|
||||
if !empty(name)
|
||||
return name
|
||||
endif
|
||||
@@ -1220,15 +1438,13 @@ function! s:preview_commit()
|
||||
execute 'pedit' sha
|
||||
wincmd P
|
||||
setlocal filetype=git buftype=nofile nobuflisted
|
||||
execute 'cd' s:esc(g:plugs[name].dir)
|
||||
execute 'silent read !git show' sha
|
||||
cd -
|
||||
execute 'silent read !cd' s:esc(g:plugs[name].dir) '&& git show' sha
|
||||
normal! gg"_dd
|
||||
wincmd p
|
||||
endfunction
|
||||
|
||||
function! s:section(flags)
|
||||
call search('\(^- \)\@<=.', a:flags)
|
||||
call search('\(^[x-] \)\@<=[^:]\+:', a:flags)
|
||||
endfunction
|
||||
|
||||
function! s:diff()
|
||||
@@ -1243,17 +1459,15 @@ function! s:diff()
|
||||
continue
|
||||
endif
|
||||
|
||||
execute 'cd' s:esc(v.dir)
|
||||
let diff = system('git log --pretty=format:"%h %s (%cr)" "HEAD...HEAD@{1}"')
|
||||
if !v:shell_error && !empty(diff)
|
||||
let diff = s:system_chomp('git log --pretty=format:"%h %s (%cr)" "HEAD...HEAD@{1}"', v.dir)
|
||||
if !empty(diff)
|
||||
call append(1, '')
|
||||
call append(2, '- '.k.':')
|
||||
call append(3, map(split(diff, '\n'), '" ". v:val'))
|
||||
call append(3, map(s:lines(diff), '" ". v:val'))
|
||||
let cnt += 1
|
||||
normal! gg
|
||||
redraw
|
||||
endif
|
||||
cd -
|
||||
endfor
|
||||
|
||||
call setline(1, cnt == 0 ? 'No updates.' : 'Last update:')
|
||||
@@ -1269,19 +1483,55 @@ endfunction
|
||||
function! s:revert()
|
||||
let name = s:find_name(line('.'))
|
||||
if empty(name) || !has_key(g:plugs, name) ||
|
||||
\ input(printf('Revert the update of %s? (Y/N) ', name)) !~? '^y'
|
||||
\ input(printf('Revert the update of %s? (y/N) ', name)) !~? '^y'
|
||||
return
|
||||
endif
|
||||
|
||||
execute 'cd' s:esc(g:plugs[name].dir)
|
||||
call system('git reset --hard HEAD@{1} && git checkout '.s:esc(g:plugs[name].branch))
|
||||
cd -
|
||||
call s:system('git reset --hard HEAD@{1} && git checkout '.s:esc(g:plugs[name].branch), g:plugs[name].dir)
|
||||
setlocal modifiable
|
||||
normal! "_dap
|
||||
setlocal nomodifiable
|
||||
echo 'Reverted.'
|
||||
endfunction
|
||||
|
||||
function! s:snapshot(...) abort
|
||||
let home = get(s:, 'plug_home_org', g:plug_home)
|
||||
let [type, var, header] = s:is_win ?
|
||||
\ ['dosbatch', '%PLUG_HOME%',
|
||||
\ ['@echo off', ':: Generated by vim-plug', ':: '.strftime("%c"), '',
|
||||
\ ':: Make sure to PlugUpdate first', '', 'set PLUG_HOME='.s:esc(home)]] :
|
||||
\ ['sh', '$PLUG_HOME',
|
||||
\ ['#!/bin/bash', '# Generated by vim-plug', '# '.strftime("%c"), '',
|
||||
\ 'vim +PlugUpdate +qa', '', 'PLUG_HOME='.s:esc(home)]]
|
||||
|
||||
call s:prepare()
|
||||
execute 'setf' type
|
||||
call append(0, header)
|
||||
call append('$', '')
|
||||
1
|
||||
redraw
|
||||
|
||||
let dirs = sort(map(values(filter(copy(g:plugs),
|
||||
\'has_key(v:val, "uri") && isdirectory(v:val.dir)')), 'v:val.dir'))
|
||||
let anchor = line('$') - 1
|
||||
for dir in reverse(dirs)
|
||||
let sha = s:system_chomp('git rev-parse --short HEAD', dir)
|
||||
if !empty(sha)
|
||||
call append(anchor, printf('cd %s && git reset --hard %s',
|
||||
\ substitute(dir, '^'.g:plug_home, var, ''), sha))
|
||||
redraw
|
||||
endif
|
||||
endfor
|
||||
|
||||
if a:0 > 0
|
||||
let fn = s:esc(expand(a:1))
|
||||
call writefile(getline(1, '$'), fn)
|
||||
if !s:is_win | call system('chmod +x ' . fn) | endif
|
||||
echo 'Saved to '.a:1
|
||||
silent execute 'e' fn
|
||||
endif
|
||||
endfunction
|
||||
|
||||
function! s:split_rtp()
|
||||
return split(&rtp, '\\\@<!,')
|
||||
endfunction
|
||||
|
||||
5
test/fixtures/.gitignore
vendored
Normal file
5
test/fixtures/.gitignore
vendored
Normal file
@@ -0,0 +1,5 @@
|
||||
fzf*
|
||||
xxx
|
||||
yyy
|
||||
z1
|
||||
z2
|
||||
1
test/fixtures/ftplugin-msg/ftplugin/c.vim
vendored
Normal file
1
test/fixtures/ftplugin-msg/ftplugin/c.vim
vendored
Normal file
@@ -0,0 +1 @@
|
||||
echomsg 'ftplugin'
|
||||
33
test/run
33
test/run
@@ -5,18 +5,20 @@ cd ..
|
||||
PLUG_SRC=$(pwd)/plug.vim
|
||||
cd - > /dev/null
|
||||
|
||||
export PLUG_FIXTURES=$(pwd)/fixtures
|
||||
|
||||
if [ ! -d vader.vim ]; then
|
||||
git clone https://github.com/junegunn/vader.vim.git
|
||||
fi
|
||||
|
||||
rm -rf fzf
|
||||
rm -rf $PLUG_FIXTURES/fzf
|
||||
if [ ! -d fzf-staged ]; then
|
||||
git clone https://github.com/junegunn/fzf.git fzf-staged
|
||||
git clone https://github.com/junegunn/fzf.git $PLUG_FIXTURES/fzf-staged
|
||||
fi
|
||||
|
||||
make_dirs() {
|
||||
mkdir -p "$1"
|
||||
cd "$1"
|
||||
mkdir -p "$PLUG_FIXTURES/$1"
|
||||
cd "$PLUG_FIXTURES/$1"
|
||||
mkdir -p autoload colors ftdetect ftplugin indent plugin syntax
|
||||
for d in *; do
|
||||
[ -d $d ] || continue
|
||||
@@ -32,18 +34,22 @@ EOF
|
||||
cd - > /dev/null
|
||||
}
|
||||
|
||||
make_dirs xxx/ xxx
|
||||
make_dirs xxx/after xxx
|
||||
mkdir -p xxx/doc
|
||||
cat > xxx/doc/xxx.txt << DOC
|
||||
init() {
|
||||
rm -rf $PLUG_FIXTURES/{xxx,yyy,z1,z2}
|
||||
|
||||
make_dirs xxx/ xxx
|
||||
make_dirs xxx/after xxx
|
||||
mkdir -p $PLUG_FIXTURES/xxx/doc
|
||||
cat > $PLUG_FIXTURES/xxx/doc/xxx.txt << DOC
|
||||
hello *xxx*
|
||||
DOC
|
||||
|
||||
make_dirs yyy/ yyy
|
||||
make_dirs yyy/after yyy
|
||||
make_dirs yyy/ yyy
|
||||
make_dirs yyy/after yyy
|
||||
|
||||
make_dirs z1/ z1
|
||||
make_dirs z2/ z2
|
||||
make_dirs z1/ z1
|
||||
make_dirs z2/ z2
|
||||
}
|
||||
|
||||
cat > /tmp/mini-vimrc << VIMRC
|
||||
set rtp+=vader.vim
|
||||
@@ -51,8 +57,11 @@ set shell=/bin/bash
|
||||
source $PLUG_SRC
|
||||
VIMRC
|
||||
|
||||
[ -z "$TMPDIR" ] && export TMPDIR=/tmp/
|
||||
init
|
||||
if [ "$1" = '!' ]; then
|
||||
/usr/local/bin/vim -Nu /tmp/mini-vimrc -c 'Vader! workflow.vader' > /dev/null &&
|
||||
init &&
|
||||
/usr/local/bin/vim -Nu /tmp/mini-vimrc -c 'let g:plug_threads = 1 | Vader! workflow.vader' > /dev/null
|
||||
else
|
||||
/usr/local/bin/vim -Nu /tmp/mini-vimrc -c 'Vader workflow.vader'
|
||||
|
||||
@@ -304,7 +304,8 @@ Execute (Rollback recent updates, PlugUpdate, then PlugDiff):
|
||||
|
||||
" ]] motion
|
||||
execute 'normal $]]'
|
||||
AssertEqual lnum + 4, line('.')
|
||||
Assert index([lnum + 4, lnum + 5], line('.')) >= 0
|
||||
" +5 for merge commit
|
||||
AssertEqual 3, col('.')
|
||||
|
||||
" [[ motion
|
||||
@@ -337,7 +338,8 @@ Execute (Rollback recent updates, PlugUpdate, then PlugDiff):
|
||||
AssertEqual 1, &previewwindow
|
||||
pclose
|
||||
|
||||
Execute (Plug window in a new tab):
|
||||
Execute (Reuse Plug window in another tab):
|
||||
let tabnr = tabpagenr()
|
||||
PlugDiff
|
||||
tab new new-tab
|
||||
set buftype=nofile
|
||||
@@ -345,8 +347,8 @@ Execute (Plug window in a new tab):
|
||||
normal D
|
||||
AssertExpect '^- ', 1
|
||||
normal q
|
||||
AssertEqual 'new-tab', expand('%')
|
||||
q
|
||||
AssertEqual tabnr, tabpagenr()
|
||||
normal! gt
|
||||
q
|
||||
|
||||
**********************************************************************
|
||||
@@ -420,7 +422,7 @@ Execute (On-demand loading based on filetypes):
|
||||
**********************************************************************
|
||||
|
||||
Execute (Add unmanaged plugin):
|
||||
let fzf = fnamemodify(g:vader_file, ':h') . '/fzf'
|
||||
let fzf = expand('$PLUG_FIXTURES/fzf')
|
||||
Log fzf
|
||||
|
||||
call plug#begin()
|
||||
@@ -450,6 +452,7 @@ Execute (Plug block for following tests):
|
||||
call plug#end()
|
||||
" Remove plugins from previous tests
|
||||
PlugClean!
|
||||
q
|
||||
|
||||
Execute (PlugInstall will only install vim-easy-align):
|
||||
PlugInstall
|
||||
@@ -478,7 +481,7 @@ Execute (PlugStatus should point out that the plugin is missing):
|
||||
|
||||
Execute (Deploy unmanaged plugin):
|
||||
Assert !exists(':FZF'), ':FZF command should not exist'
|
||||
call rename('fzf-staged', 'fzf')
|
||||
call rename(expand('$PLUG_FIXTURES/fzf-staged'), fzf)
|
||||
|
||||
Execute (PlugUpdate still should not care):
|
||||
PlugUpdate
|
||||
@@ -516,12 +519,37 @@ Execute (Common parent):
|
||||
**********************************************************************
|
||||
~ Frozen plugins
|
||||
**********************************************************************
|
||||
- We've decided to install plugins that are frozen: see #113
|
||||
Execute (Frozen plugin are not ~~installed nor~~ updated):
|
||||
" Remove plugins
|
||||
call plug#begin()
|
||||
call plug#end()
|
||||
PlugClean!
|
||||
q
|
||||
|
||||
Execute (Frozen plugin are not installed nor updated):
|
||||
" vim-easy-align is not found, so it will be installed even though it's frozen
|
||||
call plug#begin()
|
||||
Plug 'junegunn/vim-easy-align', { 'frozen': 1 }
|
||||
call plug#end()
|
||||
PlugInstall
|
||||
AssertEqual 1, len(filter(getline(1, '$'), 'v:val =~ "vim-easy-align"'))
|
||||
q
|
||||
|
||||
" Remove plugins again
|
||||
call plug#begin()
|
||||
call plug#end()
|
||||
PlugClean!
|
||||
q
|
||||
|
||||
" PlugUpdate will do the same
|
||||
call plug#begin()
|
||||
Plug 'junegunn/vim-easy-align', { 'frozen': 1 }
|
||||
call plug#end()
|
||||
PlugInstall
|
||||
AssertEqual 1, len(filter(getline(1, '$'), 'v:val =~ "vim-easy-align"'))
|
||||
q
|
||||
|
||||
" Since vim-easy-align already exists, PlugInstall or PlugUpdate will skip it
|
||||
redir => out
|
||||
silent PlugInstall
|
||||
redir END
|
||||
@@ -593,6 +621,7 @@ Execute (Cleanup):
|
||||
call plug#begin()
|
||||
call plug#end()
|
||||
PlugClean!
|
||||
q
|
||||
|
||||
Execute (On install):
|
||||
call plug#begin()
|
||||
@@ -731,12 +760,12 @@ Execute (Using custom dir):
|
||||
**********************************************************************
|
||||
Before (Clear global vars):
|
||||
let g:xxx = []
|
||||
set rtp-=$PWD/xxx/
|
||||
set rtp-=$PWD/xxx/after
|
||||
set rtp-=$PLUG_FIXTURES/xxx/
|
||||
set rtp-=$PLUG_FIXTURES/xxx/after
|
||||
|
||||
Execute (Immediate loading):
|
||||
call plug#begin()
|
||||
Plug '$PWD/xxx'
|
||||
Plug '$PLUG_FIXTURES/xxx'
|
||||
call plug#end()
|
||||
|
||||
" FIXME:
|
||||
@@ -750,7 +779,7 @@ Execute (Immediate loading):
|
||||
|
||||
Execute (Command-based on-demand loading):
|
||||
call plug#begin()
|
||||
Plug '$PWD/xxx', { 'on': 'XXX' }
|
||||
Plug '$PLUG_FIXTURES/xxx', { 'on': 'XXX' }
|
||||
call plug#end()
|
||||
|
||||
AssertEqual [], g:xxx
|
||||
@@ -763,7 +792,7 @@ Execute (Command-based on-demand loading):
|
||||
|
||||
Execute (Filetype-based on-demand loading):
|
||||
call plug#begin()
|
||||
Plug '$PWD/xxx', { 'for': 'xxx' }
|
||||
Plug '$PLUG_FIXTURES/xxx', { 'for': 'xxx' }
|
||||
call plug#end()
|
||||
|
||||
AssertEqual ['xxx/ftdetect', 'xxx/after/ftdetect'], g:xxx
|
||||
@@ -778,10 +807,10 @@ Before:
|
||||
**********************************************************************
|
||||
|
||||
Execute (plug#helptags):
|
||||
silent! call delete(expand('$PWD/xxx/doc/tags'))
|
||||
Assert !filereadable(expand('$PWD/xxx/doc/tags'))
|
||||
silent! call delete(expand('$PLUG_FIXTURES/xxx/doc/tags'))
|
||||
Assert !filereadable(expand('$PLUG_FIXTURES/xxx/doc/tags'))
|
||||
AssertEqual 1, plug#helptags()
|
||||
Assert filereadable(expand('$PWD/xxx/doc/tags'))
|
||||
Assert filereadable(expand('$PLUG_FIXTURES/xxx/doc/tags'))
|
||||
|
||||
**********************************************************************
|
||||
~ Manual loading
|
||||
@@ -822,7 +851,7 @@ Execute (PlugStatus should not contain (not loaded)):
|
||||
|
||||
Execute (Load plugin from PlugStatus screen with L key in normal mode):
|
||||
call plug#begin()
|
||||
Plug '$PWD/yyy', { 'on': [] }
|
||||
Plug '$PLUG_FIXTURES/yyy', { 'on': [] }
|
||||
call plug#end()
|
||||
|
||||
PlugStatus
|
||||
@@ -836,8 +865,8 @@ Execute (Load plugin from PlugStatus screen with L key in normal mode):
|
||||
|
||||
Execute (Load plugin from PlugStatus screen with L key in visual mode):
|
||||
call plug#begin()
|
||||
Plug '$PWD/z1', { 'on': [] }
|
||||
Plug '$PWD/z2', { 'for': [] }
|
||||
Plug '$PLUG_FIXTURES/z1', { 'on': [] }
|
||||
Plug '$PLUG_FIXTURES/z2', { 'for': [] }
|
||||
call plug#end()
|
||||
|
||||
PlugStatus
|
||||
@@ -963,8 +992,8 @@ Execute (Plug directory with comma):
|
||||
Execute (Strict load order):
|
||||
let g:total_order = []
|
||||
call plug#begin()
|
||||
Plug '$PWD/xxx'
|
||||
Plug '$PWD/yyy', { 'for': ['xxx'] }
|
||||
Plug '$PLUG_FIXTURES/xxx'
|
||||
Plug '$PLUG_FIXTURES/yyy', { 'for': ['xxx'] }
|
||||
call plug#end()
|
||||
call EnsureLoaded()
|
||||
setf xxx
|
||||
@@ -976,8 +1005,8 @@ Execute (Strict load order):
|
||||
|
||||
let g:total_order = []
|
||||
call plug#begin()
|
||||
Plug '$PWD/xxx', { 'for': ['xxx'] }
|
||||
Plug '$PWD/yyy'
|
||||
Plug '$PLUG_FIXTURES/xxx', { 'for': ['xxx'] }
|
||||
Plug '$PLUG_FIXTURES/yyy'
|
||||
call plug#end()
|
||||
call EnsureLoaded()
|
||||
set rtp^=manually-prepended
|
||||
@@ -993,8 +1022,8 @@ Execute (Strict load order):
|
||||
|
||||
let g:total_order = []
|
||||
call plug#begin()
|
||||
Plug '$PWD/xxx', { 'for': ['xxx'] }
|
||||
Plug '$PWD/yyy', { 'for': ['xxx'] }
|
||||
Plug '$PLUG_FIXTURES/xxx', { 'for': ['xxx'] }
|
||||
Plug '$PLUG_FIXTURES/yyy', { 'for': ['xxx'] }
|
||||
call plug#end()
|
||||
call EnsureLoaded()
|
||||
setf xxx
|
||||
@@ -1004,9 +1033,126 @@ Execute (Strict load order):
|
||||
Assert index(g:total_order, 'xxx/after/plugin') < index(g:total_order, 'yyy/after/plugin')
|
||||
AssertEqual len + 2, len(split(&rtp, ','))
|
||||
|
||||
**********************************************************************
|
||||
Execute (PlugClean should not try to remove unmanaged plugins inside g:plug_home):
|
||||
call plug#begin('$PLUG_FIXTURES')
|
||||
Plug '$PLUG_FIXTURES/ftplugin-msg', { 'for': [] }
|
||||
Plug '$PLUG_FIXTURES/fzf'
|
||||
Plug '$PLUG_FIXTURES/xxx'
|
||||
Plug '$PLUG_FIXTURES/yyy'
|
||||
call plug#end()
|
||||
|
||||
" Remove z1, z2
|
||||
PlugClean!
|
||||
AssertExpect '^- ', 2
|
||||
AssertExpect 'Already clean', 0
|
||||
|
||||
PlugClean!
|
||||
AssertExpect '^- ', 0
|
||||
AssertExpect 'Already clean', 1
|
||||
q
|
||||
|
||||
**********************************************************************
|
||||
Execute (#112 On-demand loading should not suppress messages from ftplugin):
|
||||
call plug#begin('$PLUG_FIXTURES')
|
||||
Plug '$PLUG_FIXTURES/ftplugin-msg', { 'for': 'c' }
|
||||
call plug#end()
|
||||
|
||||
redir => out
|
||||
tabnew a.c
|
||||
redir END
|
||||
Assert stridx(out, 'ftplugin') >= 0
|
||||
|
||||
* The same applies to plug#load())
|
||||
redir => out
|
||||
call plug#load('ftplugin-msg')
|
||||
redir END
|
||||
Assert stridx(out, 'ftplugin') >= 0
|
||||
q
|
||||
|
||||
**********************************************************************
|
||||
Execute (PlugSnapshot):
|
||||
call plug#begin('$TMPDIR/plugged')
|
||||
Plug 'junegunn/vim-emoji'
|
||||
Plug 'junegunn/seoul256.vim'
|
||||
call plug#end()
|
||||
|
||||
PlugClean!
|
||||
PlugInstall
|
||||
PlugSnapshot
|
||||
AssertEqual '#!/bin/bash', getline(1)
|
||||
AssertEqual '# Generated by vim-plug', getline(2)
|
||||
AssertEqual 'vim +PlugUpdate +qa', getline(5)
|
||||
AssertEqual 'PLUG_HOME=$TMPDIR/plugged', getline(7)
|
||||
AssertEqual 0, stridx(getline(9), 'cd $PLUG_HOME/seoul256.vim/ && git reset --hard')
|
||||
AssertEqual 0, stridx(getline(10), 'cd $PLUG_HOME/vim-emoji/ && git reset --hard')
|
||||
AssertEqual 'sh', &filetype
|
||||
|
||||
execute 'PlugSnapshot' g:plug_home.'/snapshot.sh'
|
||||
AssertEqual 'sh', &filetype
|
||||
AssertEqual 'snapshot.sh', fnamemodify(expand('%'), ':t')
|
||||
q
|
||||
|
||||
**********************************************************************
|
||||
Execute (#114 Should not contain empty path in &rtp):
|
||||
call plug#begin('$TMPDIR/plugged')
|
||||
call plug#end()
|
||||
|
||||
Log &rtp
|
||||
Assert &rtp !~ ',,', 'Commas'
|
||||
Assert &rtp !~ '^,', 'Comma prefix'
|
||||
Assert &rtp !~ ',$', 'Comma suffix'
|
||||
|
||||
**********************************************************************
|
||||
Execute (#130 Proper cleanup of on-demand loading triggers):
|
||||
augroup PlugLOD
|
||||
autocmd!
|
||||
augroup END
|
||||
|
||||
" Cleared on command
|
||||
call plug#begin('$TMPDIR/plugged')
|
||||
Plug 'junegunn/vim-emoji', { 'on': ['EmojiCommand', 'EmojiCommand2', '<Plug>(EmojiMapping)'] }
|
||||
call plug#end()
|
||||
PlugInstall | q
|
||||
|
||||
Assert exists(':EmojiCommand'), 'EmojiCommand not defined'
|
||||
Assert exists(':EmojiCommand2'), 'EmojiCommand2 not defined'
|
||||
Assert !empty(mapcheck('<Plug>(EmojiMapping)')), '<Plug>(EmojiMapping) not defined'
|
||||
|
||||
silent! EmojiCommand
|
||||
|
||||
Assert !exists(':EmojiCommand'), 'EmojiCommand defined'
|
||||
Assert !exists(':EmojiCommand2'), 'EmojiCommand2 defined'
|
||||
Assert empty(mapcheck('<Plug>(EmojiMapping)')), '<Plug>(EmojiMapping) defined'
|
||||
|
||||
" Cleared on FileType
|
||||
call plug#begin('$TMPDIR/plugged')
|
||||
Plug 'junegunn/vim-emoji', { 'on': ['EmojiCommandExtra', '<Plug>(EmojiMappingExtra)'], 'for': ['emoji'] }
|
||||
call plug#end()
|
||||
|
||||
Assert exists(':EmojiCommandExtra'), 'EmojiCommandExtra not defined'
|
||||
Assert !empty(mapcheck('<Plug>(EmojiMappingExtra)')), '<Plug>(EmojiMappingExtra) not defined'
|
||||
|
||||
setf emoji
|
||||
|
||||
Assert !exists(':EmojiCommandExtra'), 'EmojiCommandExtra defined'
|
||||
Assert empty(mapcheck('<Plug>(EmojiMappingExtra)')), '<Plug>(EmojiMappingExtra) defined'
|
||||
|
||||
**********************************************************************
|
||||
Execute (#131 Syntax error):
|
||||
call plug#begin('/no-permission')
|
||||
Plug 'junegunn/vim-emoji'
|
||||
call plug#end()
|
||||
|
||||
redir => out
|
||||
silent PlugInstall
|
||||
redir END
|
||||
Assert out =~ 'Invalid plug directory: /no-permission'
|
||||
|
||||
Execute (Cleanup):
|
||||
silent! call system('rm -rf '.temp_plugged)
|
||||
silent! call rename('fzf', 'fzf-staged')
|
||||
silent! call system('rm -rf '.temp_plugged)
|
||||
silent! call rename(fzf, expand('$PLUG_FIXTURES/fzf-staged'))
|
||||
silent! unlet g:plugs
|
||||
silent! unlet g:plug_home
|
||||
silent! unlet g:plug_url_format
|
||||
|
||||
Reference in New Issue
Block a user