plug.vim 20 KB

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