changeset 34457:125dcecbfa09 v9.1.0144

patch 9.1.0144: getregion() needs more tests Commit: https://github.com/vim/vim/commit/4d55c54e307c27600c644c6631ff673ed89dd53a Author: Yegappan Lakshmanan <yegappan@yahoo.com> Date: Thu Feb 29 17:30:43 2024 +0100 patch 9.1.0144: getregion() needs more tests Problem: getregion() needs more tests Solution: Run the getregion() test in both the legacy and Vim9 contexts (Yegappan Lakshmanan) closes: #14114 Signed-off-by: Yegappan Lakshmanan <yegappan@yahoo.com> Signed-off-by: Christian Brabandt <cb@256bit.org>
author Christian Brabandt <cb@256bit.org>
date Thu, 29 Feb 2024 17:45:03 +0100
parents e3d2ba1fd1a3
children bbad1a9e04d3
files src/testdir/test_visual.vim src/version.c
diffstat 2 files changed, 260 insertions(+), 239 deletions(-) [+]
line wrap: on
line diff
--- a/src/testdir/test_visual.vim
+++ b/src/testdir/test_visual.vim
@@ -3,6 +3,7 @@
 source shared.vim
 source check.vim
 source screendump.vim
+import './vim9.vim' as v9
 
 func Test_block_shift_multibyte()
   " Uses double-wide character.
@@ -1631,261 +1632,279 @@ func Test_visual_substitute_visual()
 endfunc
 
 func Test_visual_getregion()
-  new
+  let lines =<< trim END
+    new
 
-  call setline(1, ['one', 'two', 'three'])
+    call setline(1, ['one', 'two', 'three'])
 
