undo_spec.lua 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223
  1. local t = require('test.testutil')
  2. local n = require('test.functional.testnvim')()
  3. local clear = n.clear
  4. local command = n.command
  5. local eval = n.eval
  6. local expect = n.expect
  7. local eq = t.eq
  8. local feed = n.feed
  9. local feed_command = n.feed_command
  10. local insert = n.insert
  11. local fn = n.fn
  12. local exec = n.exec
  13. local exec_lua = n.exec_lua
  14. local function lastmessage()
  15. local messages = fn.split(fn.execute('messages'), '\n')
  16. return messages[#messages]
  17. end
  18. describe('u CTRL-R g- g+', function()
  19. before_each(clear)
  20. local function create_history(num_steps)
  21. if num_steps == 0 then
  22. return
  23. end
  24. insert('1')
  25. if num_steps == 1 then
  26. return
  27. end
  28. feed('o2<esc>')
  29. feed('o3<esc>')
  30. feed('u')
  31. if num_steps == 2 then
  32. return
  33. end
  34. feed('o4<esc>')
  35. if num_steps == 3 then
  36. return
  37. end
  38. feed('u')
  39. end
  40. local function undo_and_redo(hist_pos, undo, redo, expect_str)
  41. command('enew!')
  42. create_history(hist_pos)
  43. local cur_contents = n.curbuf_contents()
  44. feed(undo)
  45. expect(expect_str)
  46. feed(redo)
  47. expect(cur_contents)
  48. end
  49. -- TODO Look for message saying 'Already at oldest change'
  50. it('does nothing when no changes have happened', function()
  51. undo_and_redo(0, 'u', '<C-r>', '')
  52. undo_and_redo(0, 'g-', 'g+', '')
  53. end)
  54. it('undoes a change when at a leaf', function()
  55. undo_and_redo(1, 'u', '<C-r>', '')
  56. undo_and_redo(1, 'g-', 'g+', '')
  57. end)
  58. it('undoes a change when in a non-leaf', function()
  59. undo_and_redo(2, 'u', '<C-r>', '1')
  60. undo_and_redo(2, 'g-', 'g+', '1')
  61. end)
  62. it('undoes properly around a branch point', function()
  63. undo_and_redo(
  64. 3,
  65. 'u',
  66. '<C-r>',
  67. [[
  68. 1
  69. 2]]
  70. )
  71. undo_and_redo(
  72. 3,
  73. 'g-',
  74. 'g+',
  75. [[
  76. 1
  77. 2
  78. 3]]
  79. )
  80. end)
  81. it('can find the previous sequence after undoing to a branch', function()
  82. undo_and_redo(4, 'u', '<C-r>', '1')
  83. undo_and_redo(4, 'g-', 'g+', '1')
  84. end)
  85. describe('undo works correctly when writing in Insert mode', function()
  86. before_each(function()
  87. exec([[
  88. edit Xtestfile.txt
  89. set undolevels=100 undofile
  90. write
  91. ]])
  92. end)
  93. after_each(function()
  94. command('bwipe!')
  95. os.remove('Xtestfile.txt')
  96. os.remove('Xtestfile.txt.un~')
  97. end)
  98. -- oldtest: Test_undo_after_write()
  99. it('using <Cmd> mapping', function()
  100. command('imap . <Cmd>write<CR>')
  101. feed('Otest.<CR>boo!!!<Esc>')
  102. expect([[
  103. test
  104. boo!!!
  105. ]])
  106. feed('u')
  107. expect([[
  108. test
  109. ]])
  110. feed('u')
  111. expect('')
  112. end)
  113. it('using Lua mapping', function()
  114. exec_lua([[
  115. vim.api.nvim_set_keymap('i', '.', '', {callback = function()
  116. vim.cmd('write')
  117. end})
  118. ]])
  119. feed('Otest.<CR>boo!!!<Esc>')
  120. expect([[
  121. test
  122. boo!!!
  123. ]])
  124. feed('u')
  125. expect([[
  126. test
  127. ]])
  128. feed('u')
  129. expect('')
  130. end)
  131. it('using RPC call', function()
  132. feed('Otest')
  133. command('write')
  134. feed('<CR>boo!!!<Esc>')
  135. expect([[
  136. test
  137. boo!!!
  138. ]])
  139. feed('u')
  140. expect([[
  141. test
  142. ]])
  143. feed('u')
  144. expect('')
  145. end)
  146. end)
  147. end)
  148. describe(':undo! command', function()
  149. before_each(function()
  150. clear()
  151. feed('i1 little bug in the code<Esc>')
  152. feed('o1 little bug in the code<Esc>')
  153. feed('oTake 1 down, patch it around<Esc>')
  154. feed('o99 little bugs in the code<Esc>')
  155. end)
  156. it('works', function()
  157. feed_command('undo!')
  158. expect([[
  159. 1 little bug in the code
  160. 1 little bug in the code
  161. Take 1 down, patch it around]])
  162. feed('<C-r>')
  163. eq('Already at newest change', lastmessage())
  164. end)
  165. it('works with arguments', function()
  166. feed_command('undo! 2')
  167. expect([[
  168. 1 little bug in the code
  169. 1 little bug in the code]])
  170. feed('<C-r>')
  171. eq('Already at newest change', lastmessage())
  172. end)
  173. it('correctly sets alternative redo', function()
  174. feed('uo101 little bugs in the code<Esc>')
  175. feed_command('undo!')
  176. feed('<C-r>')
  177. expect([[
  178. 1 little bug in the code
  179. 1 little bug in the code
  180. Take 1 down, patch it around
  181. 99 little bugs in the code]])
  182. feed('uuoTake 2 down, patch them around<Esc>')
  183. feed('o101 little bugs in the code<Esc>')
  184. feed_command('undo! 2')
  185. feed('<C-r><C-r>')
  186. expect([[
  187. 1 little bug in the code
  188. 1 little bug in the code
  189. Take 1 down, patch it around
  190. 99 little bugs in the code]])
  191. end)
  192. it('fails when attempting to redo or move to different undo branch', function()
  193. feed_command('undo! 4')
  194. eq('E5767: Cannot use :undo! to redo or move to a different undo branch', eval('v:errmsg'))
  195. feed('u')
  196. feed_command('undo! 4')
  197. eq('E5767: Cannot use :undo! to redo or move to a different undo branch', eval('v:errmsg'))
  198. feed('o101 little bugs in the code<Esc>')
  199. feed('o101 little bugs in the code<Esc>')
  200. feed_command('undo! 4')
  201. eq('E5767: Cannot use :undo! to redo or move to a different undo branch', eval('v:errmsg'))
  202. end)
  203. end)