mirror of
				https://github.com/neovim/neovim.git
				synced 2025-10-26 12:27:24 +00:00 
			
		
		
		
	 263849b2dd
			
		
	
	263849b2dd
	
	
	
		
			
			Closes #6540 In #6221 there was a mistake in calculating which folds need to be re-ordered. When there are no folds after those that have been adjusted, then `move_end` remains 0. This results in reverse_fold_order() swapping folds that have been adjusted with uninitialised folds in the remainder of the grow array. Add a check in foldMoveRange() to account for this case.
		
			
				
	
	
		
			363 lines
		
	
	
		
			6.4 KiB
		
	
	
	
		
			Lua
		
	
	
	
	
	
			
		
		
	
	
			363 lines
		
	
	
		
			6.4 KiB
		
	
	
	
		
			Lua
		
	
	
	
	
	
| local helpers = require('test.functional.helpers')(after_each)
 | |
| 
 | |
| local clear = helpers.clear
 | |
| local insert = helpers.insert
 | |
| local feed = helpers.feed
 | |
| local expect = helpers.expect
 | |
| local feed_command = helpers.feed_command
 | |
| local funcs = helpers.funcs
 | |
| local foldlevel = funcs.foldlevel
 | |
| local foldclosedend = funcs.foldclosedend
 | |
| local eq = helpers.eq
 | |
| 
 | |
