ctrlp.vim 77 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903
  1. " =============================================================================
  2. " File: autoload/ctrlp.vim
  3. " Description: Fuzzy file, buffer, mru, tag, etc finder.
  4. " Author: CtrlP Dev Team
  5. " Original: Kien Nguyen <github.com/kien>
  6. " Version: 1.80
  7. " =============================================================================
  8. " ** Static variables {{{1
  9. " s:ignore() {{{2
  10. fu! s:ignore()
  11. let igdirs = [
  12. \ '\.git',
  13. \ '\.hg',
  14. \ '\.svn',
  15. \ '_darcs',
  16. \ '\.bzr',
  17. \ '\.cdv',
  18. \ '\~\.dep',
  19. \ '\~\.dot',
  20. \ '\~\.nib',
  21. \ '\~\.plst',
  22. \ '\.pc',
  23. \ '_MTN',
  24. \ 'blib',
  25. \ 'CVS',
  26. \ 'RCS',
  27. \ 'SCCS',
  28. \ '_sgbak',
  29. \ 'autom4te\.cache',
  30. \ 'cover_db',
  31. \ '_build',
  32. \ ]
  33. let igfiles = [
  34. \ '\~$',
  35. \ '#.+#$',
  36. \ '[._].*\.swp$',
  37. \ 'core\.\d+$',
  38. \ '\.exe$',
  39. \ '\.so$',
  40. \ '\.bak$',
  41. \ '\.png$',
  42. \ '\.jpg$',
  43. \ '\.gif$',
  44. \ '\.zip$',
  45. \ '\.rar$',
  46. \ '\.tar\.gz$',
  47. \ ]
  48. retu {
  49. \ 'dir': '\v[\/]('.join(igdirs, '|').')$',
  50. \ 'file': '\v'.join(igfiles, '|'),
  51. \ }
  52. endf
  53. " Script local vars {{{2
  54. let [s:pref, s:bpref, s:opts, s:new_opts, s:lc_opts] =
  55. \ ['g:ctrlp_', 'b:ctrlp_', {
  56. \ 'abbrev': ['s:abbrev', {}],
  57. \ 'arg_map': ['s:argmap', 0],
  58. \ 'buffer_func': ['s:buffunc', {}],
  59. \ 'by_filename': ['s:byfname', 0],
  60. \ 'custom_ignore': ['s:usrign', s:ignore()],
  61. \ 'default_input': ['s:deftxt', 0],
  62. \ 'dont_split': ['s:nosplit', 'netrw'],
  63. \ 'dotfiles': ['s:showhidden', 0],
  64. \ 'extensions': ['s:extensions', []],
  65. \ 'follow_symlinks': ['s:folsym', 0],
  66. \ 'highlight_match': ['s:mathi', [1, 'CtrlPMatch']],
  67. \ 'jump_to_buffer': ['s:jmptobuf', 'Et'],
  68. \ 'key_loop': ['s:keyloop', 0],
  69. \ 'lazy_update': ['s:lazy', 0],
  70. \ 'match_func': ['s:matcher', {}],
  71. \ 'match_window': ['s:mw', ''],
  72. \ 'match_window_bottom': ['s:mwbottom', 1],
  73. \ 'match_window_reversed': ['s:mwreverse', 1],
  74. \ 'max_depth': ['s:maxdepth', 40],
  75. \ 'max_files': ['s:maxfiles', 10000],
  76. \ 'max_height': ['s:mxheight', 10],
  77. \ 'max_history': ['s:maxhst', exists('+hi') ? &hi : 20],
  78. \ 'mruf_default_order': ['s:mrudef', 0],
  79. \ 'open_func': ['s:openfunc', {}],
  80. \ 'open_multi': ['s:opmul', '1v'],
  81. \ 'open_new_file': ['s:newfop', 'v'],
  82. \ 'prompt_mappings': ['s:urprtmaps', 0],
  83. \ 'regexp_search': ['s:regexp', 0],
  84. \ 'root_markers': ['s:rmarkers', []],
  85. \ 'split_window': ['s:splitwin', 0],
  86. \ 'status_func': ['s:status', {}],
  87. \ 'tabpage_position': ['s:tabpage', 'ac'],
  88. \ 'use_caching': ['s:caching', 1],
  89. \ 'user_command': ['s:usrcmd', ''],
  90. \ 'validate': ['s:validate', ''],
  91. \ 'working_path_mode': ['s:pathmode', 'ra'],
  92. \ 'line_prefix': ['s:lineprefix', '> '],
  93. \ 'open_single_match': ['s:opensingle', []],
  94. \ 'brief_prompt': ['s:brfprt', 0],
  95. \ 'match_current_file': ['s:matchcrfile', 0],
  96. \ 'match_natural_name': ['s:matchnatural', 0],
  97. \ 'compare_lim': ['s:compare_lim', 0],
  98. \ 'bufname_mod': ['s:bufname_mod', ':t'],
  99. \ 'bufpath_mod': ['s:bufpath_mod', ':~:.:h'],
  100. \ 'formatline_func': ['s:flfunc', 's:formatline(v:val)'],
  101. \ 'user_command_async': ['s:usrcmdasync', 0],
  102. \ }, {
  103. \ 'open_multiple_files': 's:opmul',
  104. \ 'regexp': 's:regexp',
  105. \ 'reuse_window': 's:nosplit',
  106. \ 'show_hidden': 's:showhidden',
  107. \ 'switch_buffer': 's:jmptobuf',
  108. \ }, {
  109. \ 'root_markers': 's:rmarkers',
  110. \ 'user_command': 's:usrcmd',
  111. \ 'working_path_mode': 's:pathmode',
  112. \ }]
  113. " Global options
  114. let s:glbs = { 'magic': 1, 'to': 1, 'tm': 0, 'sb': 1, 'hls': 0, 'im': 0,
  115. \ 'report': 9999, 'sc': 0, 'ss': 0, 'siso': 0, 'mfd': 200, 'ttimeout': 0,
  116. \ 'gcr': 'a:blinkon0', 'ic': 1, 'lmap': '', 'mousef': 0, 'imd': 1 }
  117. " Keymaps
  118. let [s:lcmap, s:prtmaps] = ['nn <buffer> <silent>', {
  119. \ 'PrtBS()': ['<bs>', '<c-]>'],
  120. \ 'PrtDelete()': ['<del>'],
  121. \ 'PrtDeleteWord()': ['<c-w>'],
  122. \ 'PrtClear()': ['<c-u>'],
  123. \ 'PrtSelectMove("j")': ['<c-j>', '<down>'],
  124. \ 'PrtSelectMove("k")': ['<c-k>', '<up>'],
  125. \ 'PrtSelectMove("t")': ['<Home>', '<kHome>'],
  126. \ 'PrtSelectMove("b")': ['<End>', '<kEnd>'],
  127. \ 'PrtSelectMove("u")': ['<PageUp>', '<kPageUp>'],
  128. \ 'PrtSelectMove("d")': ['<PageDown>', '<kPageDown>'],
  129. \ 'PrtHistory(-1)': ['<c-n>'],
  130. \ 'PrtHistory(1)': ['<c-p>'],
  131. \ 'AcceptSelection("e")': ['<cr>', '<2-LeftMouse>'],
  132. \ 'AcceptSelection("h")': ['<c-x>', '<c-cr>', '<c-s>'],
  133. \ 'AcceptSelection("t")': ['<c-t>'],
  134. \ 'AcceptSelection("v")': ['<c-v>', '<RightMouse>'],
  135. \ 'ToggleFocus()': ['<s-tab>'],
  136. \ 'ToggleRegex()': ['<c-r>'],
  137. \ 'ToggleByFname()': ['<c-d>'],
  138. \ 'ToggleType(1)': ['<c-f>', '<c-up>'],
  139. \ 'ToggleType(-1)': ['<c-b>', '<c-down>'],
  140. \ 'PrtExpandDir()': ['<tab>'],
  141. \ 'PrtInsert("c")': ['<MiddleMouse>', '<insert>'],
  142. \ 'PrtInsert()': ['<c-\>'],
  143. \ 'PrtCurStart()': ['<c-a>'],
  144. \ 'PrtCurEnd()': ['<c-e>'],
  145. \ 'PrtCurLeft()': ['<c-h>', '<left>', '<c-^>'],
  146. \ 'PrtCurRight()': ['<c-l>', '<right>'],
  147. \ 'PrtClearCache()': ['<F5>'],
  148. \ 'PrtDeleteEnt()': ['<F7>'],
  149. \ 'CreateNewFile()': ['<c-y>'],
  150. \ 'MarkToOpen()': ['<c-z>'],
  151. \ 'OpenMulti()': ['<c-o>'],
  152. \ 'YankLine()': [],
  153. \ 'PrtExit()': ['<esc>', '<c-c>', '<c-g>'],
  154. \ }]
  155. if !has('gui_running')
  156. cal add(s:prtmaps['PrtBS()'], remove(s:prtmaps['PrtCurLeft()'], 0))
  157. en
  158. let s:ficounts = {}
  159. let s:ccex = s:pref.'clear_cache_on_exit'
  160. " Regexp
  161. let s:fpats = {
  162. \ '^\(\\|\)\|\(\\|\)$': '\\|',
  163. \ '^\\\(zs\|ze\|<\|>\)': '^\\\(zs\|ze\|<\|>\)',
  164. \ '^\S\*$': '\*',
  165. \ '^\S\\?$': '\\?',
  166. \ }
  167. let s:has_conceal = has('conceal')
  168. let s:bufnr_width = 3
  169. " Keypad
  170. let s:kprange = {
  171. \ 'Plus': '+',
  172. \ 'Minus': '-',
  173. \ 'Divide': '/',
  174. \ 'Multiply': '*',
  175. \ 'Point': '.',
  176. \ }
  177. " Highlight groups
  178. let s:hlgrps = {
  179. \ 'NoEntries': 'Error',
  180. \ 'Mode1': 'Character',
  181. \ 'Mode2': 'LineNr',
  182. \ 'Stats': 'Function',
  183. \ 'Match': 'Identifier',
  184. \ 'PrtBase': 'Comment',
  185. \ 'PrtText': 'Normal',
  186. \ 'PrtCursor': 'Constant',
  187. \ 'BufferNr': 'Constant',
  188. \ 'BufferInd': 'Normal',
  189. \ 'BufferHid': 'Comment',
  190. \ 'BufferHidMod': 'String',
  191. \ 'BufferVis': 'Normal',
  192. \ 'BufferVisMod': 'Identifier',
  193. \ 'BufferCur': 'Question',
  194. \ 'BufferCurMod': 'WarningMsg',
  195. \ 'BufferPath': 'Comment',
  196. \ }
  197. " lname, sname of the basic(non-extension) modes
  198. let s:types = ['fil', 'buf', 'mru']
  199. if !exists('g:ctrlp_types')
  200. let g:ctrlp_types = s:types
  201. el
  202. call filter(g:ctrlp_types, "index(['fil', 'buf', 'mru'], v:val)!=-1")
  203. en
  204. let g:ctrlp_builtins = len(g:ctrlp_types)-1
  205. let s:coretype_names = {
  206. \ 'fil' : 'files',
  207. \ 'buf' : 'buffers',
  208. \ 'mru' : 'mru files',
  209. \ }
  210. let s:coretypes = map(copy(g:ctrlp_types), '[s:coretype_names[v:val], v:val]')
  211. " Get the options {{{2
  212. fu! s:opts(...)
  213. unl! s:usrign s:usrcmd s:urprtmaps
  214. for each in ['byfname', 'regexp', 'extensions'] | if exists('s:'.each)
  215. let {each} = s:{each}
  216. en | endfo
  217. for [ke, va] in items(s:opts)
  218. let {va[0]} = exists(s:pref.ke) ? {s:pref.ke} : va[1]
  219. endfo
  220. unl va
  221. for [ke, va] in items(s:new_opts)
  222. let {va} = {exists(s:pref.ke) ? s:pref.ke : va}
  223. endfo
  224. unl va
  225. for [ke, va] in items(s:lc_opts)
  226. if exists(s:bpref.ke)
  227. unl {va}
  228. let {va} = {s:bpref.ke}
  229. en
  230. endfo
  231. " Match window options
  232. cal s:match_window_opts()
  233. " One-time values
  234. if a:0 && a:1 != {}
  235. unl va
  236. for [ke, va] in items(a:1)
  237. let opke = substitute(ke, '\(\w:\)\?ctrlp_', '', '')
  238. if has_key(s:lc_opts, opke)
  239. let sva = s:lc_opts[opke]
  240. unl {sva}
  241. let {sva} = va
  242. en
  243. endfo
  244. en
  245. for each in ['byfname', 'regexp'] | if exists(each)
  246. let s:{each} = {each}
  247. en | endfo
  248. if !exists('g:ctrlp_tilde_homedir') | let g:ctrlp_tilde_homedir = 0 | en
  249. if !exists('g:ctrlp_newcache') | let g:ctrlp_newcache = 0 | en
  250. let s:maxdepth = min([s:maxdepth, 100])
  251. let s:glob = s:showhidden ? '.*\|*' : '*'
  252. let s:igntype = empty(s:usrign) ? -1 : type(s:usrign)
  253. let s:lash = ctrlp#utils#lash()
  254. if s:keyloop
  255. let [s:lazy, s:glbs['imd']] = [0, 0]
  256. en
  257. if s:lazy
  258. cal extend(s:glbs, { 'ut': ( s:lazy > 1 ? s:lazy : 250 ) })
  259. en
  260. " Extensions
  261. if !( exists('extensions') && extensions == s:extensions )
  262. for each in s:extensions
  263. exe 'ru autoload/ctrlp/'.each.'.vim'
  264. endfo
  265. en
  266. " Keymaps
  267. if type(s:urprtmaps) == 4
  268. cal extend(s:prtmaps, s:urprtmaps)
  269. en
  270. endf
  271. fu! s:match_window_opts()
  272. let s:mw_pos =
  273. \ s:mw =~ 'top\|bottom' ? matchstr(s:mw, 'top\|bottom') :
  274. \ exists('g:ctrlp_match_window_bottom') ? ( s:mwbottom ? 'bottom' : 'top' )
  275. \ : 'bottom'
  276. let s:mw_order =
  277. \ s:mw =~ 'order:[^,]\+' ? matchstr(s:mw, 'order:\zs[^,]\+') :
  278. \ exists('g:ctrlp_match_window_reversed') ? ( s:mwreverse ? 'btt' : 'ttb' )
  279. \ : 'btt'
  280. let s:mw_max =
  281. \ s:mw =~ 'max:[^,]\+' ? str2nr(matchstr(s:mw, 'max:\zs\d\+')) :
  282. \ exists('g:ctrlp_max_height') ? s:mxheight
  283. \ : 10
  284. let s:mw_min =
  285. \ s:mw =~ 'min:[^,]\+' ? str2nr(matchstr(s:mw, 'min:\zs\d\+')) : 1
  286. let [s:mw_max, s:mw_min] = [max([s:mw_max, 1]), max([s:mw_min, 1])]
  287. let s:mw_min = min([s:mw_min, s:mw_max])
  288. let s:mw_res =
  289. \ s:mw =~ 'results:[^,]\+' ? str2nr(matchstr(s:mw, 'results:\zs\d\+'))
  290. \ : min([s:mw_max, &lines])
  291. endf
  292. "}}}1
  293. " * Open & Close {{{1
  294. fu! s:Open()
  295. cal s:log(1)
  296. cal s:getenv()
  297. cal s:execextvar('enter')
  298. sil! exe 'keepa' ( s:mw_pos == 'top' ? 'to' : 'bo' ) '1new ControlP'
  299. cal s:buffunc(1)
  300. let [s:bufnr, s:winw] = [bufnr('%'), winwidth(0)]
  301. let [s:focus, s:prompt] = [1, ['', '', '']]
  302. abc <buffer>
  303. if !exists('s:hstry')
  304. let hst = filereadable(s:gethistloc()[1]) ? s:gethistdata() : ['']
  305. let s:hstry = empty(hst) || !s:maxhst ? [''] : hst
  306. en
  307. for [ke, va] in items(s:glbs) | if exists('+'.ke)
  308. sil! exe 'let s:glb_'.ke.' = &'.ke.' | let &'.ke.' = '.string(va)
  309. en | endfo
  310. if s:opmul != '0' && has('signs')
  311. sign define ctrlpmark text=+> texthl=CtrlPMark
  312. hi def link CtrlPMark Search
  313. en
  314. cal s:setupblank()
  315. endf
  316. fu! s:Close()
  317. if has('patch-9.0.0115') && exists('s:cmdheight')
  318. let &cmdheight = s:cmdheight
  319. unlet s:cmdheight
  320. en
  321. cal s:async_glob_abort(0)
  322. cal s:buffunc(0)
  323. if winnr('$') == 1
  324. bw!
  325. el
  326. try | bun!
  327. cat | clo! | endt
  328. cal s:unmarksigns()
  329. en
  330. for key in keys(s:glbs) | if exists('+'.key)
  331. sil! exe 'let &'.key.' = s:glb_'.key
  332. en | endfo
  333. if exists('s:glb_acd') | let &acd = s:glb_acd | en
  334. let g:ctrlp_lines = []
  335. if s:winres[1] >= &lines && s:winres[2] == winnr('$')
  336. exe s:winres[0].s:winres[0]
  337. en
  338. unl! s:focus s:hisidx s:hstgot s:marked s:statypes s:init s:savestr
  339. \ s:mrbs s:did_exp
  340. cal ctrlp#recordhist()
  341. cal s:execextvar('exit')
  342. cal s:log(0)
  343. let v:errmsg = s:ermsg
  344. ec
  345. endf
  346. " * Clear caches {{{1
  347. fu! ctrlp#clr(...)
  348. let [s:matches, g:ctrlp_new{ a:0 ? a:1 : 'cache' }] = [1, 1]
  349. endf
  350. fu! ctrlp#clra()
  351. let cadir = ctrlp#utils#cachedir()
  352. if isdirectory(cadir)
  353. let cafiles = split(s:glbpath(s:fnesc(cadir, 'g', ','), '**', 1), "\n")
  354. let eval = '!isdirectory(v:val) && v:val !~ ''\v[\/]cache[.a-z]+$|\.log$'''
  355. sil! cal map(s:ifilter(cafiles, eval), 'delete(v:val)')
  356. en
  357. cal ctrlp#clr()
  358. endf
  359. fu! s:Reset(args)
  360. let opts = has_key(a:args, 'opts') ? [a:args['opts']] : []
  361. cal call('s:opts', opts)
  362. cal s:autocmds()
  363. cal ctrlp#utils#opts()
  364. cal s:execextvar('opts')
  365. endf
  366. " * Files {{{1
  367. fu! ctrlp#files()
  368. let cafile = ctrlp#utils#cachefile()
  369. if g:ctrlp_newcache || !filereadable(cafile) || s:nocache(cafile)
  370. let [lscmd, s:initcwd, g:ctrlp_allfiles] = [s:lsCmd(), s:dyncwd, []]
  371. " Get the list of files
  372. if empty(lscmd)
  373. if !ctrlp#igncwd(s:dyncwd)
  374. cal s:InitCustomFuncs()
  375. cal s:GlobPath(s:fnesc(s:dyncwd, 'g', ','), 0)
  376. cal s:CloseCustomFuncs()
  377. en
  378. el
  379. sil! cal ctrlp#progress('Indexing...')
  380. try | cal s:UserCmd(lscmd)
  381. cat | retu [] | endt
  382. en
  383. " Remove base directory
  384. cal ctrlp#rmbasedir(g:ctrlp_allfiles)
  385. if !s:compare_lim || len(g:ctrlp_allfiles) <= s:compare_lim
  386. cal sort(g:ctrlp_allfiles, 'ctrlp#complen')
  387. en
  388. cal s:writecache(cafile)
  389. let catime = getftime(cafile)
  390. el
  391. let catime = getftime(cafile)
  392. if !( exists('s:initcwd') && s:initcwd == s:dyncwd )
  393. \ || get(s:ficounts, s:dyncwd, [0, catime])[1] != catime
  394. let s:initcwd = s:dyncwd
  395. let g:ctrlp_allfiles = ctrlp#utils#readfile(cafile)
  396. en
  397. en
  398. cal extend(s:ficounts, { s:dyncwd : [len(g:ctrlp_allfiles), catime] })
  399. retu g:ctrlp_allfiles
  400. endf
  401. fu! s:InitCustomFuncs()
  402. if s:igntype == 4 && get(s:usrign, 'func-init', '') != ''
  403. exe call(s:usrign['func-init'], [])
  404. en
  405. endf
  406. fu! s:CloseCustomFuncs()
  407. if s:igntype == 4 && get(s:usrign, 'func-close', '') != ''
  408. exe call(s:usrign['func-close'], [])
  409. en
  410. endf
  411. if has('patch-8.2-0995') && get(g:, 'ctrlp_use_readdir', 1)
  412. fu! s:GlobPath(dirs, depth)
  413. let entries = []
  414. let dirs = substitute(a:dirs, '\\\([%# ]\)', '\1', 'g')
  415. for e in split(dirs, ',')
  416. try
  417. let files = readdir(e, '1', {'sort': 'none'})
  418. if !s:showhidden | cal filter(files, 'v:val[0] != "."') | en
  419. let entries += map(files, 'e.s:lash.v:val')
  420. cat
  421. endt
  422. endfo
  423. let [dnf, depth] = [ctrlp#dirnfile(entries), a:depth + 1]
  424. if &wig != '' | cal filter(dnf[1], 'glob(v:val) != ""') | en
  425. let g:ctrlp_allfiles += dnf[1]
  426. if !empty(dnf[0]) && !s:maxf(len(g:ctrlp_allfiles)) && depth <= s:maxdepth
  427. sil! cal ctrlp#progress(len(g:ctrlp_allfiles), 1)
  428. cal s:GlobPath(join(dnf[0], ','), depth)
  429. en
  430. endf
  431. el
  432. fu! s:GlobPath(dirs, depth)
  433. let entries = split(globpath(a:dirs, s:glob), "\n")
  434. let [dnf, depth] = [ctrlp#dirnfile(entries), a:depth + 1]
  435. let g:ctrlp_allfiles += dnf[1]
  436. if !empty(dnf[0]) && !s:maxf(len(g:ctrlp_allfiles)) && depth <= s:maxdepth
  437. sil! cal ctrlp#progress(len(g:ctrlp_allfiles), 1)
  438. cal s:GlobPath(join(map(dnf[0], 's:fnesc(v:val, "g", ",")'), ','), depth)
  439. en
  440. endf
  441. en
  442. fu! s:async_glob_update_progress(timer)
  443. let s:must_wait = 0
  444. if exists('s:focus') && get(s:, 'setlines_post_ended', 0)
  445. cal s:ForceUpdate()
  446. en
  447. if exists('s:timer')
  448. sil! cal ctrlp#statusline()
  449. en
  450. if !exists('s:job')
  451. call s:stop_timer_if_exists()
  452. en
  453. endf
  454. fu! s:async_glob_on_stdout(job, data, ...)
  455. if type(a:data) ==# type([])
  456. let g:ctrlp_allfiles += filter(a:data, 'v:val !=# ""')
  457. el
  458. let g:ctrlp_allfiles += [a:data]
  459. en
  460. endf
  461. fu! s:async_glob_on_exit(...)
  462. let s:must_wait = 0
  463. if exists('s:job')
  464. unl s:job
  465. en
  466. cal s:stop_timer_if_exists()
  467. if exists('s:focus') && get(s:, 'setlines_post_ended', 0)
  468. sil! cal ctrlp#statusline()
  469. cal s:ForceUpdate()
  470. en
  471. endf
  472. fu! s:async_glob_abort(upd)
  473. cal s:stop_job_if_exists()
  474. cal s:stop_timer_if_exists()
  475. if a:upd
  476. cal s:ForceUpdate()
  477. en
  478. endf
  479. fu! s:stop_timer_if_exists()
  480. if exists('s:timer')
  481. cal timer_stop(s:timer)
  482. unl s:timer
  483. en
  484. endf
  485. fu! s:stop_job_if_exists()
  486. if exists('s:job')
  487. if !has('nvim')
  488. cal job_stop(s:job)
  489. el
  490. cal jobstop(s:job)
  491. en
  492. unl s:job
  493. en
  494. endf
  495. fu! s:safe_printf(format, ...)
  496. try
  497. retu call('printf', [a:format] + a:000)
  498. cat
  499. retu a:format
  500. endt
  501. endf
  502. fu! s:UserCmd(lscmd)
  503. let [path, lscmd] = [s:dyncwd, a:lscmd]
  504. let do_ign =
  505. \ type(s:usrcmd) == 4 && get(s:usrcmd, 'ignore', 0)
  506. if do_ign && ctrlp#igncwd(s:cwd) | retu | en
  507. if exists('+ssl') && &ssl && &shell !~ 'sh'
  508. let [ssl, &ssl, path] = [&ssl, 0, tr(path, '/', '\')]
  509. en
  510. if (has('win32') || has('win64')) && match(&shellcmdflag, "/") != -1
  511. let lscmd = substitute(lscmd, '\v(^|\&\&\s*)\zscd (/d)@!', 'cd /d ', '')
  512. en
  513. let path = exists('*shellescape') ? shellescape(path) : path
  514. if (has('win32') || has('win64')) && match(&shell, 'sh') != -1
  515. let path = tr(path, '\', '/')
  516. en
  517. if s:usrcmdasync && (v:version >= 800 || has('nvim')) && (exists('*job_start') || exists('*jobstart'))
  518. cal s:stop_job_if_exists()
  519. let g:ctrlp_allfiles = []
  520. let s:must_wait = 1
  521. let argv = [&shell, &shellcmdflag, printf(lscmd, path)]
  522. if !has('nvim')
  523. let s:job = job_start(argv, {
  524. \ 'out_cb': function('s:async_glob_on_stdout'),
  525. \ 'exit_cb': function('s:async_glob_on_exit')
  526. \ })
  527. el
  528. let s:job = jobstart(argv, {
  529. \ 'on_stdout': function('s:async_glob_on_stdout'),
  530. \ 'on_exit': function('s:async_glob_on_exit')
  531. \ })
  532. en
  533. let s:timer = timer_start(250, function('s:async_glob_update_progress'), {'repeat': -1})
  534. while s:must_wait
  535. sleep 50m
  536. endwhile
  537. elsei has('patch-7.4-597') && !(has('win32') || has('win64'))
  538. let g:ctrlp_allfiles = systemlist(s:safe_printf(lscmd, path))
  539. el
  540. let g:ctrlp_allfiles = split(system(s:safe_printf(lscmd, path)), "\n")
  541. en
  542. if exists('+ssl') && exists('ssl')
  543. let &ssl = ssl
  544. cal map(g:ctrlp_allfiles, 'tr(v:val, "\\", "/")')
  545. en
  546. if exists('s:vcscmd') && s:vcscmd
  547. cal map(g:ctrlp_allfiles, 'tr(v:val, "/", "\\")')
  548. en
  549. if do_ign
  550. if !empty(s:usrign)
  551. let g:ctrlp_allfiles = ctrlp#dirnfile(g:ctrlp_allfiles)[1]
  552. en
  553. if &wig != ''
  554. cal filter(g:ctrlp_allfiles, 'glob(v:val) != ""')
  555. en
  556. en
  557. endf
  558. fu! s:lsCmd()
  559. let cmd = s:usrcmd
  560. if type(cmd) == 1
  561. retu cmd
  562. elsei type(cmd) == 3 && len(cmd) >= 2 && cmd[:1] != ['', '']
  563. if s:findroot(s:dyncwd, cmd[0], 0, 1) == []
  564. retu len(cmd) == 3 ? cmd[2] : ''
  565. en
  566. let s:vcscmd = s:lash == '\'
  567. retu cmd[1]
  568. elsei type(cmd) == 4 && ( has_key(cmd, 'types') || has_key(cmd, 'fallback') )
  569. let fndroot = []
  570. if get(cmd, 'types', {}) != {}
  571. let [markrs, cmdtypes] = [[], values(cmd['types'])]
  572. for pair in cmdtypes
  573. cal add(markrs, pair[0])
  574. endfo
  575. let fndroot = s:findroot(s:dyncwd, markrs, 0, 1)
  576. en
  577. if fndroot == []
  578. retu get(cmd, 'fallback', '')
  579. en
  580. for pair in cmdtypes
  581. if pair[0] == fndroot[0] | brea | en
  582. endfo
  583. let s:vcscmd = s:lash == '\'
  584. retu pair[1]
  585. en
  586. endf
  587. " - Buffers {{{1
  588. fu! s:bufparts(bufnr)
  589. let idc = (a:bufnr == bufnr('#') ? '#' : '') " alternative
  590. let idc .= (getbufvar(a:bufnr, '&mod') ? '+' : '') " modified
  591. let idc .= (getbufvar(a:bufnr, '&ma') ? '' : '-') " nomodifiable
  592. let idc .= (getbufvar(a:bufnr, '&ro') ? '=' : '') " readonly
  593. " flags for highlighting
  594. let hiflags = (bufwinnr(a:bufnr) != -1 ? '*' : '') " visible
  595. let hiflags .= (getbufvar(a:bufnr, '&mod') ? '+' : '') " modified
  596. let hiflags .= (a:bufnr == s:crbufnr ? '!' : '') " current
  597. let bname = bufname(a:bufnr)
  598. let bname = (bname == '' ? '[No Name]' : fnamemodify(bname, s:bufname_mod))
  599. let bpath = empty(s:bufpath_mod) ? '' : fnamemodify(bufname(a:bufnr), s:bufpath_mod).s:lash()
  600. retu [idc, hiflags, bname, bpath]
  601. endf
  602. fu! ctrlp#buffers(...)
  603. let ids = sort(filter(range(1, bufnr('$')), '(empty(getbufvar(v:val, "&bt"))'
  604. \ .' || s:isterminal(v:val)) && getbufvar(v:val, "&bl")'), 's:compmreb')
  605. if a:0 && a:1 == 'id'
  606. retu ids
  607. el
  608. let bufs = [[], []]
  609. if s:matcher != {} && !s:matchcrfile
  610. call filter(ids, 'v:val != s:crbufnr')
  611. en
  612. for id in ids
  613. let bname = bufname(id)
  614. let ebname = bname == ''
  615. let fname = fnamemodify(ebname ? '['.id.'*No Name]' : bname, ':.')
  616. cal add(bufs[ebname], fname)
  617. endfo
  618. retu bufs[0] + bufs[1]
  619. en
  620. endf
  621. " * MatchedItems() {{{1
  622. fu! s:MatchIt(items, pat, limit, exc)
  623. let [lines, id] = [[], 0]
  624. let pat =
  625. \ s:byfname() ? map(split(a:pat, '^[^;]\+\\\@<!\zs;', 1), 's:martcs.v:val')
  626. \ : s:martcs.a:pat
  627. for item in a:items
  628. let id += 1
  629. try
  630. if (s:matchcrfile || !( s:ispath && item ==# a:exc )) &&
  631. \call(s:mfunc, [item, pat]) >= 0
  632. let lines += [item]
  633. en
  634. cat | brea | endt
  635. if a:limit > 0 && len(lines) >= a:limit | brea | en
  636. endfo
  637. let s:mdata = [s:dyncwd, s:itemtype, s:regexp, s:sublist(a:items, id, -1)]
  638. retu lines
  639. endf
  640. fu! s:MatchedItems(items, pat, limit)
  641. let exc = exists('s:crfilerel') ? s:crfilerel : ''
  642. let items = s:narrowable() ? s:matched + s:mdata[3] : a:items
  643. let matcher = s:getextvar('matcher')
  644. if empty(matcher) || type(matcher) != 4 || !has_key(matcher, 'match')
  645. unl matcher
  646. let matcher = s:matcher
  647. en
  648. if matcher != {}
  649. let argms =
  650. \ get(matcher, 'arg_type', '') == 'dict' ? [{
  651. \ 'items': items,
  652. \ 'str': a:pat,
  653. \ 'limit': a:limit,
  654. \ 'mmode': s:mmode(),
  655. \ 'ispath': s:ispath,
  656. \ 'crfile': exc,
  657. \ 'regex': s:regexp,
  658. \ }] : [items, a:pat, a:limit, s:mmode(), s:ispath, exc, s:regexp]
  659. let lines = call(matcher['match'], argms, matcher)
  660. el
  661. let lines = s:MatchIt(items, a:pat, a:limit, exc)
  662. en
  663. let s:matches = len(lines)
  664. unl! s:did_exp
  665. retu lines
  666. endf
  667. fu! s:SplitPattern(str)
  668. let str = a:str
  669. let s:savestr = str
  670. if s:regexp
  671. let pat = s:regexfilter(str)
  672. el
  673. let lst = split(str, '\zs')
  674. if exists('+ssl') && !&ssl
  675. cal map(lst, 'escape(v:val, ''\'')')
  676. en
  677. for each in ['^', '$', '.']
  678. cal map(lst, 'escape(v:val, each)')
  679. endfo
  680. en
  681. if exists('lst')
  682. let pat = ''
  683. if !empty(lst)
  684. if s:byfname() && index(lst, ';') > 0
  685. let fbar = index(lst, ';')
  686. let lst_1 = s:sublist(lst, 0, fbar - 1)
  687. let lst_2 = len(lst) - 1 > fbar ? s:sublist(lst, fbar + 1, -1) : ['']
  688. let pat = s:buildpat(lst_1).';'.s:buildpat(lst_2)
  689. el
  690. let pat = s:buildpat(lst)
  691. en
  692. en
  693. en
  694. retu escape(pat, '~')
  695. endf
  696. " * BuildPrompt() {{{1
  697. fu! s:Render(lines, pat)
  698. let [&ma, lines, s:res_count] = [1, a:lines, len(a:lines)]
  699. let height = min([max([s:mw_min, s:res_count]), s:winmaxh])
  700. let pat = s:byfname() ? split(a:pat, '^[^;]\+\\\@<!\zs;', 1)[0] : a:pat
  701. let cur_cmd = 'keepj norm! '.( s:mw_order == 'btt' ? 'G' : 'gg' ).'1|'
  702. " Setup the match window
  703. sil! exe '%d _ | res' height
  704. " Print the new items
  705. if empty(lines)
  706. let [s:matched, s:lines] = [[], []]
  707. let lines = [' == NO ENTRIES ==']
  708. cal setline(1, s:offset(lines, height - 1))
  709. setl noma nocul
  710. exe cur_cmd
  711. cal s:unmarksigns()
  712. if s:dohighlight() | cal clearmatches() | en
  713. retu
  714. en
  715. let s:matched = copy(lines)
  716. " Sorting
  717. if !s:nosort()
  718. let s:compat = s:martcs.pat
  719. if has('patch-8.1-0')
  720. cal sort(lines, function('s:mixedsort2', [s:curtype()]))
  721. el
  722. cal sort(lines, 's:mixedsort')
  723. en
  724. unl s:compat
  725. en
  726. if s:mw_order == 'btt' | cal reverse(lines) | en
  727. let s:lines = copy(lines)
  728. if s:nolim == 0 && len(lines) > height
  729. let lines = lines[:height-1]
  730. en
  731. if has('patch-8.1-0') && s:flfunc ==# 's:formatline(v:val)'
  732. cal map(lines, function('s:formatline2', [s:curtype()]))
  733. el
  734. cal map(lines, s:flfunc)
  735. en
  736. cal setline(1, s:offset(lines, height))
  737. cal s:unmarksigns()
  738. cal s:remarksigns()
  739. " Highlighting
  740. if s:dohighlight()
  741. cal s:highlight(pat, s:mathi[1])
  742. en
  743. setl noma cul
  744. exe cur_cmd
  745. endf
  746. fu! s:Update(str)
  747. " Get the previous string if existed
  748. let oldstr = exists('s:savestr') ? s:savestr : ''
  749. " Get the new string sans tail
  750. let str = s:sanstail(a:str)
  751. " Stop if the string's unchanged
  752. if str == oldstr && !empty(str) && !exists('s:force') | retu | en
  753. " Optionally send the string to a custom validate function
  754. if s:validate != '' | let str = call(s:validate, [str]) | en
  755. let s:martcs = &scs && str =~ '\u' ? '\C' : ''
  756. let pat = s:matcher == {} ? s:SplitPattern(str) : str
  757. let lines = s:nolim == 1 && empty(str) ? copy(g:ctrlp_lines)
  758. \ : s:MatchedItems(g:ctrlp_lines, pat, s:mw_res)
  759. if empty(str) | cal clearmatches() | en
  760. cal s:Render(lines, pat)
  761. retu lines
  762. endf
  763. fu! s:ForceUpdate()
  764. let pos = exists('*getcurpos') ? getcurpos() : getpos('.')
  765. sil! cal s:Update(escape(s:getinput(), '\'))
  766. cal setpos('.', pos)
  767. endf
  768. fu! s:BuildPrompt(upd)
  769. let base = ( s:regexp ? 'r' : '>' ).( s:byfname() ? 'd' : '>' ).'> '
  770. let str = escape(s:getinput(), '\')
  771. let lazy = str == '' || exists('s:force') || !has('autocmd') ? 0 : s:lazy
  772. if a:upd && !lazy && ( s:matches || s:regexp || exists('s:did_exp')
  773. \ || str =~ '\(\\\(<\|>\)\|[*|]\)\|\(\\\:\([^:]\|\\:\)*$\)' )
  774. sil! cal s:Update(str)
  775. en
  776. sil! cal ctrlp#statusline()
  777. " Toggling
  778. let [hiactive, hicursor, base] = s:focus
  779. \ ? ['CtrlPPrtText', 'CtrlPPrtCursor', base]
  780. \ : ['CtrlPPrtBase', 'CtrlPPrtBase', tr(base, '>', '-')]
  781. let hibase = 'CtrlPPrtBase'
  782. " Build it
  783. redr
  784. let prt = copy(s:prompt)
  785. cal map(prt, 'escape(v:val, ''"\'')')
  786. exe 'echoh' hibase '| echon "'.base.'"
  787. \ | echoh' hiactive '| echon "'.prt[0].'"
  788. \ | echoh' hicursor '| echon "'.prt[1].'"
  789. \ | echoh' hiactive '| echon "'.prt[2].'" | echoh None'
  790. " Append the cursor at the end
  791. if empty(prt[1]) && s:focus
  792. exe 'echoh' hibase '| echon "_" | echoh None'
  793. en
  794. if a:upd
  795. cal s:NotifySearch()
  796. en
  797. endf
  798. " - SetDefTxt() {{{1
  799. fu! s:SetDefTxt()
  800. if s:deftxt == '0' || ( s:deftxt == 1 && !s:ispath ) | retu | en
  801. let txt = s:deftxt
  802. if !type(txt)
  803. let path = s:crfpath.s:lash(s:crfpath)
  804. let txt = txt && !stridx(path, s:dyncwd) ? ctrlp#rmbasedir([path])[0] : ''
  805. en
  806. let s:prompt[0] = txt
  807. endf
  808. " ** Prt Actions {{{1
  809. " Editing {{{2
  810. fu! s:PrtClear()
  811. if !s:focus | retu | en
  812. unl! s:hstgot
  813. let [s:prompt, s:matches] = [['', '', ''], 1]
  814. cal s:BuildPrompt(1)
  815. endf
  816. fu! s:PrtAdd(char)
  817. unl! s:hstgot
  818. let s:act_add = 1
  819. let s:prompt[0] .= a:char
  820. cal s:BuildPrompt(1)
  821. unl s:act_add
  822. endf
  823. fu! s:PrtBS()
  824. if !s:focus | retu | en
  825. if empty(s:prompt[0]) && s:brfprt != 0
  826. cal s:PrtExit()
  827. retu
  828. en
  829. unl! s:hstgot
  830. let [s:prompt[0], s:matches] = [substitute(s:prompt[0], '.$', '', ''), 1]
  831. cal s:BuildPrompt(1)
  832. endf
  833. fu! s:PrtDelete()
  834. if !s:focus | retu | en
  835. unl! s:hstgot
  836. let [prt, s:matches] = [s:prompt, 1]
  837. let prt[1] = matchstr(prt[2], '^.')
  838. let prt[2] = substitute(prt[2], '^.', '', '')
  839. cal s:BuildPrompt(1)
  840. endf
  841. fu! s:PrtDeleteWord()
  842. if !s:focus | retu | en
  843. unl! s:hstgot
  844. let [str, s:matches] = [s:prompt[0], 1]
  845. let str = str =~ '\W\w\+$' ? matchstr(str, '^.\+\W\ze\w\+$')
  846. \ : str =~ '\w\W\+$' ? matchstr(str, '^.\+\w\ze\W\+$')
  847. \ : str =~ '\s\+$' ? matchstr(str, '^.*\S\ze\s\+$')
  848. \ : str =~ '\v^(\S+|\s+)$' ? '' : str
  849. let s:prompt[0] = str
  850. cal s:BuildPrompt(1)
  851. endf
  852. fu! s:PrtInsert(...)
  853. if !s:focus | retu | en
  854. let type = !a:0 ? '' : a:1
  855. if !a:0
  856. let type = s:insertstr()
  857. if type == 'cancel' | retu | en
  858. en
  859. if type ==# 'r'
  860. let regcont = s:getregs()
  861. if regcont < 0 | retu | en
  862. en
  863. unl! s:hstgot
  864. let s:act_add = 1
  865. let s:prompt[0] .= type ==# 'w' ? s:crword
  866. \ : type ==# 'f' ? s:crgfile
  867. \ : type ==# 's' ? s:regisfilter('/')
  868. \ : type ==# 'v' ? s:crvisual
  869. \ : type ==# 'c' ? s:regisfilter('+')
  870. \ : type ==# 'r' ? regcont : ''
  871. cal s:BuildPrompt(1)
  872. unl s:act_add
  873. endf
  874. fu! s:PrtExpandDir()
  875. if !s:focus | retu | en
  876. let str = s:getinput('c')
  877. if str =~ '\v^\@(cd|lc[hd]?|chd)\s.+' && s:spi
  878. let hasat = split(str, '\v^\@(cd|lc[hd]?|chd)\s*\zs')
  879. let str = get(hasat, 1, '')
  880. if str =~# '\v^[~$]\i{-}[\/]?|^#(\<?\d+)?:(p|h|8|\~|\.|g?s+)'
  881. let str = expand(s:fnesc(str, 'g'))
  882. elsei str =~# '\v^(\%|\<c\h{4}\>):(p|h|8|\~|\.|g?s+)'
  883. let spc = str =~# '^%' ? s:crfile
  884. \ : str =~# '^<cfile>' ? s:crgfile
  885. \ : str =~# '^<cword>' ? s:crword
  886. \ : str =~# '^<cWORD>' ? s:crnbword : ''
  887. let pat = '(:(p|h|8|\~|\.|g?s(.)[^\3]*\3[^\3]*\3))+'
  888. let mdr = matchstr(str, '\v^[^:]+\zs'.pat)
  889. let nmd = matchstr(str, '\v^[^:]+'.pat.'\zs.{-}$')
  890. let str = fnamemodify(s:fnesc(spc, 'g'), mdr).nmd
  891. en
  892. en
  893. if str == '' | retu | en
  894. unl! s:hstgot
  895. let s:act_add = 1
  896. let [base, seed] = s:headntail(str)
  897. if str =~# '^[\/]'
  898. let base = expand('/').base
  899. en
  900. let dirs = s:dircompl(base, seed)
  901. if len(dirs) == 1
  902. let str = dirs[0]
  903. elsei len(dirs) > 1
  904. let str .= s:findcommon(dirs, str)
  905. en
  906. let s:prompt[0] = exists('hasat') ? hasat[0].str : str
  907. cal s:BuildPrompt(1)
  908. unl s:act_add
  909. endf
  910. " Movement {{{2
  911. fu! s:PrtCurLeft()
  912. if !s:focus | retu | en
  913. let prt = s:prompt
  914. if !empty(prt[0])
  915. let s:prompt = [substitute(prt[0], '.$', '', ''), matchstr(prt[0], '.$'),
  916. \ prt[1] . prt[2]]
  917. en
  918. cal s:BuildPrompt(0)
  919. endf
  920. fu! s:PrtCurRight()
  921. if !s:focus | retu | en
  922. let prt = s:prompt
  923. let s:prompt = [prt[0] . prt[1], matchstr(prt[2], '^.'),
  924. \ substitute(prt[2], '^.', '', '')]
  925. cal s:BuildPrompt(0)
  926. endf
  927. fu! s:PrtCurStart()
  928. if !s:focus | retu | en
  929. let str = join(s:prompt, '')
  930. let s:prompt = ['', matchstr(str, '^.'), substitute(str, '^.', '', '')]
  931. cal s:BuildPrompt(0)
  932. endf
  933. fu! s:PrtCurEnd()
  934. if !s:focus | retu | en
  935. let s:prompt = [join(s:prompt, ''), '', '']
  936. cal s:BuildPrompt(0)
  937. endf
  938. fu! s:PrtSelectMove(dir)
  939. let wht = winheight(0)
  940. let dirs = {'t': 'gg','b': 'G','j': 'j','k': 'k','u': wht.'k','d': wht.'j'}
  941. exe 'keepj norm!' dirs[a:dir]
  942. let pos = exists('*getcurpos') ? getcurpos() : getpos('.')
  943. cal s:BuildPrompt(0)
  944. cal setpos('.', pos)
  945. endf
  946. fu! s:PrtSelectJump(char)
  947. let lines = copy(s:lines)
  948. if s:byfname()
  949. cal map(lines, 'split(v:val, ''[\/]\ze[^\/]\+$'')[-1]')
  950. en
  951. " Cycle through matches, use s:jmpchr to store last jump
  952. let chr = escape(matchstr(a:char, '^.'), '.~')
  953. let smartcs = &scs && chr =~ '\u' ? '\C' : ''
  954. if match(lines, smartcs.'^'.chr) >= 0
  955. " If not exists or does but not for the same char
  956. let pos = match(lines, smartcs.'^'.chr)
  957. if !exists('s:jmpchr') || ( exists('s:jmpchr') && s:jmpchr[0] != chr )
  958. let [jmpln, s:jmpchr] = [pos, [chr, pos]]
  959. elsei exists('s:jmpchr') && s:jmpchr[0] == chr
  960. " Start of lines
  961. if s:jmpchr[1] == -1 | let s:jmpchr[1] = pos | en
  962. let npos = match(lines, smartcs.'^'.chr, s:jmpchr[1] + 1)
  963. let [jmpln, s:jmpchr] = [npos == -1 ? pos : npos, [chr, npos]]
  964. en
  965. exe 'keepj norm!' ( jmpln + 1 ).'G'
  966. let pos = exists('*getcurpos') ? getcurpos() : getpos('.')
  967. cal s:BuildPrompt(0)
  968. cal setpos('.', pos)
  969. en
  970. endf
  971. " Misc {{{2
  972. fu! s:PrtFocusMap(char)
  973. cal call(( s:focus ? 's:PrtAdd' : 's:PrtSelectJump' ), [a:char])
  974. endf
  975. fu! s:PrtClearCache()
  976. let ct = s:curtype()
  977. if ct == 'fil'
  978. cal ctrlp#clr()
  979. elsei s:itemtype >= len(s:coretypes)
  980. cal ctrlp#clr(s:statypes[s:itemtype][1])
  981. en
  982. if ct == 'mru'
  983. let g:ctrlp_lines = ctrlp#mrufiles#refresh()
  984. el
  985. cal ctrlp#setlines()
  986. en
  987. let s:force = 1
  988. cal s:BuildPrompt(1)
  989. unl s:force
  990. endf
  991. fu! s:PrtDeleteEnt()
  992. let ct = s:curtype()
  993. if ct == 'mru'
  994. cal s:PrtDeleteMRU()
  995. elsei ct == 'buf'
  996. cal s:delbuf()
  997. elsei type(s:getextvar('wipe')) == 1
  998. cal s:delent(s:getextvar('wipe'))
  999. en
  1000. endf
  1001. fu! s:PrtDeleteMRU()
  1002. if s:curtype() == 'mru'
  1003. cal s:delent('ctrlp#mrufiles#remove')
  1004. en
  1005. endf
  1006. fu! s:PrtExit()
  1007. let bw = bufwinnr('%')
  1008. exe bufwinnr(s:bufnr).'winc w'
  1009. if bufnr('%') == s:bufnr && bufname('%') == 'ControlP'
  1010. noa cal s:Close()
  1011. noa winc p
  1012. els
  1013. exe bw.'winc w'
  1014. en
  1015. endf
  1016. fu! s:PrtHistory(...)
  1017. if !s:focus || !s:maxhst | retu | en
  1018. let [str, hst, s:matches] = [join(s:prompt, ''), s:hstry, 1]
  1019. " Save to history if not saved before
  1020. let [hst[0], hslen] = [exists('s:hstgot') ? hst[0] : str, len(hst)]
  1021. let idx = exists('s:hisidx') ? s:hisidx + a:1 : a:1
  1022. " Limit idx within 0 and hslen
  1023. let idx = idx < 0 ? 0 : idx >= hslen ? hslen > 1 ? hslen - 1 : 0 : idx
  1024. let s:prompt = [hst[idx], '', '']
  1025. let [s:hisidx, s:hstgot, s:force] = [idx, 1, 1]
  1026. cal s:BuildPrompt(1)
  1027. unl s:force
  1028. endf
  1029. "}}}1
  1030. " * Mappings {{{1
  1031. fu! s:MapNorms()
  1032. if exists('s:nmapped') && s:nmapped == s:bufnr | retu | en
  1033. let pcmd = "nn \<buffer> \<silent> \<k%s> :\<c-u>cal \<SID>%s(\"%s\")\<cr>"
  1034. let cmd = substitute(pcmd, 'k%s', 'char-%d', '')
  1035. let pfunc = 'PrtFocusMap'
  1036. let ranges = [32, 33, 125, 126] + range(35, 91) + range(93, 123)
  1037. for each in [34, 92, 124]
  1038. exe printf(cmd, each, pfunc, escape(nr2char(each), '"|\'))
  1039. endfo
  1040. for each in ranges
  1041. exe printf(cmd, each, pfunc, nr2char(each))
  1042. endfo
  1043. for each in range(0, 9)
  1044. exe printf(pcmd, each, pfunc, each)
  1045. endfo
  1046. for [ke, va] in items(s:kprange)
  1047. exe printf(pcmd, ke, pfunc, va)
  1048. endfo
  1049. let s:nmapped = s:bufnr
  1050. endf
  1051. fu! s:MapSpecs()
  1052. if !( exists('s:smapped') && s:smapped == s:bufnr )
  1053. " Correct arrow keys in terminal
  1054. if ( has('termresponse') && v:termresponse =~ "\<ESC>" )
  1055. \ || &term =~? '\vxterm|<k?vt|gnome|screen|linux|ansi|tmux|alacritty|st(-[-a-z0-9]*)?(\:tc)?$'
  1056. for each in ['\A <up>','\B <down>','\C <right>','\D <left>']
  1057. exe s:lcmap.' <esc>['.each
  1058. endfo
  1059. en
  1060. en
  1061. for [ke, va] in items(s:prtmaps) | for kp in va
  1062. exe s:lcmap kp ':<c-u>cal <SID>'.ke.'<cr>'
  1063. endfo | endfo
  1064. let s:smapped = s:bufnr
  1065. endf
  1066. fu! s:KeyLoop()
  1067. let [t_ve, guicursor] = [&t_ve, &guicursor]
  1068. wh exists('s:init') && s:keyloop
  1069. try
  1070. set t_ve=
  1071. if guicursor != ''
  1072. set guicursor=a:NONE
  1073. en
  1074. let nr = getchar()
  1075. fina
  1076. let &t_ve = t_ve
  1077. let &guicursor = guicursor
  1078. endt
  1079. let chr = !type(nr) ? nr2char(nr) : nr
  1080. if nr >=# 0x20
  1081. cal s:PrtFocusMap(chr)
  1082. el
  1083. let cmd = matchstr(maparg(chr), ':<C-U>\zs.\+\ze<CR>$')
  1084. try
  1085. exe ( cmd != '' ? cmd : 'norm '.chr )
  1086. cat
  1087. endt
  1088. en
  1089. endw
  1090. endf
  1091. " * Toggling {{{1
  1092. fu! s:ToggleFocus()
  1093. let s:focus = !s:focus
  1094. cal s:BuildPrompt(0)
  1095. endf
  1096. fu! s:ToggleRegex()
  1097. let s:regexp = !s:regexp
  1098. cal s:PrtSwitcher()
  1099. endf
  1100. fu! s:ToggleByFname()
  1101. if s:ispath
  1102. let s:byfname = !s:byfname
  1103. let s:mfunc = s:mfunc()
  1104. cal s:PrtSwitcher()
  1105. en
  1106. endf
  1107. fu! s:ToggleType(dir)
  1108. cal s:async_glob_abort(1)
  1109. let max = len(g:ctrlp_ext_vars) + len(s:coretypes) - 1
  1110. let next = s:walker(max, s:itemtype, a:dir)
  1111. cal ctrlp#setlines(next)
  1112. cal ctrlp#syntax()
  1113. cal s:PrtSwitcher()
  1114. endf
  1115. fu! s:ToggleKeyLoop()
  1116. let s:keyloop = !s:keyloop
  1117. if exists('+imd')
  1118. let &imd = !s:keyloop
  1119. en
  1120. if s:keyloop
  1121. let [&ut, s:lazy] = [0, 0]
  1122. cal s:KeyLoop()
  1123. elsei has_key(s:glbs, 'ut')
  1124. let [&ut, s:lazy] = [s:glbs['ut'], 1]
  1125. en
  1126. endf
  1127. fu! s:ToggleMRURelative()
  1128. cal ctrlp#mrufiles#tgrel()
  1129. cal s:PrtClearCache()
  1130. endf
  1131. fu! s:PrtSwitcher()
  1132. let [s:force, s:matches] = [1, 1]
  1133. cal s:BuildPrompt(1)
  1134. unl s:force
  1135. endf
  1136. " - SetWD() {{{1
  1137. fu! s:SetWD(args)
  1138. if has_key(a:args, 'args') && stridx(a:args['args'], '--dir') >= 0
  1139. \ && exists('s:dyncwd')
  1140. cal ctrlp#setdir(s:dyncwd) | retu
  1141. en
  1142. if get(a:args, 'dir', '') != ''
  1143. cal ctrlp#setdir(a:args['dir']) | retu
  1144. en
  1145. let pmodes = get(a:args, 'mode', s:pathmode)
  1146. let [s:crfilerel, s:dyncwd] = [fnamemodify(s:crfile, ':.'), getcwd()]
  1147. if (!type(pmodes))
  1148. let pmodes =
  1149. \ pmodes == 0 ? '' :
  1150. \ pmodes == 1 ? 'a' :
  1151. \ pmodes == 2 ? 'r' :
  1152. \ 'c'
  1153. en
  1154. let spath = pmodes =~ 'd' ? s:dyncwd : pmodes =~ 'w' ? s:cwd : s:crfpath
  1155. for pmode in split(pmodes, '\zs')
  1156. if ctrlp#setpathmode(pmode, spath) | retu | en
  1157. endfo
  1158. endf
  1159. " * AcceptSelection() {{{1
  1160. fu! ctrlp#acceptfile(...)
  1161. let useb = 0
  1162. if a:0 == 1 && type(a:1) == 4
  1163. let [md, line] = [a:1['action'], a:1['line']]
  1164. let atl = get(a:1, 'tail', '')
  1165. el
  1166. let [md, line] = [a:1, a:2]
  1167. let atl = a:0 > 2 ? a:3 : ''
  1168. en
  1169. if !type(line)
  1170. let [filpath, bufnr, useb] = [line, line, 1]
  1171. el
  1172. let [bufnr, filpath] = s:bufnrfilpath(line)
  1173. if bufnr == filpath
  1174. let useb = 1
  1175. en
  1176. en
  1177. cal s:PrtExit()
  1178. let tail = s:tail()
  1179. let j2l = atl != '' ? atl : matchstr(tail, '^ +\zs\d\+$')
  1180. let openmyself = bufnr == bufnr('%')
  1181. if bufnr > 0 && ( !empty(s:jmptobuf) && s:jmptobuf =~ md )
  1182. \ && !( md == 'e' && openmyself )
  1183. let [jmpb, bufwinnr] = [1, bufwinnr(bufnr)]
  1184. let buftab = ( s:jmptobuf =~# '[tTVH]' || s:jmptobuf > 1 )
  1185. \ ? s:buftab(bufnr, md) : [0, 0]
  1186. en
  1187. " Switch to existing buffer or open new one
  1188. if exists('jmpb') && bufwinnr > 0
  1189. \ && !( md == 't' && ( s:jmptobuf !~# toupper(md) || buftab[0] ) )
  1190. exe bufwinnr.'winc w'
  1191. if j2l | cal ctrlp#j2l(j2l) | en
  1192. elsei exists('jmpb') && buftab[0]
  1193. \ && !( md =~ '[evh]' && s:jmptobuf !~# toupper(md) )
  1194. exe 'tabn' buftab[0]
  1195. exe buftab[1].'winc w'
  1196. if j2l | cal ctrlp#j2l(j2l) | en
  1197. el
  1198. " Determine the command to use
  1199. let useb = bufnr > 0 && ( buflisted(bufnr) || openmyself ) && ( empty(tail) || useb )
  1200. let cmd =
  1201. \ md == 't' || s:splitwin == 1 ? ( useb ? 'tab sb' : 'tabe' ) :
  1202. \ md == 'h' || s:splitwin == 2 ? ( useb ? 'sb' : 'new' ) :
  1203. \ md == 'v' || s:splitwin == 3 ? ( useb ? 'vert sb' : 'vne' ) :
  1204. \ &bt == 'help' && openmyself ? 'b' :
  1205. \ call('ctrlp#normcmd', useb ? ['b', 'bo vert sb'] : ['e'])
  1206. " Reset &switchbuf option
  1207. let [swb, &swb] = [&swb, '']
  1208. " Open new window/buffer
  1209. let [fid, tail] = [( useb ? bufnr : filpath ), ( atl != '' ? ' +'.atl : tail )]
  1210. let args = [cmd, fid, tail, 1, [useb, j2l]]
  1211. cal call('s:openfile', args)
  1212. let &swb = swb
  1213. en
  1214. endf
  1215. fu! s:SpecInputs(str)
  1216. if a:str =~ '\v^(\.\.([\/]\.\.)*[\/]?[.\/]*)$' && s:spi
  1217. let cwd = s:dyncwd
  1218. cal ctrlp#setdir(a:str =~ '^\.\.\.*$' ?
  1219. \ '../'.repeat('../', strlen(a:str) - 2) : a:str)
  1220. if cwd != s:dyncwd | cal ctrlp#setlines() | en
  1221. cal s:PrtClear()
  1222. retu 1
  1223. elsei a:str == s:lash && s:spi
  1224. cal s:SetWD({ 'mode': 'rd' })
  1225. cal ctrlp#setlines()
  1226. cal s:PrtClear()
  1227. retu 1
  1228. elsei a:str =~ '^@.\+' && s:spi
  1229. retu s:at(a:str)
  1230. elsei a:str == '?'
  1231. cal s:PrtExit()
  1232. let hlpwin = &columns > 159 ? '| vert res 80' : ''
  1233. sil! exe 'bo vert h ctrlp-mappings' hlpwin '| norm! 0'
  1234. retu 1
  1235. en
  1236. retu 0
  1237. endf
  1238. fu! s:AcceptSelection(action)
  1239. let [md, icr] = [a:action[0], match(a:action, 'r') >= 0]
  1240. let subm = icr || ( !icr && md == 'e' )
  1241. if !subm && s:OpenMulti(md) != -1 | retu | en
  1242. let str = s:getinput()
  1243. if subm | if s:SpecInputs(str) | retu | en | en
  1244. " Get the selected line
  1245. let line = ctrlp#getcline()
  1246. if !subm && s:curtype() != 'fil' && line == '' && line('.') > s:offset
  1247. \ && str !~ '\v^(\.\.([\/]\.\.)*[\/]?[.\/]*|/|\\|\?|\@.+)$'
  1248. cal s:CreateNewFile(md) | retu
  1249. en
  1250. if empty(line) | retu | en
  1251. " Do something with it
  1252. if s:openfunc != {} && has_key(s:openfunc, s:ctype)
  1253. let actfunc = s:openfunc[s:ctype]
  1254. let type = get(s:openfunc, 'arg_type', 'list')
  1255. el
  1256. if s:itemtype < len(s:coretypes)
  1257. let [actfunc, type] = ['ctrlp#acceptfile', 'dict']
  1258. el
  1259. let [actfunc, exttype] = [s:getextvar('accept'), s:getextvar('act_farg')]
  1260. let type = exttype == 'dict' ? exttype : 'list'
  1261. en
  1262. en
  1263. let actargs = type == 'dict' ? [{ 'action': md, 'line': line, 'icr': icr, 'input': str}]
  1264. \ : [md, line]
  1265. cal call(actfunc, actargs)
  1266. endf
  1267. " - CreateNewFile() {{{1
  1268. fu! s:CreateNewFile(...)
  1269. let [md, str] = ['', s:getinput('n')]
  1270. if empty(str) | retu | en
  1271. if s:argmap && !a:0
  1272. " Get the extra argument
  1273. let md = s:argmaps(md, 1)
  1274. if md == 'cancel' | retu | en
  1275. en
  1276. let str = s:sanstail(str)
  1277. let [base, fname] = s:headntail(str)
  1278. if fname =~ '^[\/]$' | retu | en
  1279. if exists('s:marked') && len(s:marked)
  1280. " Use the first marked file's path
  1281. let path = fnamemodify(values(s:marked)[0], ':p:h')
  1282. let base = path.s:lash(path).base
  1283. let str = fnamemodify(base.s:lash.fname, ':.')
  1284. en
  1285. if base != '' | if isdirectory(ctrlp#utils#mkdir(base))
  1286. let optyp = str | en | el | let optyp = fname
  1287. en
  1288. if !exists('optyp') | retu | en
  1289. let [filpath, tail] = [fnamemodify(optyp, ':p'), s:tail()]
  1290. if !stridx(filpath, s:dyncwd) | cal s:insertcache(str) | en
  1291. cal s:PrtExit()
  1292. let cmd = md == 'r' ? ctrlp#normcmd('e') :
  1293. \ s:newfop =~ '1\|t' || ( a:0 && a:1 == 't' ) || md == 't' ? 'tabe' :
  1294. \ s:newfop =~ '2\|h' || ( a:0 && a:1 == 'h' ) || md == 'h' ? 'new' :
  1295. \ s:newfop =~ '3\|v' || ( a:0 && a:1 == 'v' ) || md == 'v' ? 'vne' :
  1296. \ ctrlp#normcmd('e')
  1297. cal s:openfile(cmd, filpath, tail, 1)
  1298. endf
  1299. " * OpenMulti() {{{1
  1300. fu! s:MarkToOpen()
  1301. let ct = s:curtype()
  1302. if s:bufnr <= 0 || s:opmul == '0'
  1303. \ || ( s:itemtype >= len(s:coretypes) && s:getextvar('opmul') != 1 )
  1304. retu
  1305. en
  1306. let line = ctrlp#getcline()
  1307. " Do not allow to mark modified or current buffer
  1308. let bufnr = s:bufnrfilpath(line)[0]
  1309. if (ct == 'buf' && s:delbufcond(bufnr))
  1310. retu
  1311. en
  1312. if empty(line) | retu | en
  1313. let filpath = s:ispath ? fnamemodify(line, ':p') : line
  1314. if exists('s:marked') && s:dictindex(s:marked, filpath) > 0
  1315. " Unmark and remove the file from s:marked
  1316. let key = s:dictindex(s:marked, filpath)
  1317. cal remove(s:marked, key)
  1318. if empty(s:marked) | unl s:marked | en
  1319. if has('signs')
  1320. exe 'sign unplace' key 'buffer='.s:bufnr
  1321. en
  1322. el
  1323. " Add to s:marked and place a new sign
  1324. if exists('s:marked')
  1325. let vac = s:vacantdict(s:marked)
  1326. let key = empty(vac) ? len(s:marked) + 1 : vac[0]
  1327. cal extend(s:marked, { key : filpath })
  1328. el
  1329. let [key, s:marked] = [1, { 1 : filpath }]
  1330. en
  1331. if has('signs')
  1332. exe 'sign place' key 'line='.line('.').' name=ctrlpmark buffer='.s:bufnr
  1333. en
  1334. en
  1335. sil! cal ctrlp#statusline()
  1336. redr
  1337. endf
  1338. fu! s:OpenMulti(...)
  1339. let has_marked = exists('s:marked')
  1340. if ( !has_marked && a:0 ) || s:opmul == '0' || !s:ispath
  1341. \ || ( s:itemtype >= len(s:coretypes) && s:getextvar('opmul') != 1 )
  1342. retu -1
  1343. en
  1344. " Get the options
  1345. let [nr, md] = [matchstr(s:opmul, '\d\+'), matchstr(s:opmul, '[thvi]')]
  1346. let [ur, jf] = [s:opmul =~ 'r', s:opmul =~ 'j']
  1347. let md = a:0 ? a:1 : ( md == '' ? 'v' : md )
  1348. let nopt = exists('g:ctrlp_open_multiple_files')
  1349. if !has_marked
  1350. let line = ctrlp#getcline()
  1351. if line == '' | retu | en
  1352. let marked = { 1 : fnamemodify(line, ':p') }
  1353. let [nr, ur, jf, nopt] = ['1', 0, 0, 1]
  1354. en
  1355. if ( s:argmap || !has_marked ) && !a:0
  1356. let md = s:argmaps(md, !has_marked ? 2 : 0)
  1357. if md == 'c'
  1358. cal s:unmarksigns()
  1359. unl! s:marked
  1360. cal s:BuildPrompt(0)
  1361. elsei !has_marked && md =~ '[axd]'
  1362. retu s:OpenNoMarks(md, line)
  1363. en
  1364. if md =~ '\v^c(ancel)?$' | retu | en
  1365. let nr = nr == '0' ? ( nopt ? '' : '1' ) : nr
  1366. let ur = !has_marked && md == 'r' ? 1 : ur
  1367. en
  1368. let mkd = values(has_marked ? s:marked : marked)
  1369. cal s:sanstail(join(s:prompt, ''))
  1370. cal s:PrtExit()
  1371. if nr == '0' || md == 'i'
  1372. retu map(mkd, "s:openfile('bad', v:val, '', 0)")
  1373. en
  1374. let tail = s:tail()
  1375. let [emptytail, bufnr] = [empty(tail), bufnr('^'.mkd[0].'$')]
  1376. let useb = bufnr > 0 && buflisted(bufnr) && emptytail
  1377. " Move to a replaceable window
  1378. let ncmd = ( useb ? ['b', 'bo vert sb'] : ['e', 'bo vne'] )
  1379. \ + ( ur ? [] : ['ignruw'] )
  1380. let fst = call('ctrlp#normcmd', ncmd)
  1381. " Check if the current window has a replaceable buffer
  1382. let repabl = !( md == 't' && !ur ) && empty(bufname('%')) && empty(&l:ft)
  1383. " Commands for the rest of the files
  1384. let [ic, cmds] = [1, { 'v': ['vert sb', 'vne'], 'h': ['sb', 'new'],
  1385. \ 't': ['tab sb', 'tabe'] }]
  1386. let [swb, &swb] = [&swb, '']
  1387. if md == 't' && ctrlp#tabcount() < tabpagenr()
  1388. let s:tabct = ctrlp#tabcount()
  1389. en
  1390. " Open the files
  1391. for va in mkd
  1392. let bufnr = bufnr('^'.va.'$')
  1393. if bufnr < 0 && getftype(va) == '' | con | en
  1394. let useb = bufnr > 0 && buflisted(bufnr) && emptytail
  1395. let snd = md != '' && has_key(cmds, md) ?
  1396. \ ( useb ? cmds[md][0] : cmds[md][1] ) : ( useb ? 'vert sb' : 'vne' )
  1397. let cmd = ic == 1 && ( !( !ur && fst =~ '^[eb]$' ) || repabl ) ? fst : snd
  1398. let conds = [( nr != '' && nr > 1 && nr < ic ) || ( nr == '' && ic > 1 ),
  1399. \ nr != '' && nr < ic]
  1400. if conds[nopt]
  1401. if !buflisted(bufnr) | cal s:openfile('bad', va, '', 0) | en
  1402. el
  1403. cal s:openfile(cmd, useb ? bufnr : va, tail, ic == 1)
  1404. if jf | if ic == 1
  1405. let crpos = [tabpagenr(), winnr()]
  1406. el
  1407. let crpos[0] += tabpagenr() <= crpos[0]
  1408. let crpos[1] += winnr() <= crpos[1]
  1409. en | en
  1410. let ic += 1
  1411. en
  1412. endfo
  1413. if jf && exists('crpos') && ic > 2
  1414. exe ( md == 't' ? 'tabn '.crpos[0] : crpos[1].'winc w' )
  1415. en
  1416. let &swb = swb
  1417. unl! s:tabct
  1418. endf
  1419. fu! s:YankLine(...)
  1420. let @" = s:getinput()
  1421. let has_marked = exists('s:marked')
  1422. if !has_marked
  1423. let line = ctrlp#getcline()
  1424. if line == '' | retu | en
  1425. let marked = { 1 : fnamemodify(line, ':p') }
  1426. en
  1427. let @" = join(values(has_marked ? s:marked : marked), "\n")
  1428. cal s:PrtExit()
  1429. endf
  1430. fu! s:OpenNoMarks(md, line)
  1431. if a:md == 'a'
  1432. let [s:marked, key] = [{}, 1]
  1433. for line in s:lines
  1434. cal extend(s:marked, { key : fnamemodify(line, ':p') })
  1435. let key += 1
  1436. endfo
  1437. cal s:remarksigns()
  1438. cal s:BuildPrompt(0)
  1439. elsei a:md == 'x'
  1440. let type = get(s:openfunc, 'arg_type', 'dict')
  1441. let argms = type == 'dict' ? [{ 'action': a:md, 'line': a:line }]
  1442. \ : [a:md, a:line]
  1443. cal call(s:openfunc[s:ctype], argms, s:openfunc)
  1444. elsei a:md == 'd'
  1445. let dir = fnamemodify(a:line, ':h')
  1446. if isdirectory(dir)
  1447. cal ctrlp#setdir(dir)
  1448. cal ctrlp#switchtype(0)
  1449. cal ctrlp#recordhist()
  1450. cal s:PrtClear()
  1451. en
  1452. en
  1453. endf
  1454. " ** Helper functions {{{1
  1455. " Sorting {{{2
  1456. fu! ctrlp#complen(...)
  1457. " By length
  1458. let [len1, len2] = [strlen(a:1), strlen(a:2)]
  1459. retu len1 == len2 ? 0 : len1 > len2 ? 1 : -1
  1460. endf
  1461. fu! s:compmatlen(...)
  1462. " By match length
  1463. let mln1 = s:shortest(s:matchlens(a:1, s:compat))
  1464. let mln2 = s:shortest(s:matchlens(a:2, s:compat))
  1465. retu mln1 == mln2 ? 0 : mln1 > mln2 ? 1 : -1
  1466. endf
  1467. fu! s:comptime(...)
  1468. " By last modified time
  1469. let [time1, time2] = [getftime(a:1), getftime(a:2)]
  1470. retu time1 == time2 ? 0 : time1 < time2 ? 1 : -1
  1471. endf
  1472. fu! s:compmreb(...)
  1473. " By last entered time (bufnr)
  1474. let [id1, id2] = [index(s:mrbs, a:1), index(s:mrbs, a:2)]
  1475. if id1 == id2
  1476. retu 0
  1477. en
  1478. if id1 < 0
  1479. retu 1
  1480. en
  1481. if id2 < 0
  1482. retu -1
  1483. en
  1484. retu id1 > id2 ? 1 : -1
  1485. endf
  1486. fu! s:compmref(...)
  1487. " By last entered time (MRU)
  1488. let [id1, id2] = [index(g:ctrlp_lines, a:1), index(g:ctrlp_lines, a:2)]
  1489. retu id1 == id2 ? 0 : id1 > id2 ? 1 : -1
  1490. endf
  1491. fu! s:comparent(...)
  1492. " By same parent dir
  1493. if !stridx(s:crfpath, s:dyncwd)
  1494. let [as1, as2] = [s:dyncwd.s:lash().a:1, s:dyncwd.s:lash().a:2]
  1495. let [loc1, loc2] = [s:getparent(as1), s:getparent(as2)]
  1496. if loc1 == s:crfpath && loc2 != s:crfpath | retu -1 | en
  1497. if loc2 == s:crfpath && loc1 != s:crfpath | retu 1 | en
  1498. retu 0
  1499. en
  1500. retu 0
  1501. endf
  1502. fu! s:compfnlen(...)
  1503. " By filename length
  1504. let len1 = strlen(split(a:1, s:lash)[-1])
  1505. let len2 = strlen(split(a:2, s:lash)[-1])
  1506. retu len1 == len2 ? 0 : len1 > len2 ? 1 : -1
  1507. endf
  1508. fu! s:matchlens(str, pat, ...)
  1509. if empty(a:pat) || index(['^', '$'], a:pat) >= 0 | retu {} | en
  1510. let st = a:0 ? a:1 : 0
  1511. let lens = a:0 >= 2 ? a:2 : {}
  1512. let nr = a:0 >= 3 ? a:3 : 0
  1513. if nr > 20 | retu {} | en
  1514. if match(a:str, a:pat, st) >= 0
  1515. let [mst, mnd] = [matchstr(a:str, a:pat, st), matchend(a:str, a:pat, st)]
  1516. cal extend(lens, { nr : [strlen(mst), mst] })
  1517. let lens = s:matchlens(a:str, a:pat, mnd, lens, nr + 1)
  1518. en
  1519. retu lens
  1520. endf
  1521. fu! s:shortest(lens)
  1522. retu min(map(values(a:lens), 'v:val[0]'))
  1523. endf
  1524. fu! s:mixedsort2(ct, ...)
  1525. if a:ct == 'buf'
  1526. let pat = '[\/]\?\[\d\+\*No Name\]$'
  1527. if a:1 =~# pat && a:2 =~# pat | retu 0
  1528. elsei a:1 =~# pat | retu 1
  1529. elsei a:2 =~# pat | retu -1 | en
  1530. en
  1531. let [cln, cml] = [ctrlp#complen(a:1, a:2), s:compmatlen(a:1, a:2)]
  1532. if s:ispath
  1533. let ms = []
  1534. if s:res_count < 21
  1535. let ms += [s:compfnlen(a:1, a:2)]
  1536. if a:ct !~ '^\(buf\|mru\)$' | let ms += [s:comptime(a:1, a:2)] | en
  1537. if !s:itemtype | let ms += [s:comparent(a:1, a:2)] | en
  1538. en
  1539. if a:ct =~ '^\(buf\|mru\)$'
  1540. let ms += [s:compmref(a:1, a:2)]
  1541. let cln = cml ? cln : 0
  1542. en
  1543. let ms += [cml, 0, 0, 0]
  1544. let mp = call('s:multipliers', ms[:3])
  1545. retu cln + ms[0] * mp[0] + ms[1] * mp[1] + ms[2] * mp[2] + ms[3] * mp[3]
  1546. en
  1547. retu cln + cml * 2
  1548. endf
  1549. fu! s:mixedsort(...)
  1550. let ct = s:curtype()
  1551. if ct == 'buf'
  1552. let pat = '[\/]\?\[\d\+\*No Name\]$'
  1553. if a:1 =~# pat && a:2 =~# pat | retu 0
  1554. elsei a:1 =~# pat | retu 1
  1555. elsei a:2 =~# pat | retu -1 | en
  1556. en
  1557. let [cln, cml] = [ctrlp#complen(a:1, a:2), s:compmatlen(a:1, a:2)]
  1558. if s:ispath
  1559. let ms = []
  1560. if s:res_count < 21
  1561. let ms += [s:compfnlen(a:1, a:2)]
  1562. if ct !~ '^\(buf\|mru\)$' | let ms += [s:comptime(a:1, a:2)] | en
  1563. if !s:itemtype | let ms += [s:comparent(a:1, a:2)] | en
  1564. en
  1565. if ct =~ '^\(buf\|mru\)$'
  1566. let ms += [s:compmref(a:1, a:2)]
  1567. let cln = cml ? cln : 0
  1568. en
  1569. let ms += [cml, 0, 0, 0]
  1570. let mp = call('s:multipliers', ms[:3])
  1571. retu cln + ms[0] * mp[0] + ms[1] * mp[1] + ms[2] * mp[2] + ms[3] * mp[3]
  1572. en
  1573. retu cln + cml * 2
  1574. endf
  1575. fu! s:multipliers(...)
  1576. let mp0 = !a:1 ? 0 : 2
  1577. let mp1 = !a:2 ? 0 : 1 + ( !mp0 ? 1 : mp0 )
  1578. let mp2 = !a:3 ? 0 : 1 + ( !( mp0 + mp1 ) ? 1 : ( mp0 + mp1 ) )
  1579. let mp3 = !a:4 ? 0 : 1 + ( !( mp0 + mp1 + mp2 ) ? 1 : ( mp0 + mp1 + mp2 ) )
  1580. retu [mp0, mp1, mp2, mp3]
  1581. endf
  1582. fu! s:compval(...)
  1583. retu a:1 - a:2
  1584. endf
  1585. " Statusline {{{2
  1586. fu! ctrlp#statusline()
  1587. if !exists('s:statypes')
  1588. let s:statypes = copy(s:coretypes)
  1589. if !empty(g:ctrlp_ext_vars)
  1590. cal map(copy(g:ctrlp_ext_vars),
  1591. \ 'add(s:statypes, [ v:val["lname"], v:val["sname"] ])')
  1592. en
  1593. en
  1594. let tps = s:statypes
  1595. let max = len(tps) - 1
  1596. let nxt = tps[s:walker(max, s:itemtype, 1)][1]
  1597. let prv = tps[s:walker(max, s:itemtype, -1)][1]
  1598. let s:ctype = tps[s:itemtype][0]
  1599. let focus = s:focus ? 'prt' : 'win'
  1600. let byfname = s:ispath ? s:byfname ? 'file' : 'path' : 'line'
  1601. let marked = s:opmul != '0' ?
  1602. \ exists('s:marked') ? ' <'.s:dismrk().'>' : ' <->' : ''
  1603. if s:status != {}
  1604. let argms =
  1605. \ get(s:status, 'arg_type', '') == 'dict' ? [{
  1606. \ 'focus': focus,
  1607. \ 'byfname': byfname,
  1608. \ 'regex': s:regexp,
  1609. \ 'prev': prv,
  1610. \ 'item': s:ctype,
  1611. \ 'next': nxt,
  1612. \ 'marked': marked,
  1613. \ }] : [focus, byfname, s:regexp, prv, s:ctype, nxt, marked]
  1614. let &l:stl = call(s:status['main'], argms, s:status)
  1615. el
  1616. let item = '%#CtrlPMode1# '.s:ctype.' %*'
  1617. let focus = '%#CtrlPMode2# '.focus.' %*'
  1618. let byfname = '%#CtrlPMode1# '.byfname.' %*'
  1619. let regex = s:regexp ? '%#CtrlPMode2# regex %*' : ''
  1620. let slider = ' <'.prv.'>={'.item.'}=<'.nxt.'>'
  1621. let dir = ' %=%<%#CtrlPMode2# %{getcwd()} %*'
  1622. let &l:stl = focus.byfname.regex.slider.marked.dir
  1623. if exists('s:timer')
  1624. let &l:stl = '%#CtrlPStats# '.len(g:ctrlp_allfiles).' '.&l:stl
  1625. en
  1626. en
  1627. endf
  1628. fu! s:dismrk()
  1629. retu has('signs') ? len(s:marked) :
  1630. \ '%<'.join(values(map(copy(s:marked), 'split(v:val, "[\\/]")[-1]')), ', ')
  1631. endf
  1632. fu! ctrlp#progress(enum, ...)
  1633. if has('macunix') || has('mac') | sl 1m | en
  1634. let txt = a:0 ? '(press ctrl-c to abort)' : ''
  1635. if s:status != {}
  1636. let argms = get(s:status, 'arg_type', '') == 'dict'
  1637. \ ? [{ 'str': a:enum }] : [a:enum]
  1638. let &l:stl = call(s:status['prog'], argms, s:status)
  1639. el
  1640. let &l:stl = '%#CtrlPStats# '.a:enum.' %* '.txt.'%=%<%#CtrlPMode2# %{getcwd()} %*'
  1641. en
  1642. redraws
  1643. endf
  1644. " *** Paths {{{2
  1645. " Line formatting {{{3
  1646. fu! s:formatline(str)
  1647. let str = a:str
  1648. let ct = s:curtype()
  1649. if ct == 'buf'
  1650. let bufnr = s:bufnrfilpath(str)[0]
  1651. let parts = s:bufparts(bufnr)
  1652. let str = printf('%'.s:bufnr_width.'s', bufnr)
  1653. if s:has_conceal && has('syntax_items')
  1654. let str .= printf(' %-13s %s%-36s',
  1655. \ '<bi>'.parts[0].'</bi>',
  1656. \ '<bn>'.parts[1], '{'.parts[2].'}</bn>')
  1657. if (!empty(s:bufpath_mod))
  1658. let str .= printf(' %s', '<bp>'.parts[3].'</bp>')
  1659. en
  1660. el
  1661. let str .= printf(' %-5s %-30s',
  1662. \ parts[0],
  1663. \ parts[2])
  1664. if (!empty(s:bufpath_mod))
  1665. let str .= printf(' %s', parts[3])
  1666. en
  1667. en
  1668. en
  1669. let cond = ct != 'buf' &&s:ispath && ( s:winw - 4 ) < s:strwidth(str)
  1670. retu s:lineprefix.( cond ? s:pathshorten(str) : str )
  1671. endf
  1672. fu! s:formatline2(ct, key, str)
  1673. let str = a:str
  1674. if a:ct == 'buf'
  1675. let bufnr = s:bufnrfilpath(str)[0]
  1676. let parts = s:bufparts(bufnr)
  1677. let str = printf('%'.s:bufnr_width.'s', bufnr)
  1678. if s:has_conceal && has('syntax_items')
  1679. let str .= printf(' %-13s %s%-36s',
  1680. \ '<bi>'.parts[0].'</bi>',
  1681. \ '<bn>'.parts[1], '{'.parts[2].'}</bn>')
  1682. if (!empty(s:bufpath_mod))
  1683. let str .= printf(' %s', '<bp>'.parts[3].'</bp>')
  1684. en
  1685. el
  1686. let str .= printf(' %-5s %-30s',
  1687. \ parts[0],
  1688. \ parts[2])
  1689. if (!empty(s:bufpath_mod))
  1690. let str .= printf(' %s', parts[3])
  1691. en
  1692. en
  1693. retu s:lineprefix.str
  1694. en
  1695. let cond = s:ispath && ( s:winw - 4 ) < strchars(str)
  1696. retu s:lineprefix.( cond ? s:pathshorten(str) : str )
  1697. endf
  1698. if exists('*strchars') && exists('*strcharpart')
  1699. fu! s:pathshorten(str)
  1700. retu strcharpart(a:str, 0, 9).'...'.strcharpart(a:str, strchars(a:str) - s:winw + 16)
  1701. endf
  1702. el
  1703. fu! s:pathshorten(str)
  1704. retu matchstr(a:str, '^.\{9}').'...'
  1705. \ .matchstr(a:str, '.\{'.( s:winw - 16 ).'}$')
  1706. endf
  1707. en
  1708. fu! s:offset(lines, height)
  1709. let s:offset = s:mw_order == 'btt' ? ( a:height - s:res_count ) : 0
  1710. retu s:offset > 0 ? ( repeat([''], s:offset) + a:lines ) : a:lines
  1711. endf
  1712. " Directory completion {{{3
  1713. fu! s:dircompl(be, sd)
  1714. if a:sd == '' | retu [] | en
  1715. if a:be == ''
  1716. let [be, sd] = [s:dyncwd, a:sd]
  1717. el
  1718. let be = a:be.s:lash(a:be)
  1719. let sd = be.a:sd
  1720. en
  1721. let dirs = split(globpath(s:fnesc(be, 'g', ','), a:sd.'*/'), "\n")
  1722. if a:be == ''
  1723. let dirs = ctrlp#rmbasedir(dirs)
  1724. en
  1725. cal filter(dirs, '!match(v:val, escape(sd, ''~$.\''))'
  1726. \ . ' && v:val !~ ''\v(^|[\/])\.{1,2}[\/]$''')
  1727. retu dirs
  1728. endf
  1729. fu! s:findcommon(items, seed)
  1730. let [items, id, cmn, ic] = [copy(a:items), strlen(a:seed), '', 0]
  1731. cal map(items, 'strpart(v:val, id)')
  1732. for char in split(items[0], '\zs')
  1733. for item in items[1:]
  1734. if item[ic] != char | let brk = 1 | brea | en
  1735. endfo
  1736. if exists('brk') | brea | en
  1737. let cmn .= char
  1738. let ic += 1
  1739. endfo
  1740. retu cmn
  1741. endf
  1742. " Misc {{{3
  1743. fu! s:headntail(str)
  1744. let parts = split(a:str, '[\/]\ze[^\/]\+[\/:]\?$')
  1745. retu len(parts) == 1 ? ['', parts[0]] : len(parts) == 2 ? parts : []
  1746. endf
  1747. fu! s:lash(...)
  1748. retu ( a:0 ? a:1 : s:dyncwd ) !~ '[\/]$' ? s:lash : ''
  1749. endf
  1750. fu! s:ispathitem()
  1751. retu s:itemtype < len(s:coretypes) || s:getextvar('type') == 'path'
  1752. endf
  1753. fu! ctrlp#igncwd(cwd)
  1754. retu ctrlp#utils#glob(a:cwd, 0) == '' ||
  1755. \ ( s:igntype >= 0 && s:usrign(a:cwd, getftype(a:cwd)) )
  1756. endf
  1757. fu! ctrlp#dirnfile(entries)
  1758. let [items, cwd] = [[[], []], s:dyncwd.s:lash()]
  1759. for each in a:entries
  1760. let etype = getftype(each)
  1761. if s:igntype >= 0 && s:usrign(each, etype) | con | en
  1762. if etype == 'dir'
  1763. if s:showhidden | if each !~ '[\/]\.\{1,2}$'
  1764. let items[0] += [each]
  1765. en | el
  1766. let items[0] += [each]
  1767. en
  1768. elsei etype == 'link'
  1769. if s:folsym
  1770. let isfile = !isdirectory(each)
  1771. if s:folsym == 2 || !s:samerootsyml(each, isfile, cwd)
  1772. let items[isfile] += [each]
  1773. en
  1774. en
  1775. elsei etype == 'file'
  1776. let items[1] += [each]
  1777. en
  1778. endfo
  1779. retu items
  1780. endf
  1781. fu! s:usrign(item, type)
  1782. if s:igntype == 1 | retu a:item =~ s:usrign | en
  1783. if s:igntype == 2 | retu call(s:usrign, [a:item, a:type]) | en
  1784. if s:igntype == 4
  1785. if get(s:usrign, a:type, '') != ''
  1786. retu a:item =~ s:usrign[a:type]
  1787. elsei get(s:usrign, 'func', '') != ''
  1788. retu call(s:usrign['func'], [a:item, a:type])
  1789. en
  1790. en
  1791. retu 0
  1792. endf
  1793. fu! s:samerootsyml(each, isfile, cwd)
  1794. let resolve = fnamemodify(resolve(a:each), ':p:h')
  1795. let resolve .= s:lash(resolve)
  1796. retu !( stridx(resolve, a:cwd) && ( stridx(a:cwd, resolve) || a:isfile ) )
  1797. endf
  1798. fu! ctrlp#rmbasedir(items)
  1799. if a:items == []
  1800. retu a:items
  1801. en
  1802. let cwd = s:dyncwd.s:lash()
  1803. let first = a:items[0]
  1804. if has('win32') || has('win64')
  1805. let cwd = tr(cwd, '\', '/')
  1806. let first = tr(first, '\', '/')
  1807. en
  1808. if !stridx(first, cwd)
  1809. let idx = strlen(cwd)
  1810. retu map(a:items, 'strpart(v:val, idx)')
  1811. en
  1812. retu a:items
  1813. endf
  1814. " Working directory {{{3
  1815. fu! s:getparent(item)
  1816. let parent = substitute(a:item, '[\/][^\/]\+[\/:]\?$', '', '')
  1817. if parent == '' || parent !~ '[\/]'
  1818. let parent .= s:lash
  1819. en
  1820. retu parent
  1821. endf
  1822. fu! s:findroot(curr, mark, depth, type)
  1823. let [depth, fnd] = [a:depth + 1, 0]
  1824. if type(a:mark) == 1
  1825. let fnd = s:glbpath(s:fnesc(a:curr, 'g', ','), a:mark, 1) != ''
  1826. elsei type(a:mark) == 3
  1827. for markr in a:mark
  1828. if s:glbpath(s:fnesc(a:curr, 'g', ','), markr, 1) != ''
  1829. let fnd = 1
  1830. brea
  1831. en
  1832. endfo
  1833. en
  1834. if fnd
  1835. if !a:type | cal ctrlp#setdir(a:curr) | en
  1836. retu [exists('markr') ? markr : a:mark, a:curr]
  1837. elsei depth > s:maxdepth
  1838. cal ctrlp#setdir(s:cwd)
  1839. el
  1840. let parent = s:getparent(a:curr)
  1841. if parent != a:curr
  1842. retu s:findroot(parent, a:mark, depth, a:type)
  1843. en
  1844. en
  1845. retu []
  1846. endf
  1847. fu! ctrlp#setpathmode(pmode, ...)
  1848. if a:pmode == 'c' || ( a:pmode == 'a' && stridx(s:crfpath, s:cwd) < 0 )
  1849. if exists('+acd') | let [s:glb_acd, &acd] = [&acd, 0] | en
  1850. cal ctrlp#setdir(s:crfpath)
  1851. retu 1
  1852. elsei a:pmode == 'r'
  1853. let spath = a:0 ? a:1 : s:crfpath
  1854. let markers = ['.git', '.hg', '.svn', '.bzr', '_darcs']
  1855. if type(s:rmarkers) == 3 && !empty(s:rmarkers)
  1856. if s:findroot(spath, s:rmarkers, 0, 0) != [] | retu 1 | en
  1857. cal filter(markers, 'index(s:rmarkers, v:val) < 0')
  1858. let markers = s:rmarkers + markers
  1859. en
  1860. if s:findroot(spath, markers, 0, 0) != [] | retu 1 | en
  1861. en
  1862. retu 0
  1863. endf
  1864. fu! ctrlp#setdir(path, ...)
  1865. let cmd = a:0 ? a:1 : 'lc!'
  1866. sil! exe cmd s:fnesc(a:path, 'c')
  1867. let [s:crfilerel, s:dyncwd] = [fnamemodify(s:crfile, ':.'), getcwd()]
  1868. endf
  1869. " Fallbacks {{{3
  1870. fu! s:glbpath(...)
  1871. retu call('ctrlp#utils#globpath', a:000)
  1872. endf
  1873. fu! s:fnesc(...)
  1874. retu call('ctrlp#utils#fnesc', a:000)
  1875. endf
  1876. fu! ctrlp#setlcdir()
  1877. if exists('*haslocaldir')
  1878. cal ctrlp#setdir(getcwd(), haslocaldir() ? 'lc!' : 'cd!')
  1879. en
  1880. endf
  1881. " Highlighting {{{2
  1882. fu! ctrlp#syntax()
  1883. if ctrlp#nosy() | retu | en
  1884. for [ke, va] in items(s:hlgrps) | cal ctrlp#hicheck('CtrlP'.ke, va) | endfo
  1885. let bgColor=synIDattr(synIDtrans(hlID('Normal')), 'bg')
  1886. if bgColor !~ '^-1$\|^$'
  1887. sil! exe 'hi CtrlPLinePre guifg='.bgColor.' ctermfg='.bgColor
  1888. en
  1889. sy match CtrlPNoEntries '^ == NO ENTRIES ==$'
  1890. if hlexists('CtrlPLinePre')
  1891. exe "sy match CtrlPLinePre '^".escape(get(g:, 'ctrlp_line_prefix', '>'),'^$.*~\')."'"
  1892. en
  1893. if s:curtype() == 'buf' && s:has_conceal
  1894. sy region CtrlPBufferNr matchgroup=CtrlPLinePre start='^>\s\+' end='\s'
  1895. sy region CtrlPBufferInd concealends matchgroup=Ignore start='<bi>' end='</bi>'
  1896. sy region CtrlPBufferRegion concealends matchgroup=Ignore start='<bn>' end='</bn>'
  1897. \ contains=CtrlPBufferHid,CtrlPBufferHidMod,CtrlPBufferVis,CtrlPBufferVisMod,CtrlPBufferCur,CtrlPBufferCurMod
  1898. sy region CtrlPBufferHid concealends matchgroup=Ignore start='\s*{' end='}' contained
  1899. sy region CtrlPBufferHidMod concealends matchgroup=Ignore start='+\s*{' end='}' contained
  1900. sy region CtrlPBufferVis concealends matchgroup=Ignore start='\*\s*{' end='}' contained
  1901. sy region CtrlPBufferVisMod concealends matchgroup=Ignore start='\*+\s*{' end='}' contained
  1902. sy region CtrlPBufferCur concealends matchgroup=Ignore start='\*!\s*{' end='}' contained
  1903. sy region CtrlPBufferCurMod concealends matchgroup=Ignore start='\*+!\s*{' end='}' contained
  1904. sy region CtrlPBufferPath concealends matchgroup=Ignore start='<bp>' end='</bp>'
  1905. en
  1906. endf
  1907. fu! s:highlight(pat, grp)
  1908. if s:matcher != {} | retu | en
  1909. cal clearmatches()
  1910. if !empty(a:pat) && s:ispath
  1911. if s:regexp
  1912. let pat = substitute(a:pat, '\\\@<!\^', '^> \\zs', 'g')
  1913. cal matchadd(a:grp, ( s:martcs == '' ? '\c' : '\C' ).pat)
  1914. el
  1915. let pat = a:pat
  1916. " get original characters so we can rebuild pat
  1917. let chars = split(pat, '\[\^\\\?.\]\\{-}')
  1918. " Build a pattern like /a.*b.*c/ from abc (but with .\{-} non-greedy
  1919. " matchers instead)
  1920. let pat = join(chars, '.\{-}')
  1921. " Ensure we match the last version of our pattern
  1922. let ending = '\(.*'.pat.'\)\@!'
  1923. " Case sensitive?
  1924. let beginning = ( s:martcs == '' ? '\c' : '\C' ).'^.*'
  1925. if s:byfname()
  1926. " Make sure there are no slashes in our match
  1927. let beginning = beginning.'\([^\/]*$\)\@='
  1928. en
  1929. for i in range(len(chars))
  1930. " Surround our current target letter with \zs and \ze so it only
  1931. " actually matches that one letter, but has all preceding and trailing
  1932. " letters as well.
  1933. " \zsa.*b.*c
  1934. " a\(\zsb\|.*\zsb)\ze.*c
  1935. let charcopy = copy(chars)
  1936. if i == 0
  1937. let charcopy[i] = '\zs'.charcopy[i].'\ze'
  1938. let middle = join(charcopy, '.\{-}')
  1939. el
  1940. let before = join(charcopy[0:i-1], '.\{-}')
  1941. let after = join(charcopy[i+1:-1], '.\{-}')
  1942. let c = charcopy[i]
  1943. " for abc, match either ab.\{-}c or a.*b.\{-}c in that order
  1944. let cpat = '\(\zs'.c.'\|'.'.*\zs'.c.'\)\ze.*'
  1945. let middle = before.cpat.after
  1946. en
  1947. " Now we matchadd for each letter, the basic form being:
  1948. " ^.*\zsx\ze.*$, but with our pattern we built above for the letter,
  1949. " and a negative lookahead ensuring that we only highlight the last
  1950. " occurrence of our letters. We also ensure that our matcher is case
  1951. " insensitive or sensitive depending.
  1952. cal matchadd(a:grp, beginning.middle.ending)
  1953. endfo
  1954. en
  1955. cal matchadd('CtrlPLinePre', '^>')
  1956. elseif !empty(a:pat) && s:regexp &&
  1957. \ exists('g:ctrlp_regex_always_higlight') &&
  1958. \ g:ctrlp_regex_always_higlight
  1959. let pat = substitute(a:pat, '\\\@<!\^', '^> \\zs', 'g')
  1960. cal matchadd(a:grp, ( s:martcs == '' ? '\c' : '\C').pat)
  1961. en
  1962. endf
  1963. fu! s:dohighlight()
  1964. retu s:mathi[0] && exists('*clearmatches') && !ctrlp#nosy()
  1965. endf
  1966. " Prompt history {{{2
  1967. fu! s:gethistloc()
  1968. let utilcadir = ctrlp#utils#cachedir()
  1969. let cache_dir = utilcadir.s:lash(utilcadir).'hist'
  1970. retu [cache_dir, cache_dir.s:lash(cache_dir).'cache.txt']
  1971. endf
  1972. fu! s:gethistdata()
  1973. retu ctrlp#utils#readfile(s:gethistloc()[1])
  1974. endf
  1975. fu! ctrlp#recordhist()
  1976. let str = join(s:prompt, '')
  1977. if empty(str) || !s:maxhst | retu | en
  1978. let hst = s:hstry
  1979. if len(hst) > 1 && hst[1] == str | retu | en
  1980. cal extend(hst, [str], 1)
  1981. if len(hst) > s:maxhst | cal remove(hst, s:maxhst, -1) | en
  1982. cal ctrlp#utils#writecache(hst, s:gethistloc()[0], s:gethistloc()[1])
  1983. endf
  1984. " Signs {{{2
  1985. fu! s:unmarksigns()
  1986. if !s:dosigns() | retu | en
  1987. for key in keys(s:marked)
  1988. exe 'sign unplace' key 'buffer='.s:bufnr
  1989. endfo
  1990. endf
  1991. fu! s:remarksigns()
  1992. if !s:dosigns() | retu | en
  1993. for ic in range(1, len(s:lines))
  1994. let line = s:ispath ? fnamemodify(s:lines[ic - 1], ':p') : s:lines[ic - 1]
  1995. let key = s:dictindex(s:marked, line)
  1996. if key > 0
  1997. exe 'sign place' key 'line='.ic.' name=ctrlpmark buffer='.s:bufnr
  1998. en
  1999. endfo
  2000. endf
  2001. fu! s:dosigns()
  2002. retu exists('s:marked') && s:bufnr > 0 && s:opmul != '0' && has('signs')
  2003. endf
  2004. " Lists & Dictionaries {{{2
  2005. fu! s:ifilter(list, str)
  2006. let [rlist, estr] = [[], substitute(a:str, 'v:val', 'each', 'g')]
  2007. for each in a:list
  2008. try
  2009. if eval(estr)
  2010. let rlist += [each]
  2011. en
  2012. cat | con | endt
  2013. endfo
  2014. retu rlist
  2015. endf
  2016. fu! s:dictindex(dict, expr)
  2017. for key in keys(a:dict)
  2018. if a:dict[key] ==# a:expr | retu key | en
  2019. endfo
  2020. retu -1
  2021. endf
  2022. fu! s:vacantdict(dict)
  2023. retu filter(range(1, max(keys(a:dict))), '!has_key(a:dict, v:val)')
  2024. endf
  2025. fu! s:sublist(l, s, e)
  2026. retu v:version > 701 ? a:l[(a:s):(a:e)] : s:sublist7071(a:l, a:s, a:e)
  2027. endf
  2028. fu! s:sublist7071(l, s, e)
  2029. let [newlist, id, ae] = [[], a:s, a:e == -1 ? len(a:l) - 1 : a:e]
  2030. wh id <= ae
  2031. let newlist += [get(a:l, id)]
  2032. let id += 1
  2033. endw
  2034. retu newlist
  2035. endf
  2036. " Buffers {{{2
  2037. fu! s:buftab(bufnr, md)
  2038. for tabnr in range(1, tabpagenr('$'))
  2039. if tabpagenr() == tabnr && a:md == 't' | con | en
  2040. let buflist = tabpagebuflist(tabnr)
  2041. if index(buflist, a:bufnr) >= 0
  2042. for winnr in range(1, tabpagewinnr(tabnr, '$'))
  2043. if buflist[winnr - 1] == a:bufnr | retu [tabnr, winnr] | en
  2044. endfo
  2045. en
  2046. endfo
  2047. retu [0, 0]
  2048. endf
  2049. fu! s:bufwins(bufnr)
  2050. let winns = 0
  2051. for tabnr in range(1, tabpagenr('$'))
  2052. let winns += count(tabpagebuflist(tabnr), a:bufnr)
  2053. endfo
  2054. retu winns
  2055. endf
  2056. fu! s:isabs(path)
  2057. if (has('win32') || has('win64'))
  2058. retu a:path =~ '^\([a-zA-Z]:\)\{-}[/\\]'
  2059. el
  2060. retu a:path =~ '^[/\\]'
  2061. en
  2062. endf
  2063. fu! s:bufnrfilpath(line)
  2064. if s:isabs(a:line) || a:line =~ '^\~[/\\]' || a:line =~ '^\w\+:\/\/'
  2065. let filpath = a:line
  2066. el
  2067. let filpath = s:dyncwd.s:lash().a:line
  2068. en
  2069. let filpath = fnamemodify(filpath, ':p')
  2070. let bufnr = bufnr('^'.fnameescape(filpath).'$')
  2071. if (!filereadable(filpath) && bufnr < 1)
  2072. if (a:line =~ '[\/]\?\[\d\+\*No Name\]$')
  2073. let bufnr = str2nr(matchstr(a:line, '[\/]\?\[\zs\d\+\ze\*No Name\]$'))
  2074. let filpath = bufnr
  2075. els
  2076. let bufnr = bufnr(a:line)
  2077. retu [bufnr, a:line]
  2078. en
  2079. en
  2080. retu [bufnr, filpath]
  2081. endf
  2082. fu! ctrlp#normcmd(cmd, ...)
  2083. let buftypes = [ 'quickfix', 'help', 'nofile' ]
  2084. if a:0 < 2 && s:nosplit() | retu a:cmd | en
  2085. let norwins = filter(range(1, winnr('$')),
  2086. \ 'index(buftypes, getbufvar(winbufnr(v:val), "&bt")) == -1 || s:isterminal(winbufnr(v:val))')
  2087. for each in norwins
  2088. let bufnr = winbufnr(each)
  2089. if empty(bufname(bufnr)) && empty(getbufvar(bufnr, '&ft'))
  2090. let fstemp = each | brea
  2091. en
  2092. endfo
  2093. let norwin = empty(norwins) ? 0 : norwins[0]
  2094. if norwin
  2095. if index(norwins, winnr()) < 0
  2096. exe ( exists('fstemp') ? fstemp : norwin ).'winc w'
  2097. en
  2098. retu a:cmd
  2099. en
  2100. retu a:0 ? a:1 : 'bo vne'
  2101. endf
  2102. fu! ctrlp#modfilecond(w)
  2103. retu &mod && !&hid && &bh != 'hide' && s:bufwins(bufnr('%')) == 1 && !&cf &&
  2104. \ ( ( !&awa && a:w ) || filewritable(fnamemodify(bufname('%'), ':p')) != 1 )
  2105. endf
  2106. fu! s:nosplit()
  2107. retu !empty(s:nosplit) && match([bufname('%'), &l:ft, &l:bt], s:nosplit) >= 0
  2108. endf
  2109. fu! s:setupblank()
  2110. setl noswf nonu nobl nowrap nolist nospell nocuc wfh
  2111. setl fdc=0 fdl=99 tw=0 bt=nofile bh=unload
  2112. if v:version > 702
  2113. setl nornu noudf cc=0
  2114. en
  2115. if s:has_conceal
  2116. setl cole=2 cocu=nc
  2117. en
  2118. endf
  2119. fu! s:leavepre()
  2120. if exists('s:bufnr') && s:bufnr == bufnr('%') | bw! | en
  2121. if !( exists(s:ccex) && !{s:ccex} )
  2122. \ && !( has('clientserver') && len(split(serverlist(), "\n")) > 1 )
  2123. cal ctrlp#clra()
  2124. en
  2125. endf
  2126. fu! s:checkbuf()
  2127. if !exists('s:init') && exists('s:bufnr') && s:bufnr > 0
  2128. exe s:bufnr.'bw!'
  2129. en
  2130. endf
  2131. fu! s:iscmdwin()
  2132. let [ermsg, v:errmsg] = [v:errmsg, '']
  2133. sil! noa winc p
  2134. sil! noa winc p
  2135. let [v:errmsg, ermsg] = [ermsg, v:errmsg]
  2136. retu ermsg =~ '^E11:'
  2137. endf
  2138. " Arguments {{{2
  2139. fu! s:at(str)
  2140. if a:str =~ '\v^\@(cd|lc[hd]?|chd).*'
  2141. let str = substitute(a:str, '\v^\@(cd|lc[hd]?|chd)\s*', '', '')
  2142. if str == '' | retu 1 | en
  2143. let str = str =~ '^%:.\+' ? fnamemodify(s:crfile, str[1:]) : str
  2144. let path = fnamemodify(expand(str, 1), ':p')
  2145. if isdirectory(path)
  2146. if path != s:dyncwd
  2147. cal ctrlp#setdir(path)
  2148. cal ctrlp#setlines()
  2149. en
  2150. cal ctrlp#recordhist()
  2151. cal s:PrtClear()
  2152. en
  2153. retu 1
  2154. en
  2155. retu 0
  2156. endf
  2157. fu! s:tail()
  2158. if exists('s:optail') && !empty('s:optail')
  2159. let tailpref = s:optail !~ '^\s*+' ? ' +' : ' '
  2160. retu tailpref.s:optail
  2161. en
  2162. retu ''
  2163. endf
  2164. fu! s:sanstail(str)
  2165. let str = s:spi ?
  2166. \ substitute(a:str, '^\(@.*$\|\\\\\ze@\|\.\.\zs[.\/]\+$\)', '', 'g') : a:str
  2167. let [str, pat] = [substitute(str, '\\\\', '\', 'g'), '\([^:]\|\\:\)*$']
  2168. unl! s:optail
  2169. if str =~ '\\\@<!:'.pat
  2170. let s:optail = matchstr(str, '\\\@<!:\zs'.pat)
  2171. let str = substitute(str, '\\\@<!:'.pat, '', '')
  2172. en
  2173. retu substitute(str, '\\\ze:', '', 'g')
  2174. endf
  2175. fu! s:argmaps(md, i)
  2176. let roh = [
  2177. \ ['Open Multiple Files', '/h[i]dden/[c]lear', ['i', 'c']],
  2178. \ ['Create a New File', '/[r]eplace', ['r']],
  2179. \ ['Open Selected', '/[r]eplace', ['r', 'd', 'a']],
  2180. \ ]
  2181. if a:i == 2
  2182. if !buflisted(bufnr('^'.fnamemodify(ctrlp#getcline(), ':p').'$'))
  2183. let roh[2][1] .= '/h[i]dden'
  2184. let roh[2][2] += ['i']
  2185. en
  2186. if s:openfunc != {} && has_key(s:openfunc, s:ctype)
  2187. let roh[2][1] .= '/e[x]ternal'
  2188. let roh[2][2] += ['x']
  2189. en
  2190. en
  2191. let str = roh[a:i][0].': [t]ab/[v]ertical/[h]orizontal'.roh[a:i][1].'? '
  2192. retu s:choices(str, ['t', 'v', 'h'] + roh[a:i][2], 's:argmaps', [a:md, a:i])
  2193. endf
  2194. fu! s:insertstr()
  2195. let str = 'Insert: c[w]ord/c[f]ile/[s]earch/[v]isual/[c]lipboard/[r]egister? '
  2196. retu s:choices(str, ['w', 'f', 's', 'v', 'c', 'r'], 's:insertstr', [])
  2197. endf
  2198. fu! s:textdialog(str)
  2199. redr | echoh MoreMsg | echon a:str | echoh None
  2200. retu nr2char(getchar())
  2201. endf
  2202. fu! s:choices(str, choices, func, args)
  2203. let char = s:textdialog(a:str)
  2204. if index(a:choices, char) >= 0
  2205. retu char
  2206. elsei char =~# "\\v\<Esc>|\<C-c>|\<C-g>|\<C-u>|\<C-w>|\<C-[>"
  2207. cal s:BuildPrompt(0)
  2208. retu 'cancel'
  2209. elsei char =~# "\<CR>" && a:args != []
  2210. retu a:args[0]
  2211. en
  2212. retu call(a:func, a:args)
  2213. endf
  2214. fu! s:getregs()
  2215. let char = s:textdialog('Insert from register: ')
  2216. if char =~# "\\v\<Esc>|\<C-c>|\<C-g>|\<C-u>|\<C-w>|\<C-[>"
  2217. cal s:BuildPrompt(0)
  2218. retu -1
  2219. elsei char =~# "\<CR>"
  2220. retu s:getregs()
  2221. en
  2222. retu s:regisfilter(char)
  2223. endf
  2224. fu! s:regisfilter(reg)
  2225. retu substitute(getreg(a:reg), "[\t\n]", ' ', 'g')
  2226. endf
  2227. " Misc {{{2
  2228. fu! s:modevar()
  2229. let s:matchtype = s:mtype()
  2230. let s:ispath = s:ispathitem()
  2231. let s:mfunc = s:mfunc()
  2232. let s:nolim = s:getextvar('nolim')
  2233. let s:dosort = s:getextvar('sort')
  2234. let s:spi = !s:itemtype || s:getextvar('specinput') > 0
  2235. endf
  2236. fu! s:nosort()
  2237. let ct = s:curtype()
  2238. retu s:matcher != {} || s:nolim == 1 || ( ct == 'mru' && s:mrudef )
  2239. \ || ( ct =~ '^\(buf\|mru\)$' && s:prompt == ['', '', ''] ) || !s:dosort
  2240. endf
  2241. fu! s:byfname()
  2242. retu s:curtype() != 'buf' && s:ispath && s:byfname
  2243. endf
  2244. fu! s:narrowable()
  2245. retu exists('s:act_add') && exists('s:matched') && s:matched != []
  2246. \ && exists('s:mdata') && s:mdata[:2] == [s:dyncwd, s:itemtype, s:regexp]
  2247. \ && s:matcher == {} && !exists('s:did_exp')
  2248. endf
  2249. fu! s:getinput(...)
  2250. let [prt, spi] = [s:prompt, ( a:0 ? a:1 : '' )]
  2251. if s:abbrev != {}
  2252. let gmd = get(s:abbrev, 'gmode', '')
  2253. let str = ( gmd =~ 't' && !a:0 ) || spi == 'c' ? prt[0] : join(prt, '')
  2254. if gmd =~ 't' && gmd =~ 'k' && !a:0 && matchstr(str, '.$') =~ '\k'
  2255. retu join(prt, '')
  2256. en
  2257. let [pf, rz] = [( s:byfname() ? 'f' : 'p' ), ( s:regexp ? 'r' : 'z' )]
  2258. for dict in s:abbrev['abbrevs']
  2259. let dmd = get(dict, 'mode', '')
  2260. let pat = escape(dict['pattern'], '~')
  2261. if ( dmd == '' || ( dmd =~ pf && dmd =~ rz && !a:0 )
  2262. \ || dmd =~ '['.spi.']' ) && str =~ pat
  2263. let [str, s:did_exp] = [join(split(str, pat, 1), dict['expanded']), 1]
  2264. en
  2265. endfo
  2266. if gmd =~ 't' && !a:0
  2267. let prt[0] = str
  2268. el
  2269. retu str
  2270. en
  2271. en
  2272. retu spi == 'c' ? prt[0] : join(prt, '')
  2273. endf
  2274. if exists('*strdisplaywidth')
  2275. fu! s:strwidth(str)
  2276. retu strdisplaywidth(a:str)
  2277. endf
  2278. el
  2279. fu! s:strwidth(str)
  2280. retu strlen(a:str)
  2281. endf
  2282. en
  2283. fu! ctrlp#j2l(nr)
  2284. exe 'norm!' a:nr.'G'
  2285. sil! norm! zvzz
  2286. endf
  2287. fu! s:maxf(len)
  2288. retu s:maxfiles && a:len > s:maxfiles
  2289. endf
  2290. fu! s:regexfilter(str)
  2291. let str = a:str
  2292. for key in keys(s:fpats) | if str =~ key
  2293. let str = substitute(str, s:fpats[key], '', 'g')
  2294. en | endfo
  2295. retu str
  2296. endf
  2297. fu! s:walker(m, p, d)
  2298. retu a:d >= 0 ? a:p < a:m ? a:p + a:d : 0 : a:p > 0 ? a:p + a:d : a:m
  2299. endf
  2300. fu! s:delent(rfunc)
  2301. if a:rfunc == '' | retu | en
  2302. let [s:force, tbrem] = [1, []]
  2303. if exists('s:marked')
  2304. let tbrem = values(s:marked)
  2305. cal s:unmarksigns()
  2306. unl s:marked
  2307. en
  2308. if tbrem == [] && ( has('dialog_gui') || has('dialog_con') ) &&
  2309. \ confirm("Wipe all entries?", "&OK\n&Cancel") != 1
  2310. unl s:force
  2311. cal s:BuildPrompt(0)
  2312. retu
  2313. en
  2314. let g:ctrlp_lines = call(a:rfunc, [tbrem])
  2315. cal s:BuildPrompt(1)
  2316. unl s:force
  2317. endf
  2318. fu! s:delbufcond(bufnr)
  2319. retu getbufvar(a:bufnr, "&mod") || a:bufnr == s:crbufnr
  2320. endf
  2321. fu! s:delbuf()
  2322. let lines = []
  2323. if exists('s:marked')
  2324. let lines = values(s:marked)
  2325. cal s:unmarksigns()
  2326. unl s:marked
  2327. el
  2328. let lines += [ctrlp#getcline()]
  2329. en
  2330. for line in lines
  2331. let bufnr = s:bufnrfilpath(line)[0]
  2332. if (s:delbufcond(bufnr))
  2333. con
  2334. en
  2335. exe 'bd '. bufnr
  2336. endfo
  2337. cal s:PrtClearCache()
  2338. endf
  2339. fu! s:isterminal(buf)
  2340. retu getbufvar(a:buf, "&bt") == "terminal"
  2341. endf
  2342. " Entering & Exiting {{{2
  2343. fu! s:getenv()
  2344. let [s:cwd, s:winres] = [getcwd(), [winrestcmd(), &lines, winnr('$')]]
  2345. let [s:crword, s:crnbword] = [expand('<cword>', 1), expand('<cWORD>', 1)]
  2346. let [s:crgfile, s:crline] = [expand('<cfile>', 1), getline('.')]
  2347. let [s:winmaxh, s:crcursor] = [min([s:mw_max, &lines]), getpos('.')]
  2348. let [s:crbufnr, s:crvisual] = [bufnr('%'), s:lastvisual()]
  2349. let s:crfile = bufname('%') == ''
  2350. \ ? '['.s:crbufnr.'*No Name]' : expand('%:p', 1)
  2351. let s:crfpath = expand('%:p:h', 1)
  2352. let s:mrbs = ctrlp#mrufiles#bufs()
  2353. endf
  2354. fu! s:lastvisual()
  2355. let cview = winsaveview()
  2356. let [ovreg, ovtype] = [getreg('v'), getregtype('v')]
  2357. let [oureg, outype] = [getreg('"'), getregtype('"')]
  2358. sil! norm! gV"vy
  2359. let selected = s:regisfilter('v')
  2360. cal setreg('v', ovreg, ovtype)
  2361. cal setreg('"', oureg, outype)
  2362. cal winrestview(cview)
  2363. retu selected
  2364. endf
  2365. fu! s:log(m)
  2366. if exists('g:ctrlp_log') && g:ctrlp_log | if a:m
  2367. let cadir = ctrlp#utils#cachedir()
  2368. let apd = g:ctrlp_log > 1 ? '>' : ''
  2369. sil! exe 'redi! >'.apd cadir.s:lash(cadir).'ctrlp.log'
  2370. el
  2371. sil! redi END
  2372. en | en
  2373. endf
  2374. fu! s:buffunc(e)
  2375. if a:e && has_key(s:buffunc, 'enter')
  2376. cal call(s:buffunc['enter'], [], s:buffunc)
  2377. elsei !a:e && has_key(s:buffunc, 'exit')
  2378. cal call(s:buffunc['exit'], [], s:buffunc)
  2379. en
  2380. endf
  2381. fu! s:openfile(cmd, fid, tail, chkmod, ...)
  2382. let cmd = a:cmd
  2383. if a:chkmod && cmd =~ '^[eb]$' && ctrlp#modfilecond(!( cmd == 'b' && &aw ))
  2384. let cmd = cmd == 'b' ? 'sb' : 'sp'
  2385. en
  2386. let cmd = cmd =~ '^tab' ? ctrlp#tabcount().cmd : cmd
  2387. let j2l = a:0 && a:1[0] ? a:1[1] : 0
  2388. exe cmd.( a:0 && a:1[0] ? '' : a:tail ) s:fnesc(a:fid, 'f')
  2389. if j2l
  2390. cal ctrlp#j2l(j2l)
  2391. en
  2392. if !empty(a:tail)
  2393. sil! norm! zvzz
  2394. en
  2395. if cmd != 'bad'
  2396. cal ctrlp#setlcdir()
  2397. en
  2398. endf
  2399. fu! ctrlp#tabcount()
  2400. if exists('s:tabct')
  2401. let tabct = s:tabct
  2402. let s:tabct += 1
  2403. elsei !type(s:tabpage)
  2404. let tabct = s:tabpage
  2405. elsei type(s:tabpage) == 1
  2406. let tabpos =
  2407. \ s:tabpage =~ 'c' ? tabpagenr() :
  2408. \ s:tabpage =~ 'f' ? 1 :
  2409. \ s:tabpage =~ 'l' ? tabpagenr('$') :
  2410. \ tabpagenr()
  2411. let tabct =
  2412. \ s:tabpage =~ 'a' ? tabpos :
  2413. \ s:tabpage =~ 'b' ? tabpos - 1 :
  2414. \ tabpos
  2415. en
  2416. retu tabct < 0 ? 0 : tabct
  2417. endf
  2418. fu! s:settype(type)
  2419. retu a:type < 0 ? exists('s:itemtype') ? s:itemtype : 0 : a:type
  2420. endf
  2421. " Matching {{{2
  2422. fu! s:matchfname(item, pat)
  2423. let parts = split(a:item, '[\/]\ze[^\/]\+$')
  2424. let mfn = match(parts[-1], a:pat[0])
  2425. retu len(a:pat) == 1 ? mfn : len(a:pat) == 2 ?
  2426. \ ( mfn >= 0 && ( len(parts) == 2 ? match(parts[0], a:pat[1]) : -1 ) >= 0
  2427. \ ? 0 : -1 ) : -1
  2428. endf
  2429. fu! s:matchbuf(item, pat)
  2430. let bufnr = s:bufnrfilpath(a:item)[0]
  2431. let parts = s:bufparts(bufnr)
  2432. let item = s:byfname ? parts[2] : bufnr.parts[0].parts[2].s:lash().parts[3]
  2433. retu match(item, a:pat)
  2434. endf
  2435. fu! s:matchtabs(item, pat)
  2436. retu match(split(a:item, '\t\+')[0], a:pat)
  2437. endf
  2438. fu! s:matchtabe(item, pat)
  2439. retu match(split(a:item, '\t\+[^\t]\+$')[0], a:pat)
  2440. endf
  2441. fu! s:buildpat(lst)
  2442. let pat = a:lst[0]
  2443. if s:matchnatural == 1
  2444. for item in range(1, len(a:lst) - 1)
  2445. let c = a:lst[item - 1]
  2446. let pat .= (c == '/' ? '[^/]\{-}' : '[^'.c.'/]\{-}').a:lst[item]
  2447. endfo
  2448. els
  2449. for item in range(1, len(a:lst) - 1)
  2450. let pat .= '[^'.a:lst[item - 1].']\{-}'.a:lst[item]
  2451. endfo
  2452. en
  2453. retu pat
  2454. endf
  2455. fu! s:curtype()
  2456. retu s:CurTypeName()[1]
  2457. endf
  2458. fu! s:mfunc()
  2459. let mfunc = 'match'
  2460. if s:byfname()
  2461. let mfunc = 's:matchfname'
  2462. elsei s:curtype() == 'buf'
  2463. let mfunc = 's:matchbuf'
  2464. elsei s:itemtype >= len(s:coretypes)
  2465. let matchtypes = { 'tabs': 's:matchtabs', 'tabe': 's:matchtabe' }
  2466. if has_key(matchtypes, s:matchtype)
  2467. let mfunc = matchtypes[s:matchtype]
  2468. en
  2469. en
  2470. retu mfunc
  2471. endf
  2472. fu! s:mmode()
  2473. let matchmodes = {
  2474. \ 'match': 'full-line',
  2475. \ 's:matchfname': 'filename-only',
  2476. \ 's:matchbuf': 'full-line',
  2477. \ 's:matchtabs': 'first-non-tab',
  2478. \ 's:matchtabe': 'until-last-tab',
  2479. \ }
  2480. retu matchmodes[s:mfunc]
  2481. endf
  2482. " Cache {{{2
  2483. fu! s:writecache(cafile)
  2484. if ( g:ctrlp_newcache || !filereadable(a:cafile) ) && !s:nocache()
  2485. cal ctrlp#utils#writecache(g:ctrlp_allfiles)
  2486. let g:ctrlp_newcache = 0
  2487. en
  2488. endf
  2489. fu! s:nocache(...)
  2490. if !s:caching
  2491. retu 1
  2492. elsei s:caching > 1
  2493. if !( exists(s:ccex) && !{s:ccex} ) || has_key(s:ficounts, s:dyncwd)
  2494. retu get(s:ficounts, s:dyncwd, [0, 0])[0] < s:caching
  2495. elsei a:0 && filereadable(a:1)
  2496. retu len(ctrlp#utils#readfile(a:1)) < s:caching
  2497. en
  2498. retu 1
  2499. en
  2500. retu 0
  2501. endf
  2502. fu! s:insertcache(str)
  2503. let [data, g:ctrlp_newcache, str] = [g:ctrlp_allfiles, 1, a:str]
  2504. if data == [] || strlen(str) <= strlen(data[0])
  2505. let pos = 0
  2506. elsei strlen(str) >= strlen(data[-1])
  2507. let pos = len(data) - 1
  2508. el
  2509. let pos = 0
  2510. for each in data
  2511. if strlen(each) > strlen(str) | brea | en
  2512. let pos += 1
  2513. endfo
  2514. en
  2515. cal insert(data, str, pos)
  2516. cal s:writecache(ctrlp#utils#cachefile())
  2517. endf
  2518. " Extensions {{{2
  2519. fu! s:mtype()
  2520. retu s:itemtype >= len(s:coretypes) ? s:getextvar('type') : 'path'
  2521. endf
  2522. fu! s:execextvar(key)
  2523. if !empty(g:ctrlp_ext_vars)
  2524. cal map(filter(copy(g:ctrlp_ext_vars),
  2525. \ 'has_key(v:val, a:key)'), 'eval(v:val[a:key])')
  2526. en
  2527. endf
  2528. fu! s:getextvar(key)
  2529. if s:itemtype >= len(s:coretypes) && len(g:ctrlp_ext_vars) > 0
  2530. let vars = g:ctrlp_ext_vars[s:itemtype - len(s:coretypes)]
  2531. if has_key(vars, a:key)
  2532. retu vars[a:key]
  2533. en
  2534. en
  2535. retu get(g:, 'ctrlp_' . s:matchtype . '_' . a:key, -1)
  2536. endf
  2537. fu! ctrlp#getcline()
  2538. let [linenr, offset] = [line('.'), ( s:offset > 0 ? s:offset : 0 )]
  2539. retu !empty(s:lines) && !( offset && linenr <= offset )
  2540. \ ? s:lines[linenr - 1 - offset] : ''
  2541. endf
  2542. fu! ctrlp#getmarkedlist()
  2543. retu exists('s:marked') ? values(s:marked) : []
  2544. endf
  2545. fu! ctrlp#clearmarkedlist()
  2546. let s:marked = {}
  2547. endf
  2548. fu! ctrlp#input()
  2549. retu s:getinput()
  2550. endf
  2551. fu! ctrlp#exit()
  2552. cal s:PrtExit()
  2553. endf
  2554. fu! ctrlp#prtclear()
  2555. cal s:PrtClear()
  2556. endf
  2557. fu! ctrlp#switchtype(id)
  2558. cal s:ToggleType(a:id - s:itemtype)
  2559. endf
  2560. fu! ctrlp#nosy()
  2561. retu !( has('syntax') && exists('g:syntax_on') )
  2562. endf
  2563. fu! s:hiupdate()
  2564. for [ke, va] in items(s:hlgrps)
  2565. let ke = 'CtrlP' . ke
  2566. if hlexists(ke)
  2567. exe 'hi link' ke va
  2568. en
  2569. endfo
  2570. endf
  2571. fu! ctrlp#hicheck(grp, defgrp)
  2572. if !hlexists(a:grp)
  2573. exe 'hi link' a:grp a:defgrp
  2574. en
  2575. endf
  2576. fu! ctrlp#call(func, ...)
  2577. retu call(a:func, a:000)
  2578. endf
  2579. fu! ctrlp#getvar(var)
  2580. retu {a:var}
  2581. endf
  2582. "}}}1
  2583. " * Initialization {{{1
  2584. fu! s:setlines_pre(...)
  2585. if a:0 | let s:itemtype = a:1 | en
  2586. cal s:modevar()
  2587. let s:setlines_post_ended = 0
  2588. let g:ctrlp_lines = []
  2589. endf
  2590. fu! s:setlines_post()
  2591. let inits = {'fil': 'ctrlp#files()', 'buf': 'ctrlp#buffers()', 'mru': 'ctrlp#mrufiles#list()'}
  2592. let types = map(copy(g:ctrlp_types), 'inits[v:val]')
  2593. if !empty(g:ctrlp_ext_vars)
  2594. cal map(copy(g:ctrlp_ext_vars), 'add(types, v:val["init"])')
  2595. en
  2596. let g:ctrlp_lines = eval(types[s:itemtype])
  2597. let s:setlines_post_ended = 1
  2598. endf
  2599. fu! ctrlp#setlines(...)
  2600. cal call('s:setlines_pre', a:000)
  2601. cal s:setlines_post()
  2602. endf
  2603. " Returns [lname, sname]
  2604. fu! s:CurTypeName()
  2605. if s:itemtype < len(s:coretypes)
  2606. retu filter(copy(s:coretypes), 'v:val[1]==g:ctrlp_types[s:itemtype]')[0]
  2607. el
  2608. retu [s:getextvar("lname"), s:getextvar('sname')]
  2609. en
  2610. endfu
  2611. fu! s:ExitIfSingleCandidate()
  2612. if len(s:Update(s:prompt[0])) == 1
  2613. call s:AcceptSelection('e')
  2614. call ctrlp#exit()
  2615. retu 1
  2616. en
  2617. retu 0
  2618. endfu
  2619. fu! s:IsBuiltin()
  2620. let builtins = ['tag', 'dir', 'bft', 'rts', 'bkd', 'lns', 'chs', 'mix', 'udo', 'qfx']
  2621. let curtype = s:getextvar('sname')
  2622. retu s:itemtype < len(s:coretypes) || index(builtins, curtype) > -1
  2623. endfu
  2624. fu! s:DetectFileType(type, ft)
  2625. if s:IsBuiltin() || empty(a:ft) || a:ft ==# 'ctrlp'
  2626. retu 'ctrlp'
  2627. el
  2628. retu 'ctrlp.' . a:ft
  2629. en
  2630. endfu
  2631. fu! ctrlp#init(type, ...)
  2632. if exists('s:init') || s:iscmdwin() | retu | en
  2633. let [s:ermsg, v:errmsg] = [v:errmsg, '']
  2634. let [s:matches, s:init] = [1, 1]
  2635. cal s:Reset(a:0 ? a:1 : {})
  2636. noa cal s:Open()
  2637. cal s:SetWD(a:0 ? a:1 : {})
  2638. cal s:MapNorms()
  2639. cal s:MapSpecs()
  2640. if empty(g:ctrlp_types) && empty(g:ctrlp_ext_vars)
  2641. call ctrlp#exit()
  2642. retu
  2643. en
  2644. if type(a:type) == 0
  2645. let type = a:type
  2646. el
  2647. let type = index(g:ctrlp_types, a:type)
  2648. if type == -1
  2649. call ctrlp#exit()
  2650. retu
  2651. en
  2652. en
  2653. " Fixed issue ctrlpvim/ctrlp.vim#463 : Opening 'ctrlp' in certain modes
  2654. " (':CtrlPBufTag', ':CtrlPLine') seems to trigger a partially deffective
  2655. " intialisation (for example, syntax highlighting not working as expected).
  2656. " Fix: ctrlp#setlines() split in two, as the second part (now in
  2657. " s:setlines_post()) seems to need '&filetype', and s:DetectFileType() seems
  2658. " to need the first part of the old ctrlp#setlines() (now in
  2659. " s:setlines_pre()).
  2660. cal s:setlines_pre(s:settype(type))
  2661. let &filetype = s:DetectFileType(type, &filetype)
  2662. cal s:setlines_post()
  2663. cal ctrlp#syntax()
  2664. cal s:SetDefTxt()
  2665. let curName = s:CurTypeName()
  2666. let shouldExitSingle = index(s:opensingle, curName[0])>=0 || index(s:opensingle, curName[1])>=0
  2667. if shouldExitSingle && s:ExitIfSingleCandidate()
  2668. retu 0
  2669. en
  2670. if has('patch-9.0.0115') && &cmdheight == 0
  2671. let s:cmdheight = &cmdheight
  2672. set cmdheight=1
  2673. en
  2674. cal s:BuildPrompt(1)
  2675. if s:keyloop | cal s:KeyLoop() | en
  2676. retu 1
  2677. endf
  2678. " - Events {{{1
  2679. fu! s:NotifySearch()
  2680. let l:cb = s:getextvar('search')
  2681. if l:cb != -1
  2682. cal eval(l:cb)
  2683. en
  2684. endf
  2685. fu! ctrlp#update(...)
  2686. cal s:ForceUpdate()
  2687. if a:0 | cal s:BuildPrompt(a:1) | en
  2688. endf
  2689. " - Autocmds {{{1
  2690. if has('autocmd')
  2691. aug CtrlPAug
  2692. au!
  2693. au BufEnter ControlP cal s:checkbuf()
  2694. au BufLeave ControlP noa cal s:Close()
  2695. au VimLeavePre * cal s:leavepre()
  2696. au ColorScheme * cal s:hiupdate()
  2697. aug END
  2698. en
  2699. fu! s:autocmds()
  2700. if !has('autocmd') | retu | en
  2701. if exists('#CtrlPLazy')
  2702. au! CtrlPLazy
  2703. en
  2704. if s:lazy
  2705. aug CtrlPLazy
  2706. au!
  2707. au CursorHold ControlP cal s:ForceUpdate()
  2708. aug END
  2709. en
  2710. endf
  2711. "}}}
  2712. " vim:fen:fdm=marker:fmr={{{,}}}:fdl=0:fdc=1:ts=2:sw=2:sts=2