plug.vim 20 KB

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