plug.vim 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683
  1. " vim-plug: Vim plugin manager
  2. " ============================
  3. "
  4. " Download plug.vim and put it in ~/.vim/autoload
  5. "
  6. " mkdir -p ~/.vim/autoload
  7. " curl -fLo ~/.vim/autoload/plug.vim \
  8. " https://raw.github.com/junegunn/vim-plug/master/plug.vim
  9. "
  10. " Edit your .vimrc
  11. "
  12. " call plug#begin()
  13. "
  14. " Plug 'junegunn/seoul256.vim'
  15. " Plug 'junegunn/vim-easy-align'
  16. " " Plug 'user/repo1', 'branch_or_tag'
  17. " " Plug 'user/repo2', { 'rtp': 'vim/plugin/dir', 'branch': 'devel' }
  18. " " ...
  19. "
  20. " call plug#end()
  21. "
  22. " Then :PlugInstall to install plugins. (default: ~/.vim/plugged)
  23. " You can change the location of the plugins with plug#begin(path) call.
  24. "
  25. "
  26. " Copyright (c) 2013 Junegunn Choi
  27. "
  28. " MIT License
  29. "
  30. " Permission is hereby granted, free of charge, to any person obtaining
  31. " a copy of this software and associated documentation files (the
  32. " "Software"), to deal in the Software without restriction, including
  33. " without limitation the rights to use, copy, modify, merge, publish,
  34. " distribute, sublicense, and/or sell copies of the Software, and to
  35. " permit persons to whom the Software is furnished to do so, subject to
  36. " the following conditions:
  37. "
  38. " The above copyright notice and this permission notice shall be
  39. " included in all copies or substantial portions of the Software.
  40. "
  41. " THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  42. " EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  43. " MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  44. " NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
  45. " LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
  46. " OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
  47. " WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  48. if exists('g:loaded_plug')
  49. finish
  50. endif
  51. let g:loaded_plug = 1
  52. let s:cpo_save = &cpo
  53. set cpo&vim
  54. let s:plug_source = 'https://raw.github.com/junegunn/vim-plug/master/plug.vim'
  55. let s:plug_file = 'Plugfile'
  56. let s:plug_win = 0
  57. let s:is_win = has('win32') || has('win64')
  58. let s:me = expand('<sfile>:p')
  59. function! plug#begin(...)
  60. if a:0 > 0
  61. let home = s:path(fnamemodify(a:1, ':p'))
  62. elseif exists('g:plug_home')
  63. let home = s:path(g:plug_home)
  64. elseif !empty(&rtp)
  65. let home = s:path(split(&rtp, ',')[0]) . '/plugged'
  66. else
  67. echoerr "Unable to determine plug home. Try calling plug#begin() with a path argument."
  68. return
  69. endif
  70. if !isdirectory(home)
  71. try
  72. call mkdir(home, 'p')
  73. catch
  74. echoerr 'Invalid plug directory: '. home
  75. return 0
  76. endtry
  77. endif
  78. if !executable('git')
  79. echoerr "`git' executable not found. vim-plug requires git."
  80. return 0
  81. endif
  82. let g:plug_home = home
  83. let g:plugs = {}
  84. command! -nargs=+ Plug call s:add(1, <args>)
  85. command! -nargs=* PlugInstall call s:install(<f-args>)
  86. command! -nargs=* PlugUpdate call s:update(<f-args>)
  87. command! -nargs=0 -bang PlugClean call s:clean('<bang>' == '!')
  88. command! -nargs=0 PlugUpgrade if s:upgrade() | execute "source ". s:me | endif
  89. command! -nargs=0 PlugStatus call s:status()
  90. return 1
  91. endfunction
  92. function! plug#end()
  93. if !exists('g:plugs')
  94. echoerr 'Call plug#begin() first'
  95. return
  96. endif
  97. let keys = keys(g:plugs)
  98. while !empty(keys)
  99. let keys = keys(s:extend(keys))
  100. endwhile
  101. filetype off
  102. for plug in values(g:plugs)
  103. let rtp = s:rtp(plug)
  104. execute "set rtp^=".rtp
  105. if isdirectory(rtp.'after')
  106. execute "set rtp+=".rtp.'after'
  107. endif
  108. endfor
  109. filetype plugin indent on
  110. syntax on
  111. endfunction
  112. function! s:rtp(spec)
  113. let rtp = s:dirpath(a:spec.dir . get(a:spec, 'rtp', ''))
  114. if s:is_win
  115. let rtp = substitute(rtp, '\\*$', '', '')
  116. endif
  117. return rtp
  118. endfunction
  119. function! s:add(...)
  120. let force = a:1
  121. let opts = { 'branch': 'master' }
  122. if a:0 == 2
  123. let plugin = a:2
  124. elseif a:0 == 3
  125. let plugin = a:2
  126. if type(a:3) == 1
  127. let opts.branch = a:3
  128. elseif type(a:3) == 4
  129. call extend(opts, a:3)
  130. else
  131. echoerr "Invalid argument type (expected: string or dictionary)"
  132. return
  133. endif
  134. else
  135. echoerr "Invalid number of arguments (1..2)"
  136. return
  137. endif
  138. if plugin =~ ':'
  139. let uri = plugin
  140. else
  141. if plugin !~ '/'
  142. let plugin = 'vim-scripts/'. plugin
  143. endif
  144. let uri = 'https://git:@github.com/' . plugin . '.git'
  145. endif
  146. let name = substitute(split(plugin, '/')[-1], '\.git$', '', '')
  147. if !force && has_key(g:plugs, name) | return | endif
  148. let dir = s:dirpath( fnamemodify(join([g:plug_home, name], '/'), ':p') )
  149. let spec = extend(opts, { 'dir': dir, 'uri': uri })
  150. let g:plugs[name] = spec
  151. endfunction
  152. function! s:install(...)
  153. call s:update_impl(0, a:000)
  154. endfunction
  155. function! s:update(...)
  156. call s:update_impl(1, a:000)
  157. endfunction
  158. function! s:apply()
  159. for spec in values(g:plugs)
  160. let docd = join([spec.dir, 'doc'], '/')
  161. if isdirectory(docd)
  162. execute "helptags ". join([spec.dir, 'doc'], '/')
  163. endif
  164. endfor
  165. runtime! plugin/*.vim
  166. runtime! after/*.vim
  167. silent! source $MYVIMRC
  168. endfunction
  169. function! s:syntax()
  170. syntax clear
  171. syntax region plug1 start=/\%1l/ end=/\%2l/ contains=ALL
  172. syntax region plug2 start=/\%2l/ end=/\%3l/ contains=ALL
  173. syn match plugNumber /[0-9]\+[0-9.]*/ containedin=plug1 contained
  174. syn match plugBracket /[[\]]/ containedin=plug2 contained
  175. syn match plugX /x/ containedin=plug2 contained
  176. syn match plugDash /^-/
  177. syn match plugName /\(^- \)\@<=[^:]*/
  178. syn match plugError /^x.*/
  179. syn keyword Function PlugInstall PlugStatus PlugUpdate PlugClean
  180. hi def link plug1 Title
  181. hi def link plug2 Repeat
  182. hi def link plugX Exception
  183. hi def link plugBracket Structure
  184. hi def link plugNumber Number
  185. hi def link plugDash Special
  186. hi def link plugName Label
  187. hi def link plugError Error
  188. endfunction
  189. function! s:lpad(str, len)
  190. return a:str . repeat(' ', a:len - len(a:str))
  191. endfunction
  192. function! s:lastline(msg)
  193. let lines = split(a:msg, '\n')
  194. return get(lines, -1, '')
  195. endfunction
  196. function! s:prepare()
  197. execute s:plug_win . 'wincmd w'
  198. if exists('b:plug')
  199. %d
  200. else
  201. vertical topleft new
  202. noremap <silent> <buffer> q :q<cr>
  203. let b:plug = 1
  204. let s:plug_win = winnr()
  205. call s:assign_name()
  206. endif
  207. setlocal buftype=nofile bufhidden=wipe nobuflisted noswapfile nowrap cursorline
  208. setf vim-plug
  209. call s:syntax()
  210. endfunction
  211. function! s:assign_name()
  212. " Assign buffer name
  213. let prefix = '[Plugins]'
  214. let name = prefix
  215. let idx = 2
  216. while bufexists(name)
  217. let name = printf("%s (%s)", prefix, idx)
  218. let idx = idx + 1
  219. endwhile
  220. silent! execute "f ".fnameescape(name)
  221. endfunction
  222. function! s:finish()
  223. call append(3, '- Finishing ... ')
  224. redraw
  225. call s:apply()
  226. call s:syntax()
  227. call setline(4, getline(4) . 'Done!')
  228. normal! gg
  229. endfunction
  230. function! s:update_impl(pull, args)
  231. let threads = len(a:args) > 0 ? a:args[0] : get(g:, 'plug_threads', 16)
  232. call s:prepare()
  233. call append(0, a:pull ? 'Updating plugins' : 'Installing plugins')
  234. call append(1, '['. s:lpad('', len(g:plugs)) .']')
  235. normal! 2G
  236. redraw
  237. if has('ruby') && threads > 1
  238. call s:update_parallel(a:pull, threads)
  239. else
  240. call s:update_serial(a:pull)
  241. endif
  242. call s:finish()
  243. endfunction
  244. function! s:extend(names)
  245. let prev = copy(g:plugs)
  246. try
  247. command! -nargs=+ Plug call s:add(0, <args>)
  248. for name in a:names
  249. let plugfile = s:rtp(g:plugs[name]) . s:plug_file
  250. if filereadable(plugfile)
  251. execute "source ". plugfile
  252. endif
  253. endfor
  254. finally
  255. command! -nargs=+ Plug call s:add(1, <args>)
  256. endtry
  257. return filter(copy(g:plugs), '!has_key(prev, v:key)')
  258. endfunction
  259. function! s:update_progress(pull, cnt, bar, total)
  260. call setline(1, (a:pull ? 'Updating' : 'Installing').
  261. \ " plugins (".a:cnt."/".a:total.")")
  262. call s:progress_bar(2, a:bar, a:total)
  263. normal! 2G
  264. redraw
  265. endfunction
  266. function! s:update_serial(pull)
  267. let st = reltime()
  268. let base = g:plug_home
  269. let todo = copy(g:plugs)
  270. let total = len(todo)
  271. let done = {}
  272. let bar = ''
  273. while !empty(todo)
  274. for [name, spec] in items(todo)
  275. let done[name] = 1
  276. if isdirectory(spec.dir)
  277. execute 'cd '.spec.dir
  278. let [valid, msg] = s:git_valid(spec, 0, 0)
  279. if valid
  280. let result = a:pull ?
  281. \ system(
  282. \ printf('git checkout -q %s 2>&1 && git pull origin %s 2>&1',
  283. \ spec.branch, spec.branch)) : 'Already installed'
  284. let error = a:pull ? v:shell_error != 0 : 0
  285. else
  286. let result = msg
  287. let error = 1
  288. endif
  289. else
  290. if !isdirectory(base)
  291. call mkdir(base, 'p')
  292. endif
  293. execute 'cd '.base
  294. let d = shellescape(substitute(spec.dir, '[\/]\+$', '', ''))
  295. let result = system(
  296. \ printf('git clone --recursive %s -b %s %s 2>&1',
  297. \ shellescape(spec.uri), shellescape(spec.branch), d))
  298. let error = v:shell_error != 0
  299. endif
  300. cd -
  301. let bar .= error ? 'x' : '='
  302. call append(3, s:format_message(!error, name, result))
  303. call s:update_progress(a:pull, len(done), bar, total)
  304. endfor
  305. if !empty(s:extend(keys(todo)))
  306. let todo = filter(copy(g:plugs), '!has_key(done, v:key)')
  307. let total += len(todo)
  308. call s:update_progress(a:pull, len(done), bar, total)
  309. else
  310. break
  311. endif
  312. endwhile
  313. call setline(1, "Updated. Elapsed time: " . split(reltimestr(reltime(st)))[0] . ' sec.')
  314. endfunction
  315. function! s:update_parallel(pull, threads)
  316. ruby << EOF
  317. st = Time.now
  318. require 'thread'
  319. require 'fileutils'
  320. require 'timeout'
  321. running = true
  322. iswin = VIM::evaluate('s:is_win').to_i == 1
  323. pull = VIM::evaluate('a:pull').to_i == 1
  324. base = VIM::evaluate('g:plug_home')
  325. all = VIM::evaluate('copy(g:plugs)')
  326. limit = VIM::evaluate('get(g:, "plug_timeout", 60)')
  327. nthr = VIM::evaluate('a:threads').to_i
  328. cd = iswin ? 'cd /d' : 'cd'
  329. done = {}
  330. tot = 0
  331. bar = ''
  332. skip = 'Already installed'
  333. mtx = Mutex.new
  334. take1 = proc { mtx.synchronize { running && all.shift } }
  335. logh = proc {
  336. cnt = done.length
  337. tot = VIM::evaluate('len(g:plugs)') || tot
  338. $curbuf[1] = "#{pull ? 'Updating' : 'Installing'} plugins (#{cnt}/#{tot})"
  339. $curbuf[2] = '[' + bar.ljust(tot) + ']'
  340. VIM::command('normal! 2G')
  341. VIM::command('redraw') unless iswin
  342. }
  343. log = proc { |name, result, ok|
  344. mtx.synchronize do
  345. bar += ok ? '=' : 'x'
  346. done[name] = true
  347. result =
  348. if ok
  349. ["- #{name}: #{result.lines.to_a.last.strip}"]
  350. elsif result =~ /^Interrupted|^Timeout/
  351. ["x #{name}: #{result}"]
  352. else
  353. ["x #{name}"] + result.lines.map { |l| " " << l }
  354. end
  355. result.each_with_index do |line, offset|
  356. $curbuf.append 3 + offset, line.chomp
  357. end
  358. logh.call
  359. end
  360. }
  361. bt = proc { |cmd|
  362. begin
  363. fd = nil
  364. Timeout::timeout(limit) do
  365. if iswin
  366. tmp = VIM::evaluate('tempname()')
  367. system("#{cmd} > #{tmp}")
  368. data = File.read(tmp).chomp
  369. File.unlink tmp rescue nil
  370. else
  371. fd = IO.popen(cmd)
  372. data = fd.read.chomp
  373. fd.close
  374. end
  375. [$? == 0, data]
  376. end
  377. rescue Timeout::Error, Interrupt => e
  378. if fd && !fd.closed?
  379. pids = [fd.pid]
  380. unless `which pgrep`.empty?
  381. children = pids
  382. until children.empty?
  383. children = children.map { |pid|
  384. `pgrep -P #{pid}`.lines.map(&:chomp)
  385. }.flatten
  386. pids += children
  387. end
  388. end
  389. pids.each { |pid| Process.kill 'TERM', pid.to_i rescue nil }
  390. fd.close
  391. end
  392. [false, e.is_a?(Interrupt) ? "Interrupted!" : "Timeout!"]
  393. end
  394. }
  395. main = Thread.current
  396. threads = []
  397. watcher = Thread.new {
  398. while VIM::evaluate('getchar(1)')
  399. sleep 0.1
  400. end
  401. mtx.synchronize do
  402. running = false
  403. threads.each { |t| t.raise Interrupt }
  404. end
  405. threads.each { |t| t.join rescue nil }
  406. main.kill
  407. }
  408. until all.empty?
  409. names = all.keys
  410. [names.length, nthr].min.times do
  411. mtx.synchronize do
  412. threads << Thread.new {
  413. while pair = take1.call
  414. name = pair.first
  415. dir, uri, branch = pair.last.values_at *%w[dir uri branch]
  416. ok, result =
  417. if File.directory? dir
  418. ret, data = bt.call "#{cd} #{dir} && git rev-parse --abbrev-ref HEAD 2>&1 && git config remote.origin.url"
  419. current_uri = data.lines.to_a.last
  420. if !ret
  421. if data =~ /^Interrupted|^Timeout/
  422. [false, data]
  423. else
  424. [false, [data.chomp, "PlugClean required."].join($/)]
  425. end
  426. elsif current_uri.sub(/git:@/, '') != uri.sub(/git:@/, '')
  427. [false, ["Invalid URI: #{current_uri}",
  428. "Expected: #{uri}",
  429. "PlugClean required."].join($/)]
  430. else
  431. if pull
  432. bt.call "#{cd} #{dir} && git checkout -q #{branch} 2>&1 && git pull origin #{branch} 2>&1"
  433. else
  434. [true, skip]
  435. end
  436. end
  437. else
  438. FileUtils.mkdir_p(base)
  439. d = dir.sub(%r{[\\/]+$}, '')
  440. bt.call "#{cd} #{base} && git clone --recursive #{uri} -b #{branch} #{d} 2>&1"
  441. end
  442. log.call name, result, ok
  443. end
  444. } if running
  445. end
  446. end
  447. threads.each(&:join)
  448. mtx.synchronize { threads.clear }
  449. all.merge!(VIM::evaluate("s:extend(#{names.inspect})") || {})
  450. logh.call
  451. end
  452. watcher.kill
  453. $curbuf[1] = "Updated. Elapsed time: #{"%.6f" % (Time.now - st)} sec."
  454. EOF
  455. endfunction
  456. function! s:path(path)
  457. return substitute(s:is_win ? substitute(a:path, '/', '\', 'g') : a:path,
  458. \ '[/\\]*$', '', '')
  459. endfunction
  460. function! s:dirpath(path)
  461. let path = s:path(a:path)
  462. if s:is_win
  463. return path !~ '\\$' ? path.'\' : path
  464. else
  465. return path !~ '/$' ? path.'/' : path
  466. endif
  467. endfunction
  468. function! s:glob_dir(path)
  469. return map(filter(split(globpath(a:path, '**'), '\n'), 'isdirectory(v:val)'), 's:dirpath(v:val)')
  470. endfunction
  471. function! s:progress_bar(line, bar, total)
  472. call setline(a:line, '[' . s:lpad(a:bar, a:total) . ']')
  473. endfunction
  474. function! s:compare_git_uri(a, b)
  475. let a = substitute(a:a, 'git:@', '', '')
  476. let b = substitute(a:b, 'git:@', '', '')
  477. return a ==# b
  478. endfunction
  479. function! s:format_message(ok, name, message)
  480. if a:ok
  481. return [printf('- %s: %s', a:name, s:lastline(a:message))]
  482. else
  483. let lines = map(split(a:message, '\n'), '" ".v:val')
  484. return extend([printf('x %s:', a:name)], lines)
  485. endif
  486. endfunction
  487. function! s:git_valid(spec, check_branch, cd)
  488. let ret = 1
  489. let msg = 'OK'
  490. if isdirectory(a:spec.dir)
  491. if a:cd | execute "cd " . a:spec.dir | endif
  492. let result = split(system("git rev-parse --abbrev-ref HEAD 2>&1 && git config remote.origin.url"), '\n')
  493. let remote = result[-1]
  494. if v:shell_error != 0
  495. let msg = join([remote, "PlugClean required."], "\n")
  496. let ret = 0
  497. elseif !s:compare_git_uri(remote, a:spec.uri)
  498. let msg = join(['Invalid URI: '.remote,
  499. \ 'Expected: '.a:spec.uri,
  500. \ "PlugClean required."], "\n")
  501. let ret = 0
  502. elseif a:check_branch
  503. let branch = result[0]
  504. if a:spec.branch != branch
  505. let msg = 'Invalid branch: '.branch.'. Try PlugUpdate.'
  506. let ret = 0
  507. endif
  508. endif
  509. if a:cd | cd - | endif
  510. else
  511. let msg = 'Not found'
  512. let ret = 0
  513. endif
  514. return [ret, msg]
  515. endfunction
  516. function! s:clean(force)
  517. call s:prepare()
  518. call append(0, 'Searching for unused plugins in '.g:plug_home)
  519. call append(1, '')
  520. " List of valid directories
  521. let dirs = []
  522. let [cnt, total] = [0, len(g:plugs)]
  523. for spec in values(g:plugs)
  524. if s:git_valid(spec, 0, 1)[0]
  525. call add(dirs, spec.dir)
  526. endif
  527. let cnt += 1
  528. call s:progress_bar(2, repeat('=', cnt), total)
  529. redraw
  530. endfor
  531. let allowed = {}
  532. for dir in dirs
  533. let allowed[dir] = 1
  534. for child in s:glob_dir(dir)
  535. let allowed[child] = 1
  536. endfor
  537. endfor
  538. let todo = []
  539. let found = sort(s:glob_dir(g:plug_home))
  540. while !empty(found)
  541. let f = remove(found, 0)
  542. if !has_key(allowed, f) && isdirectory(f)
  543. call add(todo, f)
  544. call append(line('$'), '- ' . f)
  545. let found = filter(found, 'stridx(v:val, f) != 0')
  546. end
  547. endwhile
  548. normal! G
  549. redraw
  550. if empty(todo)
  551. call append(line('$'), 'Already clean.')
  552. else
  553. call inputsave()
  554. let yes = a:force || (input("Proceed? (Y/N) ") =~? '^y')
  555. call inputrestore()
  556. if yes
  557. for dir in todo
  558. if isdirectory(dir)
  559. call system((s:is_win ? 'rmdir /S /Q ' : 'rm -rf ') . dir)
  560. endif
  561. endfor
  562. call append(line('$'), 'Removed.')
  563. else
  564. call append(line('$'), 'Cancelled.')
  565. endif
  566. endif
  567. normal! G
  568. endfunction
  569. function! s:upgrade()
  570. if executable('curl')
  571. let mee = shellescape(s:me)
  572. let new = shellescape(s:me . '.new')
  573. echo "Downloading ". s:plug_source
  574. redraw
  575. let mv = s:is_win ? 'move /Y' : 'mv -f'
  576. let cp = s:is_win ? 'copy /Y' : 'cp -f'
  577. call system(printf(
  578. \ "curl -fLo %s %s && ".cp." %s %s.old && ".mv." %s %s",
  579. \ new, s:plug_source, mee, mee, new, mee))
  580. if v:shell_error == 0
  581. unlet g:loaded_plug
  582. echo "Downloaded ". s:plug_source
  583. return 1
  584. else
  585. echoerr "Error upgrading vim-plug"
  586. return 0
  587. endif
  588. elseif has('ruby')
  589. echo "Downloading ". s:plug_source
  590. ruby << EOF
  591. require 'open-uri'
  592. require 'fileutils'
  593. me = VIM::evaluate('s:me')
  594. old = me + '.old'
  595. new = me + '.new'
  596. File.open(new, 'w') do |f|
  597. f << open(VIM::evaluate('s:plug_source')).read
  598. end
  599. FileUtils.cp me, old
  600. File.rename new, me
  601. EOF
  602. unlet g:loaded_plug
  603. echo "Downloaded ". s:plug_source
  604. return 1
  605. else
  606. echoerr "curl executable or ruby support not found"
  607. return 0
  608. endif
  609. endfunction
  610. function! s:status()
  611. call s:prepare()
  612. call append(0, 'Checking plugins')
  613. let ecnt = 0
  614. for [name, spec] in items(g:plugs)
  615. if isdirectory(spec.dir)
  616. execute 'cd '.spec.dir
  617. let [valid, msg] = s:git_valid(spec, 1, 0)
  618. cd -
  619. else
  620. let [valid, msg] = [0, 'Not found. Try PlugInstall.']
  621. endif
  622. let ecnt += !valid
  623. call append(2, s:format_message(valid, name, msg))
  624. call cursor(3, 1)
  625. redraw
  626. endfor
  627. call setline(1, 'Finished. '.ecnt.' error(s).')
  628. normal! gg
  629. endfunction
  630. let &cpo = s:cpo_save
  631. unlet s:cpo_save