diff src/testdir/test_normal.vim @ 26456:7eaf61a67d18 v8.2.3758

patch 8.2.3758: options that take a function insufficiently tested Commit: https://github.com/vim/vim/commit/2172bff36417ddd90653531edc65897411c83b3f Author: Yegappan Lakshmanan <yegappan@yahoo.com> Date: Wed Dec 8 10:46:21 2021 +0000 patch 8.2.3758: options that take a function insufficiently tested Problem: Options that take a function insufficiently tested. Solution: Add additional tests and enhance existing tests. (Yegappan Lakshmanan, closes #9298)
author Bram Moolenaar <Bram@vim.org>
date Wed, 08 Dec 2021 12:00:05 +0100
parents 92fbed13ca4d
children 13ba00ef7687
line wrap: on
line diff
--- a/src/testdir/test_normal.vim
+++ b/src/testdir/test_normal.vim
@@ -3,6 +3,7 @@
 source shared.vim
 source check.vim
 source view_util.vim
+source vim9.vim
 
 func Setup_NewWindow()
   10new
@@ -386,70 +387,6 @@ func Test_normal09a_operatorfunc()
   norm V10j,,
   call assert_equal(22, g:a)
 
-  " Use a lambda function for 'opfunc'
-  unmap <buffer> ,,
-  call cursor(1, 1)
-  let g:a=0
-  nmap <buffer><silent> ,, :set opfunc={type\ ->\ CountSpaces(type)}<CR>g@
-  vmap <buffer><silent> ,, :<C-U>call CountSpaces(visualmode(), 1)<CR>
-  50
-  norm V2j,,
-  call assert_equal(6, g:a)
-  norm V,,
-  call assert_equal(2, g:a)
-  norm ,,l
-  call assert_equal(0, g:a)
-  50
-  exe "norm 0\<c-v>10j2l,,"
-  call assert_equal(11, g:a)
-  50
-  norm V10j,,
-  call assert_equal(22, g:a)
-
-  " use a partial function for 'opfunc'
-  let g:OpVal = 0
-  func! Test_opfunc1(x, y, type)
-    let g:OpVal =  a:x + a:y
-  endfunc
-  set opfunc=function('Test_opfunc1',\ [5,\ 7])
-  normal! g@l
-  call assert_equal(12, g:OpVal)
-  " delete the function and try to use g@
-  delfunc Test_opfunc1
-  call test_garbagecollect_now()
-  call assert_fails('normal! g@l', 'E117:')
-  set opfunc=
-
-  " use a funcref for 'opfunc'
-  let g:OpVal = 0
-  func! Test_opfunc2(x, y, type)
-    let g:OpVal =  a:x + a:y
-  endfunc
-  set opfunc=funcref('Test_opfunc2',\ [4,\ 3])
-  normal! g@l
-  call assert_equal(7, g:OpVal)
-  " delete the function and try to use g@
-  delfunc Test_opfunc2
-  call test_garbagecollect_now()
-  call assert_fails('normal! g@l', 'E933:')
-  set opfunc=
-
-  " Try to use a function with two arguments for 'operatorfunc'
-  let g:OpVal = 0
-  func! Test_opfunc3(x, y)
-    let g:OpVal = 4
-  endfunc
-  set opfunc=Test_opfunc3
-  call assert_fails('normal! g@l', 'E119:')
-  call assert_equal(0, g:OpVal)
-  set opfunc=
-  delfunc Test_opfunc3
-  unlet g:OpVal
-
-  " Try to use a lambda function with two arguments for 'operatorfunc'
-  set opfunc={x,\ y\ ->\ 'done'}
-  call assert_fails('normal! g@l', 'E119:')
-
   " clean up
   unmap <buffer> ,,
   set opfunc=
@@ -504,6 +441,182 @@ func Test_normal09c_operatorfunc()
   set operatorfunc=
 endfunc
 
