prompt.vim 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214
  1. scriptencoding utf-8
  2. let s:is_vim = !has('nvim')
  3. let s:activated = 0
  4. let s:session_names = []
  5. let s:saved_ve = &t_ve
  6. let s:saved_cursor = &guicursor
  7. let s:gui = has('gui_running') || has('nvim')
  8. let s:char_map = {
  9. \ "\<Plug>": '<plug>',
  10. \ "\<Esc>": '<esc>',
  11. \ "\<Tab>": '<tab>',
  12. \ "\<S-Tab>": '<s-tab>',
  13. \ "\<bs>": '<bs>',
  14. \ "\<right>": '<right>',
  15. \ "\<left>": '<left>',
  16. \ "\<up>": '<up>',
  17. \ "\<down>": '<down>',
  18. \ "\<home>": '<home>',
  19. \ "\<end>": '<end>',
  20. \ "\<cr>": '<cr>',
  21. \ "\<PageUp>":'<PageUp>' ,
  22. \ "\<PageDown>":'<PageDown>' ,
  23. \ "\<FocusGained>":'<FocusGained>',
  24. \ "\<FocusLost>":'<FocusLost>',
  25. \ "\<ScrollWheelUp>": '<ScrollWheelUp>',
  26. \ "\<ScrollWheelDown>": '<ScrollWheelDown>',
  27. \ "\<LeftMouse>": '<LeftMouse>',
  28. \ "\<LeftDrag>": '<LeftDrag>',
  29. \ "\<LeftRelease>": '<LeftRelease>',
  30. \ "\<2-LeftMouse>": '<2-LeftMouse>',
  31. \ "\<C-a>": '<C-a>',
  32. \ "\<C-b>": '<C-b>',
  33. \ "\<C-c>": '<C-c>',
  34. \ "\<C-d>": '<C-d>',
  35. \ "\<C-e>": '<C-e>',
  36. \ "\<C-f>": '<C-f>',
  37. \ "\<C-g>": '<C-g>',
  38. \ "\<C-h>": '<C-h>',
  39. \ "\<C-j>": '<C-j>',
  40. \ "\<C-k>": '<C-k>',
  41. \ "\<C-l>": '<C-l>',
  42. \ "\<C-n>": '<C-n>',
  43. \ "\<C-o>": '<C-o>',
  44. \ "\<C-p>": '<C-p>',
  45. \ "\<C-q>": '<C-q>',
  46. \ "\<C-r>": '<C-r>',
  47. \ "\<C-s>": '<C-s>',
  48. \ "\<C-t>": '<C-t>',
  49. \ "\<C-u>": '<C-u>',
  50. \ "\<C-v>": '<C-v>',
  51. \ "\<C-w>": '<C-w>',
  52. \ "\<C-x>": '<C-x>',
  53. \ "\<C-y>": '<C-y>',
  54. \ "\<C-z>": '<C-z>',
  55. \ "\<A-a>": '<A-a>',
  56. \ "\<A-b>": '<A-b>',
  57. \ "\<A-c>": '<A-c>',
  58. \ "\<A-d>": '<A-d>',
  59. \ "\<A-e>": '<A-e>',
  60. \ "\<A-f>": '<A-f>',
  61. \ "\<A-g>": '<A-g>',
  62. \ "\<A-h>": '<A-h>',
  63. \ "\<A-i>": '<A-i>',
  64. \ "\<A-j>": '<A-j>',
  65. \ "\<A-k>": '<A-k>',
  66. \ "\<A-l>": '<A-l>',
  67. \ "\<A-m>": '<A-m>',
  68. \ "\<A-n>": '<A-n>',
  69. \ "\<A-o>": '<A-o>',
  70. \ "\<A-p>": '<A-p>',
  71. \ "\<A-q>": '<A-q>',
  72. \ "\<A-r>": '<A-r>',
  73. \ "\<A-s>": '<A-s>',
  74. \ "\<A-t>": '<A-t>',
  75. \ "\<A-u>": '<A-u>',
  76. \ "\<A-v>": '<A-v>',
  77. \ "\<A-w>": '<A-w>',
  78. \ "\<A-x>": '<A-x>',
  79. \ "\<A-y>": '<A-y>',
  80. \ "\<A-z>": '<A-z>',
  81. \ }
  82. function! coc#prompt#getc() abort
  83. let c = getchar()
  84. return type(c) is 0 ? nr2char(c) : c
  85. endfunction
  86. function! coc#prompt#getchar() abort
  87. let input = coc#prompt#getc()
  88. if 1 != &iminsert
  89. return input
  90. endif
  91. "a language keymap is activated, so input must be resolved to the mapped values.
  92. let partial_keymap = mapcheck(input, 'l')
  93. while partial_keymap !=# ''
  94. let dict = maparg(input, 'l', 0, 1)
  95. if empty(dict) || get(dict, 'expr', 0)
  96. return input
  97. endif
  98. let full_keymap = get(dict, 'rhs', '')
  99. if full_keymap ==# "" && len(input) >= 3 "HACK: assume there are no keymaps longer than 3.
  100. return input
  101. elseif full_keymap ==# partial_keymap
  102. return full_keymap
  103. endif
  104. let c = coc#prompt#getc()
  105. if c ==# "\<Esc>" || c ==# "\<CR>"
  106. "if the short sequence has a valid mapping, return that.
  107. if !empty(full_keymap)
  108. return full_keymap
  109. endif
  110. return input
  111. endif
  112. let input .= c
  113. let partial_keymap = mapcheck(input, 'l')
  114. endwhile
  115. return input
  116. endfunction
  117. function! coc#prompt#start_prompt(session) abort
  118. let s:session_names = s:filter(s:session_names, a:session)
  119. call add(s:session_names, a:session)
  120. if s:activated | return | endif
  121. if s:is_vim
  122. call s:start_prompt_vim()
  123. else
  124. call s:start_prompt()
  125. endif
  126. endfunction
  127. function! s:start_prompt_vim() abort
  128. call timer_start(10, {-> s:start_prompt()})
  129. endfunction
  130. function! s:start_prompt()
  131. if s:activated | return | endif
  132. if !get(g:, 'coc_disable_transparent_cursor', 0)
  133. if s:gui
  134. if has('nvim-0.5.0') && !empty(s:saved_cursor)
  135. set guicursor+=a:ver1-CocCursorTransparent/lCursor
  136. endif
  137. elseif s:is_vim
  138. set t_ve=
  139. endif
  140. endif
  141. let s:activated = 1
  142. try
  143. while s:activated
  144. let ch = coc#prompt#getchar()
  145. if ch ==# "\<FocusLost>" || ch ==# "\<FocusGained>" || ch ==# "\<CursorHold>"
  146. continue
  147. else
  148. let curr = s:current_session()
  149. let mapped = get(s:char_map, ch, ch)
  150. if !empty(curr)
  151. call coc#rpc#notify('InputChar', [curr, mapped, getcharmod()])
  152. endif
  153. if mapped == '<esc>'
  154. let s:session_names = []
  155. call s:reset()
  156. break
  157. endif
  158. endif
  159. endwhile
  160. catch /^Vim:Interrupt$/
  161. let s:activated = 0
  162. call coc#rpc#notify('InputChar', [s:current_session(), '<esc>'])
  163. return
  164. endtry
  165. let s:activated = 0
  166. endfunction
  167. function! coc#prompt#stop_prompt(session)
  168. let s:session_names = s:filter(s:session_names, a:session)
  169. if len(s:session_names)
  170. return
  171. endif
  172. if s:activated
  173. let s:activated = 0
  174. call s:reset()
  175. call feedkeys("\<esc>", 'int')
  176. endif
  177. endfunction
  178. function! coc#prompt#activated() abort
  179. return s:activated
  180. endfunction
  181. function! s:reset() abort
  182. if !get(g:, 'coc_disable_transparent_cursor',0)
  183. " neovim has bug with revert empty &guicursor
  184. if s:gui && !empty(s:saved_cursor)
  185. if has('nvim-0.5.0')
  186. set guicursor+=a:ver1-Cursor/lCursor
  187. let &guicursor = s:saved_cursor
  188. endif
  189. elseif s:is_vim
  190. let &t_ve = s:saved_ve
  191. endif
  192. endif
  193. echo ""
  194. endfunction
  195. function! s:current_session() abort
  196. if empty(s:session_names)
  197. return v:null
  198. endif
  199. return s:session_names[len(s:session_names) - 1]
  200. endfunction
  201. function! s:filter(list, id) abort
  202. return filter(copy(a:list), 'v:val !=# a:id')
  203. endfunction