cmdline_spec.lua 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225
  1. local helpers = require('test.functional.helpers')(after_each)
  2. local Screen = require('test.functional.ui.screen')
  3. local clear = helpers.clear
  4. local command = helpers.command
  5. local eq = helpers.eq
  6. local expect = helpers.expect
  7. local eval = helpers.eval
  8. local next_msg = helpers.next_msg
  9. local feed = helpers.feed
  10. local meths = helpers.meths
  11. describe('cmdline autocommands', function()
  12. local channel
  13. before_each(function()
  14. clear()
  15. channel = meths.get_api_info()[1]
  16. meths.set_var("channel",channel)
  17. command("autocmd CmdlineEnter * call rpcnotify(g:channel, 'CmdlineEnter', v:event)")
  18. command("autocmd CmdlineLeave * call rpcnotify(g:channel, 'CmdlineLeave', v:event)")
  19. command("autocmd CmdWinEnter * call rpcnotify(g:channel, 'CmdWinEnter', v:event)")
  20. command("autocmd CmdWinLeave * call rpcnotify(g:channel, 'CmdWinLeave', v:event)")
  21. end)
  22. it('works', function()
  23. feed(':')
  24. eq({'notification', 'CmdlineEnter', {{cmdtype=':', cmdlevel=1}}}, next_msg())
  25. feed('redraw<cr>')
  26. eq({'notification', 'CmdlineLeave',
  27. {{cmdtype=':', cmdlevel=1, abort=false}}}, next_msg())
  28. feed(':')
  29. eq({'notification', 'CmdlineEnter', {{cmdtype=':', cmdlevel=1}}}, next_msg())
  30. -- note: feed('bork<c-c>') might not consume 'bork'
  31. -- due to out-of-band interupt handling
  32. feed('bork<esc>')
  33. eq({'notification', 'CmdlineLeave',
  34. {{cmdtype=':', cmdlevel=1, abort=true}}}, next_msg())
  35. end)
  36. it('can abort cmdline', function()
  37. command("autocmd CmdlineLeave * let v:event.abort= len(getcmdline())>15")
  38. feed(":put! ='ok'<cr>")
  39. expect([[
  40. ok
  41. ]])
  42. feed(":put! ='blah blah'<cr>")
  43. expect([[
  44. ok
  45. ]])
  46. end)
  47. it('handles errors correctly', function()
  48. clear()
  49. local screen = Screen.new(72, 8)
  50. screen:attach()
  51. screen:set_default_attr_ids({
  52. [1] = {bold = true, foreground = Screen.colors.Blue1},
  53. [2] = {foreground = Screen.colors.Grey100, background = Screen.colors.Red},
  54. [3] = {bold = true, foreground = Screen.colors.SeaGreen4},
  55. [4] = {bold = true, reverse = true},
  56. })
  57. command("autocmd CmdlineEnter * echoerr 'FAIL'")
  58. command("autocmd CmdlineLeave * echoerr 'very error'")
  59. feed(':')
  60. screen:expect([[
  61. |
  62. {1:~ }|
  63. {1:~ }|
  64. {1:~ }|
  65. {4: }|
  66. : |
  67. {2:E5500: autocmd has thrown an exception: Vim(echoerr):FAIL} |
  68. :^ |
  69. ]])
  70. feed("put ='lorem ipsum'<cr>")
  71. screen:expect([[
  72. |
  73. {4: }|
  74. : |
  75. {2:E5500: autocmd has thrown an exception: Vim(echoerr):FAIL} |
  76. :put ='lorem ipsum' |
  77. {2:E5500: autocmd has thrown an exception: Vim(echoerr):very error} |
  78. |
  79. {3:Press ENTER or type command to continue}^ |
  80. ]])
  81. -- cmdline was still executed
  82. feed('<cr>')
  83. screen:expect([[
  84. |
  85. ^lorem ipsum |
  86. {1:~ }|
  87. {1:~ }|
  88. {1:~ }|
  89. {1:~ }|
  90. {1:~ }|
  91. |
  92. ]])
  93. command("autocmd CmdlineChanged * echoerr 'change erreor'")
  94. -- history recall still works
  95. feed(":<c-p>")
  96. screen:expect([[
  97. |
  98. lorem ipsum |
  99. {4: }|
  100. : |
  101. {2:E5500: autocmd has thrown an exception: Vim(echoerr):FAIL} |
  102. :put ='lorem ipsum' |
  103. {2:E5500: autocmd has thrown an exception: Vim(echoerr):change erreor} |
  104. :put ='lorem ipsum'^ |
  105. ]])
  106. feed("<left>")
  107. screen:expect([[
  108. |
  109. lorem ipsum |
  110. {4: }|
  111. : |
  112. {2:E5500: autocmd has thrown an exception: Vim(echoerr):FAIL} |
  113. :put ='lorem ipsum' |
  114. {2:E5500: autocmd has thrown an exception: Vim(echoerr):change erreor} |
  115. :put ='lorem ipsum^' |
  116. ]])
  117. -- edit still works
  118. feed(".")
  119. screen:expect([[
  120. {4: }|
  121. : |
  122. {2:E5500: autocmd has thrown an exception: Vim(echoerr):FAIL} |
  123. :put ='lorem ipsum' |
  124. {2:E5500: autocmd has thrown an exception: Vim(echoerr):change erreor} |
  125. :put ='lorem ipsum.' |
  126. {2:E5500: autocmd has thrown an exception: Vim(echoerr):change erreor} |
  127. :put ='lorem ipsum.^' |
  128. ]])
  129. feed('<cr>')
  130. screen:expect([[
  131. :put ='lorem ipsum' |
  132. {2:E5500: autocmd has thrown an exception: Vim(echoerr):change erreor} |
  133. :put ='lorem ipsum.' |
  134. {2:E5500: autocmd has thrown an exception: Vim(echoerr):change erreor} |
  135. :put ='lorem ipsum.' |
  136. {2:E5500: autocmd has thrown an exception: Vim(echoerr):very error} |
  137. |
  138. {3:Press ENTER or type command to continue}^ |
  139. ]])
  140. -- cmdline was still executed
  141. feed('<cr>')
  142. screen:expect([[
  143. |
  144. lorem ipsum |
  145. ^lorem ipsum. |
  146. {1:~ }|
  147. {1:~ }|
  148. {1:~ }|
  149. {1:~ }|
  150. |
  151. ]])
  152. end)
  153. it('works with nested cmdline', function()
  154. feed(':')
  155. eq({'notification', 'CmdlineEnter', {{cmdtype=':', cmdlevel=1}}}, next_msg())
  156. feed('<c-r>=')
  157. eq({'notification', 'CmdlineEnter', {{cmdtype='=', cmdlevel=2}}}, next_msg())
  158. feed('<c-f>')
  159. eq({'notification', 'CmdWinEnter', {{}}}, next_msg())
  160. feed(':')
  161. eq({'notification', 'CmdlineEnter', {{cmdtype=':', cmdlevel=3}}}, next_msg())
  162. feed('<c-c>')
  163. eq({'notification', 'CmdlineLeave', {{cmdtype=':', cmdlevel=3, abort=true}}}, next_msg())
  164. feed('<c-c>')
  165. eq({'notification', 'CmdWinLeave', {{}}}, next_msg())
  166. feed('1+2<cr>')
  167. eq({'notification', 'CmdlineLeave', {{cmdtype='=', cmdlevel=2, abort=false}}}, next_msg())
  168. end)
  169. it('supports CmdlineChanged' ,function()
  170. command("autocmd CmdlineChanged * call rpcnotify(g:channel, 'CmdlineChanged', v:event, getcmdline())")
  171. feed(':')
  172. eq({'notification', 'CmdlineEnter', {{cmdtype=':', cmdlevel=1}}}, next_msg())
  173. feed('l')
  174. eq({'notification', 'CmdlineChanged', {{cmdtype=':', cmdlevel=1}, "l"}}, next_msg())
  175. feed('e')
  176. eq({'notification', 'CmdlineChanged', {{cmdtype=':', cmdlevel=1}, "le"}}, next_msg())
  177. feed('t')
  178. eq({'notification', 'CmdlineChanged', {{cmdtype=':', cmdlevel=1}, "let"}}, next_msg())
  179. feed('<space>')
  180. eq({'notification', 'CmdlineChanged', {{cmdtype=':', cmdlevel=1}, "let "}}, next_msg())
  181. feed('x')
  182. eq({'notification', 'CmdlineChanged', {{cmdtype=':', cmdlevel=1}, "let x"}}, next_msg())
  183. feed('<space>')
  184. eq({'notification', 'CmdlineChanged', {{cmdtype=':', cmdlevel=1}, "let x "}}, next_msg())
  185. feed('=')
  186. eq({'notification', 'CmdlineChanged', {{cmdtype=':', cmdlevel=1}, "let x ="}}, next_msg())
  187. feed('<space>')
  188. eq({'notification', 'CmdlineChanged', {{cmdtype=':', cmdlevel=1}, "let x = "}}, next_msg())
  189. feed('<c-r>=')
  190. eq({'notification', 'CmdlineEnter', {{cmdtype='=', cmdlevel=2}}}, next_msg())
  191. feed('1')
  192. eq({'notification', 'CmdlineChanged', {{cmdtype='=', cmdlevel=2}, "1"}}, next_msg())
  193. feed('+')
  194. eq({'notification', 'CmdlineChanged', {{cmdtype='=', cmdlevel=2}, "1+"}}, next_msg())
  195. feed('1')
  196. eq({'notification', 'CmdlineChanged', {{cmdtype='=', cmdlevel=2}, "1+1"}}, next_msg())
  197. feed('<cr>')
  198. eq({'notification', 'CmdlineLeave', {{cmdtype='=', cmdlevel=2, abort=false}}}, next_msg())
  199. eq({'notification', 'CmdlineChanged', {{cmdtype=':', cmdlevel=1}, "let x = "}}, next_msg())
  200. eq({'notification', 'CmdlineChanged', {{cmdtype=':', cmdlevel=1}, "let x = 2"}}, next_msg())
  201. feed('<cr>')
  202. eq({'notification', 'CmdlineLeave', {{cmdtype=':', cmdlevel=1, abort=false}}}, next_msg())
  203. eq(2, eval('x'))
  204. end)
  205. end)