patch 8.0.0457: using :move messes up manual folds

Problem:    Using :move messes up manual folds.
Solution:   Split adjusting marks and folds.  Add foldMoveRange(). (neovim
            patch #6221)
diff --git a/src/testdir/test_fold.vim b/src/testdir/test_fold.vim
index f10480b..19c9414 100644
--- a/src/testdir/test_fold.vim
+++ b/src/testdir/test_fold.vim
@@ -1,5 +1,9 @@
 " Test for folding
 
+func! PrepIndent(arg)
+  return [a:arg] + repeat(["\t".a:arg], 5)
+endfu
+
 func! Test_address_fold()
   new
   call setline(1, ['int FuncName() {/*{{{*/', 1, 2, 3, 4, 5, '}/*}}}*/',
@@ -219,3 +223,121 @@
   bwipe!
   set foldmethod& foldexpr&
 endfunc
+
+func! Test_move_folds_around_manual()
+  new
+  let input = PrepIndent("a") + PrepIndent("b") + PrepIndent("c")
+  call setline(1, PrepIndent("a") + PrepIndent("b") + PrepIndent("c"))
+  let folds=[-1, 2, 2, 2, 2, 2, -1, 8, 8, 8, 8, 8, -1, 14, 14, 14, 14, 14]
+  " all folds closed
+  set foldenable foldlevel=0 fdm=indent
+  " needs a forced redraw
+  redraw!
+  set fdm=manual
+  call assert_equal(folds, map(range(1, line('$')), 'foldclosed(v:val)'))
+  call assert_equal(input, getline(1, '$'))
+  7,12m0
+  call assert_equal(PrepIndent("b") + PrepIndent("a") + PrepIndent("c"), getline(1, '$'))
+  call assert_equal(folds, map(range(1, line('$')), 'foldclosed(v:val)'))
+  10,12m0
+  call assert_equal(PrepIndent("a")[1:] + PrepIndent("b") + ["a"] +  PrepIndent("c"), getline(1, '$'))
+  call assert_equal([1, 1, 1, 1, 1, -1, 7, 7, 7, 7, 7, -1, -1, 14, 14, 14, 14, 14], map(range(1, line('$')), 'foldclosed(v:val)'))
+  " moving should not close the folds
+  %d
+  call setline(1, PrepIndent("a") + PrepIndent("b") + PrepIndent("c"))
+  set fdm=indent
+  redraw!
+  set fdm=manual
+  call cursor(2, 1)
+  norm! zR
+  7,12m0
+  let folds=repeat([-1], 18)
+  call assert_equal(PrepIndent("b") + PrepIndent("a") + PrepIndent("c"), getline(1, '$'))
+  call assert_equal(folds, map(range(1, line('$')), 'foldclosed(v:val)'))
+  norm! zM
+  " folds are not corrupted and all have been closed
+  call assert_equal([-1, 2, 2, 2, 2, 2, -1, 8, 8, 8, 8, 8, -1, 14, 14, 14, 14, 14], map(range(1, line('$')), 'foldclosed(v:val)'))
+  %d
+  call setline(1, ["a", "\tb", "\tc", "\td", "\te"])
+  set fdm=indent
+  redraw!
+  set fdm=manual
+  %foldopen
+  3m4
+  %foldclose
+  call assert_equal(["a", "\tb", "\td", "\tc", "\te"], getline(1, '$'))
+  call assert_equal([-1, 5, 5, 5, 5], map(range(1, line('$')), 'foldclosedend(v:val)'))
+  %d
+  call setline(1, ["a", "\tb", "\tc", "\td", "\te", "z", "\ty", "\tx", "\tw", "\tv"])
+  set fdm=indent foldlevel=0
+  set fdm=manual
+  %foldopen
+  3m1
+  %foldclose
+  call assert_equal(["a", "\tc", "\tb", "\td", "\te", "z", "\ty", "\tx", "\tw", "\tv"], getline(1, '$'))
+  call assert_equal(0, foldlevel(2))
+  call assert_equal(5, foldclosedend(3))
+  call assert_equal([-1, -1, 3, 3, 3, -1, 7, 7, 7, 7], map(range(1, line('$')), 'foldclosed(v:val)'))
+  2,6m$
+  %foldclose
+  call assert_equal(5, foldclosedend(2))
+  call assert_equal(0, foldlevel(6))
+  call assert_equal(9, foldclosedend(7))
+  call assert_equal([-1, 2, 2, 2, 2, -1, 7, 7, 7, -1], map(range(1, line('$')), 'foldclosed(v:val)'))
+  bw!
+endfunc
+
+func! Test_move_folds_around_indent()
+  new
+  let input = PrepIndent("a") + PrepIndent("b") + PrepIndent("c")
+  call setline(1, PrepIndent("a") + PrepIndent("b") + PrepIndent("c"))
+  let folds=[-1, 2, 2, 2, 2, 2, -1, 8, 8, 8, 8, 8, -1, 14, 14, 14, 14, 14]
+  " all folds closed
+  set fdm=indent
+  call assert_equal(folds, map(range(1, line('$')), 'foldclosed(v:val)'))
+  call assert_equal(input, getline(1, '$'))
+  7,12m0
+  call assert_equal(PrepIndent("b") + PrepIndent("a") + PrepIndent("c"), getline(1, '$'))
+  call assert_equal(folds, map(range(1, line('$')), 'foldclosed(v:val)'))
+  10,12m0
+  call assert_equal(PrepIndent("a")[1:] + PrepIndent("b") + ["a"] +  PrepIndent("c"), getline(1, '$'))
+  call assert_equal([1, 1, 1, 1, 1, -1, 7, 7, 7, 7, 7, -1, -1, 14, 14, 14, 14, 14], map(range(1, line('$')), 'foldclosed(v:val)'))
+  " moving should not close the folds
+  %d
+  call setline(1, PrepIndent("a") + PrepIndent("b") + PrepIndent("c"))
+  set fdm=indent
+  call cursor(2, 1)
+  norm! zR
+  7,12m0
+  let folds=repeat([-1], 18)
+  call assert_equal(PrepIndent("b") + PrepIndent("a") + PrepIndent("c"), getline(1, '$'))
+  call assert_equal(folds, map(range(1, line('$')), 'foldclosed(v:val)'))
+  norm! zM
+  " folds are not corrupted and all have been closed
+  call assert_equal([-1, 2, 2, 2, 2, 2, -1, 8, 8, 8, 8, 8, -1, 14, 14, 14, 14, 14], map(range(1, line('$')), 'foldclosed(v:val)'))
+  %d
+  call setline(1, ["a", "\tb", "\tc", "\td", "\te"])
+  set fdm=indent
+  %foldopen
+  3m4
+  %foldclose
+  call assert_equal(["a", "\tb", "\td", "\tc", "\te"], getline(1, '$'))
+  call assert_equal([-1, 5, 5, 5, 5], map(range(1, line('$')), 'foldclosedend(v:val)'))
+  %d
+  call setline(1, ["a", "\tb", "\tc", "\td", "\te", "z", "\ty", "\tx", "\tw", "\tv"])
+  set fdm=indent foldlevel=0
+  %foldopen
+  3m1
+  %foldclose
+  call assert_equal(["a", "\tc", "\tb", "\td", "\te", "z", "\ty", "\tx", "\tw", "\tv"], getline(1, '$'))
+  call assert_equal(1, foldlevel(2))
+  call assert_equal(5, foldclosedend(3))
+  call assert_equal([-1, 2, 2, 2, 2, -1, 7, 7, 7, 7], map(range(1, line('$')), 'foldclosed(v:val)'))
+  2,6m$
+  %foldclose
+  call assert_equal(9, foldclosedend(2))
+  call assert_equal(1, foldlevel(6))
+  call assert_equal(9, foldclosedend(7))
+  call assert_equal([-1, 2, 2, 2, 2, 2, 2, 2, 2, -1], map(range(1, line('$')), 'foldclosed(v:val)'))
+  bw!
+endfunc