util.vim 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622
  1. if exists('g:loaded_syntastic_util_autoload') || !exists('g:loaded_syntastic_plugin')
  2. finish
  3. endif
  4. let g:loaded_syntastic_util_autoload = 1
  5. let s:save_cpo = &cpo
  6. set cpo&vim
  7. " Public functions {{{1
  8. function! syntastic#util#isRunningWindows() abort " {{{2
  9. return has('win16') || has('win32') || has('win64')
  10. endfunction " }}}2
  11. function! syntastic#util#DevNull() abort " {{{2
  12. if syntastic#util#isRunningWindows()
  13. return 'NUL'
  14. endif
  15. return '/dev/null'
  16. endfunction " }}}2
  17. " Get directory separator
  18. function! syntastic#util#Slash() abort " {{{2
  19. return (!exists('+shellslash') || &shellslash) ? '/' : '\'
  20. endfunction " }}}2
  21. function! syntastic#util#CygwinPath(path) abort " {{{2
  22. return substitute(syntastic#util#system('cygpath -m ' . syntastic#util#shescape(a:path)), "\n", '', 'g')
  23. endfunction " }}}2
  24. function! syntastic#util#system(command) abort " {{{2
  25. let old_shell = &shell
  26. let old_lc_messages = $LC_MESSAGES
  27. let old_lc_all = $LC_ALL
  28. let &shell = syntastic#util#var('shell')
  29. let $LC_MESSAGES = 'C'
  30. let $LC_ALL = ''
  31. let crashed = 0
  32. let cmd_start = reltime()
  33. try
  34. let out = system(a:command)
  35. catch
  36. let crashed = 1
  37. call syntastic#log#error('exception running system(' . string(a:command) . '): ' . v:exception)
  38. if syntastic#util#isRunningWindows()
  39. call syntastic#log#debug(g:_SYNTASTIC_DEBUG_CHECKERS, '$TMP = ' . string($TMP) . ', $TEMP = ' . string($TEMP))
  40. else
  41. call syntastic#log#debug(g:_SYNTASTIC_DEBUG_CHECKERS, '$TERM = ' . string($TERM))
  42. call syntastic#log#debug(g:_SYNTASTIC_DEBUG_CHECKERS, '$TMPDIR = ' . string($TMPDIR))
  43. endif
  44. call syntastic#log#debug(g:_SYNTASTIC_DEBUG_TRACE, '$PATH = ' . string($PATH))
  45. call syntastic#log#debug(g:_SYNTASTIC_DEBUG_TRACE, 'getcwd() = ' . string(getcwd()))
  46. call syntastic#log#debugShowOptions(g:_SYNTASTIC_DEBUG_TRACE, g:_SYNTASTIC_SHELL_OPTIONS)
  47. let out = ''
  48. endtry
  49. let cmd_time = split(reltimestr(reltime(cmd_start)))[0]
  50. let $LC_ALL = old_lc_all
  51. let $LC_MESSAGES = old_lc_messages
  52. let &shell = old_shell
  53. if !crashed && exists('g:_SYNTASTIC_DEBUG_TRACE')
  54. call syntastic#log#debug(g:_SYNTASTIC_DEBUG_TRACE, 'system: command run in ' . cmd_time . 's')
  55. endif
  56. return out
  57. endfunction " }}}2
  58. " Create a temporary directory
  59. function! syntastic#util#tmpdir() abort " {{{2
  60. let tempdir = ''
  61. if (has('unix') || has('mac')) && executable('mktemp') && !has('win32unix')
  62. " TODO: option "-t" to mktemp(1) is not portable
  63. let tmp = $TMPDIR !=# '' ? $TMPDIR : $TMP !=# '' ? $TMP : '/tmp'
  64. let out = split(syntastic#util#system('mktemp -q -d ' . tmp . '/vim-syntastic-' . getpid() . '-XXXXXXXX'), "\n")
  65. if v:shell_error == 0 && len(out) == 1
  66. let tempdir = out[0]
  67. endif
  68. endif
  69. if tempdir ==# ''
  70. if has('win32') || has('win64')
  71. let tempdir = $TEMP . syntastic#util#Slash() . 'vim-syntastic-' . getpid()
  72. elseif has('win32unix')
  73. let tempdir = syntastic#util#CygwinPath('/tmp/vim-syntastic-' . getpid())
  74. elseif $TMPDIR !=# ''
  75. let tempdir = $TMPDIR . '/vim-syntastic-' . getpid()
  76. else
  77. let tempdir = '/tmp/vim-syntastic-' . getpid()
  78. endif
  79. try
  80. call mkdir(tempdir, 'p', 0700)
  81. catch /\m^Vim\%((\a\+)\)\=:E739/
  82. call syntastic#log#error(v:exception)
  83. let tempdir = '.'
  84. endtry
  85. endif
  86. return tempdir
  87. endfunction " }}}2
  88. " Recursively remove a directory
  89. function! syntastic#util#rmrf(what) abort " {{{2
  90. " try to make sure we don't delete directories we didn't create
  91. if a:what !~? 'vim-syntastic-'
  92. return
  93. endif
  94. if getftype(a:what) ==# 'dir'
  95. call s:_delete(a:what, 'rf')
  96. else
  97. silent! call delete(a:what)
  98. endif
  99. endfunction " }}}2
  100. function! syntastic#util#getbufvar(buf, name, ...) abort " {{{2
  101. return a:0 ? s:_getbufvar(a:buf, a:name, a:1) : getbufvar(a:buf, a:name)
  102. endfunction " }}}2
  103. " Search the first 5 lines of the file for a magic number and return a map
  104. " containing the args and the executable
  105. "
  106. " e.g.
  107. "
  108. " #!/usr/bin/perl -f -bar
  109. "
  110. " returns
  111. "
  112. " {'exe': '/usr/bin/perl', 'args': ['-f', '-bar']}
  113. function! syntastic#util#parseShebang() abort " {{{2
  114. for lnum in range(1, 5)
  115. let line = getline(lnum)
  116. if line =~# '^#!'
  117. let line = substitute(line, '\v^#!\s*(\S+/env(\s+-\S+)*\s+)?', '', '')
  118. let exe = matchstr(line, '\m^\S*\ze')
  119. let args = split(matchstr(line, '\m^\S*\zs.*'))
  120. return { 'exe': exe, 'args': args }
  121. endif
  122. endfor
  123. return { 'exe': '', 'args': [] }
  124. endfunction " }}}2
  125. " Get the value of a Vim variable. Allow buffer variables to override global ones.
  126. function! syntastic#util#bufRawVar(buf, name, ...) abort " {{{2
  127. return s:_getbufvar(a:buf, a:name, get(g:, a:name, a:0 ? a:1 : ''))
  128. endfunction "}}}2
  129. " Get the value of a syntastic variable. Allow buffer variables to override global ones.
  130. function! syntastic#util#bufVar(buf, name, ...) abort " {{{2
  131. return call('syntastic#util#bufRawVar', [a:buf, 'syntastic_' . a:name] + a:000)
  132. endfunction "}}}2
  133. " Get the value of a Vim variable. Allow local variables to override global ones.
  134. function! syntastic#util#rawVar(name, ...) abort " {{{2
  135. return get(b:, a:name, get(g:, a:name, a:0 ? a:1 : ''))
  136. endfunction " }}}2
  137. " Get the value of a syntastic variable. Allow local variables to override global ones.
  138. function! syntastic#util#var(name, ...) abort " {{{2
  139. return call('syntastic#util#rawVar', ['syntastic_' . a:name] + a:000)
  140. endfunction " }}}2
  141. " Parse a version string. Return an array of version components.
  142. function! syntastic#util#parseVersion(version, ...) abort " {{{2
  143. return map(split(matchstr( a:version, a:0 ? a:1 : '\v^\D*\zs\d+(\.\d+)+\ze' ), '\m\.'), 'str2nr(v:val)')
  144. endfunction " }}}2
  145. " Verify that the 'installed' version is at least the 'required' version.
  146. "
  147. " 'installed' and 'required' must be arrays. If they have different lengths,
  148. " the "missing" elements will be assumed to be 0 for the purposes of checking.
  149. "
  150. " See http://semver.org for info about version numbers.
  151. function! syntastic#util#versionIsAtLeast(installed, required) abort " {{{2
  152. return syntastic#util#compareLexi(a:installed, a:required) >= 0
  153. endfunction " }}}2
  154. " Almost lexicographic comparison of two lists of integers. :) If lists
  155. " have different lengths, the "missing" elements are assumed to be 0.
  156. function! syntastic#util#compareLexi(a, b) abort " {{{2
  157. for idx in range(max([len(a:a), len(a:b)]))
  158. let a_element = str2nr(get(a:a, idx, 0))
  159. let b_element = str2nr(get(a:b, idx, 0))
  160. if a_element != b_element
  161. return a_element > b_element ? 1 : -1
  162. endif
  163. endfor
  164. " still here, thus everything matched
  165. return 0
  166. endfunction " }}}2
  167. function! syntastic#util#screenWidth(str, tabstop) abort " {{{2
  168. let chunks = split(a:str, "\t", 1)
  169. let width = s:_width(chunks[-1])
  170. for c in chunks[:-2]
  171. let cwidth = s:_width(c)
  172. let width += cwidth + a:tabstop - cwidth % a:tabstop
  173. endfor
  174. return width
  175. endfunction " }}}2
  176. " Print as much of a:msg as possible without "Press Enter" prompt appearing
  177. function! syntastic#util#wideMsg(msg) abort " {{{2
  178. let old_ruler = &ruler
  179. let old_showcmd = &showcmd
  180. "This is here because it is possible for some error messages to
  181. "begin with \n which will cause a "press enter" prompt.
  182. let msg = substitute(a:msg, "\n", '', 'g')
  183. "convert tabs to spaces so that the tabs count towards the window
  184. "width as the proper amount of characters
  185. let chunks = split(msg, "\t", 1)
  186. let msg = join(map(chunks[:-2], 'v:val . repeat(" ", &tabstop - s:_width(v:val) % &tabstop)'), '') . chunks[-1]
  187. let msg = strpart(msg, 0, &columns - 1)
  188. set noruler noshowcmd
  189. call syntastic#util#redraw(0)
  190. echo msg
  191. let &ruler = old_ruler
  192. let &showcmd = old_showcmd
  193. endfunction " }}}2
  194. " Check whether a buffer is loaded, listed, and not hidden
  195. function! syntastic#util#bufIsActive(buffer) abort " {{{2
  196. " convert to number, or hell breaks loose
  197. let buf = str2nr(a:buffer)
  198. if !bufloaded(buf) || !buflisted(buf)
  199. return 0
  200. endif
  201. " get rid of hidden buffers
  202. for tab in range(1, tabpagenr('$'))
  203. if index(tabpagebuflist(tab), buf) >= 0
  204. return 1
  205. endif
  206. endfor
  207. return 0
  208. endfunction " }}}2
  209. " Start in directory a:where and walk up the parent folders until it finds a
  210. " file named a:what; return path to that file
  211. function! syntastic#util#findFileInParent(what, where) abort " {{{2
  212. let old_suffixesadd = &suffixesadd
  213. let &suffixesadd = ''
  214. let file = findfile(a:what, escape(a:where, ' ') . ';')
  215. let &suffixesadd = old_suffixesadd
  216. return file
  217. endfunction " }}}2
  218. " Start in directory a:where and walk up the parent folders until it finds a
  219. " file matching a:what; return path to that file
  220. function! syntastic#util#findGlobInParent(what, where) abort " {{{2
  221. let here = fnamemodify(a:where, ':p')
  222. let root = syntastic#util#Slash()
  223. if syntastic#util#isRunningWindows() && here[1] ==# ':'
  224. " The drive letter is an ever-green source of fun. That's because
  225. " we don't care about running syntastic on Amiga these days. ;)
  226. let root = fnamemodify(root, ':p')
  227. let root = here[0] . root[1:]
  228. endif
  229. let old = ''
  230. while here !=# ''
  231. try
  232. " Vim 7.4.279 and later
  233. let p = globpath(here, a:what, 1, 1)
  234. catch /\m^Vim\%((\a\+)\)\=:E118/
  235. let p = split(globpath(here, a:what, 1), "\n")
  236. endtry
  237. if !empty(p)
  238. return fnamemodify(p[0], ':p')
  239. elseif here ==? root || here ==? old
  240. break
  241. endif
  242. let old = here
  243. " we use ':h:h' rather than ':h' since ':p' adds a trailing '/'
  244. " if 'here' is a directory
  245. let here = fnamemodify(here, ':p:h:h')
  246. endwhile
  247. return ''
  248. endfunction " }}}2
  249. " Returns the buffer number of a filename
  250. " @vimlint(EVL104, 1, l:old_shellslash)
  251. function! syntastic#util#fname2buf(fname) abort " {{{2
  252. if exists('+shellslash')
  253. " bufnr() can't cope with backslashes
  254. let old_shellslash = &shellslash
  255. let &shellslash = 1
  256. endif
  257. " this is a best-effort attempt to escape file patterns (cf. :h file-pattern)
  258. " XXX it fails for filenames containing something like \{2,3}
  259. for md in [':~:.', ':~', ':p']
  260. let buf = bufnr('^' . escape(fnamemodify(a:fname, md), '\*?,{}[') . '$')
  261. if buf != -1
  262. break
  263. endif
  264. endfor
  265. if buf == -1
  266. " XXX definitely wrong, but hope is the last thing to die :)
  267. let buf = bufnr(fnamemodify(a:fname, ':p'))
  268. endif
  269. if exists('+shellslash')
  270. let &shellslash = old_shellslash
  271. endif
  272. return buf
  273. endfunction " }}}2
  274. " @vimlint(EVL104, 0, l:old_shellslash)
  275. " Returns unique elements in a list
  276. function! syntastic#util#unique(list) abort " {{{2
  277. let seen = {}
  278. let uniques = []
  279. for e in a:list
  280. let k = string(e)
  281. if !has_key(seen, k)
  282. let seen[k] = 1
  283. call add(uniques, e)
  284. endif
  285. endfor
  286. return uniques
  287. endfunction " }}}2
  288. " A less noisy shellescape()
  289. function! syntastic#util#shescape(string) abort " {{{2
  290. return a:string =~# '\m^[A-Za-z0-9_/.-]\+$' ? a:string : shellescape(a:string)
  291. endfunction " }}}2
  292. " A less noisy shellescape(expand())
  293. function! syntastic#util#shexpand(string, ...) abort " {{{2
  294. return syntastic#util#shescape(a:0 ? expand(a:string, a:1) : expand(a:string, 1))
  295. endfunction " }}}2
  296. " Escape arguments
  297. function! syntastic#util#argsescape(opt) abort " {{{2
  298. if type(a:opt) == type('') && a:opt !=# ''
  299. return [a:opt]
  300. elseif type(a:opt) == type([])
  301. return map(copy(a:opt), 'syntastic#util#shescape(v:val)')
  302. endif
  303. return []
  304. endfunction " }}}2
  305. " Decode XML entities
  306. function! syntastic#util#decodeXMLEntities(string) abort " {{{2
  307. let str = a:string
  308. let str = substitute(str, '\m&lt;', '<', 'g')
  309. let str = substitute(str, '\m&gt;', '>', 'g')
  310. let str = substitute(str, '\m&quot;', '"', 'g')
  311. let str = substitute(str, '\m&apos;', "'", 'g')
  312. let str = substitute(str, '\m&amp;', '\&', 'g')
  313. return str
  314. endfunction " }}}2
  315. function! syntastic#util#redraw(full) abort " {{{2
  316. if a:full
  317. redraw!
  318. else
  319. redraw
  320. endif
  321. endfunction " }}}2
  322. function! syntastic#util#dictFilter(errors, filter) abort " {{{2
  323. let rules = s:_translateFilter(a:filter)
  324. " call syntastic#log#debug(g:_SYNTASTIC_DEBUG_TRACE, "applying filter:", rules)
  325. try
  326. call filter(a:errors, rules)
  327. catch /\m^Vim\%((\a\+)\)\=:E/
  328. let msg = matchstr(v:exception, '\m^Vim\%((\a\+)\)\=:\zs.*')
  329. call syntastic#log#error('quiet_messages: ' . msg)
  330. endtry
  331. endfunction " }}}2
  332. " Return a [seconds, fractions] list of strings, representing the
  333. " (hopefully high resolution) time since program start
  334. function! syntastic#util#stamp() abort " {{{2
  335. return split( split(reltimestr(reltime(g:_SYNTASTIC_START)))[0], '\.' )
  336. endfunction " }}}2
  337. function! syntastic#util#setLastTick(buf) abort " {{{2
  338. call setbufvar(a:buf, 'syntastic_lasttick', getbufvar(a:buf, 'changedtick'))
  339. endfunction " }}}2
  340. let s:_wid_base = 'syntastic_' . getpid() . '_' . reltimestr(g:_SYNTASTIC_START) . '_'
  341. let s:_wid_pool = 0
  342. " Add unique IDs to windows
  343. function! syntastic#util#setWids() abort " {{{2
  344. for tab in range(1, tabpagenr('$'))
  345. for win in range(1, tabpagewinnr(tab, '$'))
  346. if gettabwinvar(tab, win, 'syntastic_wid') ==# ''
  347. call settabwinvar(tab, win, 'syntastic_wid', s:_wid_base . s:_wid_pool)
  348. let s:_wid_pool += 1
  349. endif
  350. endfor
  351. endfor
  352. endfunction " }}}2
  353. function! syntastic#util#str2float(val) abort " {{{2
  354. return s:_str2float(a:val)
  355. endfunction " }}}2
  356. function! syntastic#util#float2str(val) abort " {{{2
  357. return s:_float2str(a:val)
  358. endfunction " }}}2
  359. " Crude printf()-like width formatter. Handles wide characters.
  360. function! syntastic#util#wformat(format, str) abort " {{{2
  361. if a:format ==# ''
  362. return a:str
  363. endif
  364. echomsg string(a:format) . ', ' . string(a:str)
  365. let specs = matchlist(a:format, '\v^(-?)(0?)(%([1-9]\d*))?%(\.(\d+))?$')
  366. if len(specs) < 5
  367. return a:str
  368. endif
  369. let flushleft = specs[1] ==# '-'
  370. let lpad = specs[2] ==# '0' ? '0' : ' '
  371. let minlen = str2nr(specs[3])
  372. let maxlen = str2nr(specs[4])
  373. let out = substitute(a:str, "\t", ' ', 'g')
  374. if maxlen && s:_width(out) > maxlen
  375. let chars = filter(split(out, '\zs\ze', 1), 'v:val !=# ""')
  376. let out = ''
  377. if flushleft
  378. for c in chars
  379. if s:_width(out . c) < maxlen
  380. let out .= c
  381. else
  382. let out .= &encoding ==# 'utf-8' && &termencoding ==# 'utf-8' ? "\u2026" : '>'
  383. break
  384. endif
  385. endfor
  386. else
  387. call reverse(chars)
  388. for c in chars
  389. if s:_width(c . out) < maxlen
  390. let out = c . out
  391. else
  392. let out = (&encoding ==# 'utf-8' && &termencoding ==# 'utf-8' ? "\u2026" : '<') . out
  393. break
  394. endif
  395. endfor
  396. endif
  397. endif
  398. if minlen && s:_width(out) < minlen
  399. if flushleft
  400. let out .= repeat(' ', minlen - s:_width(out))
  401. else
  402. let out = repeat(lpad, minlen - s:_width(out)) . out
  403. endif
  404. endif
  405. return out
  406. endfunction " }}}2
  407. " }}}1
  408. " Private functions {{{1
  409. function! s:_translateFilter(filters) abort " {{{2
  410. let conditions = []
  411. for k in keys(a:filters)
  412. if type(a:filters[k]) == type([])
  413. call extend(conditions, map(copy(a:filters[k]), 's:_translateElement(k, v:val)'))
  414. else
  415. call add(conditions, s:_translateElement(k, a:filters[k]))
  416. endif
  417. endfor
  418. if conditions == []
  419. let conditions = ['1']
  420. endif
  421. return len(conditions) == 1 ? conditions[0] : join(map(conditions, '"(" . v:val . ")"'), ' && ')
  422. endfunction " }}}2
  423. function! s:_translateElement(key, term) abort " {{{2
  424. let fkey = a:key
  425. if fkey[0] ==# '!'
  426. let fkey = fkey[1:]
  427. let not = 1
  428. else
  429. let not = 0
  430. endif
  431. if fkey ==? 'level'
  432. let op = not ? ' ==? ' : ' !=? '
  433. let ret = 'v:val["type"]' . op . string(a:term[0])
  434. elseif fkey ==? 'type'
  435. if a:term ==? 'style'
  436. let op = not ? ' ==? ' : ' !=? '
  437. let ret = 'get(v:val, "subtype", "")' . op . '"style"'
  438. else
  439. let op = not ? '!' : ''
  440. let ret = op . 'has_key(v:val, "subtype")'
  441. endif
  442. elseif fkey ==? 'regex'
  443. let op = not ? ' =~? ' : ' !~? '
  444. let ret = 'v:val["text"]' . op . string(a:term)
  445. elseif fkey ==? 'file' || fkey[:4] ==? 'file:'
  446. let op = not ? ' =~# ' : ' !~# '
  447. let ret = 'bufname(str2nr(v:val["bufnr"]))'
  448. let mod = fkey[4:]
  449. if mod !=# ''
  450. let ret = 'fnamemodify(' . ret . ', ' . string(mod) . ')'
  451. endif
  452. let ret .= op . string(a:term)
  453. else
  454. call syntastic#log#warn('quiet_messages: ignoring invalid key ' . strtrans(string(fkey)))
  455. let ret = '1'
  456. endif
  457. return ret
  458. endfunction " }}}2
  459. " strwidth() was added in Vim 7.3; if it doesn't exist, we use strlen()
  460. " and hope for the best :)
  461. let s:_width = function(exists('*strwidth') ? 'strwidth' : 'strlen')
  462. lockvar s:_width
  463. " @vimlint(EVL103, 1, a:flags)
  464. function! s:_delete_dumb(what, flags) abort " {{{2
  465. if !exists('s:rmrf')
  466. let s:rmrf =
  467. \ has('unix') || has('mac') ? 'rm -rf' :
  468. \ has('win32') || has('win64') ? 'rmdir /S /Q' :
  469. \ has('win16') || has('win95') || has('dos16') || has('dos32') ? 'deltree /Y' : ''
  470. endif
  471. if s:rmrf !=# ''
  472. silent! call syntastic#util#system(s:rmrf . ' ' . syntastic#util#shescape(a:what))
  473. else
  474. call s:_rmrf(a:what)
  475. endif
  476. endfunction " }}}2
  477. " @vimlint(EVL103, 0, a:flags)
  478. " delete(dir, 'rf') was added in Vim 7.4.1107, but it didn't become usable until 7.4.1128
  479. let s:_delete = function(v:version > 704 || (v:version == 704 && has('patch1128')) ? 'delete' : 's:_delete_dumb')
  480. lockvar s:_delete
  481. function! s:_rmrf(what) abort " {{{2
  482. if !exists('s:rmdir')
  483. let s:rmdir = syntastic#util#shescape(get(g:, 'netrw_localrmdir', 'rmdir'))
  484. endif
  485. if getftype(a:what) ==# 'dir'
  486. if filewritable(a:what) != 2
  487. return
  488. endif
  489. try
  490. " Vim 7.4.279 and later
  491. let entries = globpath(a:what, '*', 1, 1)
  492. catch /\m^Vim\%((\a\+)\)\=:E118/
  493. let entries = split(globpath(a:what, '*', 1), "\n")
  494. endtry
  495. for f in entries
  496. call s:_rmrf(f)
  497. endfor
  498. silent! call syntastic#util#system(s:rmdir . ' ' . syntastic#util#shescape(a:what))
  499. else
  500. silent! call delete(a:what)
  501. endif
  502. endfunction " }}}2
  503. let s:_str2float = function(exists('*str2float') ? 'str2float' : 'str2nr')
  504. lockvar s:_str2float
  505. function! s:_float2str_smart(val) abort " {{{2
  506. return printf('%.1f', a:val)
  507. endfunction " }}}2
  508. function! s:_float2str_dumb(val) abort " {{{2
  509. return a:val
  510. endfunction " }}}2
  511. let s:_float2str = function(has('float') ? 's:_float2str_smart' : 's:_float2str_dumb')
  512. lockvar s:_float2str
  513. function! s:_getbufvar_dumb(buf, name, ...) abort " {{{2
  514. let ret = getbufvar(a:buf, a:name)
  515. if a:0 && type(ret) == type('') && ret ==# ''
  516. unlet! ret
  517. let ret = a:1
  518. endif
  519. return ret
  520. endfunction "}}}2
  521. let s:_getbufvar = function(v:version > 703 || (v:version == 703 && has('patch831')) ? 'getbufvar' : 's:_getbufvar_dumb')
  522. lockvar s:_getbufvar
  523. " }}}1
  524. let &cpo = s:save_cpo
  525. unlet s:save_cpo
  526. " vim: set sw=4 sts=4 et fdm=marker: