ex_mode_spec.lua 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176
  1. local t = require('test.testutil')
  2. local n = require('test.functional.testnvim')()
  3. local Screen = require('test.functional.ui.screen')
  4. local clear = n.clear
  5. local command = n.command
  6. local eq = t.eq
  7. local eval = n.eval
  8. local feed = n.feed
  9. local api = n.api
  10. local poke_eventloop = n.poke_eventloop
  11. before_each(clear)
  12. describe('Ex mode', function()
  13. it('supports command line editing', function()
  14. local function test_ex_edit(expected, cmd)
  15. feed('gQ' .. cmd .. '<C-b>"<CR>')
  16. local ret = eval('@:[1:]') -- Remove leading quote.
  17. feed('visual<CR>')
  18. eq(api.nvim_replace_termcodes(expected, true, true, true), ret)
  19. end
  20. command('set sw=2')
  21. test_ex_edit('bar', 'foo bar<C-u>bar')
  22. test_ex_edit('1<C-u>2', '1<C-v><C-u>2')
  23. test_ex_edit('213', '1<C-b>2<C-e>3')
  24. test_ex_edit('2013', '01<Home>2<End>3')
  25. test_ex_edit('0213', '01<Left>2<Right>3')
  26. test_ex_edit('0342', '012<Left><Left><Insert>3<Insert>4')
  27. test_ex_edit('foo ', 'foo bar<C-w>')
  28. test_ex_edit('foo', 'fooba<Del><Del>')
  29. test_ex_edit('foobar', 'foo<Tab>bar')
  30. test_ex_edit('abbreviate', 'abbrev<Tab>')
  31. test_ex_edit('1<C-t><C-t>', '1<C-t><C-t>')
  32. test_ex_edit('1<C-t><C-t>', '1<C-t><C-t><C-d>')
  33. test_ex_edit(' foo', ' foo<C-d>')
  34. test_ex_edit(' foo0', ' foo0<C-d>')
  35. test_ex_edit(' foo^', ' foo^<C-d>')
  36. test_ex_edit('foo', '<BS><C-H><Del><kDel>foo')
  37. -- default wildchar <Tab> interferes with this test
  38. command('set wildchar=<c-e>')
  39. test_ex_edit('a\tb', 'a\t\t<C-H>b')
  40. test_ex_edit('\tm<C-T>n', '\tm<C-T>n')
  41. command('set wildchar&')
  42. end)
  43. it('substitute confirmation prompt', function()
  44. command('set noincsearch nohlsearch inccommand=')
  45. local screen = Screen.new(60, 6)
  46. command([[call setline(1, repeat(['foo foo'], 4))]])
  47. command([[set number]])
  48. feed('gQ')
  49. screen:expect([[
  50. {8: 1 }foo foo |
  51. {8: 2 }foo foo |
  52. {8: 3 }foo foo |
  53. {3: }|
  54. Entering Ex mode. Type "visual" to go to Normal mode. |
  55. :^ |
  56. ]])
  57. feed('%s/foo/bar/gc<CR>')
  58. screen:expect([[
  59. {8: 1 }foo foo |
  60. {3: }|
  61. Entering Ex mode. Type "visual" to go to Normal mode. |
  62. :%s/foo/bar/gc |
  63. {8: 1 }foo foo |
  64. ^^^^ |
  65. ]])
  66. feed('N<CR>')
  67. screen:expect([[
  68. Entering Ex mode. Type "visual" to go to Normal mode. |
  69. :%s/foo/bar/gc |
  70. {8: 1 }foo foo |
  71. ^^^N |
  72. {8: 1 }foo foo |
  73. ^^^^ |
  74. ]])
  75. feed('n<CR>')
  76. screen:expect([[
  77. {8: 1 }foo foo |
  78. ^^^N |
  79. {8: 1 }foo foo |
  80. ^^^n |
  81. {8: 1 }foo foo |
  82. ^^^^ |
  83. ]])
  84. feed('y<CR>')
  85. feed('q<CR>')
  86. screen:expect([[
  87. {8: 1 }foo foo |
  88. ^^^y |
  89. {8: 2 }foo foo |
  90. ^^^q |
  91. {8: 2 }foo foo |
  92. :^ |
  93. ]])
  94. -- Pressing enter in ex mode should print the current line
  95. feed('<CR>')
  96. screen:expect([[
  97. ^^^y |
  98. {8: 2 }foo foo |
  99. ^^^q |
  100. {8: 2 }foo foo |
  101. {8: 3 }foo foo |
  102. :^ |
  103. ]])
  104. -- The printed line should overwrite the colon
  105. feed('<CR>')
  106. screen:expect([[
  107. {8: 2 }foo foo |
  108. ^^^q |
  109. {8: 2 }foo foo |
  110. {8: 3 }foo foo |
  111. {8: 4 }foo foo |
  112. :^ |
  113. ]])
  114. feed(':vi<CR>')
  115. screen:expect([[
  116. {8: 1 }foo bar |
  117. {8: 2 }foo foo |
  118. {8: 3 }foo foo |
  119. {8: 4 }^foo foo |
  120. {1:~ }|
  121. |
  122. ]])
  123. end)
  124. it('pressing Ctrl-C in :append inside a loop in Ex mode does not hang', function()
  125. local screen = Screen.new(60, 6)
  126. feed('gQ')
  127. feed('for i in range(1)<CR>')
  128. feed('append<CR>')
  129. screen:expect([[
  130. {3: }|
  131. Entering Ex mode. Type "visual" to go to Normal mode. |
  132. :for i in range(1) |
  133. |
  134. : append |
  135. ^ |
  136. ]])
  137. feed('<C-C>')
  138. poke_eventloop() -- Wait for input to be flushed
  139. feed('foo<CR>')
  140. screen:expect([[
  141. Entering Ex mode. Type "visual" to go to Normal mode. |
  142. :for i in range(1) |
  143. |
  144. : append |
  145. foo |
  146. ^ |
  147. ]])
  148. feed('.<CR>')
  149. screen:expect([[
  150. :for i in range(1) |
  151. |
  152. : append |
  153. foo |
  154. . |
  155. : ^ |
  156. ]])
  157. feed('endfor<CR>')
  158. feed('vi<CR>')
  159. screen:expect([[
  160. ^foo |
  161. {1:~ }|*4
  162. |
  163. ]])
  164. end)
  165. end)