ctrlp.vim 57 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113
  1. " =============================================================================
  2. " File: autoload/ctrlp.vim
  3. " Description: Fuzzy file, buffer, mru, tag, etc finder.
  4. " Author: Kien Nguyen <github.com/kien>
  5. " Version: 1.79
  6. " =============================================================================
  7. " ** Static variables {{{1
  8. " s:ignore() {{{2
  9. fu! s:ignore()
  10. let igdirs = [
  11. \ '\.git',
  12. \ '\.hg',
  13. \ '\.svn',
  14. \ '_darcs',
  15. \ '\.bzr',
  16. \ '\.cdv',
  17. \ '\~\.dep',
  18. \ '\~\.dot',
  19. \ '\~\.nib',
  20. \ '\~\.plst',
  21. \ '\.pc',
  22. \ '_MTN',
  23. \ 'blib',
  24. \ 'CVS',
  25. \ 'RCS',
  26. \ 'SCCS',
  27. \ '_sgbak',
  28. \ 'autom4te\.cache',
  29. \ 'cover_db',
  30. \ '_build',
  31. \ ]
  32. let igfiles = [
  33. \ '\~$',
  34. \ '#.+#$',
  35. \ '[._].*\.swp$',
  36. \ 'core\.\d+$',
  37. \ '\.exe$',
  38. \ '\.so$',
  39. \ '\.bak$',
  40. \ '\.png$',
  41. \ '\.jpg$',
  42. \ '\.gif$',
  43. \ '\.zip$',
  44. \ '\.rar$',
  45. \ '\.tar\.gz$',
  46. \ ]
  47. retu {
  48. \ 'dir': '\v[\/]('.join(igdirs, '|').')$',
  49. \ 'file': '\v'.join(igfiles, '|'),
  50. \ }
  51. endf
  52. " Script local vars {{{2
  53. let [s:pref, s:bpref, s:opts, s:new_opts, s:lc_opts] =
  54. \ ['g:ctrlp_', 'b:ctrlp_', {
  55. \ 'abbrev': ['s:abbrev', {}],
  56. \ 'arg_map': ['s:argmap', 0],
  57. \ 'buffer_func': ['s:buffunc', {}],
  58. \ 'by_filename': ['s:byfname', 0],
  59. \ 'custom_ignore': ['s:usrign', s:ignore()],
  60. \ 'default_input': ['s:deftxt', 0],
  61. \ 'dont_split': ['s:nosplit', 'netrw'],
  62. \ 'dotfiles': ['s:showhidden', 0],
  63. \ 'extensions': ['s:extensions', []],
  64. \ 'follow_symlinks': ['s:folsym', 0],
  65. \ 'highlight_match': ['s:mathi', [1, 'CtrlPMatch']],
  66. \ 'jump_to_buffer': ['s:jmptobuf', 'Et'],
  67. \ 'key_loop': ['s:keyloop', 0],
  68. \ 'lazy_update': ['s:lazy', 0],
  69. \ 'match_func': ['s:matcher', {}],
  70. \ 'match_window_bottom': ['s:mwbottom', 1],
  71. \ 'match_window_reversed': ['s:mwreverse', 1],
  72. \ 'max_depth': ['s:maxdepth', 40],
  73. \ 'max_files': ['s:maxfiles', 10000],
  74. \ 'max_height': ['s:mxheight', 10],
  75. \ 'max_history': ['s:maxhst', exists('+hi') ? &hi : 20],
  76. \ 'mruf_default_order': ['s:mrudef', 0],
  77. \ 'open_func': ['s:openfunc', {}],
  78. \ 'open_multi': ['s:opmul', '1v'],
  79. \ 'open_new_file': ['s:newfop', 'v'],
  80. \ 'prompt_mappings': ['s:urprtmaps', 0],
  81. \ 'regexp_search': ['s:regexp', 0],
  82. \ 'root_markers': ['s:rmarkers', []],
  83. \ 'split_window': ['s:splitwin', 0],
  84. \ 'status_func': ['s:status', {}],
  85. \ 'tabpage_position': ['s:tabpage', 'ac'],
  86. \ 'use_caching': ['s:caching', 1],
  87. \ 'use_migemo': ['s:migemo', 0],
  88. \ 'user_command': ['s:usrcmd', ''],
  89. \ 'working_path_mode': ['s:pathmode', 'ra'],
  90. \ }, {
  91. \ 'open_multiple_files': 's:opmul',
  92. \ 'regexp': 's:regexp',
  93. \ 'reuse_window': 's:nosplit',
  94. \ 'show_hidden': 's:showhidden',
  95. \ 'switch_buffer': 's:jmptobuf',
  96. \ }, {
  97. \ 'root_markers': 's:rmarkers',
  98. \ 'user_command': 's:usrcmd',
  99. \ 'working_path_mode': 's:pathmode',
  100. \ }]
  101. " Global options
  102. let s:glbs = { 'magic': 1, 'to': 1, 'tm': 0, 'sb': 1, 'hls': 0, 'im': 0,
  103. \ 'report': 9999, 'sc': 0, 'ss': 0, 'siso': 0, 'mfd': 200, 'mouse': 'n',
  104. \ 'gcr': 'a:blinkon0', 'ic': 1, 'lmap': '', 'mousef': 0, 'imd': 1 }
  105. " Keymaps
  106. let [s:lcmap, s:prtmaps] = ['nn <buffer> <silent>', {
  107. \ 'PrtBS()': ['<bs>', '<c-]>'],
  108. \ 'PrtDelete()': ['<del>'],
  109. \ 'PrtDeleteWord()': ['<c-w>'],
  110. \ 'PrtClear()': ['<c-u>'],
  111. \ 'PrtSelectMove("j")': ['<c-j>', '<down>'],
  112. \ 'PrtSelectMove("k")': ['<c-k>', '<up>'],
  113. \ 'PrtSelectMove("t")': ['<Home>', '<kHome>'],
  114. \ 'PrtSelectMove("b")': ['<End>', '<kEnd>'],
  115. \ 'PrtSelectMove("u")': ['<PageUp>', '<kPageUp>'],
  116. \ 'PrtSelectMove("d")': ['<PageDown>', '<kPageDown>'],
  117. \ 'PrtHistory(-1)': ['<c-n>'],
  118. \ 'PrtHistory(1)': ['<c-p>'],
  119. \ 'AcceptSelection("e")': ['<cr>', '<2-LeftMouse>'],
  120. \ 'AcceptSelection("h")': ['<c-x>', '<c-cr>', '<c-s>'],
  121. \ 'AcceptSelection("t")': ['<c-t>'],
  122. \ 'AcceptSelection("v")': ['<c-v>', '<RightMouse>'],
  123. \ 'ToggleFocus()': ['<s-tab>'],
  124. \ 'ToggleRegex()': ['<c-r>'],
  125. \ 'ToggleByFname()': ['<c-d>'],
  126. \ 'ToggleType(1)': ['<c-f>', '<c-up>'],
  127. \ 'ToggleType(-1)': ['<c-b>', '<c-down>'],
  128. \ 'PrtExpandDir()': ['<tab>'],
  129. \ 'PrtInsert("c")': ['<MiddleMouse>', '<insert>'],
  130. \ 'PrtInsert()': ['<c-\>'],
  131. \ 'PrtCurStart()': ['<c-a>'],
  132. \ 'PrtCurEnd()': ['<c-e>'],
  133. \ 'PrtCurLeft()': ['<c-h>', '<left>', '<c-^>'],
  134. \ 'PrtCurRight()': ['<c-l>', '<right>'],
  135. \ 'PrtClearCache()': ['<F5>'],
  136. \ 'PrtDeleteEnt()': ['<F7>'],
  137. \ 'CreateNewFile()': ['<c-y>'],
  138. \ 'MarkToOpen()': ['<c-z>'],
  139. \ 'OpenMulti()': ['<c-o>'],
  140. \ 'PrtExit()': ['<esc>', '<c-c>', '<c-g>'],
  141. \ }]
  142. if !has('gui_running')
  143. cal add(s:prtmaps['PrtBS()'], remove(s:prtmaps['PrtCurLeft()'], 0))
  144. en
  145. let s:compare_lim = 3000
  146. let s:ficounts = {}
  147. let s:ccex = s:pref.'clear_cache_on_exit'
  148. " Regexp
  149. let s:fpats = {
  150. \ '^\(\\|\)\|\(\\|\)$': '\\|',
  151. \ '^\\\(zs\|ze\|<\|>\)': '^\\\(zs\|ze\|<\|>\)',
  152. \ '^\S\*$': '\*',
  153. \ '^\S\\?$': '\\?',
  154. \ }
  155. " Keypad
  156. let s:kprange = {
  157. \ 'Plus': '+',
  158. \ 'Minus': '-',
  159. \ 'Divide': '/',
  160. \ 'Multiply': '*',
  161. \ 'Point': '.',
  162. \ }
  163. " Highlight groups
  164. let s:hlgrps = {
  165. \ 'NoEntries': 'Error',
  166. \ 'Mode1': 'Character',
  167. \ 'Mode2': 'LineNr',
  168. \ 'Stats': 'Function',
  169. \ 'Match': 'Identifier',
  170. \ 'PrtBase': 'Comment',
  171. \ 'PrtText': 'Normal',
  172. \ 'PrtCursor': 'Constant',
  173. \ }
  174. " s:opts() {{{2
  175. fu! s:opts(...)
  176. unl! s:usrign s:usrcmd s:urprtmaps
  177. for each in ['byfname', 'regexp', 'extensions'] | if exists('s:'.each)
  178. let {each} = s:{each}
  179. en | endfo
  180. for [ke, va] in items(s:opts)
  181. let {va[0]} = exists(s:pref.ke) ? {s:pref.ke} : va[1]
  182. endfo
  183. unl va
  184. for [ke, va] in items(s:new_opts)
  185. let {va} = {exists(s:pref.ke) ? s:pref.ke : va}
  186. endfo
  187. unl va
  188. for [ke, va] in items(s:lc_opts)
  189. if exists(s:bpref.ke)
  190. unl {va}
  191. let {va} = {s:bpref.ke}
  192. en
  193. endfo
  194. if a:0 && a:1 != {}
  195. unl va
  196. for [ke, va] in items(a:1)
  197. let opke = substitute(ke, '\(\w:\)\?ctrlp_', '', '')
  198. if has_key(s:lc_opts, opke)
  199. let sva = s:lc_opts[opke]
  200. unl {sva}
  201. let {sva} = va
  202. en
  203. endfo
  204. en
  205. for each in ['byfname', 'regexp'] | if exists(each)
  206. let s:{each} = {each}
  207. en | endfo
  208. if !exists('g:ctrlp_newcache') | let g:ctrlp_newcache = 0 | en
  209. let s:maxdepth = min([s:maxdepth, 100])
  210. let s:mxheight = max([s:mxheight, 1])
  211. let s:glob = s:showhidden ? '.*\|*' : '*'
  212. let s:igntype = empty(s:usrign) ? -1 : type(s:usrign)
  213. let s:lash = ctrlp#utils#lash()
  214. if s:keyloop
  215. let [s:lazy, s:glbs['imd']] = [0, 0]
  216. en
  217. if s:lazy
  218. cal extend(s:glbs, { 'ut': ( s:lazy > 1 ? s:lazy : 250 ) })
  219. en
  220. " Extensions
  221. if !( exists('extensions') && extensions == s:extensions )
  222. for each in s:extensions
  223. exe 'ru autoload/ctrlp/'.each.'.vim'
  224. endfo
  225. en
  226. " Keymaps
  227. if type(s:urprtmaps) == 4
  228. cal extend(s:prtmaps, s:urprtmaps)
  229. en
  230. endf
  231. "}}}1
  232. " * Open & Close {{{1
  233. fu! s:Open()
  234. cal s:log(1)
  235. cal s:getenv()
  236. cal s:execextvar('enter')
  237. sil! exe 'keepa' ( s:mwbottom ? 'bo' : 'to' ) '1new ControlP'
  238. cal s:buffunc(1)
  239. let [s:bufnr, s:winw] = [bufnr('%'), winwidth(0)]
  240. let [s:focus, s:prompt] = [1, ['', '', '']]
  241. abc <buffer>
  242. if !exists('s:hstry')
  243. let hst = filereadable(s:gethistloc()[1]) ? s:gethistdata() : ['']
  244. let s:hstry = empty(hst) || !s:maxhst ? [''] : hst
  245. en
  246. for [ke, va] in items(s:glbs) | if exists('+'.ke)
  247. sil! exe 'let s:glb_'.ke.' = &'.ke.' | let &'.ke.' = '.string(va)
  248. en | endfo
  249. if s:opmul != '0' && has('signs')
  250. sign define ctrlpmark text=+> texthl=Search
  251. en
  252. cal s:setupblank()
  253. endf
  254. fu! s:Close()
  255. cal s:buffunc(0)
  256. try | bun!
  257. cat | clo! | endt
  258. cal s:unmarksigns()
  259. for key in keys(s:glbs) | if exists('+'.key)
  260. sil! exe 'let &'.key.' = s:glb_'.key
  261. en | endfo
  262. if exists('s:glb_acd') | let &acd = s:glb_acd | en
  263. let g:ctrlp_lines = []
  264. if s:winres[1] >= &lines && s:winres[2] == winnr('$')
  265. exe s:winres[0].s:winres[0]
  266. en
  267. unl! s:focus s:hisidx s:hstgot s:marked s:statypes s:cline s:init s:savestr
  268. \ s:mrbs s:did_exp
  269. cal ctrlp#recordhist()
  270. cal s:execextvar('exit')
  271. cal s:log(0)
  272. let v:errmsg = s:ermsg
  273. ec
  274. endf
  275. " * Clear caches {{{1
  276. fu! ctrlp#clr(...)
  277. let [s:matches, g:ctrlp_new{ a:0 ? a:1 : 'cache' }] = [1, 1]
  278. endf
  279. fu! ctrlp#clra()
  280. let cadir = ctrlp#utils#cachedir()
  281. if isdirectory(cadir)
  282. let cafiles = split(s:glbpath(s:fnesc(cadir, 'g', ','), '**', 1), "\n")
  283. let eval = '!isdirectory(v:val) && fnamemodify(v:val, ":t") !~'
  284. \ . ' ''\v^<cache>[.a-z]+$|\.log$'''
  285. sil! cal map(filter(cafiles, eval), 'delete(v:val)')
  286. en
  287. cal ctrlp#clr()
  288. endf
  289. fu! s:Reset(args)
  290. let opts = has_key(a:args, 'opts') ? [a:args['opts']] : []
  291. cal call('s:opts', opts)
  292. cal s:autocmds()
  293. cal ctrlp#utils#opts()
  294. cal s:execextvar('opts')
  295. endf
  296. " * Files {{{1
  297. fu! ctrlp#files()
  298. let cafile = ctrlp#utils#cachefile()
  299. if g:ctrlp_newcache || !filereadable(cafile) || s:nocache(cafile)
  300. let [lscmd, s:initcwd, g:ctrlp_allfiles] = [s:lsCmd(), s:dyncwd, []]
  301. " Get the list of files
  302. if empty(lscmd)
  303. cal s:GlobPath(s:fnesc(s:dyncwd, 'g', ','), 0)
  304. el
  305. sil! cal ctrlp#progress('Indexing...')
  306. try | cal s:UserCmd(lscmd)
  307. cat | retu [] | endt
  308. en
  309. " Remove base directory
  310. cal ctrlp#rmbasedir(g:ctrlp_allfiles)
  311. if len(g:ctrlp_allfiles) <= s:compare_lim
  312. cal sort(g:ctrlp_allfiles, 'ctrlp#complen')
  313. en
  314. cal s:writecache(cafile)
  315. let catime = getftime(cafile)
  316. el
  317. let catime = getftime(cafile)
  318. if !( exists('s:initcwd') && s:initcwd == s:dyncwd )
  319. \ || get(s:ficounts, s:dyncwd, [0, catime])[1] != catime
  320. let s:initcwd = s:dyncwd
  321. let g:ctrlp_allfiles = ctrlp#utils#readfile(cafile)
  322. en
  323. en
  324. cal extend(s:ficounts, { s:dyncwd : [len(g:ctrlp_allfiles), catime] })
  325. retu g:ctrlp_allfiles
  326. endf
  327. fu! s:GlobPath(dirs, depth)
  328. let entries = split(globpath(a:dirs, s:glob), "\n")
  329. let [dnf, depth] = [ctrlp#dirnfile(entries), a:depth + 1]
  330. cal extend(g:ctrlp_allfiles, dnf[1])
  331. if !empty(dnf[0]) && !s:maxf(len(g:ctrlp_allfiles)) && depth <= s:maxdepth
  332. sil! cal ctrlp#progress(len(g:ctrlp_allfiles), 1)
  333. cal s:GlobPath(join(map(dnf[0], 's:fnesc(v:val, "g", ",")'), ','), depth)
  334. en
  335. endf
  336. fu! s:UserCmd(lscmd)
  337. let [path, lscmd] = [s:dyncwd, a:lscmd]
  338. if exists('+ssl') && &ssl
  339. let [ssl, &ssl, path] = [&ssl, 0, tr(path, '/', '\')]
  340. en
  341. if has('win32') || has('win64')
  342. let lscmd = substitute(lscmd, '\v(^|&&\s*)\zscd (/d)@!', 'cd /d ', '')
  343. en
  344. let path = exists('*shellescape') ? shellescape(path) : path
  345. let g:ctrlp_allfiles = split(system(printf(lscmd, path)), "\n")
  346. if exists('+ssl') && exists('ssl')
  347. let &ssl = ssl
  348. cal map(g:ctrlp_allfiles, 'tr(v:val, "\\", "/")')
  349. en
  350. if exists('s:vcscmd') && s:vcscmd
  351. cal map(g:ctrlp_allfiles, 'tr(v:val, "/", "\\")')
  352. en
  353. if type(s:usrcmd) == 4 && has_key(s:usrcmd, 'ignore') && s:usrcmd['ignore']
  354. if !empty(s:usrign)
  355. let g:ctrlp_allfiles = ctrlp#dirnfile(g:ctrlp_allfiles)[1]
  356. en
  357. if &wig != ''
  358. cal filter(g:ctrlp_allfiles, 'glob(v:val) != ""')
  359. en
  360. en
  361. endf
  362. fu! s:lsCmd()
  363. let cmd = s:usrcmd
  364. if type(cmd) == 1
  365. retu cmd
  366. elsei type(cmd) == 3 && len(cmd) >= 2 && cmd[:1] != ['', '']
  367. if s:findroot(s:dyncwd, cmd[0], 0, 1) == []
  368. retu len(cmd) == 3 ? cmd[2] : ''
  369. en
  370. let s:vcscmd = s:lash == '\'
  371. retu cmd[1]
  372. elsei type(cmd) == 4 && ( has_key(cmd, 'types') || has_key(cmd, 'fallback') )
  373. let fndroot = []
  374. if has_key(cmd, 'types') && cmd['types'] != {}
  375. let [markrs, cmdtypes] = [[], values(cmd['types'])]
  376. for pair in cmdtypes
  377. cal add(markrs, pair[0])
  378. endfo
  379. let fndroot = s:findroot(s:dyncwd, markrs, 0, 1)
  380. en
  381. if fndroot == []
  382. retu has_key(cmd, 'fallback') ? cmd['fallback'] : ''
  383. en
  384. for pair in cmdtypes
  385. if pair[0] == fndroot[0] | brea | en
  386. endfo
  387. let s:vcscmd = s:lash == '\'
  388. retu pair[1]
  389. en
  390. endf
  391. " - Buffers {{{1
  392. fu! ctrlp#buffers(...)
  393. let ids = sort(filter(range(1, bufnr('$')), 'empty(getbufvar(v:val, "&bt"))'
  394. \ .' && getbufvar(v:val, "&bl") && strlen(bufname(v:val))'), 's:compmreb')
  395. retu a:0 && a:1 == 'id' ? ids : map(ids, 'fnamemodify(bufname(v:val), ":.")')
  396. endf
  397. " * MatchedItems() {{{1
  398. fu! s:MatchIt(items, pat, limit, exc)
  399. let [lines, id] = [[], 0]
  400. let pat =
  401. \ s:byfname ? map(split(a:pat, '^[^;]\+\\\@<!\zs;', 1), 's:martcs.v:val')
  402. \ : s:martcs.a:pat
  403. for item in a:items
  404. let id += 1
  405. try | if !( s:ispath && item == a:exc ) && call(s:mfunc, [item, pat]) >= 0
  406. cal add(lines, item)
  407. en | cat | brea | endt
  408. if a:limit > 0 && len(lines) >= a:limit | brea | en
  409. endfo
  410. let s:mdata = [s:dyncwd, s:itemtype, s:regexp, s:sublist(a:items, id, -1)]
  411. retu lines
  412. endf
  413. fu! s:MatchedItems(items, pat, limit)
  414. let exc = exists('s:crfilerel') ? s:crfilerel : ''
  415. let items = s:narrowable() ? s:matched + s:mdata[3] : a:items
  416. if s:matcher != {}
  417. let argms = [items, a:pat, a:limit, s:mmode(), s:ispath, exc, s:regexp]
  418. let lines = call(s:matcher['match'], argms, s:matcher)
  419. el
  420. let lines = s:MatchIt(items, a:pat, a:limit, exc)
  421. en
  422. let s:matches = len(lines)
  423. unl! s:did_exp
  424. retu lines
  425. endf
  426. fu! s:SplitPattern(str)
  427. let str = a:str
  428. if s:migemo && s:regexp && len(str) > 0 && executable('cmigemo')
  429. let str = s:migemo(str)
  430. en
  431. let s:savestr = str
  432. if s:regexp
  433. let pat = s:regexfilter(str)
  434. el
  435. let lst = split(str, '\zs')
  436. if exists('+ssl') && !&ssl
  437. cal map(lst, 'escape(v:val, ''\'')')
  438. en
  439. for each in ['^', '$', '.']
  440. cal map(lst, 'escape(v:val, each)')
  441. endfo
  442. en
  443. if exists('lst')
  444. let pat = ''
  445. if !empty(lst)
  446. if s:byfname && index(lst, ';') > 0
  447. let fbar = index(lst, ';')
  448. let lst_1 = s:sublist(lst, 0, fbar - 1)
  449. let lst_2 = len(lst) - 1 > fbar ? s:sublist(lst, fbar + 1, -1) : ['']
  450. let pat = s:buildpat(lst_1).';'.s:buildpat(lst_2)
  451. el
  452. let pat = s:buildpat(lst)
  453. en
  454. en
  455. en
  456. retu escape(pat, '~')
  457. endf
  458. " * BuildPrompt() {{{1
  459. fu! s:Render(lines, pat)
  460. let [&ma, lines, s:height] = [1, a:lines, min([len(a:lines), s:winh])]
  461. let pat = s:byfname ? split(a:pat, '^[^;]\+\\\@<!\zs;', 1)[0] : a:pat
  462. " Setup the match window
  463. sil! exe '%d _ | res' s:height
  464. " Print the new items
  465. if empty(lines)
  466. let [s:matched, s:lines] = [[], []]
  467. cal setline(1, ' == NO ENTRIES ==')
  468. setl noma nocul
  469. cal s:unmarksigns()
  470. if s:dohighlight() | cal clearmatches() | en
  471. retu
  472. en
  473. let s:matched = copy(lines)
  474. " Sorting
  475. if !s:nosort()
  476. let s:compat = s:martcs.pat
  477. cal sort(lines, 's:mixedsort')
  478. unl s:compat
  479. en
  480. if s:mwreverse | cal reverse(lines) | en
  481. let s:lines = copy(lines)
  482. cal map(lines, 's:formatline(v:val)')
  483. cal setline(1, lines)
  484. setl noma cul
  485. exe 'keepj norm!' ( s:mwreverse ? 'G' : 'gg' ).'1|'
  486. cal s:unmarksigns()
  487. cal s:remarksigns()
  488. if exists('s:cline') && s:nolim != 1
  489. cal cursor(s:cline, 1)
  490. en
  491. " Highlighting
  492. if s:dohighlight()
  493. cal s:highlight(pat, s:mathi[1])
  494. en
  495. endf
  496. fu! s:Update(str)
  497. " Get the previous string if existed
  498. let oldstr = exists('s:savestr') ? s:savestr : ''
  499. " Get the new string sans tail
  500. let str = s:sanstail(a:str)
  501. " Stop if the string's unchanged
  502. if str == oldstr && !empty(str) && !exists('s:force') | retu | en
  503. let s:martcs = &scs && str =~ '\u' ? '\C' : ''
  504. let pat = s:matcher == {} ? s:SplitPattern(str) : str
  505. let lines = s:nolim == 1 && empty(str) ? copy(g:ctrlp_lines)
  506. \ : s:MatchedItems(g:ctrlp_lines, pat, s:winh)
  507. cal s:Render(lines, pat)
  508. endf
  509. fu! s:ForceUpdate()
  510. sil! cal s:Update(escape(s:getinput(), '\'))
  511. endf
  512. fu! s:BuildPrompt(upd)
  513. let base = ( s:regexp ? 'r' : '>' ).( s:byfname ? 'd' : '>' ).'> '
  514. let str = escape(s:getinput(), '\')
  515. let lazy = str == '' || exists('s:force') || !has('autocmd') ? 0 : s:lazy
  516. if a:upd && !lazy && ( s:matches || s:regexp || exists('s:did_exp')
  517. \ || str =~ '\(\\\(<\|>\)\|[*|]\)\|\(\\\:\([^:]\|\\:\)*$\)' )
  518. sil! cal s:Update(str)
  519. en
  520. sil! cal ctrlp#statusline()
  521. " Toggling
  522. let [hiactive, hicursor, base] = s:focus
  523. \ ? ['CtrlPPrtText', 'CtrlPPrtCursor', base]
  524. \ : ['CtrlPPrtBase', 'CtrlPPrtBase', tr(base, '>', '-')]
  525. let hibase = 'CtrlPPrtBase'
  526. " Build it
  527. redr
  528. let prt = copy(s:prompt)
  529. cal map(prt, 'escape(v:val, ''"\'')')
  530. exe 'echoh' hibase '| echon "'.base.'"
  531. \ | echoh' hiactive '| echon "'.prt[0].'"
  532. \ | echoh' hicursor '| echon "'.prt[1].'"
  533. \ | echoh' hiactive '| echon "'.prt[2].'" | echoh None'
  534. " Append the cursor at the end
  535. if empty(prt[1]) && s:focus
  536. exe 'echoh' hibase '| echon "_" | echoh None'
  537. en
  538. endf
  539. " - SetDefTxt() {{{1
  540. fu! s:SetDefTxt()
  541. if s:deftxt == '0' || ( s:deftxt == 1 && !s:ispath ) | retu | en
  542. let txt = s:deftxt
  543. if !type(txt)
  544. let txt = txt && !stridx(s:crfpath, s:dyncwd)
  545. \ ? ctrlp#rmbasedir([s:crfpath])[0] : ''
  546. let txt = txt != '' ? txt.s:lash(s:crfpath) : ''
  547. el
  548. let txt = expand(txt, 1)
  549. en
  550. let s:prompt[0] = txt
  551. endf
  552. " ** Prt Actions {{{1
  553. " Editing {{{2
  554. fu! s:PrtClear()
  555. if !s:focus | retu | en
  556. unl! s:hstgot
  557. let [s:prompt, s:matches] = [['', '', ''], 1]
  558. cal s:BuildPrompt(1)
  559. endf
  560. fu! s:PrtAdd(char)
  561. unl! s:hstgot
  562. let s:act_add = 1
  563. let s:prompt[0] .= a:char
  564. cal s:BuildPrompt(1)
  565. unl s:act_add
  566. endf
  567. fu! s:PrtBS()
  568. if !s:focus | retu | en
  569. unl! s:hstgot
  570. let [s:prompt[0], s:matches] = [substitute(s:prompt[0], '.$', '', ''), 1]
  571. cal s:BuildPrompt(1)
  572. endf
  573. fu! s:PrtDelete()
  574. if !s:focus | retu | en
  575. unl! s:hstgot
  576. let [prt, s:matches] = [s:prompt, 1]
  577. let prt[1] = matchstr(prt[2], '^.')
  578. let prt[2] = substitute(prt[2], '^.', '', '')
  579. cal s:BuildPrompt(1)
  580. endf
  581. fu! s:PrtDeleteWord()
  582. if !s:focus | retu | en
  583. unl! s:hstgot
  584. let [str, s:matches] = [s:prompt[0], 1]
  585. let str = str =~ '\W\w\+$' ? matchstr(str, '^.\+\W\ze\w\+$')
  586. \ : str =~ '\w\W\+$' ? matchstr(str, '^.\+\w\ze\W\+$')
  587. \ : str =~ '\s\+$' ? matchstr(str, '^.*\S\ze\s\+$')
  588. \ : str =~ '\v^(\S+|\s+)$' ? '' : str
  589. let s:prompt[0] = str
  590. cal s:BuildPrompt(1)
  591. endf
  592. fu! s:PrtInsert(...)
  593. if !s:focus | retu | en
  594. let type = !a:0 ? '' : a:1
  595. if !a:0
  596. let type = s:insertstr()
  597. if type == 'cancel' | retu | en
  598. en
  599. if type ==# 'r'
  600. let regcont = s:getregs()
  601. if regcont < 0 | retu | en
  602. en
  603. unl! s:hstgot
  604. let s:act_add = 1
  605. let s:prompt[0] .= type ==# 'w' ? s:crword
  606. \ : type ==# 'f' ? s:crgfile
  607. \ : type ==# 's' ? s:regisfilter('/')
  608. \ : type ==# 'v' ? s:crvisual
  609. \ : type ==# 'c' ? s:regisfilter('+')
  610. \ : type ==# 'r' ? regcont : ''
  611. cal s:BuildPrompt(1)
  612. unl s:act_add
  613. endf
  614. fu! s:PrtExpandDir()
  615. if !s:focus | retu | en
  616. let str = s:getinput('c')
  617. if str =~ '\v^\@(cd|lc[hd]?|chd)\s.+' && s:spi
  618. let hasat = split(str, '\v^\@(cd|lc[hd]?|chd)\s*\zs')
  619. let str = get(hasat, 1, '')
  620. en
  621. if str == '' | retu | en
  622. unl! s:hstgot
  623. let s:act_add = 1
  624. let [base, seed] = s:headntail(str)
  625. let dirs = s:dircompl(base, seed)
  626. if len(dirs) == 1
  627. let str = dirs[0]
  628. elsei len(dirs) > 1
  629. let str .= s:findcommon(dirs, str)
  630. en
  631. let s:prompt[0] = exists('hasat') ? hasat[0].str : str
  632. cal s:BuildPrompt(1)
  633. unl s:act_add
  634. endf
  635. " Movement {{{2
  636. fu! s:PrtCurLeft()
  637. if !s:focus | retu | en
  638. let prt = s:prompt
  639. if !empty(prt[0])
  640. let s:prompt = [substitute(prt[0], '.$', '', ''), matchstr(prt[0], '.$'),
  641. \ prt[1] . prt[2]]
  642. en
  643. cal s:BuildPrompt(0)
  644. endf
  645. fu! s:PrtCurRight()
  646. if !s:focus | retu | en
  647. let prt = s:prompt
  648. let s:prompt = [prt[0] . prt[1], matchstr(prt[2], '^.'),
  649. \ substitute(prt[2], '^.', '', '')]
  650. cal s:BuildPrompt(0)
  651. endf
  652. fu! s:PrtCurStart()
  653. if !s:focus | retu | en
  654. let str = join(s:prompt, '')
  655. let s:prompt = ['', matchstr(str, '^.'), substitute(str, '^.', '', '')]
  656. cal s:BuildPrompt(0)
  657. endf
  658. fu! s:PrtCurEnd()
  659. if !s:focus | retu | en
  660. let s:prompt = [join(s:prompt, ''), '', '']
  661. cal s:BuildPrompt(0)
  662. endf
  663. fu! s:PrtSelectMove(dir)
  664. let wht = winheight(0)
  665. let dirs = {'t': 'gg','b': 'G','j': 'j','k': 'k','u': wht.'k','d': wht.'j'}
  666. exe 'keepj norm!' dirs[a:dir]
  667. if s:nolim != 1 | let s:cline = line('.') | en
  668. if line('$') > winheight(0) | cal s:BuildPrompt(0) | en
  669. endf
  670. fu! s:PrtSelectJump(char)
  671. let lines = copy(s:lines)
  672. if s:byfname
  673. cal map(lines, 'split(v:val, ''[\/]\ze[^\/]\+$'')[-1]')
  674. en
  675. " Cycle through matches, use s:jmpchr to store last jump
  676. let chr = escape(matchstr(a:char, '^.'), '.~')
  677. let smartcs = &scs && chr =~ '\u' ? '\C' : ''
  678. if match(lines, smartcs.'^'.chr) >= 0
  679. " If not exists or does but not for the same char
  680. let pos = match(lines, smartcs.'^'.chr)
  681. if !exists('s:jmpchr') || ( exists('s:jmpchr') && s:jmpchr[0] != chr )
  682. let [jmpln, s:jmpchr] = [pos, [chr, pos]]
  683. elsei exists('s:jmpchr') && s:jmpchr[0] == chr
  684. " Start of lines
  685. if s:jmpchr[1] == -1 | let s:jmpchr[1] = pos | en
  686. let npos = match(lines, smartcs.'^'.chr, s:jmpchr[1] + 1)
  687. let [jmpln, s:jmpchr] = [npos == -1 ? pos : npos, [chr, npos]]
  688. en
  689. exe 'keepj norm!' ( jmpln + 1 ).'G'
  690. if s:nolim != 1 | let s:cline = line('.') | en
  691. if line('$') > winheight(0) | cal s:BuildPrompt(0) | en
  692. en
  693. endf
  694. " Misc {{{2
  695. fu! s:PrtFocusMap(char)
  696. cal call(( s:focus ? 's:PrtAdd' : 's:PrtSelectJump' ), [a:char])
  697. endf
  698. fu! s:PrtClearCache()
  699. if s:itemtype == 0
  700. cal ctrlp#clr()
  701. elsei s:itemtype > 2
  702. cal ctrlp#clr(s:statypes[s:itemtype][1])
  703. en
  704. if s:itemtype == 2
  705. let g:ctrlp_lines = ctrlp#mrufiles#refresh()
  706. el
  707. cal ctrlp#setlines()
  708. en
  709. let s:force = 1
  710. cal s:BuildPrompt(1)
  711. unl s:force
  712. endf
  713. fu! s:PrtDeleteEnt()
  714. if s:itemtype == 2
  715. cal s:PrtDeleteMRU()
  716. elsei type(s:getextvar('wipe')) == 1
  717. cal s:delent(s:getextvar('wipe'))
  718. en
  719. endf
  720. fu! s:PrtDeleteMRU()
  721. if s:itemtype == 2
  722. cal s:delent('ctrlp#mrufiles#remove')
  723. en
  724. endf
  725. fu! s:PrtExit()
  726. if bufnr('%') == s:bufnr && bufname('%') == 'ControlP'
  727. if !has('autocmd') | cal s:Close() | en
  728. exe ( winnr('$') == 1 ? 'bw!' : 'winc p' )
  729. en
  730. endf
  731. fu! s:PrtHistory(...)
  732. if !s:focus || !s:maxhst | retu | en
  733. let [str, hst, s:matches] = [join(s:prompt, ''), s:hstry, 1]
  734. " Save to history if not saved before
  735. let [hst[0], hslen] = [exists('s:hstgot') ? hst[0] : str, len(hst)]
  736. let idx = exists('s:hisidx') ? s:hisidx + a:1 : a:1
  737. " Limit idx within 0 and hslen
  738. let idx = idx < 0 ? 0 : idx >= hslen ? hslen > 1 ? hslen - 1 : 0 : idx
  739. let s:prompt = [hst[idx], '', '']
  740. let [s:hisidx, s:hstgot, s:force] = [idx, 1, 1]
  741. cal s:BuildPrompt(1)
  742. unl s:force
  743. endf
  744. "}}}1
  745. " * Mappings {{{1
  746. fu! s:MapNorms()
  747. if exists('s:nmapped') && s:nmapped == s:bufnr | retu | en
  748. let pcmd = "nn \<buffer> \<silent> \<k%s> :\<c-u>cal \<SID>%s(\"%s\")\<cr>"
  749. let cmd = substitute(pcmd, 'k%s', 'char-%d', '')
  750. let pfunc = 'PrtFocusMap'
  751. let ranges = [32, 33, 125, 126] + range(35, 91) + range(93, 123)
  752. for each in [34, 92, 124]
  753. exe printf(cmd, each, pfunc, escape(nr2char(each), '"|\'))
  754. endfo
  755. for each in ranges
  756. exe printf(cmd, each, pfunc, nr2char(each))
  757. endfo
  758. for each in range(0, 9)
  759. exe printf(pcmd, each, pfunc, each)
  760. endfo
  761. for [ke, va] in items(s:kprange)
  762. exe printf(pcmd, ke, pfunc, va)
  763. endfo
  764. let s:nmapped = s:bufnr
  765. endf
  766. fu! s:MapSpecs()
  767. if !( exists('s:smapped') && s:smapped == s:bufnr )
  768. " Correct arrow keys in terminal
  769. if ( has('termresponse') && v:termresponse =~ "\<ESC>" )
  770. \ || &term =~? '\vxterm|<k?vt|gnome|screen|linux|ansi'
  771. for each in ['\A <up>','\B <down>','\C <right>','\D <left>']
  772. exe s:lcmap.' <esc>['.each
  773. endfo
  774. en
  775. en
  776. for [ke, va] in items(s:prtmaps) | for kp in va
  777. exe s:lcmap kp ':<c-u>cal <SID>'.ke.'<cr>'
  778. endfo | endfo
  779. let s:smapped = s:bufnr
  780. endf
  781. fu! s:KeyLoop()
  782. wh exists('s:init') && s:keyloop
  783. redr
  784. let nr = getchar()
  785. let chr = !type(nr) ? nr2char(nr) : nr
  786. if nr >=# 0x20
  787. cal s:PrtFocusMap(chr)
  788. el
  789. let cmd = matchstr(maparg(chr), ':<C-U>\zs.\+\ze<CR>$')
  790. exe ( cmd != '' ? cmd : 'norm '.chr )
  791. en
  792. endw
  793. endf
  794. " * Toggling {{{1
  795. fu! s:ToggleFocus()
  796. let s:focus = !s:focus
  797. cal s:BuildPrompt(0)
  798. endf
  799. fu! s:ToggleRegex()
  800. let s:regexp = !s:regexp
  801. cal s:PrtSwitcher()
  802. endf
  803. fu! s:ToggleByFname()
  804. if s:ispath
  805. let s:byfname = !s:byfname
  806. let s:mfunc = s:mfunc()
  807. cal s:PrtSwitcher()
  808. en
  809. endf
  810. fu! s:ToggleType(dir)
  811. let max = len(g:ctrlp_ext_vars) + 2
  812. let next = s:walker(max, s:itemtype, a:dir)
  813. cal ctrlp#syntax()
  814. cal ctrlp#setlines(next)
  815. cal s:PrtSwitcher()
  816. endf
  817. fu! s:ToggleKeyLoop()
  818. let s:keyloop = !s:keyloop
  819. if exists('+imd')
  820. let &imd = !s:keyloop
  821. en
  822. if s:keyloop
  823. let [&ut, s:lazy] = [0, 0]
  824. cal s:KeyLoop()
  825. elsei has_key(s:glbs, 'ut')
  826. let [&ut, s:lazy] = [s:glbs['ut'], 1]
  827. en
  828. endf
  829. fu! s:PrtSwitcher()
  830. let [s:force, s:matches] = [1, 1]
  831. cal s:BuildPrompt(1)
  832. unl s:force
  833. endf
  834. " - SetWD() {{{1
  835. fu! s:SetWD(args)
  836. if has_key(a:args, 'args') && stridx(a:args['args'], '--dir') >= 0
  837. \ && exists('s:dyncwd')
  838. cal ctrlp#setdir(s:dyncwd) | retu
  839. en
  840. if has_key(a:args, 'dir') && a:args['dir'] != ''
  841. cal ctrlp#setdir(a:args['dir']) | retu
  842. en
  843. let pmode = has_key(a:args, 'mode') ? a:args['mode'] : s:pathmode
  844. let [s:crfilerel, s:dyncwd] = [fnamemodify(s:crfile, ':.'), getcwd()]
  845. if s:crfile =~ '^.\+://' | retu | en
  846. if pmode =~ 'c' || ( pmode =~ 'a' && stridx(s:crfpath, s:cwd) < 0 )
  847. \ || ( !type(pmode) && pmode )
  848. if exists('+acd') | let [s:glb_acd, &acd] = [&acd, 0] | en
  849. cal ctrlp#setdir(s:crfpath)
  850. en
  851. if pmode =~ 'r' || pmode == 2
  852. let markers = ['.git', '.hg', '.svn', '.bzr', '_darcs']
  853. let spath = pmode =~ 'd' ? s:dyncwd : pmode =~ 'w' ? s:cwd : s:crfpath
  854. if type(s:rmarkers) == 3 && !empty(s:rmarkers)
  855. if s:findroot(spath, s:rmarkers, 0, 0) != [] | retu | en
  856. cal filter(markers, 'index(s:rmarkers, v:val) < 0')
  857. en
  858. cal s:findroot(spath, markers, 0, 0)
  859. en
  860. endf
  861. " * AcceptSelection() {{{1
  862. fu! ctrlp#acceptfile(mode, line, ...)
  863. let [md, filpath] = [a:mode, fnamemodify(a:line, ':p')]
  864. cal s:PrtExit()
  865. let [bufnr, tail] = [bufnr('^'.filpath.'$'), s:tail()]
  866. let j2l = a:0 ? a:1 : matchstr(tail, '^ +\zs\d\+$')
  867. if ( s:jmptobuf =~ md || ( s:jmptobuf && md =~ '[et]' ) ) && bufnr > 0
  868. \ && !( md == 'e' && bufnr == bufnr('%') )
  869. let [jmpb, bufwinnr] = [1, bufwinnr(bufnr)]
  870. let buftab = ( s:jmptobuf =~# '[tTVH]' || s:jmptobuf > 1 )
  871. \ ? s:buftab(bufnr, md) : [0, 0]
  872. en
  873. " Switch to existing buffer or open new one
  874. if exists('jmpb') && bufwinnr > 0
  875. \ && !( md == 't' && ( s:jmptobuf !~# toupper(md) || buftab[0] ) )
  876. exe bufwinnr.'winc w'
  877. if j2l | cal ctrlp#j2l(j2l) | en
  878. elsei exists('jmpb') && buftab[0]
  879. \ && !( md =~ '[evh]' && s:jmptobuf !~# toupper(md) )
  880. exe 'tabn' buftab[0]
  881. exe buftab[1].'winc w'
  882. if j2l | cal ctrlp#j2l(j2l) | en
  883. el
  884. " Determine the command to use
  885. let useb = bufnr > 0 && buflisted(bufnr) && empty(tail)
  886. let cmd =
  887. \ md == 't' || s:splitwin == 1 ? ( useb ? 'tab sb' : 'tabe' ) :
  888. \ md == 'h' || s:splitwin == 2 ? ( useb ? 'sb' : 'new' ) :
  889. \ md == 'v' || s:splitwin == 3 ? ( useb ? 'vert sb' : 'vne' ) :
  890. \ call('ctrlp#normcmd', useb ? ['b', 'bo vert sb'] : ['e'])
  891. " Reset &switchbuf option
  892. let [swb, &swb] = [&swb, '']
  893. " Open new window/buffer
  894. let [fid, tail] = [( useb ? bufnr : filpath ), ( a:0 ? ' +'.a:1 : tail )]
  895. let args = [cmd, fid, tail, 1, [useb, j2l]]
  896. cal call('s:openfile', args)
  897. let &swb = swb
  898. en
  899. endf
  900. fu! s:SpecInputs(str)
  901. if a:str =~ '\v^(\.\.([\/]\.\.)*[\/]?[.\/]*)$' && s:spi
  902. let cwd = s:dyncwd
  903. cal ctrlp#setdir(a:str =~ '^\.\.\.*$' ?
  904. \ '../'.repeat('../', strlen(a:str) - 2) : a:str)
  905. if cwd != s:dyncwd | cal ctrlp#setlines() | en
  906. cal s:PrtClear()
  907. retu 1
  908. elsei a:str == s:lash && s:spi
  909. cal s:SetWD({ 'mode': 'rd' })
  910. cal ctrlp#setlines()
  911. cal s:PrtClear()
  912. retu 1
  913. elsei a:str =~ '^@.\+' && s:spi
  914. retu s:at(a:str)
  915. elsei a:str == '?'
  916. cal s:PrtExit()
  917. let hlpwin = &columns > 159 ? '| vert res 80' : ''
  918. sil! exe 'bo vert h ctrlp-mappings' hlpwin '| norm! 0'
  919. retu 1
  920. en
  921. retu 0
  922. endf
  923. fu! s:AcceptSelection(mode)
  924. if a:mode != 'e' && s:OpenMulti(a:mode) != -1 | retu | en
  925. let str = s:getinput()
  926. if a:mode == 'e' | if s:SpecInputs(str) | retu | en | en
  927. " Get the selected line
  928. let line = ctrlp#getcline()
  929. if a:mode != 'e' && !s:itemtype && line == ''
  930. \ && str !~ '\v^(\.\.([\/]\.\.)*[\/]?[.\/]*|/|\\|\?|\@.+)$'
  931. cal s:CreateNewFile(a:mode) | retu
  932. en
  933. if empty(line) | retu | en
  934. " Do something with it
  935. if s:openfunc != {} && has_key(s:openfunc, s:ctype)
  936. let actfunc = s:openfunc[s:ctype]
  937. el
  938. let actfunc = s:itemtype < 3 ? 'ctrlp#acceptfile' : s:getextvar('accept')
  939. en
  940. cal call(actfunc, [a:mode, line])
  941. endf
  942. " - CreateNewFile() {{{1
  943. fu! s:CreateNewFile(...)
  944. let [md, str] = ['', s:getinput('n')]
  945. if empty(str) | retu | en
  946. if s:argmap && !a:0
  947. " Get the extra argument
  948. let md = s:argmaps(md, 1)
  949. if md == 'cancel' | retu | en
  950. en
  951. let str = s:sanstail(str)
  952. let [base, fname] = s:headntail(str)
  953. if fname =~ '^[\/]$' | retu | en
  954. if exists('s:marked') && len(s:marked)
  955. " Use the first marked file's path
  956. let path = fnamemodify(values(s:marked)[0], ':p:h')
  957. let base = path.s:lash(path).base
  958. let str = fnamemodify(base.s:lash.fname, ':.')
  959. en
  960. if base != '' | if isdirectory(ctrlp#utils#mkdir(base))
  961. let optyp = str | en | el | let optyp = fname
  962. en
  963. if !exists('optyp') | retu | en
  964. let [filpath, tail] = [fnamemodify(optyp, ':p'), s:tail()]
  965. if !stridx(filpath, s:dyncwd) | cal s:insertcache(str) | en
  966. cal s:PrtExit()
  967. let cmd = md == 'r' ? ctrlp#normcmd('e') :
  968. \ s:newfop =~ '1\|t' || ( a:0 && a:1 == 't' ) || md == 't' ? 'tabe' :
  969. \ s:newfop =~ '2\|h' || ( a:0 && a:1 == 'h' ) || md == 'h' ? 'new' :
  970. \ s:newfop =~ '3\|v' || ( a:0 && a:1 == 'v' ) || md == 'v' ? 'vne' :
  971. \ ctrlp#normcmd('e')
  972. cal s:openfile(cmd, filpath, tail, 1)
  973. endf
  974. " * OpenMulti() {{{1
  975. fu! s:MarkToOpen()
  976. if s:bufnr <= 0 || s:opmul == '0'
  977. \ || ( s:itemtype > 2 && s:getextvar('opmul') != 1 )
  978. retu
  979. en
  980. let line = ctrlp#getcline()
  981. if empty(line) | retu | en
  982. let filpath = s:ispath ? fnamemodify(line, ':p') : line
  983. if exists('s:marked') && s:dictindex(s:marked, filpath) > 0
  984. " Unmark and remove the file from s:marked
  985. let key = s:dictindex(s:marked, filpath)
  986. cal remove(s:marked, key)
  987. if empty(s:marked) | unl s:marked | en
  988. if has('signs')
  989. exe 'sign unplace' key 'buffer='.s:bufnr
  990. en
  991. el
  992. " Add to s:marked and place a new sign
  993. if exists('s:marked')
  994. let vac = s:vacantdict(s:marked)
  995. let key = empty(vac) ? len(s:marked) + 1 : vac[0]
  996. let s:marked = extend(s:marked, { key : filpath })
  997. el
  998. let [key, s:marked] = [1, { 1 : filpath }]
  999. en
  1000. if has('signs')
  1001. exe 'sign place' key 'line='.line('.').' name=ctrlpmark buffer='.s:bufnr
  1002. en
  1003. en
  1004. sil! cal ctrlp#statusline()
  1005. endf
  1006. fu! s:OpenMulti(...)
  1007. let has_marked = exists('s:marked')
  1008. if ( !has_marked && a:0 ) || s:opmul == '0' || !s:ispath
  1009. \ || ( s:itemtype > 2 && s:getextvar('opmul') != 1 )
  1010. retu -1
  1011. en
  1012. " Get the options
  1013. let [nr, md] = [matchstr(s:opmul, '\d\+'), matchstr(s:opmul, '[thvi]')]
  1014. let [ur, jf] = [s:opmul =~ 'r', s:opmul =~ 'j']
  1015. let md = a:0 ? a:1 : ( md == '' ? 'v' : md )
  1016. let nopt = exists('g:ctrlp_open_multiple_files')
  1017. if !has_marked
  1018. let line = ctrlp#getcline()
  1019. if line == '' | retu | en
  1020. let marked = { 1 : fnamemodify(line, ':p') }
  1021. let [nr, ur, jf, nopt] = ['1', 0, 0, 1]
  1022. en
  1023. if ( s:argmap || !has_marked ) && !a:0
  1024. let md = s:argmaps(md, !has_marked ? 2 : 0)
  1025. if md == 'c'
  1026. cal s:unmarksigns()
  1027. unl! s:marked
  1028. cal s:BuildPrompt(0)
  1029. elsei !has_marked && md =~ '[axd]'
  1030. retu s:OpenNoMarks(md, line)
  1031. en
  1032. if md =~ '\v^c(ancel)?$' | retu | en
  1033. let nr = nr == '0' ? ( nopt ? '' : '1' ) : nr
  1034. let ur = !has_marked && md == 'r' ? 1 : ur
  1035. en
  1036. let mkd = values(has_marked ? s:marked : marked)
  1037. cal s:sanstail(join(s:prompt, ''))
  1038. cal s:PrtExit()
  1039. if nr == '0' || md == 'i'
  1040. retu map(mkd, "s:openfile('bad', v:val, '', 0)")
  1041. en
  1042. let tail = s:tail()
  1043. let [emptytail, bufnr] = [empty(tail), bufnr('^'.mkd[0].'$')]
  1044. let useb = bufnr > 0 && buflisted(bufnr) && emptytail
  1045. " Move to a replaceable window
  1046. let ncmd = ( useb ? ['b', 'bo vert sb'] : ['e', 'bo vne'] )
  1047. \ + ( ur ? [] : ['ignruw'] )
  1048. let fst = call('ctrlp#normcmd', ncmd)
  1049. " Check if the current window has a replaceable buffer
  1050. let repabl = !( md == 't' && !ur ) && empty(bufname('%')) && empty(&l:ft)
  1051. " Commands for the rest of the files
  1052. let [ic, cmds] = [1, { 'v': ['vert sb', 'vne'], 'h': ['sb', 'new'],
  1053. \ 't': ['tab sb', 'tabe'] }]
  1054. let [swb, &swb] = [&swb, '']
  1055. if md == 't' && ctrlp#tabcount() < tabpagenr()
  1056. let s:tabct = ctrlp#tabcount()
  1057. en
  1058. " Open the files
  1059. for va in mkd
  1060. let bufnr = bufnr('^'.va.'$')
  1061. if bufnr < 0 && getftype(va) == '' | con | en
  1062. let useb = bufnr > 0 && buflisted(bufnr) && emptytail
  1063. let snd = md != '' && has_key(cmds, md) ?
  1064. \ ( useb ? cmds[md][0] : cmds[md][1] ) : ( useb ? 'vert sb' : 'vne' )
  1065. let cmd = ic == 1 && ( !( !ur && fst =~ '^[eb]$' ) || repabl ) ? fst : snd
  1066. let conds = [( nr != '' && nr > 1 && nr < ic ) || ( nr == '' && ic > 1 ),
  1067. \ nr != '' && nr < ic]
  1068. if conds[nopt]
  1069. if !buflisted(bufnr) | cal s:openfile('bad', va, '', 0) | en
  1070. el
  1071. cal s:openfile(cmd, useb ? bufnr : va, tail, ic == 1)
  1072. if jf | if ic == 1
  1073. let crpos = [tabpagenr(), winnr()]
  1074. el
  1075. let crpos[0] += tabpagenr() <= crpos[0]
  1076. let crpos[1] += winnr() <= crpos[1]
  1077. en | en
  1078. let ic += 1
  1079. en
  1080. endfo
  1081. if jf && exists('crpos') && ic > 2
  1082. exe ( md == 't' ? 'tabn '.crpos[0] : crpos[1].'winc w' )
  1083. en
  1084. let &swb = swb
  1085. unl! s:tabct
  1086. endf
  1087. fu! s:OpenNoMarks(md, line)
  1088. if a:md == 'a'
  1089. let [s:marked, key] = [{}, 1]
  1090. for line in s:lines
  1091. let s:marked = extend(s:marked, { key : fnamemodify(line, ':p') })
  1092. let key += 1
  1093. endfo
  1094. cal s:remarksigns()
  1095. cal s:BuildPrompt(0)
  1096. elsei a:md == 'x'
  1097. cal call(s:openfunc[s:ctype], [a:md, a:line], s:openfunc)
  1098. elsei a:md == 'd'
  1099. let dir = fnamemodify(a:line, ':h')
  1100. if isdirectory(dir)
  1101. cal ctrlp#setdir(dir)
  1102. cal ctrlp#switchtype(0)
  1103. cal ctrlp#recordhist()
  1104. cal s:PrtClear()
  1105. en
  1106. en
  1107. endf
  1108. " ** Helper functions {{{1
  1109. " Sorting {{{2
  1110. fu! ctrlp#complen(...)
  1111. " By length
  1112. let [len1, len2] = [strlen(a:1), strlen(a:2)]
  1113. retu len1 == len2 ? 0 : len1 > len2 ? 1 : -1
  1114. endf
  1115. fu! s:compmatlen(...)
  1116. " By match length
  1117. let mln1 = s:shortest(s:matchlens(a:1, s:compat))
  1118. let mln2 = s:shortest(s:matchlens(a:2, s:compat))
  1119. retu mln1 == mln2 ? 0 : mln1 > mln2 ? 1 : -1
  1120. endf
  1121. fu! s:comptime(...)
  1122. " By last modified time
  1123. let [time1, time2] = [getftime(a:1), getftime(a:2)]
  1124. retu time1 == time2 ? 0 : time1 < time2 ? 1 : -1
  1125. endf
  1126. fu! s:compmreb(...)
  1127. " By last entered time (bufnr)
  1128. let [id1, id2] = [index(s:mrbs, a:1), index(s:mrbs, a:2)]
  1129. retu id1 == id2 ? 0 : id1 > id2 ? 1 : -1
  1130. endf
  1131. fu! s:compmref(...)
  1132. " By last entered time (MRU)
  1133. let [id1, id2] = [index(g:ctrlp_lines, a:1), index(g:ctrlp_lines, a:2)]
  1134. retu id1 == id2 ? 0 : id1 > id2 ? 1 : -1
  1135. endf
  1136. fu! s:comparent(...)
  1137. " By same parent dir
  1138. if !stridx(s:crfpath, s:dyncwd)
  1139. let [as1, as2] = [s:dyncwd.s:lash().a:1, s:dyncwd.s:lash().a:2]
  1140. let [loc1, loc2] = [s:getparent(as1), s:getparent(as2)]
  1141. if loc1 == s:crfpath && loc2 != s:crfpath | retu -1 | en
  1142. if loc2 == s:crfpath && loc1 != s:crfpath | retu 1 | en
  1143. retu 0
  1144. en
  1145. retu 0
  1146. endf
  1147. fu! s:compfnlen(...)
  1148. " By filename length
  1149. let len1 = strlen(split(a:1, s:lash)[-1])
  1150. let len2 = strlen(split(a:2, s:lash)[-1])
  1151. retu len1 == len2 ? 0 : len1 > len2 ? 1 : -1
  1152. endf
  1153. fu! s:matchlens(str, pat, ...)
  1154. if empty(a:pat) || index(['^', '$'], a:pat) >= 0 | retu {} | en
  1155. let st = a:0 ? a:1 : 0
  1156. let lens = a:0 >= 2 ? a:2 : {}
  1157. let nr = a:0 >= 3 ? a:3 : 0
  1158. if nr > 20 | retu {} | en
  1159. if match(a:str, a:pat, st) >= 0
  1160. let [mst, mnd] = [matchstr(a:str, a:pat, st), matchend(a:str, a:pat, st)]
  1161. let lens = extend(lens, { nr : [strlen(mst), mst] })
  1162. let lens = s:matchlens(a:str, a:pat, mnd, lens, nr + 1)
  1163. en
  1164. retu lens
  1165. endf
  1166. fu! s:shortest(lens)
  1167. retu min(map(values(a:lens), 'v:val[0]'))
  1168. endf
  1169. fu! s:mixedsort(...)
  1170. let [cln, cml] = [ctrlp#complen(a:1, a:2), s:compmatlen(a:1, a:2)]
  1171. if s:ispath
  1172. let ms = []
  1173. if s:height < 21
  1174. let ms += [s:compfnlen(a:1, a:2)]
  1175. if s:itemtype !~ '^[12]$' | let ms += [s:comptime(a:1, a:2)] | en
  1176. if !s:itemtype | let ms += [s:comparent(a:1, a:2)] | en
  1177. en
  1178. if s:itemtype =~ '^[12]$'
  1179. let ms += [s:compmref(a:1, a:2)]
  1180. let cln = cml ? cln : 0
  1181. en
  1182. let ms += [cml, 0, 0, 0]
  1183. let mp = call('s:multipliers', ms[:3])
  1184. retu cln + ms[0] * mp[0] + ms[1] * mp[1] + ms[2] * mp[2] + ms[3] * mp[3]
  1185. en
  1186. retu cln + cml * 2
  1187. endf
  1188. fu! s:multipliers(...)
  1189. let mp0 = !a:1 ? 0 : 2
  1190. let mp1 = !a:2 ? 0 : 1 + ( !mp0 ? 1 : mp0 )
  1191. let mp2 = !a:3 ? 0 : 1 + ( !( mp0 + mp1 ) ? 1 : ( mp0 + mp1 ) )
  1192. let mp3 = !a:4 ? 0 : 1 + ( !( mp0 + mp1 + mp2 ) ? 1 : ( mp0 + mp1 + mp2 ) )
  1193. retu [mp0, mp1, mp2, mp3]
  1194. endf
  1195. fu! s:compval(...)
  1196. retu a:1 - a:2
  1197. endf
  1198. " Statusline {{{2
  1199. fu! ctrlp#statusline()
  1200. if !exists('s:statypes')
  1201. let s:statypes = [
  1202. \ ['files', 'fil'],
  1203. \ ['buffers', 'buf'],
  1204. \ ['mru files', 'mru'],
  1205. \ ]
  1206. if !empty(g:ctrlp_ext_vars)
  1207. cal map(copy(g:ctrlp_ext_vars),
  1208. \ 'add(s:statypes, [ v:val["lname"], v:val["sname"] ])')
  1209. en
  1210. en
  1211. let tps = s:statypes
  1212. let max = len(tps) - 1
  1213. let nxt = tps[s:walker(max, s:itemtype, 1)][1]
  1214. let prv = tps[s:walker(max, s:itemtype, -1)][1]
  1215. let s:ctype = tps[s:itemtype][0]
  1216. let focus = s:focus ? 'prt' : 'win'
  1217. let byfname = s:byfname ? 'file' : 'path'
  1218. let marked = s:opmul != '0' ?
  1219. \ exists('s:marked') ? ' <'.s:dismrk().'>' : ' <->' : ''
  1220. if s:status != {}
  1221. let args = [focus, byfname, s:regexp, prv, s:ctype, nxt, marked]
  1222. let &l:stl = call(s:status['main'], args, s:status)
  1223. el
  1224. let item = '%#CtrlPMode1# '.s:ctype.' %*'
  1225. let focus = '%#CtrlPMode2# '.focus.' %*'
  1226. let byfname = '%#CtrlPMode1# '.byfname.' %*'
  1227. let regex = s:regexp ? '%#CtrlPMode2# regex %*' : ''
  1228. let slider = ' <'.prv.'>={'.item.'}=<'.nxt.'>'
  1229. let dir = ' %=%<%#CtrlPMode2# %{getcwd()} %*'
  1230. let &l:stl = focus.byfname.regex.slider.marked.dir
  1231. en
  1232. endf
  1233. fu! s:dismrk()
  1234. retu has('signs') ? len(s:marked) :
  1235. \ '%<'.join(values(map(copy(s:marked), 'split(v:val, "[\\/]")[-1]')), ', ')
  1236. endf
  1237. fu! ctrlp#progress(enum, ...)
  1238. if has('macunix') || has('mac') | sl 1m | en
  1239. let txt = a:0 ? '(press ctrl-c to abort)' : ''
  1240. let &l:stl = s:status != {} ? call(s:status['prog'], [a:enum], s:status)
  1241. \ : '%#CtrlPStats# '.a:enum.' %* '.txt.'%=%<%#CtrlPMode2# %{getcwd()} %*'
  1242. redraws
  1243. endf
  1244. " *** Paths {{{2
  1245. " Line formatting {{{3
  1246. fu! s:formatline(str)
  1247. let str = a:str
  1248. if s:itemtype == 1
  1249. let bfnr = bufnr('^'.fnamemodify(str, ':p').'$')
  1250. let idc = ( bfnr == bufnr('#') ? '#' : '' )
  1251. \ . ( getbufvar(bfnr, '&ma') ? '' : '-' )
  1252. \ . ( getbufvar(bfnr, '&ro') ? '=' : '' )
  1253. \ . ( getbufvar(bfnr, '&mod') ? '+' : '' )
  1254. let str .= idc != '' ? ' '.idc : ''
  1255. en
  1256. let cond = s:ispath && ( s:winw - 4 ) < s:strwidth(str)
  1257. retu '> '.( cond ? s:pathshorten(str) : str )
  1258. endf
  1259. fu! s:pathshorten(str)
  1260. retu matchstr(a:str, '^.\{9}').'...'
  1261. \ .matchstr(a:str, '.\{'.( s:winw - 16 ).'}$')
  1262. endf
  1263. " Directory completion {{{3
  1264. fu! s:dircompl(be, sd)
  1265. if a:sd == '' | retu [] | en
  1266. let [be, sd] = a:be == '' ? [s:dyncwd, a:sd] : [a:be, a:be.s:lash(a:be).a:sd]
  1267. let dirs = ctrlp#rmbasedir(split(globpath(s:fnesc(be, 'g', ','), a:sd.'*/'), "\n"))
  1268. cal filter(dirs, '!match(v:val, escape(sd, ''~$.\''))'
  1269. \ . ' && v:val !~ ''\v(^|[\/])\.{1,2}[\/]$''')
  1270. retu dirs
  1271. endf
  1272. fu! s:findcommon(items, seed)
  1273. let [items, id, cmn, ic] = [copy(a:items), strlen(a:seed), '', 0]
  1274. cal map(items, 'strpart(v:val, id)')
  1275. for char in split(items[0], '\zs')
  1276. for item in items[1:]
  1277. if item[ic] != char | let brk = 1 | brea | en
  1278. endfo
  1279. if exists('brk') | brea | en
  1280. let cmn .= char
  1281. let ic += 1
  1282. endfo
  1283. retu cmn
  1284. endf
  1285. " Misc {{{3
  1286. fu! s:headntail(str)
  1287. let parts = split(a:str, '[\/]\ze[^\/]\+[\/:]\?$')
  1288. retu len(parts) == 1 ? ['', parts[0]] : len(parts) == 2 ? parts : []
  1289. endf
  1290. fu! s:lash(...)
  1291. retu ( a:0 ? a:1 : s:dyncwd ) !~ '[\/]$' ? s:lash : ''
  1292. endf
  1293. fu! s:ispathitem()
  1294. retu s:itemtype < 3 || ( s:itemtype > 2 && s:getextvar('type') == 'path' )
  1295. endf
  1296. fu! ctrlp#dirnfile(entries)
  1297. let [items, cwd] = [[[], []], s:dyncwd.s:lash()]
  1298. for each in a:entries
  1299. let etype = getftype(each)
  1300. if s:igntype >= 0 && s:usrign(each, etype) | con | en
  1301. if etype == 'dir'
  1302. if s:showhidden | if each !~ '[\/]\.\{1,2}$'
  1303. cal add(items[0], each)
  1304. en | el
  1305. cal add(items[0], each)
  1306. en
  1307. elsei etype == 'link'
  1308. if s:folsym
  1309. let isfile = !isdirectory(each)
  1310. if s:folsym == 2 || !s:samerootsyml(each, isfile, cwd)
  1311. cal add(items[isfile], each)
  1312. en
  1313. en
  1314. elsei etype == 'file'
  1315. cal add(items[1], each)
  1316. en
  1317. endfo
  1318. retu items
  1319. endf
  1320. fu! s:usrign(item, type)
  1321. retu s:igntype == 1 ? a:item =~ s:usrign
  1322. \ : s:igntype == 4 && has_key(s:usrign, a:type) && s:usrign[a:type] != ''
  1323. \ ? a:item =~ s:usrign[a:type] : 0
  1324. endf
  1325. fu! s:samerootsyml(each, isfile, cwd)
  1326. let resolve = fnamemodify(resolve(a:each), ':p:h')
  1327. let resolve .= s:lash(resolve)
  1328. retu !( stridx(resolve, a:cwd) && ( stridx(a:cwd, resolve) || a:isfile ) )
  1329. endf
  1330. fu! ctrlp#rmbasedir(items)
  1331. let cwd = s:dyncwd.( s:dyncwd !~ '[\/]$' ? s:lash : '' )
  1332. if a:items != [] && !stridx(a:items[0], cwd)
  1333. let idx = strlen(cwd)
  1334. retu map(a:items, 'strpart(v:val, idx)')
  1335. en
  1336. retu a:items
  1337. endf
  1338. " Working directory {{{3
  1339. fu! s:getparent(item)
  1340. let parent = substitute(a:item, '[\/][^\/]\+[\/:]\?$', '', '')
  1341. if parent == '' || parent !~ '[\/]'
  1342. let parent .= s:lash
  1343. en
  1344. retu parent
  1345. endf
  1346. fu! s:findroot(curr, mark, depth, type)
  1347. let [depth, fnd] = [a:depth + 1, 0]
  1348. if type(a:mark) == 1
  1349. let fnd = s:glbpath(s:fnesc(a:curr, 'g', ','), a:mark, 1) != ''
  1350. elsei type(a:mark) == 3
  1351. for markr in a:mark
  1352. if s:glbpath(s:fnesc(a:curr, 'g', ','), markr, 1) != ''
  1353. let fnd = 1
  1354. brea
  1355. en
  1356. endfo
  1357. en
  1358. if fnd
  1359. if !a:type | cal ctrlp#setdir(a:curr) | en
  1360. retu [exists('markr') ? markr : a:mark, a:curr]
  1361. elsei depth > s:maxdepth
  1362. cal ctrlp#setdir(s:cwd)
  1363. el
  1364. let parent = s:getparent(a:curr)
  1365. if parent != a:curr
  1366. retu s:findroot(parent, a:mark, depth, a:type)
  1367. en
  1368. en
  1369. retu []
  1370. endf
  1371. fu! ctrlp#setdir(path, ...)
  1372. let cmd = a:0 ? a:1 : 'lc!'
  1373. sil! exe cmd s:fnesc(a:path, 'c')
  1374. let [s:crfilerel, s:dyncwd] = [fnamemodify(s:crfile, ':.'), getcwd()]
  1375. endf
  1376. " Fallbacks {{{3
  1377. fu! s:glbpath(...)
  1378. retu call('ctrlp#utils#globpath', a:000)
  1379. endf
  1380. fu! s:fnesc(...)
  1381. retu call('ctrlp#utils#fnesc', a:000)
  1382. endf
  1383. fu! ctrlp#setlcdir()
  1384. if exists('*haslocaldir')
  1385. cal ctrlp#setdir(getcwd(), haslocaldir() ? 'lc!' : 'cd!')
  1386. en
  1387. endf
  1388. " Highlighting {{{2
  1389. fu! ctrlp#syntax()
  1390. if ctrlp#nosy() | retu | en
  1391. for [ke, va] in items(s:hlgrps) | cal ctrlp#hicheck('CtrlP'.ke, va) | endfo
  1392. if !hlexists('CtrlPLinePre')
  1393. \ && synIDattr(synIDtrans(hlID('Normal')), 'bg') !~ '^-1$\|^$'
  1394. sil! exe 'hi CtrlPLinePre '.( has("gui_running") ? 'gui' : 'cterm' ).'fg=bg'
  1395. en
  1396. sy match CtrlPNoEntries '^ == NO ENTRIES ==$'
  1397. if hlexists('CtrlPLinePre')
  1398. sy match CtrlPLinePre '^>'
  1399. en
  1400. endf
  1401. fu! s:highlight(pat, grp)
  1402. if s:matcher != {} | retu | en
  1403. cal clearmatches()
  1404. if !empty(a:pat) && s:ispath
  1405. let pat = s:regexp ? substitute(a:pat, '\\\@<!\^', '^> \\zs', 'g') : a:pat
  1406. if s:byfname
  1407. let pat = substitute(pat, '\[\^\(.\{-}\)\]\\{-}', '[^\\/\1]\\{-}', 'g')
  1408. let pat = substitute(pat, '\$\@<!$', '\\ze[^\\/]*$', 'g')
  1409. en
  1410. cal matchadd(a:grp, ( s:martcs == '' ? '\c' : '\C' ).pat)
  1411. cal matchadd('CtrlPLinePre', '^>')
  1412. en
  1413. endf
  1414. fu! s:dohighlight()
  1415. retu s:mathi[0] && exists('*clearmatches') && !ctrlp#nosy()
  1416. endf
  1417. " Prompt history {{{2
  1418. fu! s:gethistloc()
  1419. let utilcadir = ctrlp#utils#cachedir()
  1420. let cache_dir = utilcadir.s:lash(utilcadir).'hist'
  1421. retu [cache_dir, cache_dir.s:lash(cache_dir).'cache.txt']
  1422. endf
  1423. fu! s:gethistdata()
  1424. retu ctrlp#utils#readfile(s:gethistloc()[1])
  1425. endf
  1426. fu! ctrlp#recordhist()
  1427. let str = join(s:prompt, '')
  1428. if empty(str) || !s:maxhst | retu | en
  1429. let hst = s:hstry
  1430. if len(hst) > 1 && hst[1] == str | retu | en
  1431. cal extend(hst, [str], 1)
  1432. if len(hst) > s:maxhst | cal remove(hst, s:maxhst, -1) | en
  1433. cal ctrlp#utils#writecache(hst, s:gethistloc()[0], s:gethistloc()[1])
  1434. endf
  1435. " Signs {{{2
  1436. fu! s:unmarksigns()
  1437. if !s:dosigns() | retu | en
  1438. for key in keys(s:marked)
  1439. exe 'sign unplace' key 'buffer='.s:bufnr
  1440. endfo
  1441. endf
  1442. fu! s:remarksigns()
  1443. if !s:dosigns() | retu | en
  1444. for ic in range(1, len(s:lines))
  1445. let line = s:ispath ? fnamemodify(s:lines[ic - 1], ':p') : s:lines[ic - 1]
  1446. let key = s:dictindex(s:marked, line)
  1447. if key > 0
  1448. exe 'sign place' key 'line='.ic.' name=ctrlpmark buffer='.s:bufnr
  1449. en
  1450. endfo
  1451. endf
  1452. fu! s:dosigns()
  1453. retu exists('s:marked') && s:bufnr > 0 && s:opmul != '0' && has('signs')
  1454. endf
  1455. " Lists & Dictionaries {{{2
  1456. fu! s:dictindex(dict, expr)
  1457. for key in keys(a:dict)
  1458. if a:dict[key] == a:expr | retu key | en
  1459. endfo
  1460. retu -1
  1461. endf
  1462. fu! s:vacantdict(dict)
  1463. retu filter(range(1, max(keys(a:dict))), '!has_key(a:dict, v:val)')
  1464. endf
  1465. fu! s:sublist(l, s, e)
  1466. retu v:version > 701 ? a:l[(a:s):(a:e)] : s:sublist7071(a:l, a:s, a:e)
  1467. endf
  1468. fu! s:sublist7071(l, s, e)
  1469. let [newlist, id, ae] = [[], a:s, a:e == -1 ? len(a:l) - 1 : a:e]
  1470. wh id <= ae
  1471. cal add(newlist, get(a:l, id))
  1472. let id += 1
  1473. endw
  1474. retu newlist
  1475. endf
  1476. " Buffers {{{2
  1477. fu! s:buftab(bufnr, md)
  1478. for tabnr in range(1, tabpagenr('$'))
  1479. if tabpagenr() == tabnr && a:md == 't' | con | en
  1480. let buflist = tabpagebuflist(tabnr)
  1481. if index(buflist, a:bufnr) >= 0
  1482. for winnr in range(1, tabpagewinnr(tabnr, '$'))
  1483. if buflist[winnr - 1] == a:bufnr | retu [tabnr, winnr] | en
  1484. endfo
  1485. en
  1486. endfo
  1487. retu [0, 0]
  1488. endf
  1489. fu! s:bufwins(bufnr)
  1490. let winns = 0
  1491. for tabnr in range(1, tabpagenr('$'))
  1492. let winns += count(tabpagebuflist(tabnr), a:bufnr)
  1493. endfo
  1494. retu winns
  1495. endf
  1496. fu! ctrlp#normcmd(cmd, ...)
  1497. if a:0 < 2 && s:nosplit() | retu a:cmd | en
  1498. let norwins = filter(range(1, winnr('$')),
  1499. \ 'empty(getbufvar(winbufnr(v:val), "&bt"))')
  1500. for each in norwins
  1501. let bufnr = winbufnr(each)
  1502. if empty(bufname(bufnr)) && empty(getbufvar(bufnr, '&ft'))
  1503. let fstemp = each | brea
  1504. en
  1505. endfo
  1506. let norwin = empty(norwins) ? 0 : norwins[0]
  1507. if norwin
  1508. if index(norwins, winnr()) < 0
  1509. exe ( exists('fstemp') ? fstemp : norwin ).'winc w'
  1510. en
  1511. retu a:cmd
  1512. en
  1513. retu a:0 ? a:1 : 'bo vne'
  1514. endf
  1515. fu! ctrlp#modfilecond(w)
  1516. retu &mod && !&hid && &bh != 'hide' && s:bufwins(bufnr('%')) == 1 && !&cf &&
  1517. \ ( ( !&awa && a:w ) || filewritable(fnamemodify(bufname('%'), ':p')) != 1 )
  1518. endf
  1519. fu! s:nosplit()
  1520. retu !empty(s:nosplit) && match([bufname('%'), &l:ft, &l:bt], s:nosplit) >= 0
  1521. endf
  1522. fu! s:setupblank()
  1523. setl noswf nonu nobl nowrap nolist nospell nocuc wfh
  1524. setl fdc=0 fdl=99 tw=0 bt=nofile bh=unload
  1525. if v:version > 702
  1526. setl nornu noudf cc=0
  1527. en
  1528. endf
  1529. fu! s:leavepre()
  1530. if exists('s:bufnr') && s:bufnr == bufnr('%') | bw! | en
  1531. if !( exists(s:ccex) && !{s:ccex} )
  1532. \ && !( has('clientserver') && len(split(serverlist(), "\n")) > 1 )
  1533. cal ctrlp#clra()
  1534. en
  1535. endf
  1536. fu! s:checkbuf()
  1537. if !exists('s:init') && exists('s:bufnr') && s:bufnr > 0
  1538. exe s:bufnr.'bw!'
  1539. en
  1540. endf
  1541. fu! s:iscmdwin()
  1542. let ermsg = v:errmsg
  1543. sil! noa winc p
  1544. sil! noa winc p
  1545. let [v:errmsg, ermsg] = [ermsg, v:errmsg]
  1546. retu ermsg =~ '^E11:'
  1547. endf
  1548. " Arguments {{{2
  1549. fu! s:at(str)
  1550. if a:str =~ '\v^\@(cd|lc[hd]?|chd).*'
  1551. let str = substitute(a:str, '\v^\@(cd|lc[hd]?|chd)\s*', '', '')
  1552. if str == '' | retu 1 | en
  1553. let str = str =~ '^%:.\+' ? fnamemodify(s:crfile, str[1:]) : str
  1554. let path = fnamemodify(expand(str, 1), ':p')
  1555. if isdirectory(path)
  1556. if path != s:dyncwd
  1557. cal ctrlp#setdir(path)
  1558. cal ctrlp#setlines()
  1559. en
  1560. cal ctrlp#recordhist()
  1561. cal s:PrtClear()
  1562. en
  1563. retu 1
  1564. en
  1565. retu 0
  1566. endf
  1567. fu! s:tail()
  1568. if exists('s:optail') && !empty('s:optail')
  1569. let tailpref = s:optail !~ '^\s*+' ? ' +' : ' '
  1570. retu tailpref.s:optail
  1571. en
  1572. retu ''
  1573. endf
  1574. fu! s:sanstail(str)
  1575. let str = s:spi ?
  1576. \ substitute(a:str, '^\(@.*$\|\\\\\ze@\|\.\.\zs[.\/]\+$\)', '', 'g') : a:str
  1577. let [str, pat] = [substitute(str, '\\\\', '\', 'g'), '\([^:]\|\\:\)*$']
  1578. unl! s:optail
  1579. if str =~ '\\\@<!:'.pat
  1580. let s:optail = matchstr(str, '\\\@<!:\zs'.pat)
  1581. let str = substitute(str, '\\\@<!:'.pat, '', '')
  1582. en
  1583. retu substitute(str, '\\\ze:', '', 'g')
  1584. endf
  1585. fu! s:argmaps(md, i)
  1586. let roh = [
  1587. \ ['Open Multiple Files', '/h[i]dden/[c]lear', ['i', 'c']],
  1588. \ ['Create a New File', '/[r]eplace', ['r']],
  1589. \ ['Open Selected', '/[r]eplace', ['r', 'd', 'a']],
  1590. \ ]
  1591. if a:i == 2
  1592. if !buflisted(bufnr('^'.fnamemodify(ctrlp#getcline(), ':p').'$'))
  1593. let roh[2][1] .= '/h[i]dden'
  1594. let roh[2][2] += ['i']
  1595. en
  1596. if s:openfunc != {} && has_key(s:openfunc, s:ctype)
  1597. let roh[2][1] .= '/e[x]ternal'
  1598. let roh[2][2] += ['x']
  1599. en
  1600. en
  1601. let str = roh[a:i][0].': [t]ab/[v]ertical/[h]orizontal'.roh[a:i][1].'? '
  1602. retu s:choices(str, ['t', 'v', 'h'] + roh[a:i][2], 's:argmaps', [a:md, a:i])
  1603. endf
  1604. fu! s:insertstr()
  1605. let str = 'Insert: c[w]ord/c[f]ile/[s]earch/[v]isual/[c]lipboard/[r]egister? '
  1606. retu s:choices(str, ['w', 'f', 's', 'v', 'c', 'r'], 's:insertstr', [])
  1607. endf
  1608. fu! s:textdialog(str)
  1609. redr | echoh MoreMsg | echon a:str | echoh None
  1610. retu nr2char(getchar())
  1611. endf
  1612. fu! s:choices(str, choices, func, args)
  1613. let char = s:textdialog(a:str)
  1614. if index(a:choices, char) >= 0
  1615. retu char
  1616. elsei char =~# "\\v\<Esc>|\<C-c>|\<C-g>|\<C-u>|\<C-w>|\<C-[>"
  1617. cal s:BuildPrompt(0)
  1618. retu 'cancel'
  1619. elsei char =~# "\<CR>" && a:args != []
  1620. retu a:args[0]
  1621. en
  1622. retu call(a:func, a:args)
  1623. endf
  1624. fu! s:getregs()
  1625. let char = s:textdialog('Insert from register: ')
  1626. if char =~# "\\v\<Esc>|\<C-c>|\<C-g>|\<C-u>|\<C-w>|\<C-[>"
  1627. cal s:BuildPrompt(0)
  1628. retu -1
  1629. elsei char =~# "\<CR>"
  1630. retu s:getregs()
  1631. en
  1632. retu s:regisfilter(char)
  1633. endf
  1634. fu! s:regisfilter(reg)
  1635. retu substitute(getreg(a:reg), "[\t\n]", ' ', 'g')
  1636. endf
  1637. " Misc {{{2
  1638. fu! s:modevar()
  1639. let s:matchtype = s:mtype()
  1640. let s:ispath = s:ispathitem()
  1641. if !s:ispath | let s:byfname = 0 | en
  1642. let s:mfunc = s:mfunc()
  1643. let s:nolim = s:getextvar('nolim')
  1644. let s:dosort = s:getextvar('sort')
  1645. let s:spi = !s:itemtype || s:getextvar('specinput') > 0
  1646. endf
  1647. fu! s:nosort()
  1648. retu s:matcher != {} || s:nolim == 1 || ( s:itemtype == 2 && s:mrudef )
  1649. \ || ( s:itemtype =~ '\v^(1|2)$' && s:prompt == ['', '', ''] ) || !s:dosort
  1650. endf
  1651. fu! s:narrowable()
  1652. retu exists('s:act_add') && exists('s:matched') && s:matched != []
  1653. \ && exists('s:mdata') && s:mdata[:2] == [s:dyncwd, s:itemtype, s:regexp]
  1654. \ && s:matcher == {} && !exists('s:did_exp')
  1655. endf
  1656. fu! s:getinput(...)
  1657. let [prt, spi] = [s:prompt, ( a:0 ? a:1 : '' )]
  1658. if s:abbrev != {}
  1659. let gmd = has_key(s:abbrev, 'gmode') ? s:abbrev['gmode'] : ''
  1660. let str = ( gmd =~ 't' && !a:0 ) || spi == 'c' ? prt[0] : join(prt, '')
  1661. if gmd =~ 't' && gmd =~ 'k' && !a:0 && matchstr(str, '.$') =~ '\k'
  1662. retu join(prt, '')
  1663. en
  1664. let [pf, rz] = [( s:byfname ? 'f' : 'p' ), ( s:regexp ? 'r' : 'z' )]
  1665. for dict in s:abbrev['abbrevs']
  1666. let dmd = has_key(dict, 'mode') ? dict['mode'] : ''
  1667. let pat = escape(dict['pattern'], '~')
  1668. if ( dmd == '' || ( dmd =~ pf && dmd =~ rz && !a:0 )
  1669. \ || dmd =~ '['.spi.']' ) && str =~ pat
  1670. let [str, s:did_exp] = [join(split(str, pat, 1), dict['expanded']), 1]
  1671. en
  1672. endfo
  1673. if gmd =~ 't' && !a:0
  1674. let prt[0] = str
  1675. el
  1676. retu str
  1677. en
  1678. en
  1679. retu spi == 'c' ? prt[0] : join(prt, '')
  1680. endf
  1681. fu! s:migemo(str)
  1682. let [str, rtp] = [a:str, s:fnesc(&rtp, 'g')]
  1683. let dict = s:glbpath(rtp, printf("dict/%s/migemo-dict", &enc), 1)
  1684. if !len(dict)
  1685. let dict = s:glbpath(rtp, "dict/migemo-dict", 1)
  1686. en
  1687. if len(dict)
  1688. let [tokens, str, cmd] = [split(str, '\s'), '', 'cmigemo -v -w %s -d %s']
  1689. for token in tokens
  1690. let rtn = system(printf(cmd, shellescape(token), shellescape(dict)))
  1691. let str .= !v:shell_error && strlen(rtn) > 0 ? '.*'.rtn : token
  1692. endfo
  1693. en
  1694. retu str
  1695. endf
  1696. fu! s:strwidth(str)
  1697. retu exists('*strdisplaywidth') ? strdisplaywidth(a:str) : strlen(a:str)
  1698. endf
  1699. fu! ctrlp#j2l(nr)
  1700. exe 'norm!' a:nr.'G'
  1701. sil! norm! zvzz
  1702. endf
  1703. fu! s:maxf(len)
  1704. retu s:maxfiles && a:len > s:maxfiles
  1705. endf
  1706. fu! s:regexfilter(str)
  1707. let str = a:str
  1708. for key in keys(s:fpats) | if str =~ key
  1709. let str = substitute(str, s:fpats[key], '', 'g')
  1710. en | endfo
  1711. retu str
  1712. endf
  1713. fu! s:walker(m, p, d)
  1714. retu a:d >= 0 ? a:p < a:m ? a:p + a:d : 0 : a:p > 0 ? a:p + a:d : a:m
  1715. endf
  1716. fu! s:delent(rfunc)
  1717. if a:rfunc == '' | retu | en
  1718. let [s:force, tbrem] = [1, []]
  1719. if exists('s:marked')
  1720. let tbrem = values(s:marked)
  1721. cal s:unmarksigns()
  1722. unl s:marked
  1723. en
  1724. if tbrem == [] && ( has('dialog_gui') || has('dialog_con') ) &&
  1725. \ confirm("Wipe all entries?", "&OK\n&Cancel") != 1
  1726. unl s:force
  1727. cal s:BuildPrompt(0)
  1728. retu
  1729. en
  1730. let g:ctrlp_lines = call(a:rfunc, [tbrem])
  1731. cal s:BuildPrompt(1)
  1732. unl s:force
  1733. endf
  1734. " Entering & Exiting {{{2
  1735. fu! s:getenv()
  1736. let [s:cwd, s:winres] = [getcwd(), [winrestcmd(), &lines, winnr('$')]]
  1737. let [s:crfile, s:crfpath] = [expand('%:p', 1), expand('%:p:h', 1)]
  1738. let [s:crword, s:crline] = [expand('<cword>', 1), getline('.')]
  1739. let [s:winh, s:crcursor] = [min([s:mxheight, &lines]), getpos('.')]
  1740. let [s:crbufnr, s:crvisual] = [bufnr('%'), s:lastvisual()]
  1741. let [s:mrbs, s:crgfile] = [ctrlp#mrufiles#bufs(), expand('<cfile>', 1)]
  1742. endf
  1743. fu! s:lastvisual()
  1744. let cview = winsaveview()
  1745. let [ovreg, ovtype] = [getreg('v'), getregtype('v')]
  1746. let [oureg, outype] = [getreg('"'), getregtype('"')]
  1747. sil! norm! gv"vy
  1748. let selected = s:regisfilter('v')
  1749. cal setreg('v', ovreg, ovtype)
  1750. cal setreg('"', oureg, outype)
  1751. cal winrestview(cview)
  1752. retu selected
  1753. endf
  1754. fu! s:log(m)
  1755. if exists('g:ctrlp_log') && g:ctrlp_log | if a:m
  1756. let cadir = ctrlp#utils#cachedir()
  1757. sil! exe 'redi! >' cadir.s:lash(cadir).'ctrlp.log'
  1758. el
  1759. sil! redi END
  1760. en | en
  1761. endf
  1762. fu! s:buffunc(e)
  1763. if a:e && has_key(s:buffunc, 'enter')
  1764. cal call(s:buffunc['enter'], [], s:buffunc)
  1765. elsei !a:e && has_key(s:buffunc, 'exit')
  1766. cal call(s:buffunc['exit'], [], s:buffunc)
  1767. en
  1768. endf
  1769. fu! s:openfile(cmd, fid, tail, chkmod, ...)
  1770. let cmd = a:cmd
  1771. if a:chkmod && cmd =~ '^[eb]$' && ctrlp#modfilecond(!( cmd == 'b' && &aw ))
  1772. let cmd = cmd == 'b' ? 'sb' : 'sp'
  1773. en
  1774. let cmd = cmd =~ '^tab' ? ctrlp#tabcount().cmd : cmd
  1775. let j2l = a:0 && a:1[0] ? a:1[1] : 0
  1776. exe cmd.( a:0 && a:1[0] ? '' : a:tail ) s:fnesc(a:fid, 'f')
  1777. if j2l
  1778. cal ctrlp#j2l(j2l)
  1779. en
  1780. if !empty(a:tail)
  1781. sil! norm! zvzz
  1782. en
  1783. if cmd != 'bad'
  1784. cal ctrlp#setlcdir()
  1785. en
  1786. endf
  1787. fu! ctrlp#tabcount()
  1788. if exists('s:tabct')
  1789. let tabct = s:tabct
  1790. let s:tabct += 1
  1791. elsei !type(s:tabpage)
  1792. let tabct = s:tabpage
  1793. elsei type(s:tabpage) == 1
  1794. let tabpos =
  1795. \ s:tabpage =~ 'c' ? tabpagenr() :
  1796. \ s:tabpage =~ 'f' ? 1 :
  1797. \ s:tabpage =~ 'l' ? tabpagenr('$') :
  1798. \ tabpagenr()
  1799. let tabct =
  1800. \ s:tabpage =~ 'a' ? tabpos :
  1801. \ s:tabpage =~ 'b' ? tabpos - 1 :
  1802. \ tabpos
  1803. en
  1804. retu tabct < 0 ? 0 : tabct
  1805. endf
  1806. fu! s:settype(type)
  1807. retu a:type < 0 ? exists('s:itemtype') ? s:itemtype : 0 : a:type
  1808. endf
  1809. " Matching {{{2
  1810. fu! s:matchfname(item, pat)
  1811. let parts = split(a:item, '[\/]\ze[^\/]\+$')
  1812. let mfn = match(parts[-1], a:pat[0])
  1813. retu len(a:pat) == 1 ? mfn : len(a:pat) == 2 ?
  1814. \ ( mfn >= 0 && ( len(parts) == 2 ? match(parts[0], a:pat[1]) : -1 ) >= 0
  1815. \ ? 0 : -1 ) : -1
  1816. en
  1817. endf
  1818. fu! s:matchtabs(item, pat)
  1819. retu match(split(a:item, '\t\+')[0], a:pat)
  1820. endf
  1821. fu! s:matchtabe(item, pat)
  1822. retu match(split(a:item, '\t\+[^\t]\+$')[0], a:pat)
  1823. endf
  1824. fu! s:buildpat(lst)
  1825. let pat = a:lst[0]
  1826. for item in range(1, len(a:lst) - 1)
  1827. let pat .= '[^'.a:lst[item - 1].']\{-}'.a:lst[item]
  1828. endfo
  1829. retu pat
  1830. endf
  1831. fu! s:mfunc()
  1832. let mfunc = 'match'
  1833. if s:byfname && s:ispath
  1834. let mfunc = 's:matchfname'
  1835. elsei s:itemtype > 2
  1836. let matchtypes = { 'tabs': 's:matchtabs', 'tabe': 's:matchtabe' }
  1837. if has_key(matchtypes, s:matchtype)
  1838. let mfunc = matchtypes[s:matchtype]
  1839. en
  1840. en
  1841. retu mfunc
  1842. endf
  1843. fu! s:mmode()
  1844. let matchmodes = {
  1845. \ 'match': 'full-line',
  1846. \ 's:matchfname': 'filename-only',
  1847. \ 's:matchtabs': 'first-non-tab',
  1848. \ 's:matchtabe': 'until-last-tab',
  1849. \ }
  1850. retu matchmodes[s:mfunc]
  1851. endf
  1852. " Cache {{{2
  1853. fu! s:writecache(cafile)
  1854. if ( g:ctrlp_newcache || !filereadable(a:cafile) ) && !s:nocache()
  1855. cal ctrlp#utils#writecache(g:ctrlp_allfiles)
  1856. let g:ctrlp_newcache = 0
  1857. en
  1858. endf
  1859. fu! s:nocache(...)
  1860. if !s:caching
  1861. retu 1
  1862. elsei s:caching > 1
  1863. if !( exists(s:ccex) && !{s:ccex} ) || has_key(s:ficounts, s:dyncwd)
  1864. retu get(s:ficounts, s:dyncwd, [0, 0])[0] < s:caching
  1865. elsei a:0 && filereadable(a:1)
  1866. retu len(ctrlp#utils#readfile(a:1)) < s:caching
  1867. en
  1868. retu 1
  1869. en
  1870. retu 0
  1871. endf
  1872. fu! s:insertcache(str)
  1873. let [data, g:ctrlp_newcache, str] = [g:ctrlp_allfiles, 1, a:str]
  1874. if data == [] || strlen(str) <= strlen(data[0])
  1875. let pos = 0
  1876. elsei strlen(str) >= strlen(data[-1])
  1877. let pos = len(data) - 1
  1878. el
  1879. let pos = 0
  1880. for each in data
  1881. if strlen(each) > strlen(str) | brea | en
  1882. let pos += 1
  1883. endfo
  1884. en
  1885. cal insert(data, str, pos)
  1886. cal s:writecache(ctrlp#utils#cachefile())
  1887. endf
  1888. " Extensions {{{2
  1889. fu! s:mtype()
  1890. retu s:itemtype > 2 ? s:getextvar('type') : 'path'
  1891. endf
  1892. fu! s:execextvar(key)
  1893. if !empty(g:ctrlp_ext_vars)
  1894. cal map(filter(copy(g:ctrlp_ext_vars),
  1895. \ 'has_key(v:val, a:key)'), 'eval(v:val[a:key])')
  1896. en
  1897. endf
  1898. fu! s:getextvar(key)
  1899. if s:itemtype > 2
  1900. let vars = g:ctrlp_ext_vars[s:itemtype - 3]
  1901. retu has_key(vars, a:key) ? vars[a:key] : -1
  1902. en
  1903. retu -1
  1904. endf
  1905. fu! ctrlp#getcline()
  1906. retu !empty(s:lines) ? s:lines[line('.') - 1] : ''
  1907. endf
  1908. fu! ctrlp#getmarkedlist()
  1909. retu exists('s:marked') ? values(s:marked) : []
  1910. endf
  1911. fu! ctrlp#exit()
  1912. cal s:PrtExit()
  1913. endf
  1914. fu! ctrlp#prtclear()
  1915. cal s:PrtClear()
  1916. endf
  1917. fu! ctrlp#switchtype(id)
  1918. cal s:ToggleType(a:id - s:itemtype)
  1919. endf
  1920. fu! ctrlp#nosy()
  1921. retu !( has('syntax') && exists('g:syntax_on') )
  1922. endf
  1923. fu! ctrlp#hicheck(grp, defgrp)
  1924. if !hlexists(a:grp)
  1925. exe 'hi link' a:grp a:defgrp
  1926. en
  1927. endf
  1928. fu! ctrlp#call(func, ...)
  1929. retu call(a:func, a:000)
  1930. endf
  1931. "}}}1
  1932. " * Initialization {{{1
  1933. fu! ctrlp#setlines(...)
  1934. if a:0 | let s:itemtype = a:1 | en
  1935. cal s:modevar()
  1936. let types = ['ctrlp#files()', 'ctrlp#buffers()', 'ctrlp#mrufiles#list()']
  1937. if !empty(g:ctrlp_ext_vars)
  1938. cal map(copy(g:ctrlp_ext_vars), 'add(types, v:val["init"])')
  1939. en
  1940. let g:ctrlp_lines = eval(types[s:itemtype])
  1941. endf
  1942. fu! ctrlp#init(type, ...)
  1943. if exists('s:init') || s:iscmdwin() | retu | en
  1944. let [s:ermsg, v:errmsg] = [v:errmsg, '']
  1945. let [s:matches, s:init] = [1, 1]
  1946. cal s:Reset(a:0 ? a:1 : {})
  1947. noa cal s:Open()
  1948. cal s:SetWD(a:0 ? a:1 : {})
  1949. cal s:MapNorms()
  1950. cal s:MapSpecs()
  1951. cal ctrlp#syntax()
  1952. cal ctrlp#setlines(s:settype(a:type))
  1953. cal s:SetDefTxt()
  1954. cal s:BuildPrompt(1)
  1955. if s:keyloop | cal s:KeyLoop() | en
  1956. endf
  1957. " - Autocmds {{{1
  1958. if has('autocmd')
  1959. aug CtrlPAug
  1960. au!
  1961. au BufEnter ControlP cal s:checkbuf()
  1962. au BufLeave ControlP noa cal s:Close()
  1963. au VimLeavePre * cal s:leavepre()
  1964. aug END
  1965. en
  1966. fu! s:autocmds()
  1967. if !has('autocmd') | retu | en
  1968. if exists('#CtrlPLazy')
  1969. au! CtrlPLazy
  1970. en
  1971. if s:lazy
  1972. aug CtrlPLazy
  1973. au!
  1974. au CursorHold ControlP cal s:ForceUpdate()
  1975. aug END
  1976. en
  1977. endf
  1978. "}}}
  1979. " vim:fen:fdm=marker:fmr={{{,}}}:fdl=0:fdc=1:ts=2:sw=2:sts=2