-  " Visual mode
-  call cursor(1, 1)
-  call feedkeys("\<ESC>vjl", 'tx')
-  call assert_equal(['one', 'tw'],
-        \ 'v'->getpos()->getregion(getpos('.')))
-  call assert_equal(['one', 'tw'],
-        \ '.'->getpos()->getregion(getpos('v')))
-  call assert_equal(['o'],
-        \ 'v'->getpos()->getregion(getpos('v')))
-  call assert_equal(['w'],
-        \ '.'->getpos()->getregion(getpos('.'), #{ type: 'v' }))
-  call assert_equal(['one', 'two'],
-        \ getpos('.')->getregion(getpos('v'), #{ type: 'V' }))
-  call assert_equal(['on', 'tw'],
-        \ getpos('.')->getregion(getpos('v'), #{ type: "\<C-v>" }))
-
-  " Line visual mode
-  call cursor(1, 1)
-  call feedkeys("\<ESC>Vl", 'tx')
-  call assert_equal(['one'],
-        \ getregion(getpos('v'), getpos('.'), #{ type: 'V' }))
-  call assert_equal(['one'],
-        \ getregion(getpos('.'), getpos('v'), #{ type: 'V' }))
-  call assert_equal(['one'],
-        \ getregion(getpos('v'), getpos('v'), #{ type: 'V' }))
-  call assert_equal(['one'],
-        \ getregion(getpos('.'), getpos('.'), #{ type: 'V' }))
-  call assert_equal(['on'],
-        \ getpos('.')->getregion(getpos('v'), #{ type: 'v' }))
-  call assert_equal(['on'],
-        \ getpos('.')->getregion(getpos('v'), #{ type: "\<C-v>" }))
+    #" Visual mode
+    call cursor(1, 1)
+    call feedkeys("\<ESC>vjl", 'tx')
+    call assert_equal(['one', 'tw'],
+          \ 'v'->getpos()->getregion(getpos('.')))
+    call assert_equal(['one', 'tw'],
+          \ '.'->getpos()->getregion(getpos('v')))
+    call assert_equal(['o'],
+          \ 'v'->getpos()->getregion(getpos('v')))
+    call assert_equal(['w'],
+          \ '.'->getpos()->getregion(getpos('.'), {'type': 'v' }))
+    call assert_equal(['one', 'two'],
+          \ getpos('.')->getregion(getpos('v'), {'type': 'V' }))
+    call assert_equal(['on', 'tw'],
+          \ getpos('.')->getregion(getpos('v'), {'type': "\<C-v>" }))
 
-  " Block visual mode
-  call cursor(1, 1)
-  call feedkeys("\<ESC>\<C-v>ll", 'tx')
-  call assert_equal(['one'],
-        \ getregion(getpos('v'), getpos('.'), #{ type: "\<C-v>" }))
-  call assert_equal(['one'],
-        \ getregion(getpos('.'), getpos('v'), #{ type: "\<C-v>" }))
-  call assert_equal(['o'],
-        \ getregion(getpos('v'), getpos('v'), #{ type: "\<C-v>" }))
-  call assert_equal(['e'],
-        \ getregion(getpos('.'), getpos('.'), #{ type: "\<C-v>" }))
-  call assert_equal(['one'],
-        \ '.'->getpos()->getregion(getpos('v'), #{ type: 'V' }))
-  call assert_equal(['one'],
-        \ '.'->getpos()->getregion(getpos('v'), #{ type: 'v' }))
+    #" Line visual mode
+    call cursor(1, 1)
+    call feedkeys("\<ESC>Vl", 'tx')
+    call assert_equal(['one'],
+          \ getregion(getpos('v'), getpos('.'), {'type': 'V' }))
+    call assert_equal(['one'],
+          \ getregion(getpos('.'), getpos('v'), {'type': 'V' }))
+    call assert_equal(['one'],
+          \ getregion(getpos('v'), getpos('v'), {'type': 'V' }))
+    call assert_equal(['one'],
+          \ getregion(getpos('.'), getpos('.'), {'type': 'V' }))
+    call assert_equal(['on'],
+          \ getpos('.')->getregion(getpos('v'), {'type': 'v' }))
+    call assert_equal(['on'],
+          \ getpos('.')->getregion(getpos('v'), {'type': "\<C-v>" }))
 
-  " Using Marks
-  call setpos("'a", [0, 2, 3, 0])
-  call cursor(1, 1)
-  call assert_equal(['one', 'two'],
-        \ "'a"->getpos()->getregion(getpos('.'), #{ type: 'v' }))
-  call assert_equal(['one', 'two'],
-        \ "."->getpos()->getregion(getpos("'a"), #{ type: 'v' }))
-  call assert_equal(['one', 'two'],
-        \ "."->getpos()->getregion(getpos("'a"), #{ type: 'V' }))
-  call assert_equal(['two'],
-        \ "'a"->getpos()->getregion(getpos("'a"), #{ type: 'V' }))
-  call assert_equal(['one', 'two'],
-        \ "."->getpos()->getregion(getpos("'a"), #{ type: "\<c-v>" }))
-
-  " Using List
-  call cursor(1, 1)
-  call assert_equal(['one', 'two'],
-        \ [0, 2, 3, 0]->getregion(getpos('.'), #{ type: 'v' }))
-  call assert_equal(['one', 'two'],
-        \ '.'->getpos()->getregion([0, 2, 3, 0], #{ type: 'v' }))
-  call assert_equal(['one', 'two'],
-        \ '.'->getpos()->getregion([0, 2, 3, 0], #{ type: 'V' }))
-  call assert_equal(['two'],
-        \ [0, 2, 3, 0]->getregion([0, 2, 3, 0], #{ type: 'V' }))
-  call assert_equal(['one', 'two'],
-        \ '.'->getpos()->getregion([0, 2, 3, 0], #{ type: "\<c-v>" }))
-
-  " Multiline with line visual mode
-  call cursor(1, 1)
-  call feedkeys("\<ESC>Vjj", 'tx')
-  call assert_equal(['one', 'two', 'three'],
-        \ getregion(getpos('v'), getpos('.'), #{ type: 'V' }))
+    #" Block visual mode
+    call cursor(1, 1)
+    call feedkeys("\<ESC>\<C-v>ll", 'tx')
+    call assert_equal(['one'],
+          \ getregion(getpos('v'), getpos('.'), {'type': "\<C-v>" }))
+    call assert_equal(['one'],
+          \ getregion(getpos('.'), getpos('v'), {'type': "\<C-v>" }))
+    call assert_equal(['o'],
+          \ getregion(getpos('v'), getpos('v'), {'type': "\<C-v>" }))
+    call assert_equal(['e'],
+          \ getregion(getpos('.'), getpos('.'), {'type': "\<C-v>" }))
+    call assert_equal(['one'],
+          \ '.'->getpos()->getregion(getpos('v'), {'type': 'V' }))
+    call assert_equal(['one'],
+          \ '.'->getpos()->getregion(getpos('v'), {'type': 'v' }))
 
-  " Multiline with block visual mode
-  call cursor(1, 1)
-  call feedkeys("\<ESC>\<C-v>jj", 'tx')
-  call assert_equal(['o', 't', 't'],
-        \ getregion(getpos('v'), getpos('.'), #{ type: "\<C-v>" }))
-
-  call cursor(1, 1)
-  call feedkeys("\<ESC>\<C-v>jj$", 'tx')
-  call assert_equal(['one', 'two', 'three'],
-        \ getregion(getpos('v'), getpos('.'), #{ type: "\<C-v>" }))
-
-  " 'virtualedit'
-  set virtualedit=all
-  call cursor(1, 1)
-  call feedkeys("\<ESC>\<C-v>10ljj$", 'tx')
-  call assert_equal(['one   ', 'two   ', 'three '],
-        \ getregion(getpos('v'), getpos('.'), #{ type: "\<C-v>" }))
-  set virtualedit&
+    #" Using Marks
+    call setpos("'a", [0, 2, 3, 0])
+    call cursor(1, 1)
+    call assert_equal(['one', 'two'],
+          \ "'a"->getpos()->getregion(getpos('.'), {'type': 'v' }))
+    call assert_equal(['one', 'two'],
+          \ "."->getpos()->getregion(getpos("'a"), {'type': 'v' }))
+    call assert_equal(['one', 'two'],
+          \ "."->getpos()->getregion(getpos("'a"), {'type': 'V' }))
+    call assert_equal(['two'],
+          \ "'a"->getpos()->getregion(getpos("'a"), {'type': 'V' }))
+    call assert_equal(['one', 'two'],
+          \ "."->getpos()->getregion(getpos("'a"), {'type': "\<c-v>" }))
 
-  " Invalid position
-  call cursor(1, 1)
-  call feedkeys("\<ESC>vjj$", 'tx')
-  call assert_fails("call getregion(1, 2)", 'E1211:')
-  call assert_fails("call getregion(getpos('.'), {})", 'E1211:')
-  call assert_equal([], getregion(getpos('.'), getpos('.'), #{ type: '' }))
-
-  " using the wrong type
-  call assert_fails(':echo "."->getpos()->getregion("$", [])', 'E1211:')
+    #" Using List
+    call cursor(1, 1)
+    call assert_equal(['one', 'two'],
+          \ [0, 2, 3, 0]->getregion(getpos('.'), {'type': 'v' }))
+    call assert_equal(['one', 'two'],
+          \ '.'->getpos()->getregion([0, 2, 3, 0], {'type': 'v' }))
+    call assert_equal(['one', 'two'],
+          \ '.'->getpos()->getregion([0, 2, 3, 0], {'type': 'V' }))
+    call assert_equal(['two'],
+          \ [0, 2, 3, 0]->getregion([0, 2, 3, 0], {'type': 'V' }))
+    call assert_equal(['one', 'two'],
+          \ '.'->getpos()->getregion([0, 2, 3, 0], {'type': "\<c-v>" }))
 
-  " using a mark in another buffer
-  new
-  let newbuf = bufnr()
-  call setline(1, range(10))
-  normal! GmA
-  wincmd p
-  call assert_equal([newbuf, 10, 1, 0], getpos("'A"))
-  call assert_equal([], getregion(getpos('.'), getpos("'A"), #{ type: 'v' }))
-  call assert_equal([], getregion(getpos("'A"), getpos('.'), #{ type: 'v' }))
-  exe newbuf .. 'bwipe!'
+    #" Multiline with line visual mode
+    call cursor(1, 1)
+    call feedkeys("\<ESC>Vjj", 'tx')
+    call assert_equal(['one', 'two', 'three'],
+          \ getregion(getpos('v'), getpos('.'), {'type': 'V' }))
 
-  bwipe!
-  " Selection in starts or ends in the middle of a multibyte character
-  new
-  call setline(1, [
-        \   "abcdefghijk\u00ab",
-        \   "\U0001f1e6\u00ab\U0001f1e7\u00ab\U0001f1e8\u00ab\U0001f1e9",
-        \   "1234567890"
-        \ ])
-  call cursor(1, 3)
-  call feedkeys("\<Esc>\<C-v>ljj", 'xt')
-  call assert_equal(['cd', "\u00ab ", '34'],
-        \ getregion(getpos('v'), getpos('.'), #{ type: "\<C-v>" }))
-  call cursor(1, 4)
-  call feedkeys("\<Esc>\<C-v>ljj", 'xt')
-  call assert_equal(['de', "\U0001f1e7", '45'],
-        \ getregion(getpos('v'), getpos('.'), #{ type: "\<C-v>" }))
-  call cursor(1, 5)
-  call feedkeys("\<Esc>\<C-v>jj", 'xt')
-  call assert_equal(['e', ' ', '5'],
-        \ getregion(getpos('v'), getpos('.'), #{ type: "\<C-v>" }))
-  call cursor(1, 1)
-  call feedkeys("\<Esc>vj", 'xt')
-  call assert_equal(['abcdefghijk«', "\U0001f1e6"],
-        \ getregion(getpos('v'), getpos('.'), #{ type: 'v' }))
-  " marks on multibyte chars
-  set selection=exclusive
-  call setpos("'a", [0, 1, 11, 0])
-  call setpos("'b", [0, 2, 16, 0])
-  call setpos("'c", [0, 2, 0, 0])
-  call cursor(1, 1)
-  call assert_equal(['ghijk', '🇨«🇩'],
-        \ getregion(getpos("'a"), getpos("'b"), #{ type: "\<c-v>" }))
-  call assert_equal(['k«', '🇦«🇧«🇨'],
-        \ getregion(getpos("'a"), getpos("'b"), #{ type: 'v' }))
-  call assert_equal(['k«'],
-        \ getregion(getpos("'a"), getpos("'c"), #{ type: 'v' }))
+    #" Multiline with block visual mode
+    call cursor(1, 1)
+    call feedkeys("\<ESC>\<C-v>jj", 'tx')
+    call assert_equal(['o', 't', 't'],
+          \ getregion(getpos('v'), getpos('.'), {'type': "\<C-v>" }))
+
+    call cursor(1, 1)
+    call feedkeys("\<ESC>\<C-v>jj$", 'tx')
+    call assert_equal(['one', 'two', 'three'],
+          \ getregion(getpos('v'), getpos('.'), {'type': "\<C-v>" }))
+
+    #" 'virtualedit'
+    set virtualedit=all
+    call cursor(1, 1)
+    call feedkeys("\<ESC>\<C-v>10ljj$", 'tx')
+    call assert_equal(['one   ', 'two   ', 'three '],
+          \ getregion(getpos('v'), getpos('.'), {'type': "\<C-v>" }))
+    set virtualedit&
 
-  " use inclusive selection, although 'selection' is exclusive
-  call setpos("'a", [0, 1, 11, 0])
-  call setpos("'b", [0, 1, 1, 0])
-  call assert_equal(['abcdefghijk'],
-        \ getregion(getpos("'a"), getpos("'b"), #{ type: "\<c-v>", exclusive: v:false }))
-  call assert_equal(['abcdefghij'],
-        \ getregion(getpos("'a"), getpos("'b"), #{ type: "\<c-v>", exclusive: v:true }))
-  call assert_equal(['abcdefghijk'],
-        \ getregion(getpos("'a"), getpos("'b"), #{ type: 'v', exclusive: 0 }))
-  call assert_equal(['abcdefghij'],
-        \ getregion(getpos("'a"), getpos("'b"), #{ type: 'v', exclusive: 1 }))
-  call assert_equal(['abcdefghijk«'],
-        \ getregion(getpos("'a"), getpos("'b"), #{ type: 'V', exclusive: 0 }))
-  call assert_equal(['abcdefghijk«'],
-        \ getregion(getpos("'a"), getpos("'b"), #{ type: 'V', exclusive: 1 }))
+    #" Invalid position
+    call cursor(1, 1)
+    call feedkeys("\<ESC>vjj$", 'tx')
+    call assert_fails("call getregion(1, 2)", 'E1211:')
+    call assert_fails("call getregion(getpos('.'), {})", 'E1211:')
+    call assert_equal([], getregion(getpos('.'), getpos('.'), {'type': '' }))
+
+    #" using the wrong type
+    call assert_fails(':echo "."->getpos()->getregion("$", [])', 'E1211:')
+
+    #" using a mark in another buffer
+    new
+    VAR newbuf = bufnr()
+    call setline(1, range(10))
+    normal! GmA
+    wincmd p
+    call assert_equal([newbuf, 10, 1, 0], getpos("'A"))
+    call assert_equal([], getregion(getpos('.'), getpos("'A"), {'type': 'v' }))
+    call assert_equal([], getregion(getpos("'A"), getpos('.'), {'type': 'v' }))
+    exe $':{newbuf}bwipe!'
+  END
+  call v9.CheckLegacyAndVim9Success(lines)
 
   bwipe!
 
-  " Exclusive selection
-  new
-  set selection=exclusive
-  call setline(1, ["a\tc", "x\tz", '', ''])
-  call cursor(1, 1)
-  call feedkeys("\<Esc>v2l", 'xt')
-  call assert_equal(["a\t"],
-        \ getregion(getpos('v'), getpos('.'), #{ type: 'v' }))
-  call cursor(1, 1)
-  call feedkeys("\<Esc>v$G", 'xt')
-  call assert_equal(["a\tc", "x\tz", ''],
-        \ getregion(getpos('v'), getpos('.'), #{ type: 'v' }))
-  call cursor(1, 1)
-  call feedkeys("\<Esc>v$j", 'xt')
-  call assert_equal(["a\tc", "x\tz"],
-        \ getregion(getpos('v'), getpos('.'), #{ type: 'v' }))
-  call cursor(1, 1)
-  call feedkeys("\<Esc>\<C-v>$j", 'xt')
-  call assert_equal(["a\tc", "x\tz"],
-        \ getregion(getpos('v'), getpos('.'), #{ type: "\<C-v>" }))
-  call cursor(1, 1)
-  call feedkeys("\<Esc>\<C-v>$G", 'xt')
-  call assert_equal(["a", "x", '', ''],
-        \ getregion(getpos('v'), getpos('.'), #{ type: "\<C-v>" }))
-  call cursor(1, 1)
-  call feedkeys("\<Esc>wv2j", 'xt')
-  call assert_equal(["c", "x\tz"],
-        \ getregion(getpos('v'), getpos('.'), #{ type: 'v' }))
-  set selection&
+  let lines =<< trim END
+    #" Selection in starts or ends in the middle of a multibyte character
+    new
+    call setline(1, [
+          \   "abcdefghijk\u00ab",
+          \   "\U0001f1e6\u00ab\U0001f1e7\u00ab\U0001f1e8\u00ab\U0001f1e9",
+          \   "1234567890"
+          \ ])
+    call cursor(1, 3)
+    call feedkeys("\<Esc>\<C-v>ljj", 'xt')
+    call assert_equal(['cd', "\u00ab ", '34'],
+          \ getregion(getpos('v'), getpos('.'), {'type': "\<C-v>" }))
+    call cursor(1, 4)
+    call feedkeys("\<Esc>\<C-v>ljj", 'xt')
+    call assert_equal(['de', "\U0001f1e7", '45'],
+          \ getregion(getpos('v'), getpos('.'), {'type': "\<C-v>" }))
+    call cursor(1, 5)
+    call feedkeys("\<Esc>\<C-v>jj", 'xt')
+    call assert_equal(['e', ' ', '5'],
+          \ getregion(getpos('v'), getpos('.'), {'type': "\<C-v>" }))
+    call cursor(1, 1)
+    call feedkeys("\<Esc>vj", 'xt')
+    call assert_equal(['abcdefghijk«', "\U0001f1e6"],
+          \ getregion(getpos('v'), getpos('.'), {'type': 'v' }))
 
-  " Exclusive selection 2
-  new
-  call setline(1, ["a\tc", "x\tz", '', ''])
-  call cursor(1, 1)
-  call feedkeys("\<Esc>v2l", 'xt')
-  call assert_equal(["a\t"],
-        \ getregion(getpos('v'), getpos('.'), #{ exclusive: v:true }))
-  call cursor(1, 1)
-  call feedkeys("\<Esc>v$G", 'xt')
-  call assert_equal(["a\tc", "x\tz", ''],
-        \ getregion(getpos('v'), getpos('.'), #{ exclusive: v:true }))
-  call cursor(1, 1)
-  call feedkeys("\<Esc>v$j", 'xt')
-  call assert_equal(["a\tc", "x\tz"],
-        \ getregion(getpos('v'), getpos('.'), #{ exclusive: v:true }))
-  call cursor(1, 1)
-  call feedkeys("\<Esc>\<C-v>$j", 'xt')
-  call assert_equal(["a\tc", "x\tz"],
-        \ getregion(getpos('v'), getpos('.'),
-        \           #{ exclusive: v:true, type: "\<C-v>" }))
-  call cursor(1, 1)
-  call feedkeys("\<Esc>\<C-v>$G", 'xt')
-  call assert_equal(["a", "x", '', ''],
-        \ getregion(getpos('v'), getpos('.'),
-        \           #{ exclusive: v:true, type: "\<C-v>" }))
-  call cursor(1, 1)
-  call feedkeys("\<Esc>wv2j", 'xt')
-  call assert_equal(["c", "x\tz"],
-        \ getregion(getpos('v'), getpos('.'), #{ exclusive: v:true }))
+    #" marks on multibyte chars
+    :set selection=exclusive
+    call setpos("'a", [0, 1, 11, 0])
+    call setpos("'b", [0, 2, 16, 0])
+    call setpos("'c", [0, 2, 0, 0])
+    call cursor(1, 1)
+    call assert_equal(['ghijk', '🇨«🇩'],
+          \ getregion(getpos("'a"), getpos("'b"), {'type': "\<c-v>" }))
+    call assert_equal(['k«', '🇦«🇧«🇨'],
+          \ getregion(getpos("'a"), getpos("'b"), {'type': 'v' }))
+    call assert_equal(['k«'],
+          \ getregion(getpos("'a"), getpos("'c"), {'type': 'v' }))
 
-  " virtualedit
-  set selection=exclusive
-  set virtualedit=all
-  call cursor(1, 1)
-  call feedkeys("\<Esc>2lv2lj", 'xt')
-  call assert_equal(['      c', 'x   '],
-        \ getregion(getpos('v'), getpos('.'), #{ type: 'v' }))
-  call cursor(1, 1)
-  call feedkeys("\<Esc>2l\<C-v>2l2j", 'xt')
-  call assert_equal(['  ', '  ', '  '],
-        \ getregion(getpos('v'), getpos('.'), #{ type: "\<C-v>" }))
-  set virtualedit&
-  set selection&
+    #" use inclusive selection, although 'selection' is exclusive
+    call setpos("'a", [0, 1, 11, 0])
+    call setpos("'b", [0, 1, 1, 0])
+    call assert_equal(['abcdefghijk'],
+          \ getregion(getpos("'a"), getpos("'b"),
+          \ {'type': "\<c-v>", 'exclusive': v:false }))
+    call assert_equal(['abcdefghij'],
+          \ getregion(getpos("'a"), getpos("'b"),
+          \ {'type': "\<c-v>", 'exclusive': v:true }))
+    call assert_equal(['abcdefghijk'],
+          \ getregion(getpos("'a"), getpos("'b"),
+          \ {'type': 'v', 'exclusive': 0 }))
+    call assert_equal(['abcdefghij'],
+          \ getregion(getpos("'a"), getpos("'b"),
+          \ {'type': 'v', 'exclusive': 1 }))
+    call assert_equal(['abcdefghijk«'],
+          \ getregion(getpos("'a"), getpos("'b"),
+          \ {'type': 'V', 'exclusive': 0 }))
+    call assert_equal(['abcdefghijk«'],
+          \ getregion(getpos("'a"), getpos("'b"),
+          \ {'type': 'V', 'exclusive': 1 }))
+    :set selection&
+  END
+  call v9.CheckLegacyAndVim9Success(lines)
 
   bwipe!
+
+  let lines =<< trim END
+    #" Exclusive selection
+    new
+    set selection=exclusive
+    call setline(1, ["a\tc", "x\tz", '', ''])
+    call cursor(1, 1)
+    call feedkeys("\<Esc>v2l", 'xt')
+    call assert_equal(["a\t"],
+          \ getregion(getpos('v'), getpos('.'), {'type': 'v' }))
+    call cursor(1, 1)
+    call feedkeys("\<Esc>v$G", 'xt')
+    call assert_equal(["a\tc", "x\tz", ''],
+          \ getregion(getpos('v'), getpos('.'), {'type': 'v' }))
+    call cursor(1, 1)
+    call feedkeys("\<Esc>v$j", 'xt')
+    call assert_equal(["a\tc", "x\tz"],
+          \ getregion(getpos('v'), getpos('.'), {'type': 'v' }))
+    call cursor(1, 1)
+    call feedkeys("\<Esc>\<C-v>$j", 'xt')
+    call assert_equal(["a\tc", "x\tz"],
+          \ getregion(getpos('v'), getpos('.'), {'type': "\<C-v>" }))
+    call cursor(1, 1)
+    call feedkeys("\<Esc>\<C-v>$G", 'xt')
+    call assert_equal(["a", "x", '', ''],
+          \ getregion(getpos('v'), getpos('.'), {'type': "\<C-v>" }))
+    call cursor(1, 1)
+    call feedkeys("\<Esc>wv2j", 'xt')
+    call assert_equal(["c", "x\tz"],
+          \ getregion(getpos('v'), getpos('.'), {'type': 'v' }))
+    set selection&
+
+    #" Exclusive selection 2
+    new
+    call setline(1, ["a\tc", "x\tz", '', ''])
+    call cursor(1, 1)
+    call feedkeys("\<Esc>v2l", 'xt')
+    call assert_equal(["a\t"],
+          \ getregion(getpos('v'), getpos('.'), {'exclusive': v:true }))
+    call cursor(1, 1)
+    call feedkeys("\<Esc>v$G", 'xt')
+    call assert_equal(["a\tc", "x\tz", ''],
+          \ getregion(getpos('v'), getpos('.'), {'exclusive': v:true }))
+    call cursor(1, 1)
+    call feedkeys("\<Esc>v$j", 'xt')
+    call assert_equal(["a\tc", "x\tz"],
+          \ getregion(getpos('v'), getpos('.'), {'exclusive': v:true }))
+    call cursor(1, 1)
+    call feedkeys("\<Esc>\<C-v>$j", 'xt')
+    call assert_equal(["a\tc", "x\tz"],
+          \ getregion(getpos('v'), getpos('.'),
+          \           {'exclusive': v:true, 'type': "\<C-v>" }))
+    call cursor(1, 1)
+    call feedkeys("\<Esc>\<C-v>$G", 'xt')
+    call assert_equal(["a", "x", '', ''],
+          \ getregion(getpos('v'), getpos('.'),
+          \           {'exclusive': v:true, 'type': "\<C-v>" }))
+    call cursor(1, 1)
+    call feedkeys("\<Esc>wv2j", 'xt')
+    call assert_equal(["c", "x\tz"],
+          \ getregion(getpos('v'), getpos('.'), {'exclusive': v:true }))
+
+    #" virtualedit
+    set selection=exclusive
+    set virtualedit=all
+    call cursor(1, 1)
+    call feedkeys("\<Esc>2lv2lj", 'xt')
+    call assert_equal(['      c', 'x   '],
+          \ getregion(getpos('v'), getpos('.'), {'type': 'v' }))
+    call cursor(1, 1)
+    call feedkeys("\<Esc>2l\<C-v>2l2j", 'xt')
+    call assert_equal(['  ', '  ', '  '],
+          \ getregion(getpos('v'), getpos('.'), {'type': "\<C-v>" }))
+    set virtualedit&
+    set selection&
+
+    bwipe!
+  END
+  call v9.CheckLegacyAndVim9Success(lines)
 endfunc
 
 " vim: shiftwidth=2 sts=2 expandtab
--- a/src/version.c
+++ b/src/version.c
@@ -705,6 +705,8 @@ static char *(features[]) =
 static int included_patches[] =
 {   /* Add new patch number below this line */
 /**/
+    144,
+/**/
     143,
 /**/
     142,