comparison src/testdir/test_ins_complete.vim @ 26388:8aba638e91eb v8.2.3725

patch 8.2.3725: cannot use a lambda for 'completefunc' and 'omnifunc' Commit: https://github.com/vim/vim/commit/8658c759f05b317707d56e3b65a5ef63930c7498 Author: Yegappan Lakshmanan <yegappan@yahoo.com> Date: Fri Dec 3 11:09:29 2021 +0000 patch 8.2.3725: cannot use a lambda for 'completefunc' and 'omnifunc' Problem: Cannot use a lambda for 'completefunc' and 'omnifunc'. Solution: Implement lambda support. (Yegappan Lakshmanan, closes https://github.com/vim/vim/issues/9257)
author Bram Moolenaar <Bram@vim.org>
date Fri, 03 Dec 2021 12:15:04 +0100
parents 485c7c4afeb7
children 8f17f8f327f3
comparison
equal deleted inserted replaced
26387:b6eb7e295973 26388:8aba638e91eb
1 " Test for insert completion 1 " Test for insert completion
2 2
3 source screendump.vim 3 source screendump.vim
4 source check.vim 4 source check.vim
5 source vim9.vim
5 6
6 " Test for insert expansion 7 " Test for insert expansion
7 func Test_ins_complete() 8 func Test_ins_complete()
8 edit test_ins_complete.vim 9 edit test_ins_complete.vim
9 " The files in the current directory interferes with the files 10 " The files in the current directory interferes with the files
865 exe "normal owh\<C-N>" 866 exe "normal owh\<C-N>"
866 call assert_equal(currmess, execute('messages')) 867 call assert_equal(currmess, execute('messages'))
867 close! 868 close!
868 endfunc 869 endfunc
869 870
871 " Test for different ways of setting the 'completefunc' option
872 func Test_completefunc_callback()
873 " Test for using a function()
874 func MycompleteFunc1(findstart, base)
875 call add(g:MycompleteFunc1_args, [a:findstart, a:base])
876 return a:findstart ? 0 : []
877 endfunc
878 set completefunc=function('MycompleteFunc1')
879 new | only
880 call setline(1, 'one')
881 let g:MycompleteFunc1_args = []
882 call feedkeys("A\<C-X>\<C-U>\<Esc>", 'x')
883 call assert_equal([[1, ''], [0, 'one']], g:MycompleteFunc1_args)
884 bw!
885
886 " Using a funcref variable to set 'completefunc'
887 let Fn = function('MycompleteFunc1')
888 let &completefunc = string(Fn)
889 new | only
890 call setline(1, 'two')
891 let g:MycompleteFunc1_args = []
892 call feedkeys("A\<C-X>\<C-U>\<Esc>", 'x')
893 call assert_equal([[1, ''], [0, 'two']], g:MycompleteFunc1_args)
894 call assert_fails('let &completefunc = Fn', 'E729:')
895 bw!
896
897 " Test for using a funcref()
898 func MycompleteFunc2(findstart, base)
899 call add(g:MycompleteFunc2_args, [a:findstart, a:base])
900 return a:findstart ? 0 : []
901 endfunc
902 set completefunc=funcref('MycompleteFunc2')
903 new | only
904 call setline(1, 'three')
905 let g:MycompleteFunc2_args = []
906 call feedkeys("A\<C-X>\<C-U>\<Esc>", 'x')
907 call assert_equal([[1, ''], [0, 'three']], g:MycompleteFunc2_args)
908 bw!
909
910 " Using a funcref variable to set 'completefunc'
911 let Fn = funcref('MycompleteFunc2')
912 let &completefunc = string(Fn)
913 new | only
914 call setline(1, 'four')
915 let g:MycompleteFunc2_args = []
916 call feedkeys("A\<C-X>\<C-U>\<Esc>", 'x')
917 call assert_equal([[1, ''], [0, 'four']], g:MycompleteFunc2_args)
918 call assert_fails('let &completefunc = Fn', 'E729:')
919 bw!
920
921 " Test for using a lambda function
922 func MycompleteFunc3(findstart, base)
923 call add(g:MycompleteFunc3_args, [a:findstart, a:base])
924 return a:findstart ? 0 : []
925 endfunc
926 set completefunc={a,\ b,\ ->\ MycompleteFunc3(a,\ b,)}
927 new | only
928 call setline(1, 'five')
929 let g:MycompleteFunc3_args = []
930 call feedkeys("A\<C-X>\<C-U>\<Esc>", 'x')
931 call assert_equal([[1, ''], [0, 'five']], g:MycompleteFunc3_args)
932 bw!
933
934 " Set 'completefunc' to a lambda expression
935 let &completefunc = '{a, b -> MycompleteFunc3(a, b)}'
936 new | only
937 call setline(1, 'six')
938 let g:MycompleteFunc3_args = []
939 call feedkeys("A\<C-X>\<C-U>\<Esc>", 'x')
940 call assert_equal([[1, ''], [0, 'six']], g:MycompleteFunc3_args)
941 bw!
942
943 " Set 'completefunc' to a variable with a lambda expression
944 let Lambda = {a, b -> MycompleteFunc3(a, b)}
945 let &completefunc = string(Lambda)
946 new | only
947 call setline(1, 'seven')
948 let g:MycompleteFunc3_args = []
949 call feedkeys("A\<C-X>\<C-U>\<Esc>", 'x')
950 call assert_equal([[1, ''], [0, 'seven']], g:MycompleteFunc3_args)
951 call assert_fails('let &completefunc = Lambda', 'E729:')
952 bw!
953
954 " Test for using a lambda function with incorrect return value
955 let Lambda = {s -> strlen(s)}
956 let &completefunc = string(Lambda)
957 new | only
958 call setline(1, 'eight')
959 call feedkeys("A\<C-X>\<C-U>\<Esc>", 'x')
960 bw!
961
962 " Test for clearing the 'completefunc' option
963 set completefunc=''
964 set completefunc&
965
966 call assert_fails("set completefunc=function('abc')", "E700:")
967 call assert_fails("set completefunc=funcref('abc')", "E700:")
968 let &completefunc = "{a -> 'abc'}"
969 call feedkeys("A\<C-X>\<C-U>\<Esc>", 'x')
970
971 " Vim9 tests
972 let lines =<< trim END
973 vim9script
974
975 # Test for using function()
976 def MycompleteFunc1(findstart: number, base: string): any
977 add(g:MycompleteFunc1_args, [findstart, base])
978 return findstart ? 0 : []
979 enddef
980 set completefunc=function('MycompleteFunc1')
981 new | only
982 setline(1, 'one')
983 g:MycompleteFunc1_args = []
984 feedkeys("A\<C-X>\<C-U>\<Esc>", 'x')
985 assert_equal([[1, ''], [0, 'one']], g:MycompleteFunc1_args)
986 bw!
987
988 # Test for using a lambda
989 def MycompleteFunc2(findstart: number, base: string): any
990 add(g:MycompleteFunc2_args, [findstart, base])
991 return findstart ? 0 : []
992 enddef
993 &completefunc = '(a, b) => MycompleteFunc2(a, b)'
994 new | only
995 setline(1, 'two')
996 g:MycompleteFunc2_args = []
997 feedkeys("A\<C-X>\<C-U>\<Esc>", 'x')
998 assert_equal([[1, ''], [0, 'two']], g:MycompleteFunc2_args)
999 bw!
1000
1001 # Test for using a variable with a lambda expression
1002 var Fn: func = (a, b) => MycompleteFunc2(a, b)
1003 &completefunc = string(Fn)
1004 new | only
1005 setline(1, 'three')
1006 g:MycompleteFunc2_args = []
1007 feedkeys("A\<C-X>\<C-U>\<Esc>", 'x')
1008 assert_equal([[1, ''], [0, 'three']], g:MycompleteFunc2_args)
1009 bw!
1010 END
1011 call CheckScriptSuccess(lines)
1012
1013 " Using Vim9 lambda expression in legacy context should fail
1014 set completefunc=(a,\ b)\ =>\ g:MycompleteFunc2(a,\ b)
1015 new | only
1016 let g:MycompleteFunc2_args = []
1017 call assert_fails('call feedkeys("A\<C-X>\<C-U>\<Esc>", "x")', 'E117:')
1018 call assert_equal([], g:MycompleteFunc2_args)
1019
1020 " cleanup
1021 delfunc MycompleteFunc1
1022 delfunc MycompleteFunc2
1023 delfunc MycompleteFunc3
1024 set completefunc&
1025 %bw!
1026 endfunc
1027
1028 " Test for different ways of setting the 'omnifunc' option
1029 func Test_omnifunc_callback()
1030 " Test for using a function()
1031 func MyomniFunc1(findstart, base)
1032 call add(g:MyomniFunc1_args, [a:findstart, a:base])
1033 return a:findstart ? 0 : []
1034 endfunc
1035 set omnifunc=function('MyomniFunc1')
1036 new | only
1037 call setline(1, 'one')
1038 let g:MyomniFunc1_args = []
1039 call feedkeys("A\<C-X>\<C-O>\<Esc>", 'x')
1040 call assert_equal([[1, ''], [0, 'one']], g:MyomniFunc1_args)
1041 bw!
1042
1043 " Using a funcref variable to set 'omnifunc'
1044 let Fn = function('MyomniFunc1')
1045 let &omnifunc = string(Fn)
1046 new | only
1047 call setline(1, 'two')
1048 let g:MyomniFunc1_args = []
1049 call feedkeys("A\<C-X>\<C-O>\<Esc>", 'x')
1050 call assert_equal([[1, ''], [0, 'two']], g:MyomniFunc1_args)
1051 call assert_fails('let &omnifunc = Fn', 'E729:')
1052 bw!
1053
1054 " Test for using a funcref()
1055 func MyomniFunc2(findstart, base)
1056 call add(g:MyomniFunc2_args, [a:findstart, a:base])
1057 return a:findstart ? 0 : []
1058 endfunc
1059 set omnifunc=funcref('MyomniFunc2')
1060 new | only
1061 call setline(1, 'three')
1062 let g:MyomniFunc2_args = []
1063 call feedkeys("A\<C-X>\<C-O>\<Esc>", 'x')
1064 call assert_equal([[1, ''], [0, 'three']], g:MyomniFunc2_args)
1065 bw!
1066
1067 " Using a funcref variable to set 'omnifunc'
1068 let Fn = funcref('MyomniFunc2')
1069 let &omnifunc = string(Fn)
1070 new | only
1071 call setline(1, 'four')
1072 let g:MyomniFunc2_args = []
1073 call feedkeys("A\<C-X>\<C-O>\<Esc>", 'x')
1074 call assert_equal([[1, ''], [0, 'four']], g:MyomniFunc2_args)
1075 call assert_fails('let &omnifunc = Fn', 'E729:')
1076 bw!
1077
1078 " Test for using a lambda function
1079 func MyomniFunc3(findstart, base)
1080 call add(g:MyomniFunc3_args, [a:findstart, a:base])
1081 return a:findstart ? 0 : []
1082 endfunc
1083 set omnifunc={a,\ b,\ ->\ MyomniFunc3(a,\ b,)}
1084 new | only
1085 call setline(1, 'five')
1086 let g:MyomniFunc3_args = []
1087 call feedkeys("A\<C-X>\<C-O>\<Esc>", 'x')
1088 call assert_equal([[1, ''], [0, 'five']], g:MyomniFunc3_args)
1089 bw!
1090
1091 " Set 'omnifunc' to a lambda expression
1092 let &omnifunc = '{a, b -> MyomniFunc3(a, b)}'
1093 new | only
1094 call setline(1, 'six')
1095 let g:MyomniFunc3_args = []
1096 call feedkeys("A\<C-X>\<C-O>\<Esc>", 'x')
1097 call assert_equal([[1, ''], [0, 'six']], g:MyomniFunc3_args)
1098 bw!
1099
1100 " Set 'omnifunc' to a variable with a lambda expression
1101 let Lambda = {a, b -> MyomniFunc3(a, b)}
1102 let &omnifunc = string(Lambda)
1103 new | only
1104 call setline(1, 'seven')
1105 let g:MyomniFunc3_args = []
1106 call feedkeys("A\<C-X>\<C-O>\<Esc>", 'x')
1107 call assert_equal([[1, ''], [0, 'seven']], g:MyomniFunc3_args)
1108 call assert_fails('let &omnifunc = Lambda', 'E729:')
1109 bw!
1110
1111 " Test for using a lambda function with incorrect return value
1112 let Lambda = {s -> strlen(s)}
1113 let &omnifunc = string(Lambda)
1114 new | only
1115 call setline(1, 'eight')
1116 call feedkeys("A\<C-X>\<C-O>\<Esc>", 'x')
1117 bw!
1118
1119 " Test for clearing the 'omnifunc' option
1120 set omnifunc=''
1121 set omnifunc&
1122
1123 call assert_fails("set omnifunc=function('abc')", "E700:")
1124 call assert_fails("set omnifunc=funcref('abc')", "E700:")
1125 let &omnifunc = "{a -> 'abc'}"
1126 call feedkeys("A\<C-X>\<C-O>\<Esc>", 'x')
1127
1128 " Vim9 tests
1129 let lines =<< trim END
1130 vim9script
1131
1132 # Test for using function()
1133 def MyomniFunc1(findstart: number, base: string): any
1134 add(g:MyomniFunc1_args, [findstart, base])
1135 return findstart ? 0 : []
1136 enddef
1137 set omnifunc=function('MyomniFunc1')
1138 new | only
1139 setline(1, 'one')
1140 g:MyomniFunc1_args = []
1141 feedkeys("A\<C-X>\<C-O>\<Esc>", 'x')
1142 assert_equal([[1, ''], [0, 'one']], g:MyomniFunc1_args)
1143 bw!
1144
1145 # Test for using a lambda
1146 def MyomniFunc2(findstart: number, base: string): any
1147 add(g:MyomniFunc2_args, [findstart, base])
1148 return findstart ? 0 : []
1149 enddef
1150 &omnifunc = '(a, b) => MyomniFunc2(a, b)'
1151 new | only
1152 setline(1, 'two')
1153 g:MyomniFunc2_args = []
1154 feedkeys("A\<C-X>\<C-O>\<Esc>", 'x')
1155 assert_equal([[1, ''], [0, 'two']], g:MyomniFunc2_args)
1156 bw!
1157
1158 # Test for using a variable with a lambda expression
1159 var Fn: func = (a, b) => MyomniFunc2(a, b)
1160 &omnifunc = string(Fn)
1161 new | only
1162 setline(1, 'three')
1163 g:MyomniFunc2_args = []
1164 feedkeys("A\<C-X>\<C-O>\<Esc>", 'x')
1165 assert_equal([[1, ''], [0, 'three']], g:MyomniFunc2_args)
1166 bw!
1167 END
1168 call CheckScriptSuccess(lines)
1169
1170 " Using Vim9 lambda expression in legacy context should fail
1171 set omnifunc=(a,\ b)\ =>\ g:MyomniFunc2(a,\ b)
1172 new | only
1173 let g:MyomniFunc2_args = []
1174 call assert_fails('call feedkeys("A\<C-X>\<C-O>\<Esc>", "x")', 'E117:')
1175 call assert_equal([], g:MyomniFunc2_args)
1176
1177 " cleanup
1178 delfunc MyomniFunc1
1179 delfunc MyomniFunc2
1180 delfunc MyomniFunc3
1181 set omnifunc&
1182 %bw!
1183 endfunc
1184
1185 " Test for different ways of setting the 'thesaurusfunc' option
1186 func Test_thesaurusfunc_callback()
1187 " Test for using a function()
1188 func MytsrFunc1(findstart, base)
1189 call add(g:MytsrFunc1_args, [a:findstart, a:base])
1190 return a:findstart ? 0 : []
1191 endfunc
1192 set thesaurusfunc=function('MytsrFunc1')
1193 new | only
1194 call setline(1, 'one')
1195 let g:MytsrFunc1_args = []
1196 call feedkeys("A\<C-X>\<C-T>\<Esc>", 'x')
1197 call assert_equal([[1, ''], [0, 'one']], g:MytsrFunc1_args)
1198 bw!
1199
1200 " Using a funcref variable to set 'thesaurusfunc'
1201 let Fn = function('MytsrFunc1')
1202 let &thesaurusfunc = string(Fn)
1203 new | only
1204 call setline(1, 'two')
1205 let g:MytsrFunc1_args = []
1206 call feedkeys("A\<C-X>\<C-T>\<Esc>", 'x')
1207 call assert_equal([[1, ''], [0, 'two']], g:MytsrFunc1_args)
1208 call assert_fails('let &thesaurusfunc = Fn', 'E729:')
1209 bw!
1210
1211 " Test for using a funcref()
1212 func MytsrFunc2(findstart, base)
1213 call add(g:MytsrFunc2_args, [a:findstart, a:base])
1214 return a:findstart ? 0 : []
1215 endfunc
1216 set thesaurusfunc=funcref('MytsrFunc2')
1217 new | only
1218 call setline(1, 'three')
1219 let g:MytsrFunc2_args = []
1220 call feedkeys("A\<C-X>\<C-T>\<Esc>", 'x')
1221 call assert_equal([[1, ''], [0, 'three']], g:MytsrFunc2_args)
1222 bw!
1223
1224 " Using a funcref variable to set 'thesaurusfunc'
1225 let Fn = funcref('MytsrFunc2')
1226 let &thesaurusfunc = string(Fn)
1227 new | only
1228 call setline(1, 'four')
1229 let g:MytsrFunc2_args = []
1230 call feedkeys("A\<C-X>\<C-T>\<Esc>", 'x')
1231 call assert_equal([[1, ''], [0, 'four']], g:MytsrFunc2_args)
1232 call assert_fails('let &thesaurusfunc = Fn', 'E729:')
1233 bw!
1234
1235 " Test for using a lambda function
1236 func MytsrFunc3(findstart, base)
1237 call add(g:MytsrFunc3_args, [a:findstart, a:base])
1238 return a:findstart ? 0 : []
1239 endfunc
1240 set thesaurusfunc={a,\ b,\ ->\ MytsrFunc3(a,\ b,)}
1241 new | only
1242 call setline(1, 'five')
1243 let g:MytsrFunc3_args = []
1244 call feedkeys("A\<C-X>\<C-T>\<Esc>", 'x')
1245 call assert_equal([[1, ''], [0, 'five']], g:MytsrFunc3_args)
1246 bw!
1247
1248 " Set 'thesaurusfunc' to a lambda expression
1249 let &thesaurusfunc = '{a, b -> MytsrFunc3(a, b)}'
1250 new | only
1251 call setline(1, 'six')
1252 let g:MytsrFunc3_args = []
1253 call feedkeys("A\<C-X>\<C-T>\<Esc>", 'x')
1254 call assert_equal([[1, ''], [0, 'six']], g:MytsrFunc3_args)
1255 bw!
1256
1257 " Set 'thesaurusfunc' to a variable with a lambda expression
1258 let Lambda = {a, b -> MytsrFunc3(a, b)}
1259 let &thesaurusfunc = string(Lambda)
1260 new | only
1261 call setline(1, 'seven')
1262 let g:MytsrFunc3_args = []
1263 call feedkeys("A\<C-X>\<C-T>\<Esc>", 'x')
1264 call assert_equal([[1, ''], [0, 'seven']], g:MytsrFunc3_args)
1265 call assert_fails('let &thesaurusfunc = Lambda', 'E729:')
1266 bw!
1267
1268 " Test for using a lambda function with incorrect return value
1269 let Lambda = {s -> strlen(s)}
1270 let &thesaurusfunc = string(Lambda)
1271 new | only
1272 call setline(1, 'eight')
1273 call feedkeys("A\<C-X>\<C-T>\<Esc>", 'x')
1274 bw!
1275
1276 " Test for clearing the 'thesaurusfunc' option
1277 set thesaurusfunc=''
1278 set thesaurusfunc&
1279
1280 call assert_fails("set thesaurusfunc=function('abc')", "E700:")
1281 call assert_fails("set thesaurusfunc=funcref('abc')", "E700:")
1282 let &thesaurusfunc = "{a -> 'abc'}"
1283 call feedkeys("A\<C-X>\<C-T>\<Esc>", 'x')
1284
1285 " Vim9 tests
1286 let lines =<< trim END
1287 vim9script
1288
1289 # Test for using function()
1290 def MytsrFunc1(findstart: number, base: string): any
1291 add(g:MytsrFunc1_args, [findstart, base])
1292 return findstart ? 0 : []
1293 enddef
1294 set thesaurusfunc=function('MytsrFunc1')
1295 new | only
1296 setline(1, 'one')
1297 g:MytsrFunc1_args = []
1298 feedkeys("A\<C-X>\<C-T>\<Esc>", 'x')
1299 assert_equal([[1, ''], [0, 'one']], g:MytsrFunc1_args)
1300 bw!
1301
1302 # Test for using a lambda
1303 def MytsrFunc2(findstart: number, base: string): any
1304 add(g:MytsrFunc2_args, [findstart, base])
1305 return findstart ? 0 : []
1306 enddef
1307 &thesaurusfunc = '(a, b) => MytsrFunc2(a, b)'
1308 new | only
1309 setline(1, 'two')
1310 g:MytsrFunc2_args = []
1311 feedkeys("A\<C-X>\<C-T>\<Esc>", 'x')
1312 assert_equal([[1, ''], [0, 'two']], g:MytsrFunc2_args)
1313 bw!
1314
1315 # Test for using a variable with a lambda expression
1316 var Fn: func = (a, b) => MytsrFunc2(a, b)
1317 &thesaurusfunc = string(Fn)
1318 new | only
1319 setline(1, 'three')
1320 g:MytsrFunc2_args = []
1321 feedkeys("A\<C-X>\<C-T>\<Esc>", 'x')
1322 assert_equal([[1, ''], [0, 'three']], g:MytsrFunc2_args)
1323 bw!
1324 END
1325 call CheckScriptSuccess(lines)
1326
1327 " Using Vim9 lambda expression in legacy context should fail
1328 set thesaurusfunc=(a,\ b)\ =>\ g:MytsrFunc2(a,\ b)
1329 new | only
1330 let g:MytsrFunc2_args = []
1331 call assert_fails('call feedkeys("A\<C-X>\<C-T>\<Esc>", "x")', 'E117:')
1332 call assert_equal([], g:MytsrFunc2_args)
1333 bw!
1334
1335 " Use a buffer-local value and a global value
1336 func MytsrFunc4(findstart, base)
1337 call add(g:MytsrFunc4_args, [a:findstart, a:base])
1338 return a:findstart ? 0 : ['sunday']
1339 endfunc
1340 set thesaurusfunc&
1341 setlocal thesaurusfunc=function('MytsrFunc4')
1342 call setline(1, 'sun')
1343 let g:MytsrFunc4_args = []
1344 call feedkeys("A\<C-X>\<C-T>\<Esc>", "x")
1345 call assert_equal('sunday', getline(1))
1346 call assert_equal([[1, ''], [0, 'sun']], g:MytsrFunc4_args)
1347 new
1348 call setline(1, 'sun')
1349 let g:MytsrFunc4_args = []
1350 call feedkeys("A\<C-X>\<C-T>\<Esc>", "x")
1351 call assert_equal('sun', getline(1))
1352 call assert_equal([], g:MytsrFunc4_args)
1353 set thesaurusfunc=function('MytsrFunc1')
1354 wincmd w
1355 call setline(1, 'sun')
1356 let g:MytsrFunc4_args = []
1357 call feedkeys("A\<C-X>\<C-T>\<Esc>", "x")
1358 call assert_equal('sunday', getline(1))
1359 call assert_equal([[1, ''], [0, 'sun']], g:MytsrFunc4_args)
1360
1361 " cleanup
1362 set thesaurusfunc&
1363 delfunc MytsrFunc1
1364 delfunc MytsrFunc2
1365 delfunc MytsrFunc3
1366 delfunc MytsrFunc4
1367 %bw!
1368 endfunc
1369
870 " vim: shiftwidth=2 sts=2 expandtab 1370 " vim: shiftwidth=2 sts=2 expandtab