+" Test for different ways of setting the 'operatorfunc' option
+func Test_opfunc_callback()
+  new
+  func MyopFunc(val, type)
+    let g:OpFuncArgs = [a:val, a:type]
+  endfunc
+
+  " Test for using a function()
+  set opfunc=function('MyopFunc',\ [11])
+  let g:OpFuncArgs = []
+  normal! g@l
+  call assert_equal([11, 'char'], g:OpFuncArgs)
+
+  " Using a funcref variable to set 'operatorfunc'
+  let Fn = function('MyopFunc', [12])
+  let &opfunc = Fn
+  let g:OpFuncArgs = []
+  normal! g@l
+  call assert_equal([12, 'char'], g:OpFuncArgs)
+
+  " Using a string(funcref_variable) to set 'operatorfunc'
+  let Fn = function('MyopFunc', [13])
+  let &operatorfunc = string(Fn)
+  let g:OpFuncArgs = []
+  normal! g@l
+  call assert_equal([13, 'char'], g:OpFuncArgs)
+
+  " Test for using a funcref()
+  set operatorfunc=funcref('MyopFunc',\ [14])
+  let g:OpFuncArgs = []
+  normal! g@l
+  call assert_equal([14, 'char'], g:OpFuncArgs)
+
+  " Using a funcref variable to set 'operatorfunc'
+  let Fn = funcref('MyopFunc', [15])
+  let &opfunc = Fn
+  let g:OpFuncArgs = []
+  normal! g@l
+  call assert_equal([15, 'char'], g:OpFuncArgs)
+
+  " Using a string(funcref_variable) to set 'operatorfunc'
+  let Fn = funcref('MyopFunc', [16])
+  let &opfunc = string(Fn)
+  let g:OpFuncArgs = []
+  normal! g@l
+  call assert_equal([16, 'char'], g:OpFuncArgs)
+
+  " Test for using a lambda function using set
+  set opfunc={a\ ->\ MyopFunc(17,\ a)}
+  let g:OpFuncArgs = []
+  normal! g@l
+  call assert_equal([17, 'char'], g:OpFuncArgs)
+
+  " Test for using a lambda function using let
+  let &opfunc = {a -> MyopFunc(18, a)}
+  let g:OpFuncArgs = []
+  normal! g@l
+  call assert_equal([18, 'char'], g:OpFuncArgs)
+
+  " Set 'operatorfunc' to a string(lambda expression)
+  let &opfunc = '{a -> MyopFunc(19, a)}'
+  let g:OpFuncArgs = []
+  normal! g@l
+  call assert_equal([19, 'char'], g:OpFuncArgs)
+
+  " Set 'operatorfunc' to a variable with a lambda expression
+  let Lambda = {a -> MyopFunc(20, a)}
+  let &opfunc = Lambda
+  let g:OpFuncArgs = []
+  normal! g@l
+  call assert_equal([20, 'char'], g:OpFuncArgs)
+
+  " Set 'operatorfunc' to a string(variable with a lambda expression)
+  let Lambda = {a -> MyopFunc(21, a)}
+  let &opfunc = string(Lambda)
+  let g:OpFuncArgs = []
+  normal! g@l
+  call assert_equal([21, 'char'], g:OpFuncArgs)
+
+  " Try to use 'operatorfunc' after the function is deleted
+  func TmpOpFunc(type)
+    let g:OpFuncArgs = [22, a:type]
+  endfunc
+  let &opfunc = function('TmpOpFunc')
+  delfunc TmpOpFunc
+  call test_garbagecollect_now()
+  let g:OpFuncArgs = []
+  call assert_fails('normal! g@l', 'E117:')
+  call assert_equal([], g:OpFuncArgs)
+
+  " Try to use a function with two arguments for 'operatorfunc'
+  func! MyopFunc2(x, y)
+    let g:OpFuncArgs = [a:x, a:y]
+  endfunc
+  set opfunc=MyopFunc2
+  let g:OpFuncArgs = []
+  call assert_fails('normal! g@l', 'E119:')
+  call assert_equal([], g:OpFuncArgs)
+
+  " Try to use a lambda function with two arguments for 'operatorfunc'
+  let &opfunc = {a, b -> MyopFunc(23, b)}
+  let g:OpFuncArgs = []
+  call assert_fails('normal! g@l', 'E119:')
+  call assert_equal([], g:OpFuncArgs)
+
+  " Test for clearing the 'operatorfunc' option
+  set opfunc=''
+  set opfunc&
+
+  call assert_fails("set opfunc=function('abc')", "E700:")
+  call assert_fails("set opfunc=funcref('abc')", "E700:")
+
+  " Using Vim9 lambda expression in legacy context should fail
+  set opfunc=(a)\ =>\ MyopFunc(24,\ a)
+  let g:OpFuncArgs = []
+  call assert_fails('normal! g@l', 'E117:')
+  call assert_equal([], g:OpFuncArgs)
+
+  " set 'operatorfunc' to a non-existing function
+  let &opfunc = function('MyopFunc', [25])
+  call assert_fails("set opfunc=function('NonExistingFunc')", 'E700:')
+  call assert_fails("let &opfunc = function('NonExistingFunc')", 'E700:')
+  let g:OpFuncArgs = []
+  normal! g@l
+  call assert_equal([25, 'char'], g:OpFuncArgs)
+
+  " Vim9 tests
+  let lines =<< trim END
+    vim9script
+
+    # Test for using function()
+    def g:Vim9opFunc(val: number, type: string): void
+      g:OpFuncArgs = [val, type]
+    enddef
+    set opfunc=function('g:Vim9opFunc',\ [60])
+    g:OpFuncArgs = []
+    normal! g@l
+    assert_equal([60, 'char'], g:OpFuncArgs)
+
+    # Test for using a lambda
+    &opfunc = (a) => Vim9opFunc(61, a)
+    g:OpFuncArgs = []
+    normal! g@l
+    assert_equal([61, 'char'], g:OpFuncArgs)
+
+    # Test for using a string(lambda)
+    &opfunc = '(a) => Vim9opFunc(62, a)'
+    g:OpFuncArgs = []
+    normal! g@l
+    assert_equal([62, 'char'], g:OpFuncArgs)
+
+    # Test for using a variable with a lambda expression
+    var Fn: func = (a) => Vim9opFunc(63, a)
+    &opfunc = Fn
+    g:OpFuncArgs = []
+    normal! g@l
+    assert_equal([63, 'char'], g:OpFuncArgs)
+
+    # Test for using a string(variable with a lambda expression)
+    Fn = (a) => Vim9opFunc(64, a)
+    &opfunc = string(Fn)
+    g:OpFuncArgs = []
+    normal! g@l
+    assert_equal([64, 'char'], g:OpFuncArgs)
+    bw!
+  END
+  call CheckScriptSuccess(lines)
+
+  " cleanup
+  set opfunc&
+  delfunc MyopFunc
+  delfunc MyopFunc2
+  unlet g:OpFuncArgs
+  %bw!
+endfunc
+
 func Test_normal10_expand()
   " Test for expand()
   10new