compat.vim 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244
  1. scriptencoding utf-8
  2. let s:is_vim = !has('nvim')
  3. " first window id for bufnr
  4. " builtin bufwinid returns window of current tab only
  5. function! coc#compat#buf_win_id(bufnr) abort
  6. let info = filter(getwininfo(), 'v:val["bufnr"] =='.a:bufnr)
  7. if empty(info)
  8. return -1
  9. endif
  10. return info[0]['winid']
  11. endfunction
  12. function! coc#compat#buf_set_lines(bufnr, start, end, replacement) abort
  13. if s:is_vim
  14. call coc#api#exec('buf_set_lines', [a:bufnr, a:start, a:end, 0, a:replacement])
  15. else
  16. call nvim_buf_set_lines(a:bufnr, a:start, a:end, 0, a:replacement)
  17. endif
  18. endfunction
  19. function! coc#compat#buf_line_count(bufnr) abort
  20. if exists('*nvim_buf_line_count')
  21. return nvim_buf_line_count(a:bufnr)
  22. endif
  23. if bufnr('%') == a:bufnr
  24. return line('$')
  25. endif
  26. if exists('*getbufinfo')
  27. let info = getbufinfo(a:bufnr)
  28. if empty(info)
  29. return 0
  30. endif
  31. " vim 8.1 has getbufinfo but no linecount
  32. if has_key(info[0], 'linecount')
  33. return info[0]['linecount']
  34. endif
  35. endif
  36. if exists('*getbufline')
  37. let lines = getbufline(a:bufnr, 1, '$')
  38. return len(lines)
  39. endif
  40. let curr = bufnr('%')
  41. execute 'noa buffer '.a:bufnr
  42. let n = line('$')
  43. execute 'noa buffer '.curr
  44. return n
  45. endfunction
  46. function! coc#compat#prepend_lines(bufnr, replacement) abort
  47. if exists('*appendbufline')
  48. call appendbufline(a:bufnr, 0, a:replacement)
  49. elseif !s:is_vim
  50. call nvim_buf_set_lines(a:bufnr, 0, 0, 0, a:replacement)
  51. else
  52. throw 'appendbufline() required for prepend lines.'
  53. endif
  54. endfunction
  55. function! coc#compat#win_is_valid(winid) abort
  56. if exists('*nvim_win_is_valid')
  57. return nvim_win_is_valid(a:winid)
  58. endif
  59. return !empty(getwininfo(a:winid))
  60. endfunction
  61. " clear matches by window id, not throw on none exists window.
  62. " may not work on vim < 8.1.1084 & neovim < 0.4.0
  63. function! coc#compat#clear_matches(winid) abort
  64. if !coc#compat#win_is_valid(a:winid)
  65. return
  66. endif
  67. let curr = win_getid()
  68. if curr == a:winid
  69. call clearmatches()
  70. return
  71. endif
  72. if s:is_vim
  73. if has('patch-8.1.1084')
  74. call clearmatches(a:winid)
  75. endif
  76. else
  77. if exists('*nvim_set_current_win')
  78. noa call nvim_set_current_win(a:winid)
  79. call clearmatches()
  80. noa call nvim_set_current_win(curr)
  81. endif
  82. endif
  83. endfunction
  84. function! coc#compat#matchaddpos(group, pos, priority, winid) abort
  85. let curr = win_getid()
  86. if curr == a:winid
  87. call matchaddpos(a:group, a:pos, a:priority, -1)
  88. else
  89. if s:is_vim
  90. if has('patch-8.1.0218')
  91. call matchaddpos(a:group, a:pos, a:priority, -1, {'window': a:winid})
  92. endif
  93. else
  94. if has('nvim-0.4.0')
  95. call matchaddpos(a:group, a:pos, a:priority, -1, {'window': a:winid})
  96. elseif exists('*nvim_set_current_win')
  97. noa call nvim_set_current_win(a:winid)
  98. call matchaddpos(a:group, a:pos, a:priority, -1)
  99. noa call nvim_set_current_win(curr)
  100. endif
  101. endif
  102. endif
  103. endfunction
  104. function! coc#compat#buf_del_var(bufnr, name) abort
  105. if !bufloaded(a:bufnr)
  106. return
  107. endif
  108. if exists('*nvim_buf_del_var')
  109. silent! call nvim_buf_del_var(a:bufnr, a:name)
  110. else
  111. if a:bufnr == bufnr('%')
  112. execute 'unlet! b:'.a:name
  113. elseif exists('*win_execute')
  114. let winid = coc#compat#buf_win_id(a:bufnr)
  115. if winid != -1
  116. call win_execute(winid, 'unlet! b:'.a:name)
  117. endif
  118. endif
  119. endif
  120. endfunction
  121. " hlGroup, pos, priority
  122. function! coc#compat#matchaddgroups(winid, groups) abort
  123. " add by winid
  124. if has('patch-8.1.0218') || has('nvim-0.4.0')
  125. for group in a:groups
  126. call matchaddpos(group['hlGroup'], [group['pos']], group['priority'], -1, {'window': a:winid})
  127. endfor
  128. return
  129. endif
  130. let curr = win_getid()
  131. if curr == a:winid
  132. for group in a:groups
  133. call matchaddpos(group['hlGroup'], [group['pos']], group['priority'], -1)
  134. endfor
  135. elseif exists('*nvim_set_current_win')
  136. noa call nvim_set_current_win(a:winid)
  137. for group in a:groups
  138. call matchaddpos(group['hlGroup'], [group['pos']], group['priority'], -1)
  139. endfor
  140. noa call nvim_set_current_win(curr)
  141. endif
  142. endfunction
  143. function! coc#compat#del_var(name) abort
  144. if exists('*nvim_del_var')
  145. silent! call nvim_del_var(a:name)
  146. else
  147. execute 'unlet! '.a:name
  148. endif
  149. endfunction
  150. " remove keymap for specific buffer
  151. function! coc#compat#buf_del_keymap(bufnr, mode, lhs) abort
  152. if !bufloaded(a:bufnr)
  153. return
  154. endif
  155. if exists('*nvim_buf_del_keymap')
  156. try
  157. call nvim_buf_del_keymap(a:bufnr, a:mode, a:lhs)
  158. catch /^Vim\%((\a\+)\)\=:E5555/
  159. " ignore keymap doesn't exist
  160. endtry
  161. return
  162. endif
  163. if bufnr == a:bufnr
  164. execute 'silent! '.a:mode.'unmap <buffer> '.a:lhs
  165. return
  166. endif
  167. if exists('*win_execute')
  168. let winid = coc#compat#buf_win_id(a:bufnr)
  169. if winid != -1
  170. call win_execute(winid, a:mode.'unmap <buffer> '.a:lhs, 'silent!')
  171. endif
  172. endif
  173. endfunction
  174. function! coc#compat#buf_add_keymap(bufnr, mode, lhs, rhs, opts) abort
  175. if !bufloaded(a:bufnr)
  176. return
  177. endif
  178. if exists('*nvim_buf_set_keymap')
  179. call nvim_buf_set_keymap(a:bufnr, a:mode, a:lhs, a:rhs, a:opts)
  180. else
  181. let cmd = a:mode . 'noremap '
  182. for key in keys(a:opts)
  183. if get(a:opts, key, 0)
  184. let cmd .= '<'.key.'>'
  185. endif
  186. endfor
  187. let cmd .= '<buffer> '.a:lhs.' '.a:rhs
  188. if bufnr('%') == a:bufnr
  189. execute cmd
  190. elseif exists('*win_execute')
  191. let winid = coc#compat#buf_win_id(a:bufnr)
  192. if winid != -1
  193. call win_execute(winid, cmd)
  194. endif
  195. endif
  196. endif
  197. endfunction
  198. " execute command or list of commands in window
  199. function! coc#compat#execute(winid, command, ...) abort
  200. if exists('*win_execute')
  201. if type(a:command) == v:t_string
  202. keepalt call win_execute(a:winid, a:command, get(a:, 1, ''))
  203. elseif type(a:command) == v:t_list
  204. keepalt call win_execute(a:winid, join(a:command, "\n"), get(a:, 1, ''))
  205. endif
  206. elseif has('nvim')
  207. if !nvim_win_is_valid(a:winid)
  208. return
  209. endif
  210. let curr = nvim_get_current_win()
  211. noa keepalt call nvim_set_current_win(a:winid)
  212. if type(a:command) == v:t_string
  213. exe get(a:, 1, '').' '.a:command
  214. elseif type(a:command) == v:t_list
  215. for cmd in a:command
  216. exe get(a:, 1, '').' '.cmd
  217. endfor
  218. endif
  219. noa keepalt call nvim_set_current_win(curr)
  220. else
  221. throw 'win_execute does not exist, please upgrade vim.'
  222. endif
  223. endfunc
  224. function! coc#compat#trim(str)
  225. if exists('*trim')
  226. return trim(a:str)
  227. endif
  228. " TODO trim from beginning
  229. return substitute(a:str, '\s\+$', '', '')
  230. endfunction