plug.vim 20 KB

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