| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664 | " vim-plug: Vim plugin manager" ============================"" Download plug.vim and put it in ~/.vim/autoload""   curl -fLo ~/.vim/autoload/plug.vim --create-dirs \"     https://raw.githubusercontent.com/junegunn/vim-plug/master/plug.vim"" Edit your .vimrc""   call plug#begin('~/.vim/plugged')""   " Make sure you use single quotes""   " Shorthand notation; fetches https://github.com/junegunn/vim-easy-align"   Plug 'junegunn/vim-easy-align'""   " Any valid git URL is allowed"   Plug 'https://github.com/junegunn/vim-github-dashboard.git'""   " Multiple Plug commands can be written in a single line using | separators"   Plug 'SirVer/ultisnips' | Plug 'honza/vim-snippets'""   " On-demand loading"   Plug 'scrooloose/nerdtree', { 'on':  'NERDTreeToggle' }"   Plug 'tpope/vim-fireplace', { 'for': 'clojure' }""   " Using a non-master branch"   Plug 'rdnetto/YCM-Generator', { 'branch': 'stable' }""   " Using a tagged release; wildcard allowed (requires git 1.9.2 or above)"   Plug 'fatih/vim-go', { 'tag': '*' }""   " Plugin options"   Plug 'nsf/gocode', { 'tag': 'v.20150303', 'rtp': 'vim' }""   " Plugin outside ~/.vim/plugged with post-update hook"   Plug 'junegunn/fzf', { 'dir': '~/.fzf', 'do': './install --all' }""   " Unmanaged plugin (manually installed and updated)"   Plug '~/my-prototype-plugin'""   " Initialize plugin system"   call plug#end()"" Then reload .vimrc and :PlugInstall to install plugins."" Plug options:""| Option                  | Description                                      |"| ----------------------- | ------------------------------------------------ |"| `branch`/`tag`/`commit` | Branch/tag/commit of the repository to use       |"| `rtp`                   | Subdirectory that contains Vim plugin            |"| `dir`                   | Custom directory for the plugin                  |"| `as`                    | Use different name for the plugin                |"| `do`                    | Post-update hook (string or funcref)             |"| `on`                    | On-demand loading: Commands or `<Plug>`-mappings |"| `for`                   | On-demand loading: File types                    |"| `frozen`                | Do not update unless explicitly specified        |"" More information: https://github.com/junegunn/vim-plug""" Copyright (c) 2017 Junegunn Choi"" MIT License"" Permission is hereby granted, free of charge, to any person obtaining" a copy of this software and associated documentation files (the" "Software"), to deal in the Software without restriction, including" without limitation the rights to use, copy, modify, merge, publish," distribute, sublicense, and/or sell copies of the Software, and to" permit persons to whom the Software is furnished to do so, subject to" the following conditions:"" The above copyright notice and this permission notice shall be" included in all copies or substantial portions of the Software."" THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND," EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF" MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND" NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE" LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION" OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION" WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.if exists('g:loaded_plug')  finishendiflet g:loaded_plug = 1let s:cpo_save = &cposet cpo&vimlet s:plug_src = 'https://github.com/junegunn/vim-plug.git'let s:plug_tab = get(s:, 'plug_tab', -1)let s:plug_buf = get(s:, 'plug_buf', -1)let s:mac_gui = has('gui_macvim') && has('gui_running')let s:is_win = has('win32')let s:nvim = has('nvim-0.2') || (has('nvim') && exists('*jobwait') && !s:is_win)let s:vim8 = has('patch-8.0.0039') && exists('*job_start')if s:is_win && &shellslash  set noshellslash  let s:me = resolve(expand('<sfile>:p'))  set shellslashelse  let s:me = resolve(expand('<sfile>:p'))endiflet s:base_spec = { 'branch': 'master', 'frozen': 0 }let s:TYPE = {\   'string':  type(''),\   'list':    type([]),\   'dict':    type({}),\   'funcref': type(function('call'))\ }let s:loaded = get(s:, 'loaded', {})let s:triggers = get(s:, 'triggers', {})if s:is_win  function! s:plug_call(fn, ...)    let shellslash = &shellslash    try      set noshellslash      return call(a:fn, a:000)    finally      let &shellslash = shellslash    endtry  endfunctionelse  function! s:plug_call(fn, ...)    return call(a:fn, a:000)  endfunctionendiffunction! s:plug_getcwd()  return s:plug_call('getcwd')endfunctionfunction! s:plug_fnamemodify(fname, mods)  return s:plug_call('fnamemodify', a:fname, a:mods)endfunctionfunction! s:plug_expand(fmt)  return s:plug_call('expand', a:fmt, 1)endfunctionfunction! s:plug_tempname()  return s:plug_call('tempname')endfunctionfunction! plug#begin(...)  if a:0 > 0    let s:plug_home_org = a:1    let home = s:path(s:plug_fnamemodify(s:plug_expand(a:1), ':p'))  elseif exists('g:plug_home')    let home = s:path(g:plug_home)  elseif !empty(&rtp)    let home = s:path(split(&rtp, ',')[0]) . '/plugged'  else    return s:err('Unable to determine plug home. Try calling plug#begin() with a path argument.')  endif  if s:plug_fnamemodify(home, ':t') ==# 'plugin' && s:plug_fnamemodify(home, ':h') ==# s:first_rtp    return s:err('Invalid plug home. '.home.' is a standard Vim runtime path and is not allowed.')  endif  let g:plug_home = home  let g:plugs = {}  let g:plugs_order = []  let s:triggers = {}  call s:define_commands()  return 1endfunctionfunction! s:define_commands()  command! -nargs=+ -bar Plug call plug#(<args>)  if !executable('git')    return s:err('`git` executable not found. Most commands will not be available. To suppress this message, prepend `silent!` to `call plug#begin(...)`.')  endif  if has('win32')  \ && &shellslash  \ && (&shell =~# 'cmd\.exe' || &shell =~# 'powershell\.exe')    return s:err('vim-plug does not support shell, ' . &shell . ', when shellslash is set.')  endif  if !has('nvim')    \ && (has('win32') || has('win32unix'))    \ && !has('multi_byte')    return s:err('Vim needs +multi_byte feature on Windows to run shell commands. Enable +iconv for best results.')  endif  command! -nargs=* -bar -bang -complete=customlist,s:names PlugInstall call s:install(<bang>0, [<f-args>])  command! -nargs=* -bar -bang -complete=customlist,s:names PlugUpdate  call s:update(<bang>0, [<f-args>])  command! -nargs=0 -bar -bang PlugClean call s:clean(<bang>0)  command! -nargs=0 -bar PlugUpgrade if s:upgrade() | execute 'source' s:esc(s:me) | endif  command! -nargs=0 -bar PlugStatus  call s:status()  command! -nargs=0 -bar PlugDiff    call s:diff()  command! -nargs=? -bar -bang -complete=file PlugSnapshot call s:snapshot(<bang>0, <f-args>)endfunctionfunction! s:to_a(v)  return type(a:v) == s:TYPE.list ? a:v : [a:v]endfunctionfunction! s:to_s(v)  return type(a:v) == s:TYPE.string ? a:v : join(a:v, "\n") . "\n"endfunctionfunction! s:glob(from, pattern)  return s:lines(globpath(a:from, a:pattern))endfunctionfunction! s:source(from, ...)  let found = 0  for pattern in a:000    for vim in s:glob(a:from, pattern)      execute 'source' s:esc(vim)      let found = 1    endfor  endfor  return foundendfunctionfunction! s:assoc(dict, key, val)  let a:dict[a:key] = add(get(a:dict, a:key, []), a:val)endfunctionfunction! s:ask(message, ...)  call inputsave()  echohl WarningMsg  let answer = input(a:message.(a:0 ? ' (y/N/a) ' : ' (y/N) '))  echohl None  call inputrestore()  echo "\r"  return (a:0 && answer =~? '^a') ? 2 : (answer =~? '^y') ? 1 : 0endfunctionfunction! s:ask_no_interrupt(...)  try    return call('s:ask', a:000)  catch    return 0  endtryendfunctionfunction! s:lazy(plug, opt)  return has_key(a:plug, a:opt) &&        \ (empty(s:to_a(a:plug[a:opt]))         ||        \  !isdirectory(a:plug.dir)             ||        \  len(s:glob(s:rtp(a:plug), 'plugin')) ||        \  len(s:glob(s:rtp(a:plug), 'after/plugin')))endfunctionfunction! plug#end()  if !exists('g:plugs')    return s:err('plug#end() called without calling plug#begin() first')  endif  if exists('#PlugLOD')    augroup PlugLOD      autocmd!    augroup END    augroup! PlugLOD  endif  let lod = { 'ft': {}, 'map': {}, 'cmd': {} }  if exists('g:did_load_filetypes')    filetype off  endif  for name in g:plugs_order    if !has_key(g:plugs, name)      continue    endif    let plug = g:plugs[name]    if get(s:loaded, name, 0) || !s:lazy(plug, 'on') && !s:lazy(plug, 'for')      let s:loaded[name] = 1      continue    endif    if has_key(plug, 'on')      let s:triggers[name] = { 'map': [], 'cmd': [] }      for cmd in s:to_a(plug.on)        if cmd =~? '^<Plug>.\+'          if empty(mapcheck(cmd)) && empty(mapcheck(cmd, 'i'))            call s:assoc(lod.map, cmd, name)          endif          call add(s:triggers[name].map, cmd)        elseif cmd =~# '^[A-Z]'          let cmd = substitute(cmd, '!*$', '', '')          if exists(':'.cmd) != 2            call s:assoc(lod.cmd, cmd, name)          endif          call add(s:triggers[name].cmd, cmd)        else          call s:err('Invalid `on` option: '.cmd.          \ '. Should start with an uppercase letter or `<Plug>`.')        endif      endfor    endif    if has_key(plug, 'for')      let types = s:to_a(plug.for)      if !empty(types)        augroup filetypedetect        call s:source(s:rtp(plug), 'ftdetect/**/*.vim', 'after/ftdetect/**/*.vim')        augroup END      endif      for type in types        call s:assoc(lod.ft, type, name)      endfor    endif  endfor  for [cmd, names] in items(lod.cmd)    execute printf(    \ 'command! -nargs=* -range -bang -complete=file %s call s:lod_cmd(%s, "<bang>", <line1>, <line2>, <q-args>, %s)',    \ cmd, string(cmd), string(names))  endfor  for [map, names] in items(lod.map)    for [mode, map_prefix, key_prefix] in          \ [['i', '<C-O>', ''], ['n', '', ''], ['v', '', 'gv'], ['o', '', '']]      execute printf(      \ '%snoremap <silent> %s %s:<C-U>call <SID>lod_map(%s, %s, %s, "%s")<CR>',      \ mode, map, map_prefix, string(map), string(names), mode != 'i', key_prefix)    endfor  endfor  for [ft, names] in items(lod.ft)    augroup PlugLOD      execute printf('autocmd FileType %s call <SID>lod_ft(%s, %s)',            \ ft, string(ft), string(names))    augroup END  endfor  call s:reorg_rtp()  filetype plugin indent on  if has('vim_starting')    if has('syntax') && !exists('g:syntax_on')      syntax enable    end  else    call s:reload_plugins()  endifendfunctionfunction! s:loaded_names()  return filter(copy(g:plugs_order), 'get(s:loaded, v:val, 0)')endfunctionfunction! s:load_plugin(spec)  call s:source(s:rtp(a:spec), 'plugin/**/*.vim', 'after/plugin/**/*.vim')endfunctionfunction! s:reload_plugins()  for name in s:loaded_names()    call s:load_plugin(g:plugs[name])  endforendfunctionfunction! s:trim(str)  return substitute(a:str, '[\/]\+$', '', '')endfunctionfunction! s:version_requirement(val, min)  for idx in range(0, len(a:min) - 1)    let v = get(a:val, idx, 0)    if     v < a:min[idx] | return 0    elseif v > a:min[idx] | return 1    endif  endfor  return 1endfunctionfunction! s:git_version_requirement(...)  if !exists('s:git_version')    let s:git_version = map(split(split(s:system(['git', '--version']))[2], '\.'), 'str2nr(v:val)')  endif  return s:version_requirement(s:git_version, a:000)endfunctionfunction! s:progress_opt(base)  return a:base && !s:is_win &&        \ s:git_version_requirement(1, 7, 1) ? '--progress' : ''endfunctionfunction! s:rtp(spec)  return s:path(a:spec.dir . get(a:spec, 'rtp', ''))endfunctionif s:is_win  function! s:path(path)    return s:trim(substitute(a:path, '/', '\', 'g'))  endfunction  function! s:dirpath(path)    return s:path(a:path) . '\'  endfunction  function! s:is_local_plug(repo)    return a:repo =~? '^[a-z]:\|^[%~]'  endfunction  " Copied from fzf  function! s:wrap_cmds(cmds)    let cmds = [      \ '@echo off',      \ 'setlocal enabledelayedexpansion']    \ + (type(a:cmds) == type([]) ? a:cmds : [a:cmds])    \ + ['endlocal']    if has('iconv')      if !exists('s:codepage')        let s:codepage = libcallnr('kernel32.dll', 'GetACP', 0)      endif      return map(cmds, printf('iconv(v:val."\r", "%s", "cp%d")', &encoding, s:codepage))    endif    return map(cmds, 'v:val."\r"')  endfunction  function! s:batchfile(cmd)    let batchfile = s:plug_tempname().'.bat'    call writefile(s:wrap_cmds(a:cmd), batchfile)    let cmd = plug#shellescape(batchfile, {'shell': &shell, 'script': 0})    if &shell =~# 'powershell\.exe'      let cmd = '& ' . cmd    endif    return [batchfile, cmd]  endfunctionelse  function! s:path(path)    return s:trim(a:path)  endfunction  function! s:dirpath(path)    return substitute(a:path, '[/\\]*$', '/', '')  endfunction  function! s:is_local_plug(repo)    return a:repo[0] =~ '[/$~]'  endfunctionendiffunction! s:err(msg)  echohl ErrorMsg  echom '[vim-plug] '.a:msg  echohl Noneendfunctionfunction! s:warn(cmd, msg)  echohl WarningMsg  execute a:cmd 'a:msg'  echohl Noneendfunctionfunction! s:esc(path)  return escape(a:path, ' ')endfunctionfunction! s:escrtp(path)  return escape(a:path, ' ,')endfunctionfunction! s:remove_rtp()  for name in s:loaded_names()    let rtp = s:rtp(g:plugs[name])    execute 'set rtp-='.s:escrtp(rtp)    let after = globpath(rtp, 'after')    if isdirectory(after)      execute 'set rtp-='.s:escrtp(after)    endif  endforendfunctionfunction! s:reorg_rtp()  if !empty(s:first_rtp)    execute 'set rtp-='.s:first_rtp    execute 'set rtp-='.s:last_rtp  endif  " &rtp is modified from outside  if exists('s:prtp') && s:prtp !=# &rtp    call s:remove_rtp()    unlet! s:middle  endif  let s:middle = get(s:, 'middle', &rtp)  let rtps     = map(s:loaded_names(), 's:rtp(g:plugs[v:val])')  let afters   = filter(map(copy(rtps), 'globpath(v:val, "after")'), '!empty(v:val)')  let rtp      = join(map(rtps, 'escape(v:val, ",")'), ',')                 \ . ','.s:middle.','                 \ . join(map(afters, 'escape(v:val, ",")'), ',')  let &rtp     = substitute(substitute(rtp, ',,*', ',', 'g'), '^,\|,$', '', 'g')  let s:prtp   = &rtp  if !empty(s:first_rtp)    execute 'set rtp^='.s:first_rtp    execute 'set rtp+='.s:last_rtp  endifendfunctionfunction! s:doautocmd(...)  if exists('#'.join(a:000, '#'))    execute 'doautocmd' ((v:version > 703 || has('patch442')) ? '<nomodeline>' : '') join(a:000)  endifendfunctionfunction! s:dobufread(names)  for name in a:names    let path = s:rtp(g:plugs[name])    for dir in ['ftdetect', 'ftplugin', 'after/ftdetect', 'after/ftplugin']      if len(finddir(dir, path))        if exists('#BufRead')          doautocmd BufRead        endif        return      endif    endfor  endforendfunctionfunction! plug#load(...)  if a:0 == 0    return s:err('Argument missing: plugin name(s) required')  endif  if !exists('g:plugs')    return s:err('plug#begin was not called')  endif  let names = a:0 == 1 && type(a:1) == s:TYPE.list ? a:1 : a:000  let unknowns = filter(copy(names), '!has_key(g:plugs, v:val)')  if !empty(unknowns)    let s = len(unknowns) > 1 ? 's' : ''    return s:err(printf('Unknown plugin%s: %s', s, join(unknowns, ', ')))  end  let unloaded = filter(copy(names), '!get(s:loaded, v:val, 0)')  if !empty(unloaded)    for name in unloaded      call s:lod([name], ['ftdetect', 'after/ftdetect', 'plugin', 'after/plugin'])    endfor    call s:dobufread(unloaded)    return 1  end  return 0endfunctionfunction! s:remove_triggers(name)  if !has_key(s:triggers, a:name)    return  endif  for cmd in s:triggers[a:name].cmd    execute 'silent! delc' cmd  endfor  for map in s:triggers[a:name].map    execute 'silent! unmap' map    execute 'silent! iunmap' map  endfor  call remove(s:triggers, a:name)endfunctionfunction! s:lod(names, types, ...)  for name in a:names    call s:remove_triggers(name)    let s:loaded[name] = 1  endfor  call s:reorg_rtp()  for name in a:names    let rtp = s:rtp(g:plugs[name])    for dir in a:types      call s:source(rtp, dir.'/**/*.vim')    endfor    if a:0      if !s:source(rtp, a:1) && !empty(s:glob(rtp, a:2))        execute 'runtime' a:1      endif      call s:source(rtp, a:2)    endif    call s:doautocmd('User', name)  endforendfunctionfunction! s:lod_ft(pat, names)  let syn = 'syntax/'.a:pat.'.vim'  call s:lod(a:names, ['plugin', 'after/plugin'], syn, 'after/'.syn)  execute 'autocmd! PlugLOD FileType' a:pat  call s:doautocmd('filetypeplugin', 'FileType')  call s:doautocmd('filetypeindent', 'FileType')endfunctionfunction! s:lod_cmd(cmd, bang, l1, l2, args, names)  call s:lod(a:names, ['ftdetect', 'after/ftdetect', 'plugin', 'after/plugin'])  call s:dobufread(a:names)  execute printf('%s%s%s %s', (a:l1 == a:l2 ? '' : (a:l1.','.a:l2)), a:cmd, a:bang, a:args)endfunctionfunction! s:lod_map(map, names, with_prefix, prefix)  call s:lod(a:names, ['ftdetect', 'after/ftdetect', 'plugin', 'after/plugin'])  call s:dobufread(a:names)  let extra = ''  while 1    let c = getchar(0)    if c == 0      break    endif    let extra .= nr2char(c)  endwhile  if a:with_prefix    let prefix = v:count ? v:count : ''    let prefix .= '"'.v:register.a:prefix    if mode(1) == 'no'      if v:operator == 'c'        let prefix = "\<esc>" . prefix      endif      let prefix .= v:operator    endif    call feedkeys(prefix, 'n')  endif  call feedkeys(substitute(a:map, '^<Plug>', "\<Plug>", '') . extra)endfunctionfunction! plug#(repo, ...)  if a:0 > 1    return s:err('Invalid number of arguments (1..2)')  endif  try    let repo = s:trim(a:repo)    let opts = a:0 == 1 ? s:parse_options(a:1) : s:base_spec    let name = get(opts, 'as', s:plug_fnamemodify(repo, ':t:s?\.git$??'))    let spec = extend(s:infer_properties(name, repo), opts)    if !has_key(g:plugs, name)      call add(g:plugs_order, name)    endif    let g:plugs[name] = spec    let s:loaded[name] = get(s:loaded, name, 0)  catch    return s:err(v:exception)  endtryendfunctionfunction! s:parse_options(arg)  let opts = copy(s:base_spec)  let type = type(a:arg)  if type == s:TYPE.string    let opts.tag = a:arg  elseif type == s:TYPE.dict    call extend(opts, a:arg)    if has_key(opts, 'dir')      let opts.dir = s:dirpath(s:plug_expand(opts.dir))    endif  else    throw 'Invalid argument type (expected: string or dictionary)'  endif  return optsendfunctionfunction! s:infer_properties(name, repo)  let repo = a:repo  if s:is_local_plug(repo)    return { 'dir': s:dirpath(s:plug_expand(repo)) }  else    if repo =~ ':'      let uri = repo    else      if repo !~ '/'        throw printf('Invalid argument: %s (implicit `vim-scripts'' expansion is deprecated)', repo)      endif      let fmt = get(g:, 'plug_url_format', 'https://git::@github.com/%s.git')      let uri = printf(fmt, repo)    endif    return { 'dir': s:dirpath(g:plug_home.'/'.a:name), 'uri': uri }  endifendfunctionfunction! s:install(force, names)  call s:update_impl(0, a:force, a:names)endfunctionfunction! s:update(force, names)  call s:update_impl(1, a:force, a:names)endfunctionfunction! plug#helptags()  if !exists('g:plugs')    return s:err('plug#begin was not called')  endif  for spec in values(g:plugs)    let docd = join([s:rtp(spec), 'doc'], '/')    if isdirectory(docd)      silent! execute 'helptags' s:esc(docd)    endif  endfor  return 1endfunctionfunction! s:syntax()  syntax clear  syntax region plug1 start=/\%1l/ end=/\%2l/ contains=plugNumber  syntax region plug2 start=/\%2l/ end=/\%3l/ contains=plugBracket,plugX  syn match plugNumber /[0-9]\+[0-9.]*/ contained  syn match plugBracket /[[\]]/ contained  syn match plugX /x/ contained  syn match plugDash /^-/  syn match plugPlus /^+/  syn match plugStar /^*/  syn match plugMessage /\(^- \)\@<=.*/  syn match plugName /\(^- \)\@<=[^ ]*:/  syn match plugSha /\%(: \)\@<=[0-9a-f]\{4,}$/  syn match plugTag /(tag: [^)]\+)/  syn match plugInstall /\(^+ \)\@<=[^:]*/  syn match plugUpdate /\(^* \)\@<=[^:]*/  syn match plugCommit /^  \X*[0-9a-f]\{7,9} .*/ contains=plugRelDate,plugEdge,plugTag  syn match plugEdge /^  \X\+$/  syn match plugEdge /^  \X*/ contained nextgroup=plugSha  syn match plugSha /[0-9a-f]\{7,9}/ contained  syn match plugRelDate /([^)]*)$/ contained  syn match plugNotLoaded /(not loaded)$/  syn match plugError /^x.*/  syn region plugDeleted start=/^\~ .*/ end=/^\ze\S/  syn match plugH2 /^.*:\n-\+$/  syn keyword Function PlugInstall PlugStatus PlugUpdate PlugClean  hi def link plug1       Title  hi def link plug2       Repeat  hi def link plugH2      Type  hi def link plugX       Exception  hi def link plugBracket Structure  hi def link plugNumber  Number  hi def link plugDash    Special  hi def link plugPlus    Constant  hi def link plugStar    Boolean  hi def link plugMessage Function  hi def link plugName    Label  hi def link plugInstall Function  hi def link plugUpdate  Type  hi def link plugError   Error  hi def link plugDeleted Ignore  hi def link plugRelDate Comment  hi def link plugEdge    PreProc  hi def link plugSha     Identifier  hi def link plugTag     Constant  hi def link plugNotLoaded Commentendfunctionfunction! s:lpad(str, len)  return a:str . repeat(' ', a:len - len(a:str))endfunctionfunction! s:lines(msg)  return split(a:msg, "[\r\n]")endfunctionfunction! s:lastline(msg)  return get(s:lines(a:msg), -1, '')endfunctionfunction! s:new_window()  execute get(g:, 'plug_window', 'vertical topleft new')endfunctionfunction! s:plug_window_exists()  let buflist = tabpagebuflist(s:plug_tab)  return !empty(buflist) && index(buflist, s:plug_buf) >= 0endfunctionfunction! s:switch_in()  if !s:plug_window_exists()    return 0  endif  if winbufnr(0) != s:plug_buf    let s:pos = [tabpagenr(), winnr(), winsaveview()]    execute 'normal!' s:plug_tab.'gt'    let winnr = bufwinnr(s:plug_buf)    execute winnr.'wincmd w'    call add(s:pos, winsaveview())  else    let s:pos = [winsaveview()]  endif  setlocal modifiable  return 1endfunctionfunction! s:switch_out(...)  call winrestview(s:pos[-1])  setlocal nomodifiable  if a:0 > 0    execute a:1  endif  if len(s:pos) > 1    execute 'normal!' s:pos[0].'gt'    execute s:pos[1] 'wincmd w'    call winrestview(s:pos[2])  endifendfunctionfunction! s:finish_bindings()  nnoremap <silent> <buffer> R  :call <SID>retry()<cr>  nnoremap <silent> <buffer> D  :PlugDiff<cr>  nnoremap <silent> <buffer> S  :PlugStatus<cr>  nnoremap <silent> <buffer> U  :call <SID>status_update()<cr>  xnoremap <silent> <buffer> U  :call <SID>status_update()<cr>  nnoremap <silent> <buffer> ]] :silent! call <SID>section('')<cr>  nnoremap <silent> <buffer> [[ :silent! call <SID>section('b')<cr>endfunctionfunction! s:prepare(...)  if empty(s:plug_getcwd())    throw 'Invalid current working directory. Cannot proceed.'  endif  for evar in ['$GIT_DIR', '$GIT_WORK_TREE']    if exists(evar)      throw evar.' detected. Cannot proceed.'    endif  endfor  call s:job_abort()  if s:switch_in()    if b:plug_preview == 1      pc    endif    enew  else    call s:new_window()  endif  nnoremap <silent> <buffer> q  :if b:plug_preview==1<bar>pc<bar>endif<bar>bd<cr>  if a:0 == 0    call s:finish_bindings()  endif  let b:plug_preview = -1  let s:plug_tab = tabpagenr()  let s:plug_buf = winbufnr(0)  call s:assign_name()  for k in ['<cr>', 'L', 'o', 'X', 'd', 'dd']    execute 'silent! unmap <buffer>' k  endfor  setlocal buftype=nofile bufhidden=wipe nobuflisted nolist noswapfile nowrap cursorline modifiable nospell  if exists('+colorcolumn')    setlocal colorcolumn=  endif  setf vim-plug  if exists('g:syntax_on')    call s:syntax()  endifendfunctionfunction! s:assign_name()  " Assign buffer name  let prefix = '[Plugins]'  let name   = prefix  let idx    = 2  while bufexists(name)    let name = printf('%s (%s)', prefix, idx)    let idx = idx + 1  endwhile  silent! execute 'f' fnameescape(name)endfunctionfunction! s:chsh(swap)  let prev = [&shell, &shellcmdflag, &shellredir]  if !s:is_win    set shell=sh  endif  if a:swap    if &shell =~# 'powershell\.exe' || &shell =~# 'pwsh$'      let &shellredir = '2>&1 | Out-File -Encoding UTF8 %s'    elseif &shell =~# 'sh' || &shell =~# 'cmd\.exe'      set shellredir=>%s\ 2>&1    endif  endif  return prevendfunctionfunction! s:bang(cmd, ...)  let batchfile = ''  try    let [sh, shellcmdflag, shrd] = s:chsh(a:0)    " FIXME: Escaping is incomplete. We could use shellescape with eval,    "        but it won't work on Windows.    let cmd = a:0 ? s:with_cd(a:cmd, a:1) : a:cmd    if s:is_win      let [batchfile, cmd] = s:batchfile(cmd)    endif    let g:_plug_bang = (s:is_win && has('gui_running') ? 'silent ' : '').'!'.escape(cmd, '#!%')    execute "normal! :execute g:_plug_bang\<cr>\<cr>"  finally    unlet g:_plug_bang    let [&shell, &shellcmdflag, &shellredir] = [sh, shellcmdflag, shrd]    if s:is_win && filereadable(batchfile)      call delete(batchfile)    endif  endtry  return v:shell_error ? 'Exit status: ' . v:shell_error : ''endfunctionfunction! s:regress_bar()  let bar = substitute(getline(2)[1:-2], '.*\zs=', 'x', '')  call s:progress_bar(2, bar, len(bar))endfunctionfunction! s:is_updated(dir)  return !empty(s:system_chomp(['git', 'log', '--pretty=format:%h', 'HEAD...HEAD@{1}'], a:dir))endfunctionfunction! s:do(pull, force, todo)  for [name, spec] in items(a:todo)    if !isdirectory(spec.dir)      continue    endif    let installed = has_key(s:update.new, name)    let updated = installed ? 0 :      \ (a:pull && index(s:update.errors, name) < 0 && s:is_updated(spec.dir))    if a:force || installed || updated      execute 'cd' s:esc(spec.dir)      call append(3, '- Post-update hook for '. name .' ... ')      let error = ''      let type = type(spec.do)      if type == s:TYPE.string        if spec.do[0] == ':'          if !get(s:loaded, name, 0)            let s:loaded[name] = 1            call s:reorg_rtp()          endif          call s:load_plugin(spec)          try            execute spec.do[1:]          catch            let error = v:exception          endtry          if !s:plug_window_exists()            cd -            throw 'Warning: vim-plug was terminated by the post-update hook of '.name          endif        else          let error = s:bang(spec.do)        endif      elseif type == s:TYPE.funcref        try          let status = installed ? 'installed' : (updated ? 'updated' : 'unchanged')          call spec.do({ 'name': name, 'status': status, 'force': a:force })        catch          let error = v:exception        endtry      else        let error = 'Invalid hook type'      endif      call s:switch_in()      call setline(4, empty(error) ? (getline(4) . 'OK')                                 \ : ('x' . getline(4)[1:] . error))      if !empty(error)        call add(s:update.errors, name)        call s:regress_bar()      endif      cd -    endif  endforendfunctionfunction! s:hash_match(a, b)  return stridx(a:a, a:b) == 0 || stridx(a:b, a:a) == 0endfunctionfunction! s:checkout(spec)  let sha = a:spec.commit  let output = s:system(['git', 'rev-parse', 'HEAD'], a:spec.dir)  if !v:shell_error && !s:hash_match(sha, s:lines(output)[0])    let output = s:system(          \ 'git fetch --depth 999999 && git checkout '.plug#shellescape(sha).' --', a:spec.dir)  endif  return outputendfunctionfunction! s:finish(pull)  let new_frozen = len(filter(keys(s:update.new), 'g:plugs[v:val].frozen'))  if new_frozen    let s = new_frozen > 1 ? 's' : ''    call append(3, printf('- Installed %d frozen plugin%s', new_frozen, s))  endif  call append(3, '- Finishing ... ') | 4  redraw  call plug#helptags()  call plug#end()  call setline(4, getline(4) . 'Done!')  redraw  let msgs = []  if !empty(s:update.errors)    call add(msgs, "Press 'R' to retry.")  endif  if a:pull && len(s:update.new) < len(filter(getline(5, '$'),                \ "v:val =~ '^- ' && v:val !~# 'Already up.to.date'"))    call add(msgs, "Press 'D' to see the updated changes.")  endif  echo join(msgs, ' ')  call s:finish_bindings()endfunctionfunction! s:retry()  if empty(s:update.errors)    return  endif  echo  call s:update_impl(s:update.pull, s:update.force,        \ extend(copy(s:update.errors), [s:update.threads]))endfunctionfunction! s:is_managed(name)  return has_key(g:plugs[a:name], 'uri')endfunctionfunction! s:names(...)  return sort(filter(keys(g:plugs), 'stridx(v:val, a:1) == 0 && s:is_managed(v:val)'))endfunctionfunction! s:check_ruby()  silent! ruby require 'thread'; VIM::command("let g:plug_ruby = '#{RUBY_VERSION}'")  if !exists('g:plug_ruby')    redraw!    return s:warn('echom', 'Warning: Ruby interface is broken')  endif  let ruby_version = split(g:plug_ruby, '\.')  unlet g:plug_ruby  return s:version_requirement(ruby_version, [1, 8, 7])endfunctionfunction! s:update_impl(pull, force, args) abort  let sync = index(a:args, '--sync') >= 0 || has('vim_starting')  let args = filter(copy(a:args), 'v:val != "--sync"')  let threads = (len(args) > 0 && args[-1] =~ '^[1-9][0-9]*$') ?                  \ remove(args, -1) : get(g:, 'plug_threads', 16)  let managed = filter(copy(g:plugs), 's:is_managed(v:key)')  let todo = empty(args) ? filter(managed, '!v:val.frozen || !isdirectory(v:val.dir)') :                         \ filter(managed, 'index(args, v:key) >= 0')  if empty(todo)    return s:warn('echo', 'No plugin to '. (a:pull ? 'update' : 'install'))  endif  if !s:is_win && s:git_version_requirement(2, 3)    let s:git_terminal_prompt = exists('$GIT_TERMINAL_PROMPT') ? $GIT_TERMINAL_PROMPT : ''    let $GIT_TERMINAL_PROMPT = 0    for plug in values(todo)      let plug.uri = substitute(plug.uri,            \ '^https://git::@github\.com', 'https://github.com', '')    endfor  endif  if !isdirectory(g:plug_home)    try      call mkdir(g:plug_home, 'p')    catch      return s:err(printf('Invalid plug directory: %s. '.              \ 'Try to call plug#begin with a valid directory', g:plug_home))    endtry  endif  if has('nvim') && !exists('*jobwait') && threads > 1    call s:warn('echom', '[vim-plug] Update Neovim for parallel installer')  endif  let use_job = s:nvim || s:vim8  let python = (has('python') || has('python3')) && !use_job  let ruby = has('ruby') && !use_job && (v:version >= 703 || v:version == 702 && has('patch374')) && !(s:is_win && has('gui_running')) && threads > 1 && s:check_ruby()  let s:update = {    \ 'start':   reltime(),    \ 'all':     todo,    \ 'todo':    copy(todo),    \ 'errors':  [],    \ 'pull':    a:pull,    \ 'force':   a:force,    \ 'new':     {},    \ 'threads': (python || ruby || use_job) ? min([len(todo), threads]) : 1,    \ 'bar':     '',    \ 'fin':     0  \ }  call s:prepare(1)  call append(0, ['', ''])  normal! 2G  silent! redraw  let s:clone_opt = []  if get(g:, 'plug_shallow', 1)    call extend(s:clone_opt, ['--depth', '1'])    if s:git_version_requirement(1, 7, 10)      call add(s:clone_opt, '--no-single-branch')    endif  endif  if has('win32unix') || has('wsl')    call extend(s:clone_opt, ['-c', 'core.eol=lf', '-c', 'core.autocrlf=input'])  endif  let s:submodule_opt = s:git_version_requirement(2, 8) ? ' --jobs='.threads : ''  " Python version requirement (>= 2.7)  if python && !has('python3') && !ruby && !use_job && s:update.threads > 1    redir => pyv    silent python import platform; print platform.python_version()    redir END    let python = s:version_requirement(          \ map(split(split(pyv)[0], '\.'), 'str2nr(v:val)'), [2, 6])  endif  if (python || ruby) && s:update.threads > 1    try      let imd = &imd      if s:mac_gui        set noimd      endif      if ruby        call s:update_ruby()      else        call s:update_python()      endif    catch      let lines = getline(4, '$')      let printed = {}      silent! 4,$d _      for line in lines        let name = s:extract_name(line, '.', '')        if empty(name) || !has_key(printed, name)          call append('$', line)          if !empty(name)            let printed[name] = 1            if line[0] == 'x' && index(s:update.errors, name) < 0              call add(s:update.errors, name)            end          endif        endif      endfor    finally      let &imd = imd      call s:update_finish()    endtry  else    call s:update_vim()    while use_job && sync      sleep 100m      if s:update.fin        break      endif    endwhile  endifendfunctionfunction! s:log4(name, msg)  call setline(4, printf('- %s (%s)', a:msg, a:name))  redrawendfunctionfunction! s:update_finish()  if exists('s:git_terminal_prompt')    let $GIT_TERMINAL_PROMPT = s:git_terminal_prompt  endif  if s:switch_in()    call append(3, '- Updating ...') | 4    for [name, spec] in items(filter(copy(s:update.all), 'index(s:update.errors, v:key) < 0 && (s:update.force || s:update.pull || has_key(s:update.new, v:key))'))      let [pos, _] = s:logpos(name)      if !pos        continue      endif      if has_key(spec, 'commit')        call s:log4(name, 'Checking out '.spec.commit)        let out = s:checkout(spec)      elseif has_key(spec, 'tag')        let tag = spec.tag        if tag =~ '\*'          let tags = s:lines(s:system('git tag --list '.plug#shellescape(tag).' --sort -version:refname 2>&1', spec.dir))          if !v:shell_error && !empty(tags)            let tag = tags[0]            call s:log4(name, printf('Latest tag for %s -> %s', spec.tag, tag))            call append(3, '')          endif        endif        call s:log4(name, 'Checking out '.tag)        let out = s:system('git checkout -q '.plug#shellescape(tag).' -- 2>&1', spec.dir)      else        let branch = get(spec, 'branch', 'master')        call s:log4(name, 'Merging origin/'.s:esc(branch))        let out = s:system('git checkout -q '.plug#shellescape(branch).' -- 2>&1'              \. (has_key(s:update.new, name) ? '' : ('&& git merge --ff-only '.plug#shellescape('origin/'.branch).' 2>&1')), spec.dir)      endif      if !v:shell_error && filereadable(spec.dir.'/.gitmodules') &&            \ (s:update.force || has_key(s:update.new, name) || s:is_updated(spec.dir))        call s:log4(name, 'Updating submodules. This may take a while.')        let out .= s:bang('git submodule update --init --recursive'.s:submodule_opt.' 2>&1', spec.dir)      endif      let msg = s:format_message(v:shell_error ? 'x': '-', name, out)      if v:shell_error        call add(s:update.errors, name)        call s:regress_bar()        silent execute pos 'd _'        call append(4, msg) | 4      elseif !empty(out)        call setline(pos, msg[0])      endif      redraw    endfor    silent 4 d _    try      call s:do(s:update.pull, s:update.force, filter(copy(s:update.all), 'index(s:update.errors, v:key) < 0 && has_key(v:val, "do")'))    catch      call s:warn('echom', v:exception)      call s:warn('echo', '')      return    endtry    call s:finish(s:update.pull)    call setline(1, 'Updated. Elapsed time: ' . split(reltimestr(reltime(s:update.start)))[0] . ' sec.')    call s:switch_out('normal! gg')  endifendfunctionfunction! s:job_abort()  if (!s:nvim && !s:vim8) || !exists('s:jobs')    return  endif  for [name, j] in items(s:jobs)    if s:nvim      silent! call jobstop(j.jobid)    elseif s:vim8      silent! call job_stop(j.jobid)    endif    if j.new      call s:rm_rf(g:plugs[name].dir)    endif  endfor  let s:jobs = {}endfunctionfunction! s:last_non_empty_line(lines)  let len = len(a:lines)  for idx in range(len)    let line = a:lines[len-idx-1]    if !empty(line)      return line    endif  endfor  return ''endfunctionfunction! s:job_out_cb(self, data) abort  let self = a:self  let data = remove(self.lines, -1) . a:data  let lines = map(split(data, "\n", 1), 'split(v:val, "\r", 1)[-1]')  call extend(self.lines, lines)  " To reduce the number of buffer updates  let self.tick = get(self, 'tick', -1) + 1  if !self.running || self.tick % len(s:jobs) == 0    let bullet = self.running ? (self.new ? '+' : '*') : (self.error ? 'x' : '-')    let result = self.error ? join(self.lines, "\n") : s:last_non_empty_line(self.lines)    call s:log(bullet, self.name, result)  endifendfunctionfunction! s:job_exit_cb(self, data) abort  let a:self.running = 0  let a:self.error = a:data != 0  call s:reap(a:self.name)  call s:tick()endfunctionfunction! s:job_cb(fn, job, ch, data)  if !s:plug_window_exists() " plug window closed    return s:job_abort()  endif  call call(a:fn, [a:job, a:data])endfunctionfunction! s:nvim_cb(job_id, data, event) dict abort  return (a:event == 'stdout' || a:event == 'stderr') ?    \ s:job_cb('s:job_out_cb',  self, 0, join(a:data, "\n")) :    \ s:job_cb('s:job_exit_cb', self, 0, a:data)endfunctionfunction! s:spawn(name, cmd, opts)  let job = { 'name': a:name, 'running': 1, 'error': 0, 'lines': [''],            \ 'new': get(a:opts, 'new', 0) }  let s:jobs[a:name] = job  if s:nvim    if has_key(a:opts, 'dir')      let job.cwd = a:opts.dir    endif    let argv = a:cmd    call extend(job, {    \ 'on_stdout': function('s:nvim_cb'),    \ 'on_stderr': function('s:nvim_cb'),    \ 'on_exit':   function('s:nvim_cb'),    \ })    let jid = s:plug_call('jobstart', argv, job)    if jid > 0      let job.jobid = jid    else      let job.running = 0      let job.error   = 1      let job.lines   = [jid < 0 ? argv[0].' is not executable' :            \ 'Invalid arguments (or job table is full)']    endif  elseif s:vim8    let cmd = join(map(copy(a:cmd), 'plug#shellescape(v:val, {"script": 0})'))    if has_key(a:opts, 'dir')      let cmd = s:with_cd(cmd, a:opts.dir, 0)    endif    let argv = s:is_win ? ['cmd', '/s', '/c', '"'.cmd.'"'] : ['sh', '-c', cmd]    let jid = job_start(s:is_win ? join(argv, ' ') : argv, {    \ 'out_cb':   function('s:job_cb', ['s:job_out_cb',  job]),    \ 'err_cb':   function('s:job_cb', ['s:job_out_cb',  job]),    \ 'exit_cb':  function('s:job_cb', ['s:job_exit_cb', job]),    \ 'err_mode': 'raw',    \ 'out_mode': 'raw'    \})    if job_status(jid) == 'run'      let job.jobid = jid    else      let job.running = 0      let job.error   = 1      let job.lines   = ['Failed to start job']    endif  else    let job.lines = s:lines(call('s:system', has_key(a:opts, 'dir') ? [a:cmd, a:opts.dir] : [a:cmd]))    let job.error = v:shell_error != 0    let job.running = 0  endifendfunctionfunction! s:reap(name)  let job = s:jobs[a:name]  if job.error    call add(s:update.errors, a:name)  elseif get(job, 'new', 0)    let s:update.new[a:name] = 1  endif  let s:update.bar .= job.error ? 'x' : '='  let bullet = job.error ? 'x' : '-'  let result = job.error ? join(job.lines, "\n") : s:last_non_empty_line(job.lines)  call s:log(bullet, a:name, empty(result) ? 'OK' : result)  call s:bar()  call remove(s:jobs, a:name)endfunctionfunction! s:bar()  if s:switch_in()    let total = len(s:update.all)    call setline(1, (s:update.pull ? 'Updating' : 'Installing').          \ ' plugins ('.len(s:update.bar).'/'.total.')')    call s:progress_bar(2, s:update.bar, total)    call s:switch_out()  endifendfunctionfunction! s:logpos(name)  let max = line('$')  for i in range(4, max > 4 ? max : 4)    if getline(i) =~# '^[-+x*] '.a:name.':'      for j in range(i + 1, max > 5 ? max : 5)        if getline(j) !~ '^ '          return [i, j - 1]        endif      endfor      return [i, i]    endif  endfor  return [0, 0]endfunctionfunction! s:log(bullet, name, lines)  if s:switch_in()    let [b, e] = s:logpos(a:name)    if b > 0      silent execute printf('%d,%d d _', b, e)      if b > winheight('.')        let b = 4      endif    else      let b = 4    endif    " FIXME For some reason, nomodifiable is set after :d in vim8    setlocal modifiable    call append(b - 1, s:format_message(a:bullet, a:name, a:lines))    call s:switch_out()  endifendfunctionfunction! s:update_vim()  let s:jobs = {}  call s:bar()  call s:tick()endfunctionfunction! s:tick()  let pull = s:update.pull  let prog = s:progress_opt(s:nvim || s:vim8)while 1 " Without TCO, Vim stack is bound to explode  if empty(s:update.todo)    if empty(s:jobs) && !s:update.fin      call s:update_finish()      let s:update.fin = 1    endif    return  endif  let name = keys(s:update.todo)[0]  let spec = remove(s:update.todo, name)  let new  = empty(globpath(spec.dir, '.git', 1))  call s:log(new ? '+' : '*', name, pull ? 'Updating ...' : 'Installing ...')  redraw  let has_tag = has_key(spec, 'tag')  if !new    let [error, _] = s:git_validate(spec, 0)    if empty(error)      if pull        let cmd = ['git', 'fetch']        if has_tag && !empty(globpath(spec.dir, '.git/shallow'))          call extend(cmd, ['--depth', '99999999'])        endif        if !empty(prog)          call add(cmd, prog)        endif        call s:spawn(name, cmd, { 'dir': spec.dir })      else        let s:jobs[name] = { 'running': 0, 'lines': ['Already installed'], 'error': 0 }      endif    else      let s:jobs[name] = { 'running': 0, 'lines': s:lines(error), 'error': 1 }    endif  else    let cmd = ['git', 'clone']    if !has_tag      call extend(cmd, s:clone_opt)    endif    if !empty(prog)      call add(cmd, prog)    endif    call s:spawn(name, extend(cmd, [spec.uri, s:trim(spec.dir)]), { 'new': 1 })  endif  if !s:jobs[name].running    call s:reap(name)  endif  if len(s:jobs) >= s:update.threads    break  endifendwhileendfunctionfunction! s:update_python()let py_exe = has('python') ? 'python' : 'python3'execute py_exe "<< EOF"import datetimeimport functoolsimport ostry:  import queueexcept ImportError:  import Queue as queueimport randomimport reimport shutilimport signalimport subprocessimport tempfileimport threading as thrimport timeimport tracebackimport vimG_NVIM = vim.eval("has('nvim')") == '1'G_PULL = vim.eval('s:update.pull') == '1'G_RETRIES = int(vim.eval('get(g:, "plug_retries", 2)')) + 1G_TIMEOUT = int(vim.eval('get(g:, "plug_timeout", 60)'))G_CLONE_OPT = ' '.join(vim.eval('s:clone_opt'))G_PROGRESS = vim.eval('s:progress_opt(1)')G_LOG_PROB = 1.0 / int(vim.eval('s:update.threads'))G_STOP = thr.Event()G_IS_WIN = vim.eval('s:is_win') == '1'class PlugError(Exception):  def __init__(self, msg):    self.msg = msgclass CmdTimedOut(PlugError):  passclass CmdFailed(PlugError):  passclass InvalidURI(PlugError):  passclass Action(object):  INSTALL, UPDATE, ERROR, DONE = ['+', '*', 'x', '-']class Buffer(object):  def __init__(self, lock, num_plugs, is_pull):    self.bar = ''    self.event = 'Updating' if is_pull else 'Installing'    self.lock = lock    self.maxy = int(vim.eval('winheight(".")'))    self.num_plugs = num_plugs  def __where(self, name):    """ Find first line with name in current buffer. Return line num. """    found, lnum = False, 0    matcher = re.compile('^[-+x*] {0}:'.format(name))    for line in vim.current.buffer:      if matcher.search(line) is not None:        found = True        break      lnum += 1    if not found:      lnum = -1    return lnum  def header(self):    curbuf = vim.current.buffer    curbuf[0] = self.event + ' plugins ({0}/{1})'.format(len(self.bar), self.num_plugs)    num_spaces = self.num_plugs - len(self.bar)    curbuf[1] = '[{0}{1}]'.format(self.bar, num_spaces * ' ')    with self.lock:      vim.command('normal! 2G')      vim.command('redraw')  def write(self, action, name, lines):    first, rest = lines[0], lines[1:]    msg = ['{0} {1}{2}{3}'.format(action, name, ': ' if first else '', first)]    msg.extend(['    ' + line for line in rest])    try:      if action == Action.ERROR:        self.bar += 'x'        vim.command("call add(s:update.errors, '{0}')".format(name))      elif action == Action.DONE:        self.bar += '='      curbuf = vim.current.buffer      lnum = self.__where(name)      if lnum != -1: # Found matching line num        del curbuf[lnum]        if lnum > self.maxy and action in set([Action.INSTALL, Action.UPDATE]):          lnum = 3      else:        lnum = 3      curbuf.append(msg, lnum)      self.header()    except vim.error:      passclass Command(object):  CD = 'cd /d' if G_IS_WIN else 'cd'  def __init__(self, cmd, cmd_dir=None, timeout=60, cb=None, clean=None):    self.cmd = cmd    if cmd_dir:      self.cmd = '{0} {1} && {2}'.format(Command.CD, cmd_dir, self.cmd)    self.timeout = timeout    self.callback = cb if cb else (lambda msg: None)    self.clean = clean if clean else (lambda: None)    self.proc = None  @property  def alive(self):    """ Returns true only if command still running. """    return self.proc and self.proc.poll() is None  def execute(self, ntries=3):    """ Execute the command with ntries if CmdTimedOut.        Returns the output of the command if no Exception.    """    attempt, finished, limit = 0, False, self.timeout    while not finished:      try:        attempt += 1        result = self.try_command()        finished = True        return result      except CmdTimedOut:        if attempt != ntries:          self.notify_retry()          self.timeout += limit        else:          raise  def notify_retry(self):    """ Retry required for command, notify user. """    for count in range(3, 0, -1):      if G_STOP.is_set():        raise KeyboardInterrupt      msg = 'Timeout. Will retry in {0} second{1} ...'.format(            count, 's' if count != 1 else '')      self.callback([msg])      time.sleep(1)    self.callback(['Retrying ...'])  def try_command(self):    """ Execute a cmd & poll for callback. Returns list of output.        Raises CmdFailed   -> return code for Popen isn't 0        Raises CmdTimedOut -> command exceeded timeout without new output    """    first_line = True    try:      tfile = tempfile.NamedTemporaryFile(mode='w+b')      preexec_fn = not G_IS_WIN and os.setsid or None      self.proc = subprocess.Popen(self.cmd, stdout=tfile,                                   stderr=subprocess.STDOUT,                                   stdin=subprocess.PIPE, shell=True,                                   preexec_fn=preexec_fn)      thrd = thr.Thread(target=(lambda proc: proc.wait()), args=(self.proc,))      thrd.start()      thread_not_started = True      while thread_not_started:        try:          thrd.join(0.1)          thread_not_started = False        except RuntimeError:          pass      while self.alive:        if G_STOP.is_set():          raise KeyboardInterrupt        if first_line or random.random() < G_LOG_PROB:          first_line = False          line = '' if G_IS_WIN else nonblock_read(tfile.name)          if line:            self.callback([line])        time_diff = time.time() - os.path.getmtime(tfile.name)        if time_diff > self.timeout:          raise CmdTimedOut(['Timeout!'])        thrd.join(0.5)      tfile.seek(0)      result = [line.decode('utf-8', 'replace').rstrip() for line in tfile]      if self.proc.returncode != 0:        raise CmdFailed([''] + result)      return result    except:      self.terminate()      raise  def terminate(self):    """ Terminate process and cleanup. """    if self.alive:      if G_IS_WIN:        os.kill(self.proc.pid, signal.SIGINT)      else:        os.killpg(self.proc.pid, signal.SIGTERM)    self.clean()class Plugin(object):  def __init__(self, name, args, buf_q, lock):    self.name = name    self.args = args    self.buf_q = buf_q    self.lock = lock    self.tag = args.get('tag', 0)  def manage(self):    try:      if os.path.exists(self.args['dir']):        self.update()      else:        self.install()        with self.lock:          thread_vim_command("let s:update.new['{0}'] = 1".format(self.name))    except PlugError as exc:      self.write(Action.ERROR, self.name, exc.msg)    except KeyboardInterrupt:      G_STOP.set()      self.write(Action.ERROR, self.name, ['Interrupted!'])    except:      # Any exception except those above print stack trace      msg = 'Trace:\n{0}'.format(traceback.format_exc().rstrip())      self.write(Action.ERROR, self.name, msg.split('\n'))      raise  def install(self):    target = self.args['dir']    if target[-1] == '\\':      target = target[0:-1]    def clean(target):      def _clean():        try:          shutil.rmtree(target)        except OSError:          pass      return _clean    self.write(Action.INSTALL, self.name, ['Installing ...'])    callback = functools.partial(self.write, Action.INSTALL, self.name)    cmd = 'git clone {0} {1} {2} {3} 2>&1'.format(          '' if self.tag else G_CLONE_OPT, G_PROGRESS, self.args['uri'],          esc(target))    com = Command(cmd, None, G_TIMEOUT, callback, clean(target))    result = com.execute(G_RETRIES)    self.write(Action.DONE, self.name, result[-1:])  def repo_uri(self):    cmd = 'git rev-parse --abbrev-ref HEAD 2>&1 && git config -f .git/config remote.origin.url'    command = Command(cmd, self.args['dir'], G_TIMEOUT,)    result = command.execute(G_RETRIES)    return result[-1]  def update(self):    actual_uri = self.repo_uri()    expect_uri = self.args['uri']    regex = re.compile(r'^(?:\w+://)?(?:[^@/]*@)?([^:/]*(?::[0-9]*)?)[:/](.*?)(?:\.git)?/?$')    ma = regex.match(actual_uri)    mb = regex.match(expect_uri)    if ma is None or mb is None or ma.groups() != mb.groups():      msg = ['',             'Invalid URI: {0}'.format(actual_uri),             'Expected     {0}'.format(expect_uri),             'PlugClean required.']      raise InvalidURI(msg)    if G_PULL:      self.write(Action.UPDATE, self.name, ['Updating ...'])      callback = functools.partial(self.write, Action.UPDATE, self.name)      fetch_opt = '--depth 99999999' if self.tag and os.path.isfile(os.path.join(self.args['dir'], '.git/shallow')) else ''      cmd = 'git fetch {0} {1} 2>&1'.format(fetch_opt, G_PROGRESS)      com = Command(cmd, self.args['dir'], G_TIMEOUT, callback)      result = com.execute(G_RETRIES)      self.write(Action.DONE, self.name, result[-1:])    else:      self.write(Action.DONE, self.name, ['Already installed'])  def write(self, action, name, msg):    self.buf_q.put((action, name, msg))class PlugThread(thr.Thread):  def __init__(self, tname, args):    super(PlugThread, self).__init__()    self.tname = tname    self.args = args  def run(self):    thr.current_thread().name = self.tname    buf_q, work_q, lock = self.args    try:      while not G_STOP.is_set():        name, args = work_q.get_nowait()        plug = Plugin(name, args, buf_q, lock)        plug.manage()        work_q.task_done()    except queue.Empty:      passclass RefreshThread(thr.Thread):  def __init__(self, lock):    super(RefreshThread, self).__init__()    self.lock = lock    self.running = True  def run(self):    while self.running:      with self.lock:        thread_vim_command('noautocmd normal! a')      time.sleep(0.33)  def stop(self):    self.running = Falseif G_NVIM:  def thread_vim_command(cmd):    vim.session.threadsafe_call(lambda: vim.command(cmd))else:  def thread_vim_command(cmd):    vim.command(cmd)def esc(name):  return '"' + name.replace('"', '\"') + '"'def nonblock_read(fname):  """ Read a file with nonblock flag. Return the last line. """  fread = os.open(fname, os.O_RDONLY | os.O_NONBLOCK)  buf = os.read(fread, 100000).decode('utf-8', 'replace')  os.close(fread)  line = buf.rstrip('\r\n')  left = max(line.rfind('\r'), line.rfind('\n'))  if left != -1:    left += 1    line = line[left:]  return linedef main():  thr.current_thread().name = 'main'  nthreads = int(vim.eval('s:update.threads'))  plugs = vim.eval('s:update.todo')  mac_gui = vim.eval('s:mac_gui') == '1'  lock = thr.Lock()  buf = Buffer(lock, len(plugs), G_PULL)  buf_q, work_q = queue.Queue(), queue.Queue()  for work in plugs.items():    work_q.put(work)  start_cnt = thr.active_count()  for num in range(nthreads):    tname = 'PlugT-{0:02}'.format(num)    thread = PlugThread(tname, (buf_q, work_q, lock))    thread.start()  if mac_gui:    rthread = RefreshThread(lock)    rthread.start()  while not buf_q.empty() or thr.active_count() != start_cnt:    try:      action, name, msg = buf_q.get(True, 0.25)      buf.write(action, name, ['OK'] if not msg else msg)      buf_q.task_done()    except queue.Empty:      pass    except KeyboardInterrupt:      G_STOP.set()  if mac_gui:    rthread.stop()    rthread.join()main()EOFendfunctionfunction! s:update_ruby()  ruby << EOF  module PlugStream    SEP = ["\r", "\n", nil]    def get_line      buffer = ''      loop do        char = readchar rescue return        if SEP.include? char.chr          buffer << $/          break        else          buffer << char        end      end      buffer    end  end unless defined?(PlugStream)  def esc arg    %["#{arg.gsub('"', '\"')}"]  end  def killall pid    pids = [pid]    if /mswin|mingw|bccwin/ =~ RUBY_PLATFORM      pids.each { |pid| Process.kill 'INT', pid.to_i rescue nil }    else      unless `which pgrep 2> /dev/null`.empty?        children = pids        until children.empty?          children = children.map { |pid|            `pgrep -P #{pid}`.lines.map { |l| l.chomp }          }.flatten          pids += children        end      end      pids.each { |pid| Process.kill 'TERM', pid.to_i rescue nil }    end  end  def compare_git_uri a, b    regex = %r{^(?:\w+://)?(?:[^@/]*@)?([^:/]*(?::[0-9]*)?)[:/](.*?)(?:\.git)?/?$}    regex.match(a).to_a.drop(1) == regex.match(b).to_a.drop(1)  end  require 'thread'  require 'fileutils'  require 'timeout'  running = true  iswin = VIM::evaluate('s:is_win').to_i == 1  pull  = VIM::evaluate('s:update.pull').to_i == 1  base  = VIM::evaluate('g:plug_home')  all   = VIM::evaluate('s:update.todo')  limit = VIM::evaluate('get(g:, "plug_timeout", 60)')  tries = VIM::evaluate('get(g:, "plug_retries", 2)') + 1  nthr  = VIM::evaluate('s:update.threads').to_i  maxy  = VIM::evaluate('winheight(".")').to_i  vim7  = VIM::evaluate('v:version').to_i <= 703 && RUBY_PLATFORM =~ /darwin/  cd    = iswin ? 'cd /d' : 'cd'  tot   = VIM::evaluate('len(s:update.todo)') || 0  bar   = ''  skip  = 'Already installed'  mtx   = Mutex.new  take1 = proc { mtx.synchronize { running && all.shift } }  logh  = proc {    cnt = bar.length    $curbuf[1] = "#{pull ? 'Updating' : 'Installing'} plugins (#{cnt}/#{tot})"    $curbuf[2] = '[' + bar.ljust(tot) + ']'    VIM::command('normal! 2G')    VIM::command('redraw')  }  where = proc { |name| (1..($curbuf.length)).find { |l| $curbuf[l] =~ /^[-+x*] #{name}:/ } }  log   = proc { |name, result, type|    mtx.synchronize do      ing  = ![true, false].include?(type)      bar += type ? '=' : 'x' unless ing      b = case type          when :install  then '+' when :update then '*'          when true, nil then '-' else            VIM::command("call add(s:update.errors, '#{name}')")            'x'          end      result =        if type || type.nil?          ["#{b} #{name}: #{result.lines.to_a.last || 'OK'}"]        elsif result =~ /^Interrupted|^Timeout/          ["#{b} #{name}: #{result}"]        else          ["#{b} #{name}"] + result.lines.map { |l| "    " << l }        end      if lnum = where.call(name)        $curbuf.delete lnum        lnum = 4 if ing && lnum > maxy      end      result.each_with_index do |line, offset|        $curbuf.append((lnum || 4) - 1 + offset, line.gsub(/\e\[./, '').chomp)      end      logh.call    end  }  bt = proc { |cmd, name, type, cleanup|    tried = timeout = 0    begin      tried += 1      timeout += limit      fd = nil      data = ''      if iswin        Timeout::timeout(timeout) do          tmp = VIM::evaluate('tempname()')          system("(#{cmd}) > #{tmp}")          data = File.read(tmp).chomp          File.unlink tmp rescue nil        end      else        fd = IO.popen(cmd).extend(PlugStream)        first_line = true        log_prob = 1.0 / nthr        while line = Timeout::timeout(timeout) { fd.get_line }          data << line          log.call name, line.chomp, type if name && (first_line || rand < log_prob)          first_line = false        end        fd.close      end      [$? == 0, data.chomp]    rescue Timeout::Error, Interrupt => e      if fd && !fd.closed?        killall fd.pid        fd.close      end      cleanup.call if cleanup      if e.is_a?(Timeout::Error) && tried < tries        3.downto(1) do |countdown|          s = countdown > 1 ? 's' : ''          log.call name, "Timeout. Will retry in #{countdown} second#{s} ...", type          sleep 1        end        log.call name, 'Retrying ...', type        retry      end      [false, e.is_a?(Interrupt) ? "Interrupted!" : "Timeout!"]    end  }  main = Thread.current  threads = []  watcher = Thread.new {    if vim7      while VIM::evaluate('getchar(1)')        sleep 0.1      end    else      require 'io/console' # >= Ruby 1.9      nil until IO.console.getch == 3.chr    end    mtx.synchronize do      running = false      threads.each { |t| t.raise Interrupt } unless vim7    end    threads.each { |t| t.join rescue nil }    main.kill  }  refresh = Thread.new {    while true      mtx.synchronize do        break unless running        VIM::command('noautocmd normal! a')      end      sleep 0.2    end  } if VIM::evaluate('s:mac_gui') == 1  clone_opt = VIM::evaluate('s:clone_opt').join(' ')  progress = VIM::evaluate('s:progress_opt(1)')  nthr.times do    mtx.synchronize do      threads << Thread.new {        while pair = take1.call          name = pair.first          dir, uri, tag = pair.last.values_at *%w[dir uri tag]          exists = File.directory? dir          ok, result =            if exists              chdir = "#{cd} #{iswin ? dir : esc(dir)}"              ret, data = bt.call "#{chdir} && git rev-parse --abbrev-ref HEAD 2>&1 && git config -f .git/config remote.origin.url", nil, nil, nil              current_uri = data.lines.to_a.last              if !ret                if data =~ /^Interrupted|^Timeout/                  [false, data]                else                  [false, [data.chomp, "PlugClean required."].join($/)]                end              elsif !compare_git_uri(current_uri, uri)                [false, ["Invalid URI: #{current_uri}",                         "Expected:    #{uri}",                         "PlugClean required."].join($/)]              else                if pull                  log.call name, 'Updating ...', :update                  fetch_opt = (tag && File.exist?(File.join(dir, '.git/shallow'))) ? '--depth 99999999' : ''                  bt.call "#{chdir} && git fetch #{fetch_opt} #{progress} 2>&1", name, :update, nil                else                  [true, skip]                end              end            else              d = esc dir.sub(%r{[\\/]+$}, '')              log.call name, 'Installing ...', :install              bt.call "git clone #{clone_opt unless tag} #{progress} #{uri} #{d} 2>&1", name, :install, proc {                FileUtils.rm_rf dir              }            end          mtx.synchronize { VIM::command("let s:update.new['#{name}'] = 1") } if !exists && ok          log.call name, result, ok        end      } if running    end  end  threads.each { |t| t.join rescue nil }  logh.call  refresh.kill if refresh  watcher.killEOFendfunctionfunction! s:shellesc_cmd(arg, script)  let escaped = substitute('"'.a:arg.'"', '[&|<>()@^!"]', '^&', 'g')  return substitute(escaped, '%', (a:script ? '%' : '^') . '&', 'g')endfunctionfunction! s:shellesc_ps1(arg)  return "'".substitute(escape(a:arg, '\"'), "'", "''", 'g')."'"endfunctionfunction! s:shellesc_sh(arg)  return "'".substitute(a:arg, "'", "'\\\\''", 'g')."'"endfunction" Escape the shell argument based on the shell." Vim and Neovim's shellescape() are insufficient." 1. shellslash determines whether to use single/double quotes."    Double-quote escaping is fragile for cmd.exe." 2. It does not work for powershell." 3. It does not work for *sh shells if the command is executed"    via cmd.exe (ie. cmd.exe /c sh -c command command_args)" 4. It does not support batchfile syntax."" Accepts an optional dictionary with the following keys:" - shell: same as Vim/Neovim 'shell' option."          If unset, fallback to 'cmd.exe' on Windows or 'sh'." - script: If truthy and shell is cmd.exe, escape for batchfile syntax.function! plug#shellescape(arg, ...)  if a:arg =~# '^[A-Za-z0-9_/:.-]\+$'    return a:arg  endif  let opts = a:0 > 0 && type(a:1) == s:TYPE.dict ? a:1 : {}  let shell = get(opts, 'shell', s:is_win ? 'cmd.exe' : 'sh')  let script = get(opts, 'script', 1)  if shell =~# 'cmd\.exe'    return s:shellesc_cmd(a:arg, script)  elseif shell =~# 'powershell\.exe' || shell =~# 'pwsh$'    return s:shellesc_ps1(a:arg)  endif  return s:shellesc_sh(a:arg)endfunctionfunction! s:glob_dir(path)  return map(filter(s:glob(a:path, '**'), 'isdirectory(v:val)'), 's:dirpath(v:val)')endfunctionfunction! s:progress_bar(line, bar, total)  call setline(a:line, '[' . s:lpad(a:bar, a:total) . ']')endfunctionfunction! s:compare_git_uri(a, b)  " See `git help clone'  " https:// [user@] github.com[:port] / junegunn/vim-plug [.git]  "          [git@]  github.com[:port] : junegunn/vim-plug [.git]  " file://                            / junegunn/vim-plug        [/]  "                                    / junegunn/vim-plug        [/]  let pat = '^\%(\w\+://\)\='.'\%([^@/]*@\)\='.'\([^:/]*\%(:[0-9]*\)\=\)'.'[:/]'.'\(.\{-}\)'.'\%(\.git\)\=/\?$'  let ma = matchlist(a:a, pat)  let mb = matchlist(a:b, pat)  return ma[1:2] ==# mb[1:2]endfunctionfunction! s:format_message(bullet, name, message)  if a:bullet != 'x'    return [printf('%s %s: %s', a:bullet, a:name, s:lastline(a:message))]  else    let lines = map(s:lines(a:message), '"    ".v:val')    return extend([printf('x %s:', a:name)], lines)  endifendfunctionfunction! s:with_cd(cmd, dir, ...)  let script = a:0 > 0 ? a:1 : 1  return printf('cd%s %s && %s', s:is_win ? ' /d' : '', plug#shellescape(a:dir, {'script': script}), a:cmd)endfunctionfunction! s:system(cmd, ...)  let batchfile = ''  try    let [sh, shellcmdflag, shrd] = s:chsh(1)    if type(a:cmd) == s:TYPE.list      " Neovim's system() supports list argument to bypass the shell      " but it cannot set the working directory for the command.      " Assume that the command does not rely on the shell.      if has('nvim') && a:0 == 0        return system(a:cmd)      endif      let cmd = join(map(copy(a:cmd), 'plug#shellescape(v:val, {"shell": &shell, "script": 0})'))      if &shell =~# 'powershell\.exe'        let cmd = '& ' . cmd      endif    else      let cmd = a:cmd    endif    if a:0 > 0      let cmd = s:with_cd(cmd, a:1, type(a:cmd) != s:TYPE.list)    endif    if s:is_win && type(a:cmd) != s:TYPE.list      let [batchfile, cmd] = s:batchfile(cmd)    endif    return system(cmd)  finally    let [&shell, &shellcmdflag, &shellredir] = [sh, shellcmdflag, shrd]    if s:is_win && filereadable(batchfile)      call delete(batchfile)    endif  endtryendfunctionfunction! s:system_chomp(...)  let ret = call('s:system', a:000)  return v:shell_error ? '' : substitute(ret, '\n$', '', '')endfunctionfunction! s:git_validate(spec, check_branch)  let err = ''  if isdirectory(a:spec.dir)    let result = s:lines(s:system('git rev-parse --abbrev-ref HEAD 2>&1 && git config -f .git/config remote.origin.url', a:spec.dir))    let remote = result[-1]    if v:shell_error      let err = join([remote, 'PlugClean required.'], "\n")    elseif !s:compare_git_uri(remote, a:spec.uri)      let err = join(['Invalid URI: '.remote,                    \ 'Expected:    '.a:spec.uri,                    \ 'PlugClean required.'], "\n")    elseif a:check_branch && has_key(a:spec, 'commit')      let result = s:lines(s:system('git rev-parse HEAD 2>&1', a:spec.dir))      let sha = result[-1]      if v:shell_error        let err = join(add(result, 'PlugClean required.'), "\n")      elseif !s:hash_match(sha, a:spec.commit)        let err = join([printf('Invalid HEAD (expected: %s, actual: %s)',                              \ a:spec.commit[:6], sha[:6]),                      \ 'PlugUpdate required.'], "\n")      endif    elseif a:check_branch      let branch = result[0]      " Check tag      if has_key(a:spec, 'tag')        let tag = s:system_chomp('git describe --exact-match --tags HEAD 2>&1', a:spec.dir)        if a:spec.tag !=# tag && a:spec.tag !~ '\*'          let err = printf('Invalid tag: %s (expected: %s). Try PlugUpdate.',                \ (empty(tag) ? 'N/A' : tag), a:spec.tag)        endif      " Check branch      elseif a:spec.branch !=# branch        let err = printf('Invalid branch: %s (expected: %s). Try PlugUpdate.',              \ branch, a:spec.branch)      endif      if empty(err)        let [ahead, behind] = split(s:lastline(s:system([        \ 'git', 'rev-list', '--count', '--left-right',        \ printf('HEAD...origin/%s', a:spec.branch)        \ ], a:spec.dir)), '\t')        if !v:shell_error && ahead          if behind            " Only mention PlugClean if diverged, otherwise it's likely to be            " pushable (and probably not that messed up).            let err = printf(                  \ "Diverged from origin/%s (%d commit(s) ahead and %d commit(s) behind!\n"                  \ .'Backup local changes and run PlugClean and PlugUpdate to reinstall it.', a:spec.branch, ahead, behind)          else            let err = printf("Ahead of origin/%s by %d commit(s).\n"                  \ .'Cannot update until local changes are pushed.',                  \ a:spec.branch, ahead)          endif        endif      endif    endif  else    let err = 'Not found'  endif  return [err, err =~# 'PlugClean']endfunctionfunction! s:rm_rf(dir)  if isdirectory(a:dir)    call s:system(s:is_win    \ ? 'rmdir /S /Q '.plug#shellescape(a:dir)    \ : ['rm', '-rf', a:dir])  endifendfunctionfunction! s:clean(force)  call s:prepare()  call append(0, 'Searching for invalid plugins in '.g:plug_home)  call append(1, '')  " List of valid directories  let dirs = []  let errs = {}  let [cnt, total] = [0, len(g:plugs)]  for [name, spec] in items(g:plugs)    if !s:is_managed(name)      call add(dirs, spec.dir)    else      let [err, clean] = s:git_validate(spec, 1)      if clean        let errs[spec.dir] = s:lines(err)[0]      else        call add(dirs, spec.dir)      endif    endif    let cnt += 1    call s:progress_bar(2, repeat('=', cnt), total)    normal! 2G    redraw  endfor  let allowed = {}  for dir in dirs    let allowed[s:dirpath(s:plug_fnamemodify(dir, ':h:h'))] = 1    let allowed[dir] = 1    for child in s:glob_dir(dir)      let allowed[child] = 1    endfor  endfor  let todo = []  let found = sort(s:glob_dir(g:plug_home))  while !empty(found)    let f = remove(found, 0)    if !has_key(allowed, f) && isdirectory(f)      call add(todo, f)      call append(line('$'), '- ' . f)      if has_key(errs, f)        call append(line('$'), '    ' . errs[f])      endif      let found = filter(found, 'stridx(v:val, f) != 0')    end  endwhile  4  redraw  if empty(todo)    call append(line('$'), 'Already clean.')  else    let s:clean_count = 0    call append(3, ['Directories to delete:', ''])    redraw!    if a:force || s:ask_no_interrupt('Delete all directories?')      call s:delete([6, line('$')], 1)    else      call setline(4, 'Cancelled.')      nnoremap <silent> <buffer> d :set opfunc=<sid>delete_op<cr>g@      nmap     <silent> <buffer> dd d_      xnoremap <silent> <buffer> d :<c-u>call <sid>delete_op(visualmode(), 1)<cr>      echo 'Delete the lines (d{motion}) to delete the corresponding directories'    endif  endif  4  setlocal nomodifiableendfunctionfunction! s:delete_op(type, ...)  call s:delete(a:0 ? [line("'<"), line("'>")] : [line("'["), line("']")], 0)endfunctionfunction! s:delete(range, force)  let [l1, l2] = a:range  let force = a:force  while l1 <= l2    let line = getline(l1)    if line =~ '^- ' && isdirectory(line[2:])      execute l1      redraw!      let answer = force ? 1 : s:ask('Delete '.line[2:].'?', 1)      let force = force || answer > 1      if answer        call s:rm_rf(line[2:])        setlocal modifiable        call setline(l1, '~'.line[1:])        let s:clean_count += 1        call setline(4, printf('Removed %d directories.', s:clean_count))        setlocal nomodifiable      endif    endif    let l1 += 1  endwhileendfunctionfunction! s:upgrade()  echo 'Downloading the latest version of vim-plug'  redraw  let tmp = s:plug_tempname()  let new = tmp . '/plug.vim'  try    let out = s:system(['git', 'clone', '--depth', '1', s:plug_src, tmp])    if v:shell_error      return s:err('Error upgrading vim-plug: '. out)    endif    if readfile(s:me) ==# readfile(new)      echo 'vim-plug is already up-to-date'      return 0    else      call rename(s:me, s:me . '.old')      call rename(new, s:me)      unlet g:loaded_plug      echo 'vim-plug has been upgraded'      return 1    endif  finally    silent! call s:rm_rf(tmp)  endtryendfunctionfunction! s:upgrade_specs()  for spec in values(g:plugs)    let spec.frozen = get(spec, 'frozen', 0)  endforendfunctionfunction! s:status()  call s:prepare()  call append(0, 'Checking plugins')  call append(1, '')  let ecnt = 0  let unloaded = 0  let [cnt, total] = [0, len(g:plugs)]  for [name, spec] in items(g:plugs)    let is_dir = isdirectory(spec.dir)    if has_key(spec, 'uri')      if is_dir        let [err, _] = s:git_validate(spec, 1)        let [valid, msg] = [empty(err), empty(err) ? 'OK' : err]      else        let [valid, msg] = [0, 'Not found. Try PlugInstall.']      endif    else      if is_dir        let [valid, msg] = [1, 'OK']      else        let [valid, msg] = [0, 'Not found.']      endif    endif    let cnt += 1    let ecnt += !valid    " `s:loaded` entry can be missing if PlugUpgraded    if is_dir && get(s:loaded, name, -1) == 0      let unloaded = 1      let msg .= ' (not loaded)'    endif    call s:progress_bar(2, repeat('=', cnt), total)    call append(3, s:format_message(valid ? '-' : 'x', name, msg))    normal! 2G    redraw  endfor  call setline(1, 'Finished. '.ecnt.' error(s).')  normal! gg  setlocal nomodifiable  if unloaded    echo "Press 'L' on each line to load plugin, or 'U' to update"    nnoremap <silent> <buffer> L :call <SID>status_load(line('.'))<cr>    xnoremap <silent> <buffer> L :call <SID>status_load(line('.'))<cr>  endendfunctionfunction! s:extract_name(str, prefix, suffix)  return matchstr(a:str, '^'.a:prefix.' \zs[^:]\+\ze:.*'.a:suffix.'$')endfunctionfunction! s:status_load(lnum)  let line = getline(a:lnum)  let name = s:extract_name(line, '-', '(not loaded)')  if !empty(name)    call plug#load(name)    setlocal modifiable    call setline(a:lnum, substitute(line, ' (not loaded)$', '', ''))    setlocal nomodifiable  endifendfunctionfunction! s:status_update() range  let lines = getline(a:firstline, a:lastline)  let names = filter(map(lines, 's:extract_name(v:val, "[x-]", "")'), '!empty(v:val)')  if !empty(names)    echo    execute 'PlugUpdate' join(names)  endifendfunctionfunction! s:is_preview_window_open()  silent! wincmd P  if &previewwindow    wincmd p    return 1  endifendfunctionfunction! s:find_name(lnum)  for lnum in reverse(range(1, a:lnum))    let line = getline(lnum)    if empty(line)      return ''    endif    let name = s:extract_name(line, '-', '')    if !empty(name)      return name    endif  endfor  return ''endfunctionfunction! s:preview_commit()  if b:plug_preview < 0    let b:plug_preview = !s:is_preview_window_open()  endif  let sha = matchstr(getline('.'), '^  \X*\zs[0-9a-f]\{7,9}')  if empty(sha)    return  endif  let name = s:find_name(line('.'))  if empty(name) || !has_key(g:plugs, name) || !isdirectory(g:plugs[name].dir)    return  endif  if exists('g:plug_pwindow') && !s:is_preview_window_open()    execute g:plug_pwindow    execute 'e' sha  else    execute 'pedit' sha    wincmd P  endif  setlocal previewwindow filetype=git buftype=nofile nobuflisted modifiable  let batchfile = ''  try    let [sh, shellcmdflag, shrd] = s:chsh(1)    let cmd = 'cd '.plug#shellescape(g:plugs[name].dir).' && git show --no-color --pretty=medium '.sha    if s:is_win      let [batchfile, cmd] = s:batchfile(cmd)    endif    execute 'silent %!' cmd  finally    let [&shell, &shellcmdflag, &shellredir] = [sh, shellcmdflag, shrd]    if s:is_win && filereadable(batchfile)      call delete(batchfile)    endif  endtry  setlocal nomodifiable  nnoremap <silent> <buffer> q :q<cr>  wincmd pendfunctionfunction! s:section(flags)  call search('\(^[x-] \)\@<=[^:]\+:', a:flags)endfunctionfunction! s:format_git_log(line)  let indent = '  '  let tokens = split(a:line, nr2char(1))  if len(tokens) != 5    return indent.substitute(a:line, '\s*$', '', '')  endif  let [graph, sha, refs, subject, date] = tokens  let tag = matchstr(refs, 'tag: [^,)]\+')  let tag = empty(tag) ? ' ' : ' ('.tag.') '  return printf('%s%s%s%s%s (%s)', indent, graph, sha, tag, subject, date)endfunctionfunction! s:append_ul(lnum, text)  call append(a:lnum, ['', a:text, repeat('-', len(a:text))])endfunctionfunction! s:diff()  call s:prepare()  call append(0, ['Collecting changes ...', ''])  let cnts = [0, 0]  let bar = ''  let total = filter(copy(g:plugs), 's:is_managed(v:key) && isdirectory(v:val.dir)')  call s:progress_bar(2, bar, len(total))  for origin in [1, 0]    let plugs = reverse(sort(items(filter(copy(total), (origin ? '' : '!').'(has_key(v:val, "commit") || has_key(v:val, "tag"))'))))    if empty(plugs)      continue    endif    call s:append_ul(2, origin ? 'Pending updates:' : 'Last update:')    for [k, v] in plugs      let range = origin ? '..origin/'.v.branch : 'HEAD@{1}..'      let cmd = ['git', 'log', '--graph', '--color=never']      if s:git_version_requirement(2, 10, 0)        call add(cmd, '--no-show-signature')      endif      call extend(cmd, ['--pretty=format:%x01%h%x01%d%x01%s%x01%cr', range])      if has_key(v, 'rtp')        call extend(cmd, ['--', v.rtp])      endif      let diff = s:system_chomp(cmd, v.dir)      if !empty(diff)        let ref = has_key(v, 'tag') ? (' (tag: '.v.tag.')') : has_key(v, 'commit') ? (' '.v.commit) : ''        call append(5, extend(['', '- '.k.':'.ref], map(s:lines(diff), 's:format_git_log(v:val)')))        let cnts[origin] += 1      endif      let bar .= '='      call s:progress_bar(2, bar, len(total))      normal! 2G      redraw    endfor    if !cnts[origin]      call append(5, ['', 'N/A'])    endif  endfor  call setline(1, printf('%d plugin(s) updated.', cnts[0])        \ . (cnts[1] ? printf(' %d plugin(s) have pending updates.', cnts[1]) : ''))  if cnts[0] || cnts[1]    nnoremap <silent> <buffer> <plug>(plug-preview) :silent! call <SID>preview_commit()<cr>    if empty(maparg("\<cr>", 'n'))      nmap <buffer> <cr> <plug>(plug-preview)    endif    if empty(maparg('o', 'n'))      nmap <buffer> o <plug>(plug-preview)    endif  endif  if cnts[0]    nnoremap <silent> <buffer> X :call <SID>revert()<cr>    echo "Press 'X' on each block to revert the update"  endif  normal! gg  setlocal nomodifiableendfunctionfunction! s:revert()  if search('^Pending updates', 'bnW')    return  endif  let name = s:find_name(line('.'))  if empty(name) || !has_key(g:plugs, name) ||    \ input(printf('Revert the update of %s? (y/N) ', name)) !~? '^y'    return  endif  call s:system('git reset --hard HEAD@{1} && git checkout '.plug#shellescape(g:plugs[name].branch).' --', g:plugs[name].dir)  setlocal modifiable  normal! "_dap  setlocal nomodifiable  echo 'Reverted'endfunctionfunction! s:snapshot(force, ...) abort  call s:prepare()  setf vim  call append(0, ['" Generated by vim-plug',                \ '" '.strftime("%c"),                \ '" :source this file in vim to restore the snapshot',                \ '" or execute: vim -S snapshot.vim',                \ '', '', 'PlugUpdate!'])  1  let anchor = line('$') - 3  let names = sort(keys(filter(copy(g:plugs),        \'has_key(v:val, "uri") && !has_key(v:val, "commit") && isdirectory(v:val.dir)')))  for name in reverse(names)    let sha = s:system_chomp(['git', 'rev-parse', '--short', 'HEAD'], g:plugs[name].dir)    if !empty(sha)      call append(anchor, printf("silent! let g:plugs['%s'].commit = '%s'", name, sha))      redraw    endif  endfor  if a:0 > 0    let fn = s:plug_expand(a:1)    if filereadable(fn) && !(a:force || s:ask(a:1.' already exists. Overwrite?'))      return    endif    call writefile(getline(1, '$'), fn)    echo 'Saved as '.a:1    silent execute 'e' s:esc(fn)    setf vim  endifendfunctionfunction! s:split_rtp()  return split(&rtp, '\\\@<!,')endfunctionlet s:first_rtp = s:escrtp(get(s:split_rtp(), 0, ''))let s:last_rtp  = s:escrtp(get(s:split_rtp(), -1, ''))if exists('g:plugs')  let g:plugs_order = get(g:, 'plugs_order', keys(g:plugs))  call s:upgrade_specs()  call s:define_commands()endiflet &cpo = s:cpo_saveunlet s:cpo_save
 |