| describe('Folds', function()
 | |
|   local tempfname = 'Xtest-fold.txt'
 | |
|   clear()
 | |
|   before_each(function() feed_command('enew!') end)
 | |
|   after_each(function() os.remove(tempfname) end)
 | |
|   it('manual folding adjusts with filter', function()
 | |
|     insert([[
 | |
|     1
 | |
|     2
 | |
|     3
 | |
|     4
 | |
|     5
 | |
|     6
 | |
|     7
 | |
|     8
 | |
|     9
 | |
|     10
 | |
|     11
 | |
|     12
 | |
|     13
 | |
|     14
 | |
|     15
 | |
|     16
 | |
|     17
 | |
|     18
 | |
|     19
 | |
|     20]])
 | |
|     feed_command('4,$fold', '%foldopen', '10,$fold', '%foldopen')
 | |
|     feed_command('1,8! cat')
 | |
|     feed('5ggzdzMGdd')
 | |
|     expect([[
 | |
|     1
 | |
|     2
 | |
|     3
 | |
|     4
 | |
|     5
 | |
|     6
 | |
|     7
 | |
|     8
 | |
|     9]])
 | |
|   end)
 | |
|   describe('adjusting folds after :move', function()
 | |
|     local function manually_fold_indent()
 | |
|       -- setting foldmethod twice is a trick to get vim to set the folds for me
 | |
|       feed_command('set foldmethod=indent', 'set foldmethod=manual')
 | |
|       -- Ensure that all folds will get closed (makes it easier to test the
 | |
|       -- length of folds).
 | |
|       feed_command('set foldminlines=0')
 | |
|       -- Start with all folds open (so :move ranges aren't affected by closed
 | |
|       -- folds).
 | |
|       feed_command('%foldopen!')
 | |
|     end
 | |
| 
 | |
|     local function get_folds()
 | |
|       local rettab = {}
 | |
|       for i = 1, funcs.line('$') do
 | |
|         table.insert(rettab, foldlevel(i))
 | |
|       end
 | |
|       return rettab
 | |
|     end
 | |
| 
 | |
|     local function test_move_indent(insert_string, move_command)
 | |
|       -- This test is easy because we just need to ensure that the resulting
 | |
|       -- fold is the same as calculated when creating folds from scratch.
 | |
|       insert(insert_string)
 | |
|       feed_command(move_command)
 | |
|       local after_move_folds = get_folds()
 | |
|       -- Doesn't change anything, but does call foldUpdateAll()
 | |
|       feed_command('set foldminlines=0')
 | |
|       eq(after_move_folds, get_folds())
 | |
|       -- Set up the buffer with insert_string for the manual fold testing.
 | |
|       feed_command('enew!')
 | |
|       insert(insert_string)
 | |
|       manually_fold_indent()
 | |
|       feed_command(move_command)
 | |
|     end
 | |
| 
 | |
|     it('neither closes nor corrupts folds', function()
 | |
|       test_move_indent([[
 | |
| a
 | |
| 	a
 | |
| 	a
 | |
| 	a
 | |
| 	a
 | |
| 	a
 | |
| a
 | |
| 	a
 | |
| 	a
 | |
| 		a
 | |
| 	a
 | |
| 	a
 | |
| a
 | |
| 	a
 | |
| 	a
 | |
| 	a
 | |
| 	a
 | |
| 	a]], '7,12m0')
 | |
|       expect([[
 | |
| a
 | |
| 	a
 | |
| 	a
 | |
| 		a
 | |
| 	a
 | |
| 	a
 | |
| a
 | |
| 	a
 | |
| 	a
 | |
| 	a
 | |
| 	a
 | |
| 	a
 | |
| a
 | |
| 	a
 | |
| 	a
 | |
| 	a
 | |
| 	a
 | |
| 	a]])
 | |
|       -- lines are not closed, folds are correct
 | |
|       for i = 1,funcs.line('$') do
 | |
|         eq(-1, funcs.foldclosed(i))
 | |
|         if i == 1 or i == 7 or i == 13 then
 | |
|           eq(0, foldlevel(i))
 | |
|         elseif i == 4 then
 | |
|           eq(2, foldlevel(i))
 | |
|         else
 | |
|           eq(1, foldlevel(i))
 | |
|         end
 | |
|       end
 | |
|       -- folds are not corrupted
 | |
|       feed('zM')
 | |
|       eq(6, foldclosedend(2))
 | |
|       eq(12, foldclosedend(8))
 | |
|       eq(18, foldclosedend(14))
 | |
|     end)
 | |
|     it("doesn't split a fold when the move is within it", function()
 | |
|       test_move_indent([[
 | |
| a
 | |
| 	a
 | |
| 	a
 | |
| 		a
 | |
| 		a
 | |
| 		a
 | |
| 		a
 | |
| 	a
 | |
| 	a
 | |
| a]], '5m6')
 | |
|       eq({0, 1, 1, 2, 2, 2, 2, 1, 1, 0}, get_folds())
 | |
|     end)
 | |
|     it('truncates folds that end in the moved range', function()
 | |
|       test_move_indent([[
 | |
| a
 | |
| 	a
 | |
| 		a
 | |
| 		a
 | |
| 		a
 | |
| a
 | |
| a]], '4,5m6')
 | |
|       eq({0, 1, 2, 0, 0, 0, 0}, get_folds())
 | |
|     end)
 | |
|     it('moves folds that start between moved range and destination', function()
 | |
|       test_move_indent([[
 | |
| a
 | |
| 	a
 | |
| 	a
 | |
| 	a
 | |
| 	a
 | |
| a
 | |
| a
 | |
| 	a
 | |
| 		a
 | |
| 	a
 | |
| a
 | |
| a
 | |
| 	a]], '3,4m$')
 | |
|       eq({0, 1, 1, 0, 0, 1, 2, 1, 0, 0, 1, 0, 0}, get_folds())
 | |
|     end)
 | |
|     it('does not affect folds outside changed lines', function()
 | |
|       test_move_indent([[
 | |
| 	a
 | |
| 	a
 | |
| 	a
 | |
| a
 | |
| a
 | |
| a
 | |
| 	a
 | |
| 	a
 | |
| 	a]], '4m5')
 | |
|       eq({1, 1, 1, 0, 0, 0, 1, 1, 1}, get_folds())
 | |
|     end)
 | |
|     it('moves and truncates folds that start in moved range', function()
 | |
|       test_move_indent([[
 | |
| a
 | |
| 	a
 | |
| 		a
 | |
| 		a
 | |
| 		a
 | |
| a
 | |
| a
 | |
| a
 | |
| a
 | |
| a]], '1,3m7')
 | |
|       eq({0, 0, 0, 0, 0, 1, 2, 0, 0, 0}, get_folds())
 | |
|     end)
 | |
|     it('breaks a fold when moving text into it', function()
 | |
|       test_move_indent([[
 | |
| a
 | |
| 	a
 | |
| 		a
 | |
| 		a
 | |
| 		a
 | |
| a
 | |
| a]], '$m4')
 | |
|       eq({0, 1, 2, 2, 0, 0, 0}, get_folds())
 | |
|     end)
 | |
|     it('adjusts correctly when moving a range backwards', function()
 | |
|       test_move_indent([[
 | |
| a
 | |
| 	a
 | |
| 		a
 | |
| 		a
 | |
| a]], '2,3m0')
 | |
|       eq({1, 2, 0, 0, 0}, get_folds())
 | |
|     end)
 | |
|     it('handles shifting all remaining folds', function()
 | |
|       test_move_indent([[
 | |
| 	a
 | |
| 		a
 | |
| 		a
 | |
| 		a
 | |
| 	a
 | |
| 		a
 | |
| 		a
 | |
| 		a
 | |
| 	a
 | |
| 		a
 | |
| 		a
 | |
| 		a
 | |
| 		a
 | |
| 	a
 | |
| a]], '13m7')
 | |
|       eq({1, 2, 2, 2, 1, 2, 2, 1, 1, 1, 2, 2, 2, 1, 0}, get_folds())
 | |
|     end)
 | |
|   end)
 | |
|   it('updates correctly on :read', function()
 | |
|     -- luacheck: ignore 621
 | |
|     helpers.write_file(tempfname, [[
 | |
|     a
 | |
| 
 | |
| 
 | |
|     	a]])
 | |
|     insert([[
 | |
|     	a
 | |
|     	a
 | |
|     	a
 | |
|     	a
 | |
|     ]])
 | |
|     feed_command('set foldmethod=indent', '2', '%foldopen')
 | |
|     feed_command('read ' .. tempfname)
 | |
|     -- Just to check we have the correct file text.
 | |
|     expect([[
 | |
|     	a
 | |
|     	a
 | |
|     a
 | |
| 
 | |
| 
 | |
|     	a
 | |
|     	a
 | |
|     	a
 | |
|     ]])
 | |
|     for i = 1,2 do
 | |
|       eq(1, funcs.foldlevel(i))
 | |
|     end
 | |
|     for i = 3,5 do
 | |
|       eq(0, funcs.foldlevel(i))
 | |
|     end
 | |
|     for i = 6,8 do
 | |
|       eq(1, funcs.foldlevel(i))
 | |
|     end
 | |
|   end)
 | |
|   it('combines folds when removing separating space', function()
 | |
|     -- luacheck: ignore 621
 | |
|     insert([[
 | |
|     	a
 | |
|     	a
 | |
|     a
 | |
|     a
 | |
|     a
 | |
|     	a
 | |
|     	a
 | |
|     	a
 | |
|     ]])
 | |
|     feed_command('set foldmethod=indent', '3,5d')
 | |
|     eq(5, funcs.foldclosedend(1))
 | |
|   end)
 | |
|   it("doesn't combine folds that have a specified end", function()
 | |
|     insert([[
 | |
|     {{{
 | |
|     }}}
 | |
| 
 | |
| 
 | |
| 
 | |
|     {{{
 | |
| 
 | |
|     }}}
 | |
|     ]])
 | |
|     feed_command('set foldmethod=marker', '3,5d', '%foldclose')
 | |
|     eq(2, funcs.foldclosedend(1))
 | |
|   end)
 | |
|   it('splits folds according to >N and <N with foldexpr', function()
 | |
|     helpers.source([[
 | |
|     function TestFoldExpr(lnum)
 | |
|       let thisline = getline(a:lnum)
 | |
|       if thisline == 'a'
 | |
|         return 1
 | |
|       elseif thisline == 'b'
 | |
|         return 0
 | |
|       elseif thisline == 'c'
 | |
|         return '<1'
 | |
|       elseif thisline == 'd'
 | |
|         return '>1'
 | |
|       endif
 | |
|       return 0
 | |
|     endfunction
 | |
|     ]])
 | |
|     helpers.write_file(tempfname, [[
 | |
|     b
 | |
|     b
 | |
|     a
 | |
|     a
 | |
|     d
 | |
|     a
 | |
|     a
 | |
|     c]])
 | |
|     insert([[
 | |
|     a
 | |
|     a
 | |
|     a
 | |
|     a
 | |
|     a
 | |
|     a
 | |
|     ]])
 | |
|     feed_command('set foldmethod=expr', 'set foldexpr=TestFoldExpr(v:lnum)', '2', 'foldopen')
 | |
|     feed_command('read ' .. tempfname, '%foldclose')
 | |
|     eq(2, funcs.foldclosedend(1))
 | |
|     eq(0, funcs.foldlevel(3))
 | |
|     eq(0, funcs.foldlevel(4))
 | |
|     eq(6, funcs.foldclosedend(5))
 | |
|     eq(10, funcs.foldclosedend(7))
 | |
|     eq(14, funcs.foldclosedend(11))
 | |
|   end)
 | |
| end)
 |