async_cache.vim 7.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276
  1. "=============================================================================
  2. " FILE: async_cache.vim
  3. " AUTHOR: Shougo Matsushita <Shougo.Matsu@gmail.com>
  4. " License: MIT license {{{
  5. " Permission is hereby granted, free of charge, to any person obtaining
  6. " a copy of this software and associated documentation files (the
  7. " "Software"), to deal in the Software without restriction, including
  8. " without limitation the rights to use, copy, modify, merge, publish,
  9. " distribute, sublicense, and/or sell copies of the Software, and to
  10. " permit persons to whom the Software is furnished to do so, subject to
  11. " the following condition
  12. "
  13. " The above copyright notice and this permission notice shall be included
  14. " in all copies or substantial portions of the Software.
  15. "
  16. " THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
  17. " OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  18. " MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
  19. " IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
  20. " CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
  21. " TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
  22. " SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  23. " }}}
  24. "=============================================================================
  25. let s:save_cpo = &cpo
  26. set cpo&vim
  27. function! s:main(argv) abort "{{{
  28. " args: funcname, outputname filename pattern_file_name mark minlen fileencoding
  29. let [funcname, outputname, filename, pattern_file_name, mark, minlen, fileencoding]
  30. \ = a:argv
  31. if funcname ==# 'load_from_file'
  32. let keyword_list = s:load_from_file(
  33. \ filename, pattern_file_name, mark, minlen, fileencoding, 1)
  34. let string = '{' . escape(string(keyword_list)[1 : -2], '\\') . '}'
  35. else
  36. let keyword_list = s:load_from_tags(
  37. \ filename, pattern_file_name, mark, minlen, fileencoding)
  38. let string = string(keyword_list)
  39. endif
  40. if empty(keyword_list)
  41. return
  42. endif
  43. " For neocomplete.
  44. " Output cache.
  45. call writefile([string], outputname)
  46. endfunction"}}}
  47. function! s:load_from_file(filename, pattern_file_name, mark, minlen, fileencoding, is_string) abort "{{{
  48. if !filereadable(a:filename)
  49. " File not found.
  50. return []
  51. endif
  52. let lines = readfile(a:filename)
  53. if a:fileencoding !=# &encoding
  54. let lines = map(lines, 's:iconv(v:val, a:fileencoding, &encoding)')
  55. endif
  56. let pattern = get(readfile(a:pattern_file_name), 0, '\h\w*')
  57. let pattern2 = '^\%('.pattern.'\m\)'
  58. let keyword_list = []
  59. let dup_check = {}
  60. for line in lines "{{{
  61. let match = match(line, pattern)
  62. while match >= 0 "{{{
  63. let match_str = matchstr(line, pattern2, match)
  64. if !has_key(dup_check, match_str) && len(match_str) >= a:minlen
  65. " Append list.
  66. call add(keyword_list, match_str)
  67. let dup_check[match_str] = 1
  68. endif
  69. if match_str == ''
  70. break
  71. endif
  72. let match += len(match_str)
  73. let match = match(line, pattern, match)
  74. endwhile"}}}
  75. endfor"}}}
  76. if !a:is_string
  77. call map(keyword_list, "{'word' : match_str}")
  78. endif
  79. return keyword_list
  80. endfunction"}}}
  81. function! s:load_from_tags(filename, pattern_file_name, mark, minlen, fileencoding) abort "{{{
  82. let keyword_lists = []
  83. let dup_check = {}
  84. let [tags_file_name, filter_pattern] =
  85. \ readfile(a:pattern_file_name)[1 : 2]
  86. if tags_file_name !=# '$dummy$'
  87. " Check output.
  88. let tags_list = []
  89. let i = 0
  90. while i < 2
  91. if filereadable(tags_file_name)
  92. " Use filename.
  93. let tags_list = map(readfile(tags_file_name),
  94. \ 's:iconv(v:val, a:fileencoding, &encoding)')
  95. break
  96. endif
  97. sleep 500m
  98. let i += 1
  99. endwhile
  100. else
  101. if !filereadable(a:filename)
  102. return []
  103. endif
  104. " Use filename.
  105. let tags_list = map(readfile(a:filename),
  106. \ 's:iconv(v:val, a:fileencoding, &encoding)')
  107. endif
  108. if empty(tags_list)
  109. return s:load_from_file(a:filename, a:pattern_file_name,
  110. \ a:mark, a:minlen, a:fileencoding, 0)
  111. endif
  112. for line in tags_list
  113. let tag = split(substitute(line, "\<CR>", '', 'g'), '\t', 1)
  114. " Add keywords.
  115. if line =~ '^!' || len(tag) < 3 || len(tag[0]) < a:minlen
  116. \ || has_key(dup_check, tag[0])
  117. continue
  118. endif
  119. let opt = join(tag[2:], "\<TAB>")
  120. let cmd = matchstr(opt, '.*/;"')
  121. let option = {
  122. \ 'cmd' : substitute(substitute(substitute(cmd,
  123. \'^\%([/?]\^\?\)\?\s*\|\%(\$\?[/?]\)\?;"$', '', 'g'),
  124. \ '\\\\', '\\', 'g'), '\\/', '/', 'g'),
  125. \ 'kind' : ''
  126. \}
  127. if option.cmd =~ '\d\+'
  128. let option.cmd = tag[0]
  129. endif
  130. for opt in split(opt[len(cmd):], '\t', 1)
  131. let key = matchstr(opt, '^\h\w*\ze:')
  132. if key == ''
  133. let option['kind'] = opt
  134. else
  135. let option[key] = matchstr(opt, '^\h\w*:\zs.*')
  136. endif
  137. endfor
  138. if has_key(option, 'file')
  139. \ || (has_key(option, 'access') && option.access != 'public')
  140. continue
  141. endif
  142. let abbr = has_key(option, 'signature')? tag[0] . option.signature :
  143. \ (option['kind'] == 'd' || option['cmd'] == '') ?
  144. \ tag[0] : option['cmd']
  145. let abbr = substitute(abbr, '\s\+', ' ', 'g')
  146. " Substitute "namespace foobar" to "foobar <namespace>".
  147. let abbr = substitute(abbr,
  148. \'^\(namespace\|class\|struct\|enum\|union\)\s\+\(.*\)$',
  149. \'\2 <\1>', '')
  150. " Substitute typedef.
  151. let abbr = substitute(abbr,
  152. \'^typedef\s\+\(.*\)\s\+\(\h\w*\%(::\w*\)*\);\?$',
  153. \'\2 <typedef \1>', 'g')
  154. " Substitute extends and implements.
  155. let abbr = substitute(abbr,
  156. \'\<\%(extends\|implements\)\s\+\S\+\>', '', '')
  157. " Substitute marker.
  158. let abbr = substitute(abbr, '"\s*{{{', '', '')
  159. let keyword = {
  160. \ 'word' : tag[0], 'abbr' : abbr, 'menu' : '',
  161. \ 'kind' : option['kind'],
  162. \ }
  163. if has_key(option, 'struct')
  164. let keyword.menu = option.struct
  165. elseif has_key(option, 'class')
  166. let keyword.menu = option.class
  167. elseif has_key(option, 'enum')
  168. let keyword.menu = option.enum
  169. elseif has_key(option, 'union')
  170. let keyword.menu = option.union
  171. endif
  172. call add(keyword_lists, keyword)
  173. let dup_check[tag[0]] = 1
  174. endfor"}}}
  175. if filter_pattern != ''
  176. call filter(keyword_lists, filter_pattern)
  177. endif
  178. return keyword_lists
  179. endfunction"}}}
  180. function! s:truncate(str, width) abort "{{{
  181. " Original function is from mattn.
  182. " http://github.com/mattn/googlereader-vim/tree/master
  183. if a:str =~# '^[\x00-\x7f]*$'
  184. return len(a:str) < a:width ?
  185. \ printf('%-'.a:width.'s', a:str) : strpart(a:str, 0, a:width)
  186. endif
  187. let ret = a:str
  188. let width = strdisplaywidth(a:str)
  189. if width > a:width
  190. let ret = s:strwidthpart(ret, a:width)
  191. let width = strdisplaywidth(ret)
  192. endif
  193. if width < a:width
  194. let ret .= repeat(' ', a:width - width)
  195. endif
  196. return ret
  197. endfunction"}}}
  198. function! s:strwidthpart(str, width) abort "{{{
  199. let ret = a:str
  200. let width = strdisplaywidth(a:str)
  201. while width > a:width
  202. let char = matchstr(ret, '.$')
  203. let ret = ret[: -1 - len(char)]
  204. let width -= strwidth(char)
  205. endwhile
  206. return ret
  207. endfunction"}}}
  208. function! s:iconv(expr, from, to) abort
  209. if a:from == '' || a:to == '' || a:from ==? a:to
  210. return a:expr
  211. endif
  212. let result = iconv(a:expr, a:from, a:to)
  213. return result != '' ? result : a:expr
  214. endfunction
  215. if argc() == 7 &&
  216. \ (argv(0) ==# 'load_from_file' || argv(0) ==# 'load_from_tags')
  217. try
  218. call s:main(argv())
  219. catch
  220. call writefile([v:throwpoint, v:exception],
  221. \ fnamemodify(argv(1), ':h:h').'/async_error_log')
  222. endtry
  223. qall!
  224. else
  225. function! neocomplete#async_cache#main(argv) abort "{{{
  226. call s:main(a:argv)
  227. endfunction"}}}
  228. endif
  229. let &cpo = s:save_cpo
  230. unlet s:save_cpo
  231. " vim: foldmethod=marker