blob: 8abb680622c1de7cd77b3dc9efa4c6c7821a1b02 [file] [log] [blame]
Bram Moolenaar08cc3742019-08-11 22:51:14 +02001" Test for commands that operate on the spellfile.
2
3source shared.vim
4source check.vim
5
6CheckFeature spell
7CheckFeature syntax
8
9func Test_spell_normal()
10 new
11 call append(0, ['1 good', '2 goood', '3 goood'])
12 set spell spellfile=./Xspellfile.add spelllang=en
13 let oldlang=v:lang
14 lang C
15
16 " Test for zg
17 1
18 norm! ]s
19 call assert_equal('2 goood', getline('.'))
20 norm! zg
21 1
22 let a=execute('unsilent :norm! ]s')
23 call assert_equal('1 good', getline('.'))
24 call assert_equal('search hit BOTTOM, continuing at TOP', a[1:])
25 let cnt=readfile('./Xspellfile.add')
26 call assert_equal('goood', cnt[0])
27
Bram Moolenaar8a9bc952020-10-02 18:48:07 +020028 " zg should fail in operator-pending mode
29 call assert_beeps('norm! czg')
30
31 " zg fails in visual mode when not able to get the visual text
32 call assert_beeps('norm! ggVjzg')
33 norm! V
34
35 " zg fails for a non-identifier word
36 call append(line('$'), '###')
37 call assert_fails('norm! Gzg', 'E349:')
38 $d
39
Bram Moolenaar08cc3742019-08-11 22:51:14 +020040 " Test for zw
41 2
42 norm! $zw
43 1
44 norm! ]s
45 call assert_equal('2 goood', getline('.'))
46 let cnt=readfile('./Xspellfile.add')
47 call assert_equal('#oood', cnt[0])
48 call assert_equal('goood/!', cnt[1])
49
50 " Test for :spellrare
51 spellrare rare
52 let cnt=readfile('./Xspellfile.add')
53 call assert_equal(['#oood', 'goood/!', 'rare/?'], cnt)
54
55 " Make sure :spellundo works for rare words.
56 spellundo rare
57 let cnt=readfile('./Xspellfile.add')
58 call assert_equal(['#oood', 'goood/!', '#are/?'], cnt)
59
60 " Test for zg in visual mode
61 let a=execute('unsilent :norm! V$zg')
62 call assert_equal("Word '2 goood' added to ./Xspellfile.add", a[1:])
63 1
64 norm! ]s
65 call assert_equal('3 goood', getline('.'))
66 let cnt=readfile('./Xspellfile.add')
67 call assert_equal('2 goood', cnt[3])
68 " Remove "2 good" from spellfile
69 2
70 let a=execute('unsilent norm! V$zw')
71 call assert_equal("Word '2 goood' added to ./Xspellfile.add", a[1:])
72 let cnt=readfile('./Xspellfile.add')
73 call assert_equal('2 goood/!', cnt[4])
74
75 " Test for zG
76 let a=execute('unsilent norm! V$zG')
77 call assert_match("Word '2 goood' added to .*", a)
78 let fname=matchstr(a, 'to\s\+\zs\f\+$')
79 let cnt=readfile(fname)
80 call assert_equal('2 goood', cnt[0])
81
82 " Test for zW
83 let a=execute('unsilent norm! V$zW')
84 call assert_match("Word '2 goood' added to .*", a)
85 let cnt=readfile(fname)
86 call assert_equal('# goood', cnt[0])
87 call assert_equal('2 goood/!', cnt[1])
88
89 " Test for zuW
90 let a=execute('unsilent norm! V$zuW')
91 call assert_match("Word '2 goood' removed from .*", a)
92 let cnt=readfile(fname)
93 call assert_equal('# goood', cnt[0])
94 call assert_equal('# goood/!', cnt[1])
95
96 " Test for zuG
97 let a=execute('unsilent norm! $zG')
98 call assert_match("Word 'goood' added to .*", a)
99 let cnt=readfile(fname)
100 call assert_equal('# goood', cnt[0])
101 call assert_equal('# goood/!', cnt[1])
102 call assert_equal('goood', cnt[2])
103 let a=execute('unsilent norm! $zuG')
104 let cnt=readfile(fname)
105 call assert_match("Word 'goood' removed from .*", a)
106 call assert_equal('# goood', cnt[0])
107 call assert_equal('# goood/!', cnt[1])
108 call assert_equal('#oood', cnt[2])
109 " word not found in wordlist
110 let a=execute('unsilent norm! V$zuG')
111 let cnt=readfile(fname)
112 call assert_match("", a)
113 call assert_equal('# goood', cnt[0])
114 call assert_equal('# goood/!', cnt[1])
115 call assert_equal('#oood', cnt[2])
116
117 " Test for zug
118 call delete('./Xspellfile.add')
119 2
120 let a=execute('unsilent norm! $zg')
121 let cnt=readfile('./Xspellfile.add')
122 call assert_equal('goood', cnt[0])
123 let a=execute('unsilent norm! $zug')
124 call assert_match("Word 'goood' removed from \./Xspellfile.add", a)
125 let cnt=readfile('./Xspellfile.add')
126 call assert_equal('#oood', cnt[0])
127 " word not in wordlist
128 let a=execute('unsilent norm! V$zug')
129 call assert_match('', a)
130 let cnt=readfile('./Xspellfile.add')
131 call assert_equal('#oood', cnt[0])
132
133 " Test for zuw
134 call delete('./Xspellfile.add')
135 2
136 let a=execute('unsilent norm! Vzw')
137 let cnt=readfile('./Xspellfile.add')
138 call assert_equal('2 goood/!', cnt[0])
139 let a=execute('unsilent norm! Vzuw')
140 call assert_match("Word '2 goood' removed from \./Xspellfile.add", a)
141 let cnt=readfile('./Xspellfile.add')
142 call assert_equal('# goood/!', cnt[0])
143 " word not in wordlist
144 let a=execute('unsilent norm! $zug')
145 call assert_match('', a)
146 let cnt=readfile('./Xspellfile.add')
147 call assert_equal('# goood/!', cnt[0])
148
149 " add second entry to spellfile setting
150 set spellfile=./Xspellfile.add,./Xspellfile2.add
151 call delete('./Xspellfile.add')
152 2
153 let a=execute('unsilent norm! $2zg')
154 let cnt=readfile('./Xspellfile2.add')
155 call assert_match("Word 'goood' added to ./Xspellfile2.add", a)
156 call assert_equal('goood', cnt[0])
157
158 " Test for :spellgood!
159 let temp = execute(':spe!0/0')
160 call assert_match('Invalid region', temp)
161 let spellfile = matchstr(temp, 'Invalid region nr in \zs.*\ze line \d: 0')
162 call assert_equal(['# goood', '# goood/!', '#oood', '0/0'], readfile(spellfile))
163
164 " Test for :spellrare!
165 :spellrare! raare
166 call assert_equal(['# goood', '# goood/!', '#oood', '0/0', 'raare/?'], readfile(spellfile))
167 call delete(spellfile)
168
169 " clean up
170 exe "lang" oldlang
171 call delete("./Xspellfile.add")
172 call delete("./Xspellfile2.add")
173 call delete("./Xspellfile.add.spl")
174 call delete("./Xspellfile2.add.spl")
175
176 " zux -> no-op
177 2
178 norm! $zux
179 call assert_equal([], glob('Xspellfile.add',0,1))
180 call assert_equal([], glob('Xspellfile2.add',0,1))
181
Bram Moolenaarc0f88232020-08-16 21:51:49 +0200182 set spellfile= spell& spelllang&
Bram Moolenaar08cc3742019-08-11 22:51:14 +0200183 bw!
184endfunc
Bram Moolenaar6d91bcb2020-08-12 18:50:36 +0200185
Bram Moolenaarfc2a47f2020-08-20 15:41:55 +0200186" Spell file content test. Write 'content' to the spell file prefixed by the
187" spell file header and then enable spell checking. If 'emsg' is not empty,
188" then check for error.
189func Spellfile_Test(content, emsg)
190 let splfile = './Xtest/spell/Xtest.utf-8.spl'
191 " Add the spell file header and version (VIMspell2)
192 let v = 0z56494D7370656C6C32 + a:content
193 call writefile(v, splfile, 'b')
Bram Moolenaar64e2db62020-09-09 22:43:19 +0200194
195 " 'encoding' is set before each test to clear the previously loaded suggest
196 " file from memory.
197 set encoding=utf-8
198
Bram Moolenaarfc2a47f2020-08-20 15:41:55 +0200199 set runtimepath=./Xtest
200 set spelllang=Xtest
201 if a:emsg != ''
202 call assert_fails('set spell', a:emsg)
203 else
204 " FIXME: With some invalid spellfile contents, there are no error
205 " messages. So don't know how to check for the test result.
206 set spell
207 endif
208 set nospell spelllang& rtp&
209endfunc
210
211" Test for spell file format errors.
212" The spell file format is described in spellfile.c
Bram Moolenaarc0f88232020-08-16 21:51:49 +0200213func Test_spellfile_format_error()
214 let save_rtp = &rtp
Bram Moolenaar56564962022-10-10 22:39:42 +0100215 call mkdir('Xtest/spell', 'pR')
Bram Moolenaarfc2a47f2020-08-20 15:41:55 +0200216 let splfile = './Xtest/spell/Xtest.utf-8.spl'
Bram Moolenaarc0f88232020-08-16 21:51:49 +0200217
218 " empty spell file
Bram Moolenaarfc2a47f2020-08-20 15:41:55 +0200219 call writefile([], splfile)
Bram Moolenaarc0f88232020-08-16 21:51:49 +0200220 set runtimepath=./Xtest
221 set spelllang=Xtest
222 call assert_fails('set spell', 'E757:')
223 set nospell spelllang&
224
225 " invalid file ID
Bram Moolenaarfc2a47f2020-08-20 15:41:55 +0200226 call writefile(0z56494D, splfile, 'b')
Bram Moolenaarc0f88232020-08-16 21:51:49 +0200227 set runtimepath=./Xtest
228 set spelllang=Xtest
229 call assert_fails('set spell', 'E757:')
230 set nospell spelllang&
231
232 " missing version number
Bram Moolenaarfc2a47f2020-08-20 15:41:55 +0200233 call writefile(0z56494D7370656C6C, splfile, 'b')
Bram Moolenaarc0f88232020-08-16 21:51:49 +0200234 set runtimepath=./Xtest
235 set spelllang=Xtest
236 call assert_fails('set spell', 'E771:')
237 set nospell spelllang&
238
239 " invalid version number
Bram Moolenaarfc2a47f2020-08-20 15:41:55 +0200240 call writefile(0z56494D7370656C6C7A, splfile, 'b')
Bram Moolenaarc0f88232020-08-16 21:51:49 +0200241 set runtimepath=./Xtest
242 set spelllang=Xtest
243 call assert_fails('set spell', 'E772:')
244 set nospell spelllang&
245
246 " no sections
Bram Moolenaarfc2a47f2020-08-20 15:41:55 +0200247 call Spellfile_Test(0z, 'E758:')
Bram Moolenaarc0f88232020-08-16 21:51:49 +0200248
249 " missing section length
Bram Moolenaarfc2a47f2020-08-20 15:41:55 +0200250 call Spellfile_Test(0z00, 'E758:')
Bram Moolenaarc0f88232020-08-16 21:51:49 +0200251
252 " unsupported required section
Bram Moolenaarfc2a47f2020-08-20 15:41:55 +0200253 call Spellfile_Test(0z7A0100000004, 'E770:')
Bram Moolenaarc0f88232020-08-16 21:51:49 +0200254
255 " unsupported not-required section
Bram Moolenaarfc2a47f2020-08-20 15:41:55 +0200256 call Spellfile_Test(0z7A0000000004, 'E758:')
Bram Moolenaarc0f88232020-08-16 21:51:49 +0200257
258 " SN_REGION: invalid number of region names
Bram Moolenaarfc2a47f2020-08-20 15:41:55 +0200259 call Spellfile_Test(0z0000000000FF, 'E759:')
Bram Moolenaarc0f88232020-08-16 21:51:49 +0200260
261 " SN_CHARFLAGS: missing <charflagslen> length
Bram Moolenaarfc2a47f2020-08-20 15:41:55 +0200262 call Spellfile_Test(0z010000000004, 'E758:')
Bram Moolenaarc0f88232020-08-16 21:51:49 +0200263
264 " SN_CHARFLAGS: invalid <charflagslen> length
Bram Moolenaarfc2a47f2020-08-20 15:41:55 +0200265 call Spellfile_Test(0z0100000000010201, '')
Bram Moolenaarc0f88232020-08-16 21:51:49 +0200266
267 " SN_CHARFLAGS: charflagslen == 0 and folcharslen != 0
Bram Moolenaarfc2a47f2020-08-20 15:41:55 +0200268 call Spellfile_Test(0z01000000000400000101, 'E759:')
Bram Moolenaarc0f88232020-08-16 21:51:49 +0200269
270 " SN_CHARFLAGS: missing <folcharslen> length
Bram Moolenaarfc2a47f2020-08-20 15:41:55 +0200271 call Spellfile_Test(0z01000000000100, 'E758:')
Bram Moolenaarc0f88232020-08-16 21:51:49 +0200272
273 " SN_PREFCOND: invalid prefcondcnt
Bram Moolenaarfc2a47f2020-08-20 15:41:55 +0200274 call Spellfile_Test(0z03000000000100, 'E759:')
Bram Moolenaarc0f88232020-08-16 21:51:49 +0200275
276 " SN_PREFCOND: invalid condlen
Bram Moolenaarfc2a47f2020-08-20 15:41:55 +0200277 call Spellfile_Test(0z0300000000020001, 'E759:')
Bram Moolenaarc0f88232020-08-16 21:51:49 +0200278
279 " SN_REP: invalid repcount
Bram Moolenaarfc2a47f2020-08-20 15:41:55 +0200280 call Spellfile_Test(0z04000000000100, 'E758:')
Bram Moolenaarc0f88232020-08-16 21:51:49 +0200281
282 " SN_REP: missing rep
Bram Moolenaarfc2a47f2020-08-20 15:41:55 +0200283 call Spellfile_Test(0z0400000000020004, 'E758:')
Bram Moolenaarc0f88232020-08-16 21:51:49 +0200284
285 " SN_REP: zero repfromlen
Bram Moolenaarfc2a47f2020-08-20 15:41:55 +0200286 call Spellfile_Test(0z040000000003000100, 'E759:')
Bram Moolenaarc0f88232020-08-16 21:51:49 +0200287
288 " SN_REP: invalid reptolen
Bram Moolenaarfc2a47f2020-08-20 15:41:55 +0200289 call Spellfile_Test(0z0400000000050001014101, '')
Bram Moolenaarc0f88232020-08-16 21:51:49 +0200290
291 " SN_REP: zero reptolen
Bram Moolenaarfc2a47f2020-08-20 15:41:55 +0200292 call Spellfile_Test(0z0400000000050001014100, 'E759:')
293
294 " SN_SAL: missing salcount
295 call Spellfile_Test(0z05000000000102, 'E758:')
296
297 " SN_SAL: missing salfromlen
298 call Spellfile_Test(0z050000000003080001, 'E758:')
299
300 " SN_SAL: missing saltolen
301 call Spellfile_Test(0z0500000000050400010161, 'E758:')
302
303 " SN_WORDS: non-NUL terminated word
304 call Spellfile_Test(0z0D000000000376696D, 'E758:')
305
306 " SN_WORDS: very long word
307 let v = eval('0z0D000000012C' .. repeat('41', 300))
308 call Spellfile_Test(v, 'E759:')
309
310 " SN_SOFO: missing sofofromlen
311 call Spellfile_Test(0z06000000000100, 'E758:')
312
313 " SN_SOFO: missing sofotolen
314 call Spellfile_Test(0z06000000000400016100, 'E758:')
315
316 " SN_SOFO: missing sofoto
317 call Spellfile_Test(0z0600000000050001610000, 'E759:')
318
Bram Moolenaar64e2db62020-09-09 22:43:19 +0200319 " SN_SOFO: empty sofofrom and sofoto
320 call Spellfile_Test(0z06000000000400000000FF000000000000000000000000, '')
321
Bram Moolenaar96fdf432020-09-11 18:11:50 +0200322 " SN_SOFO: multi-byte characters in sofofrom and sofoto
323 call Spellfile_Test(0z0600000000080002CF810002CF82FF000000000000000000000000, '')
324
Bram Moolenaarfc2a47f2020-08-20 15:41:55 +0200325 " SN_COMPOUND: compmax is less than 2
326 call Spellfile_Test(0z08000000000101, 'E759:')
327
328 " SN_COMPOUND: missing compsylmax and other options
329 call Spellfile_Test(0z0800000000020401, 'E759:')
330
331 " SN_COMPOUND: missing compoptions
332 call Spellfile_Test(0z080000000005040101, 'E758:')
333
Bram Moolenaar64e2db62020-09-09 22:43:19 +0200334 " SN_COMPOUND: missing comppattern
335 call Spellfile_Test(0z08000000000704010100000001, 'E758:')
336
337 " SN_COMPOUND: incorrect comppatlen
338 call Spellfile_Test(0z080000000007040101000000020165, 'E758:')
339
Bram Moolenaarfc2a47f2020-08-20 15:41:55 +0200340 " SN_INFO: missing info
341 call Spellfile_Test(0z0F0000000005040101, '')
342
343 " SN_MIDWORD: missing midword
344 call Spellfile_Test(0z0200000000040102, '')
345
346 " SN_MAP: missing midword
347 call Spellfile_Test(0z0700000000040102, '')
348
Bram Moolenaar64e2db62020-09-09 22:43:19 +0200349 " SN_MAP: empty map string
350 call Spellfile_Test(0z070000000000FF000000000000000000000000, '')
351
352 " SN_MAP: duplicate multibyte character
353 call Spellfile_Test(0z070000000004DC81DC81, 'E783:')
354
Bram Moolenaarfc2a47f2020-08-20 15:41:55 +0200355 " SN_SYLLABLE: missing SYLLABLE item
356 call Spellfile_Test(0z0900000000040102, '')
357
358 " SN_SYLLABLE: More than SY_MAXLEN size
359 let v = eval('0z090000000022612F' .. repeat('62', 32))
360 call Spellfile_Test(v, '')
361
362 " LWORDTREE: missing
363 call Spellfile_Test(0zFF, 'E758:')
364
365 " LWORDTREE: missing tree node
366 call Spellfile_Test(0zFF00000004, 'E758:')
367
368 " LWORDTREE: missing tree node value
369 call Spellfile_Test(0zFF0000000402, 'E758:')
370
Bram Moolenaar64e2db62020-09-09 22:43:19 +0200371 " LWORDTREE: incorrect sibling node count
372 call Spellfile_Test(0zFF00000001040000000000000000, 'E759:')
373
Bram Moolenaarfc2a47f2020-08-20 15:41:55 +0200374 " KWORDTREE: missing tree node
375 call Spellfile_Test(0zFF0000000000000004, 'E758:')
376
377 " PREFIXTREE: missing tree node
378 call Spellfile_Test(0zFF000000000000000000000004, 'E758:')
379
Bram Moolenaar64e2db62020-09-09 22:43:19 +0200380 " PREFIXTREE: incorrect prefcondnr
381 call Spellfile_Test(0zFF000000000000000000000002010200000020, 'E759:')
382
383 " PREFIXTREE: invalid nodeidx
384 call Spellfile_Test(0zFF00000000000000000000000201010000, 'E759:')
385
Bram Moolenaarfc2a47f2020-08-20 15:41:55 +0200386 let &rtp = save_rtp
Bram Moolenaarfc2a47f2020-08-20 15:41:55 +0200387endfunc
388
389" Test for format errors in suggest file
390func Test_sugfile_format_error()
391 let save_rtp = &rtp
Bram Moolenaar56564962022-10-10 22:39:42 +0100392 call mkdir('Xtest/spell', 'pR')
Bram Moolenaarfc2a47f2020-08-20 15:41:55 +0200393 let splfile = './Xtest/spell/Xtest.utf-8.spl'
394 let sugfile = './Xtest/spell/Xtest.utf-8.sug'
395
396 " create an empty spell file with a suggest timestamp
397 call writefile(0z56494D7370656C6C320B00000000080000000000000044FF000000000000000000000000, splfile, 'b')
398
399 " 'encoding' is set before each test to clear the previously loaded suggest
400 " file from memory.
401
402 " empty suggest file
403 set encoding=utf-8
404 call writefile([], sugfile)
Bram Moolenaarc0f88232020-08-16 21:51:49 +0200405 set runtimepath=./Xtest
406 set spelllang=Xtest
Bram Moolenaarfc2a47f2020-08-20 15:41:55 +0200407 set spell
408 call assert_fails("let s = spellsuggest('abc')", 'E778:')
409 set nospell spelllang&
410
411 " zero suggest version
412 set encoding=utf-8
413 call writefile(0z56494D73756700, sugfile)
414 set runtimepath=./Xtest
415 set spelllang=Xtest
416 set spell
417 call assert_fails("let s = spellsuggest('abc')", 'E779:')
418 set nospell spelllang&
419
420 " unsupported suggest version
421 set encoding=utf-8
422 call writefile(0z56494D7375671F, sugfile)
423 set runtimepath=./Xtest
424 set spelllang=Xtest
425 set spell
426 call assert_fails("let s = spellsuggest('abc')", 'E780:')
427 set nospell spelllang&
428
429 " missing suggest timestamp
430 set encoding=utf-8
431 call writefile(0z56494D73756701, sugfile)
432 set runtimepath=./Xtest
433 set spelllang=Xtest
434 set spell
435 call assert_fails("let s = spellsuggest('abc')", 'E781:')
436 set nospell spelllang&
437
438 " incorrect suggest timestamp
439 set encoding=utf-8
440 call writefile(0z56494D7375670100000000000000FF, sugfile)
441 set runtimepath=./Xtest
442 set spelllang=Xtest
443 set spell
444 call assert_fails("let s = spellsuggest('abc')", 'E781:')
445 set nospell spelllang&
446
447 " missing suggest wordtree
448 set encoding=utf-8
449 call writefile(0z56494D737567010000000000000044, sugfile)
450 set runtimepath=./Xtest
451 set spelllang=Xtest
452 set spell
453 call assert_fails("let s = spellsuggest('abc')", 'E782:')
Bram Moolenaarc0f88232020-08-16 21:51:49 +0200454 set nospell spelllang&
455
Bram Moolenaarb9fc1922020-08-25 21:19:36 +0200456 " invalid suggest word count in SUGTABLE
457 set encoding=utf-8
458 call writefile(0z56494D7375670100000000000000440000000022, sugfile)
459 set runtimepath=./Xtest
460 set spelllang=Xtest
461 set spell
462 call assert_fails("let s = spellsuggest('abc')", 'E782:')
463 set nospell spelllang&
464
465 " missing sugline in SUGTABLE
466 set encoding=utf-8
467 call writefile(0z56494D7375670100000000000000440000000000000005, sugfile)
468 set runtimepath=./Xtest
469 set spelllang=Xtest
470 set spell
471 call assert_fails("let s = spellsuggest('abc')", 'E782:')
472 set nospell spelllang&
473
Bram Moolenaarc0f88232020-08-16 21:51:49 +0200474 let &rtp = save_rtp
Bram Moolenaarc0f88232020-08-16 21:51:49 +0200475endfunc
476
Bram Moolenaarfc2a47f2020-08-20 15:41:55 +0200477" Test for using :mkspell to create a spell file from a list of words
478func Test_wordlist_dic()
479 " duplicate encoding
480 let lines =<< trim [END]
481 # This is an example word list
482
483 /encoding=latin1
484 /encoding=latin1
485 example
486 [END]
Bram Moolenaar56564962022-10-10 22:39:42 +0100487 call writefile(lines, 'Xwordlist.dic', 'D')
Bram Moolenaarfc2a47f2020-08-20 15:41:55 +0200488 let output = execute('mkspell Xwordlist.spl Xwordlist.dic')
489 call assert_match('Duplicate /encoding= line ignored in Xwordlist.dic line 4: /encoding=latin1', output)
490
491 " multiple encoding for a word
492 let lines =<< trim [END]
493 example
494 /encoding=latin1
495 example
496 [END]
497 call writefile(lines, 'Xwordlist.dic')
498 let output = execute('mkspell! Xwordlist.spl Xwordlist.dic')
499 call assert_match('/encoding= line after word ignored in Xwordlist.dic line 2: /encoding=latin1', output)
500
501 " unsupported encoding for a word
502 let lines =<< trim [END]
503 /encoding=Xtest
504 example
505 [END]
506 call writefile(lines, 'Xwordlist.dic')
507 let output = execute('mkspell! Xwordlist.spl Xwordlist.dic')
508 call assert_match('Conversion in Xwordlist.dic not supported: from Xtest to utf-8', output)
509
510 " duplicate region
511 let lines =<< trim [END]
512 /regions=usca
513 /regions=usca
514 example
515 [END]
516 call writefile(lines, 'Xwordlist.dic')
517 let output = execute('mkspell! Xwordlist.spl Xwordlist.dic')
518 call assert_match('Duplicate /regions= line ignored in Xwordlist.dic line 2: regions=usca', output)
519
520 " maximum regions
521 let lines =<< trim [END]
522 /regions=uscauscauscauscausca
523 example
524 [END]
525 call writefile(lines, 'Xwordlist.dic')
526 let output = execute('mkspell! Xwordlist.spl Xwordlist.dic')
527 call assert_match('Too many regions in Xwordlist.dic line 1: uscauscauscauscausca', output)
528
529 " unsupported '/' value
530 let lines =<< trim [END]
531 /test=abc
532 example
533 [END]
534 call writefile(lines, 'Xwordlist.dic')
535 let output = execute('mkspell! Xwordlist.spl Xwordlist.dic')
536 call assert_match('/ line ignored in Xwordlist.dic line 1: /test=abc', output)
537
538 " unsupported flag
539 let lines =<< trim [END]
540 example/+
541 [END]
542 call writefile(lines, 'Xwordlist.dic')
543 let output = execute('mkspell! Xwordlist.spl Xwordlist.dic')
544 call assert_match('Unrecognized flags in Xwordlist.dic line 1: +', output)
545
546 " non-ascii word
547 call writefile(["ʀʀ"], 'Xwordlist.dic')
548 let output = execute('mkspell! -ascii Xwordlist.spl Xwordlist.dic')
549 call assert_match('Ignored 1 words with non-ASCII characters', output)
550
Bram Moolenaar64e2db62020-09-09 22:43:19 +0200551 " keep case of a word
552 let lines =<< trim [END]
553 example/=
554 [END]
555 call writefile(lines, 'Xwordlist.dic')
556 let output = execute('mkspell! Xwordlist.spl Xwordlist.dic')
557 call assert_match('Compressed keep-case:', output)
558
Bram Moolenaarfc2a47f2020-08-20 15:41:55 +0200559 call delete('Xwordlist.spl')
Bram Moolenaarfc2a47f2020-08-20 15:41:55 +0200560endfunc
561
562" Test for the :mkspell command
563func Test_mkspell()
564 call assert_fails('mkspell Xtest_us.spl', 'E751:')
Bram Moolenaar96fdf432020-09-11 18:11:50 +0200565 call assert_fails('mkspell Xtest.spl abc', 'E484:')
Bram Moolenaarfc2a47f2020-08-20 15:41:55 +0200566 call assert_fails('mkspell a b c d e f g h i j k', 'E754:')
567
Bram Moolenaar96fdf432020-09-11 18:11:50 +0200568 " create a .aff file but not the .dic file
569 call writefile([], 'Xtest.aff')
570 call assert_fails('mkspell Xtest.spl Xtest', 'E484:')
571 call delete('Xtest.aff')
572
Bram Moolenaarfc2a47f2020-08-20 15:41:55 +0200573 call writefile([], 'Xtest.spl')
574 call writefile([], 'Xtest.dic')
575 call assert_fails('mkspell Xtest.spl Xtest.dic', 'E13:')
576 call delete('Xtest.spl')
577 call delete('Xtest.dic')
578
579 call mkdir('Xtest.spl')
580 call assert_fails('mkspell! Xtest.spl Xtest.dic', 'E17:')
581 call delete('Xtest.spl', 'rf')
582
Dominique Pelle5a6cfb32021-05-29 17:29:33 +0200583 " can't write the .spl file as its directory does not exist
584 call writefile([], 'Xtest.aff')
585 call writefile([], 'Xtest.dic')
586 call assert_fails('mkspell DOES_NOT_EXIT/Xtest.spl Xtest.dic', 'E484:')
587 call delete('Xtest.aff')
588 call delete('Xtest.dic')
589
Bram Moolenaarfc2a47f2020-08-20 15:41:55 +0200590 call assert_fails('mkspell en en_US abc_xyz', 'E755:')
591endfunc
592
Bram Moolenaarc8ec5fe2020-08-24 20:28:56 +0200593" Tests for :mkspell with a .dic and .aff file
594func Test_aff_file_format_error()
Bram Moolenaarb9fc1922020-08-25 21:19:36 +0200595 " FIXME: For some reason, the :mkspell command below doesn't fail on the
596 " MS-Windows CI build. Disable this test on MS-Windows for now.
597 CheckNotMSWindows
598
Bram Moolenaarc8ec5fe2020-08-24 20:28:56 +0200599 " No word count in .dic file
Bram Moolenaar56564962022-10-10 22:39:42 +0100600 call writefile([], 'Xtest.dic', 'D')
601 call writefile([], 'Xtest.aff', 'D')
Bram Moolenaarc8ec5fe2020-08-24 20:28:56 +0200602 call assert_fails('mkspell! Xtest.spl Xtest', 'E760:')
603
Bram Moolenaarb9fc1922020-08-25 21:19:36 +0200604 " create a .dic file for the tests below
Bram Moolenaarc8ec5fe2020-08-24 20:28:56 +0200605 call writefile(['1', 'work'], 'Xtest.dic')
Bram Moolenaarb9fc1922020-08-25 21:19:36 +0200606
607 " Invalid encoding in .aff file
Bram Moolenaarc8ec5fe2020-08-24 20:28:56 +0200608 call writefile(['# comment', 'SET Xinvalidencoding'], 'Xtest.aff')
609 let output = execute('mkspell! Xtest.spl Xtest')
610 call assert_match('Conversion in Xtest.aff not supported: from xinvalidencoding', output)
611
612 " Invalid flag in .aff file
Bram Moolenaarc8ec5fe2020-08-24 20:28:56 +0200613 call writefile(['FLAG xxx'], 'Xtest.aff')
614 let output = execute('mkspell! Xtest.spl Xtest')
615 call assert_match('Invalid value for FLAG in Xtest.aff line 1: xxx', output)
616
617 " set FLAGS after using flag for an affix
Bram Moolenaarc8ec5fe2020-08-24 20:28:56 +0200618 call writefile(['SFX L Y 1', 'SFX L 0 re [^x]', 'FLAG long'], 'Xtest.aff')
619 let output = execute('mkspell! Xtest.spl Xtest')
620 call assert_match('FLAG after using flags in Xtest.aff line 3: long', output)
621
622 " INFO in affix file
623 let save_encoding = &encoding
624 call mkdir('Xrtp/spell', 'p')
625 call writefile(['1', 'work'], 'Xrtp/spell/Xtest.dic')
626 call writefile(['NAME klingon', 'VERSION 1.4', 'AUTHOR Spock'],
627 \ 'Xrtp/spell/Xtest.aff')
628 silent mkspell! Xrtp/spell/Xtest.utf-8.spl Xrtp/spell/Xtest
629 let save_rtp = &rtp
630 set runtimepath=./Xrtp
631 set spelllang=Xtest
632 set spell
633 let output = split(execute('spellinfo'), "\n")
634 call assert_equal("NAME klingon", output[1])
635 call assert_equal("VERSION 1.4", output[2])
636 call assert_equal("AUTHOR Spock", output[3])
637 let &rtp = save_rtp
638 call delete('Xrtp', 'rf')
639 set spell& spelllang& spellfile&
640 %bw!
641 " 'encoding' must be set again to clear the spell file in memory
642 let &encoding = save_encoding
643
644 " COMPOUNDFORBIDFLAG flag after PFX in an affix file
Bram Moolenaarc8ec5fe2020-08-24 20:28:56 +0200645 call writefile(['PFX L Y 1', 'PFX L 0 re x', 'COMPOUNDFLAG c', 'COMPOUNDFORBIDFLAG x'],
646 \ 'Xtest.aff')
647 let output = execute('mkspell! Xtest.spl Xtest')
648 call assert_match('Defining COMPOUNDFORBIDFLAG after PFX item may give wrong results in Xtest.aff line 4', output)
649
650 " COMPOUNDPERMITFLAG flag after PFX in an affix file
Bram Moolenaarc8ec5fe2020-08-24 20:28:56 +0200651 call writefile(['PFX L Y 1', 'PFX L 0 re x', 'COMPOUNDPERMITFLAG c'],
652 \ 'Xtest.aff')
653 let output = execute('mkspell! Xtest.spl Xtest')
654 call assert_match('Defining COMPOUNDPERMITFLAG after PFX item may give wrong results in Xtest.aff line 3', output)
655
656 " Wrong COMPOUNDRULES flag value in an affix file
Bram Moolenaarc8ec5fe2020-08-24 20:28:56 +0200657 call writefile(['COMPOUNDRULES a'], 'Xtest.aff')
658 let output = execute('mkspell! Xtest.spl Xtest')
659 call assert_match('Wrong COMPOUNDRULES value in Xtest.aff line 1: a', output)
660
661 " Wrong COMPOUNDWORDMAX flag value in an affix file
Bram Moolenaarc8ec5fe2020-08-24 20:28:56 +0200662 call writefile(['COMPOUNDWORDMAX 0'], 'Xtest.aff')
663 let output = execute('mkspell! Xtest.spl Xtest')
664 call assert_match('Wrong COMPOUNDWORDMAX value in Xtest.aff line 1: 0', output)
665
666 " Wrong COMPOUNDMIN flag value in an affix file
Bram Moolenaarc8ec5fe2020-08-24 20:28:56 +0200667 call writefile(['COMPOUNDMIN 0'], 'Xtest.aff')
668 let output = execute('mkspell! Xtest.spl Xtest')
669 call assert_match('Wrong COMPOUNDMIN value in Xtest.aff line 1: 0', output)
670
671 " Wrong COMPOUNDSYLMAX flag value in an affix file
Bram Moolenaarc8ec5fe2020-08-24 20:28:56 +0200672 call writefile(['COMPOUNDSYLMAX 0'], 'Xtest.aff')
673 let output = execute('mkspell! Xtest.spl Xtest')
674 call assert_match('Wrong COMPOUNDSYLMAX value in Xtest.aff line 1: 0', output)
675
676 " Wrong CHECKCOMPOUNDPATTERN flag value in an affix file
Bram Moolenaarc8ec5fe2020-08-24 20:28:56 +0200677 call writefile(['CHECKCOMPOUNDPATTERN 0'], 'Xtest.aff')
678 let output = execute('mkspell! Xtest.spl Xtest')
679 call assert_match('Wrong CHECKCOMPOUNDPATTERN value in Xtest.aff line 1: 0', output)
680
Dominique Pellebb162362021-05-31 20:04:07 +0200681 " Both compounding and NOBREAK specified
682 call writefile(['COMPOUNDFLAG c', 'NOBREAK'], 'Xtest.aff')
683 let output = execute('mkspell! Xtest.spl Xtest')
684 call assert_match('Warning: both compounding and NOBREAK specified', output)
685
Bram Moolenaarc8ec5fe2020-08-24 20:28:56 +0200686 " Duplicate affix entry in an affix file
Bram Moolenaarc8ec5fe2020-08-24 20:28:56 +0200687 call writefile(['PFX L Y 1', 'PFX L 0 re x', 'PFX L Y 1', 'PFX L 0 re x'],
688 \ 'Xtest.aff')
689 let output = execute('mkspell! Xtest.spl Xtest')
690 call assert_match('Duplicate affix in Xtest.aff line 3: L', output)
691
692 " Duplicate affix entry in an affix file
Bram Moolenaarc8ec5fe2020-08-24 20:28:56 +0200693 call writefile(['PFX L Y 1', 'PFX L Y 1'], 'Xtest.aff')
694 let output = execute('mkspell! Xtest.spl Xtest')
695 call assert_match('Unrecognized or duplicate item in Xtest.aff line 2: PFX', output)
696
697 " Different combining flags in an affix file
Bram Moolenaarc8ec5fe2020-08-24 20:28:56 +0200698 call writefile(['PFX L Y 1', 'PFX L 0 re x', 'PFX L N 1'], 'Xtest.aff')
699 let output = execute('mkspell! Xtest.spl Xtest')
700 call assert_match('Different combining flag in continued affix block in Xtest.aff line 3', output)
701
Dominique Pelle923dce22021-11-21 11:36:04 +0000702 " Try to reuse an affix used for BAD flag
Bram Moolenaarc8ec5fe2020-08-24 20:28:56 +0200703 call writefile(['BAD x', 'PFX x Y 1', 'PFX x 0 re x'], 'Xtest.aff')
704 let output = execute('mkspell! Xtest.spl Xtest')
705 call assert_match('Affix also used for BAD/RARE/KEEPCASE/NEEDAFFIX/NEEDCOMPOUND/NOSUGGEST in Xtest.aff line 2: x', output)
706
707 " Trailing characters in an affix entry
Bram Moolenaarc8ec5fe2020-08-24 20:28:56 +0200708 call writefile(['PFX L Y 1 Test', 'PFX L 0 re x'], 'Xtest.aff')
709 let output = execute('mkspell! Xtest.spl Xtest')
710 call assert_match('Trailing text in Xtest.aff line 1: Test', output)
711
712 " Trailing characters in an affix entry
Bram Moolenaarc8ec5fe2020-08-24 20:28:56 +0200713 call writefile(['PFX L Y 1', 'PFX L 0 re x Test'], 'Xtest.aff')
714 let output = execute('mkspell! Xtest.spl Xtest')
715 call assert_match('Trailing text in Xtest.aff line 2: Test', output)
716
717 " Incorrect combine flag in an affix entry
Bram Moolenaarc8ec5fe2020-08-24 20:28:56 +0200718 call writefile(['PFX L X 1', 'PFX L 0 re x'], 'Xtest.aff')
719 let output = execute('mkspell! Xtest.spl Xtest')
720 call assert_match('Expected Y or N in Xtest.aff line 1: X', output)
721
722 " Invalid count for REP item
Bram Moolenaarc8ec5fe2020-08-24 20:28:56 +0200723 call writefile(['REP a'], 'Xtest.aff')
724 let output = execute('mkspell! Xtest.spl Xtest')
725 call assert_match('Expected REP(SAL) count in Xtest.aff line 1', output)
726
727 " Trailing characters in REP item
Bram Moolenaarc8ec5fe2020-08-24 20:28:56 +0200728 call writefile(['REP 1', 'REP f ph test'], 'Xtest.aff')
729 let output = execute('mkspell! Xtest.spl Xtest')
730 call assert_match('Trailing text in Xtest.aff line 2: test', output)
731
732 " Invalid count for MAP item
Bram Moolenaarc8ec5fe2020-08-24 20:28:56 +0200733 call writefile(['MAP a'], 'Xtest.aff')
734 let output = execute('mkspell! Xtest.spl Xtest')
735 call assert_match('Expected MAP count in Xtest.aff line 1', output)
736
737 " Duplicate character in a MAP item
Bram Moolenaarc8ec5fe2020-08-24 20:28:56 +0200738 call writefile(['MAP 2', 'MAP xx', 'MAP yy'], 'Xtest.aff')
739 let output = execute('mkspell! Xtest.spl Xtest')
740 call assert_match('Duplicate character in MAP in Xtest.aff line 2', output)
741
742 " Use COMPOUNDSYLMAX without SYLLABLE
Bram Moolenaarc8ec5fe2020-08-24 20:28:56 +0200743 call writefile(['COMPOUNDSYLMAX 2'], 'Xtest.aff')
744 let output = execute('mkspell! Xtest.spl Xtest')
745 call assert_match('COMPOUNDSYLMAX used without SYLLABLE', output)
746
747 " Missing SOFOTO
Bram Moolenaarc8ec5fe2020-08-24 20:28:56 +0200748 call writefile(['SOFOFROM abcdef'], 'Xtest.aff')
749 let output = execute('mkspell! Xtest.spl Xtest')
750 call assert_match('Missing SOFOTO line in Xtest.aff', output)
751
Bram Moolenaarb9fc1922020-08-25 21:19:36 +0200752 " Length of SOFOFROM and SOFOTO differ
753 call writefile(['SOFOFROM abcde', 'SOFOTO ABCD'], 'Xtest.aff')
754 call assert_fails('mkspell! Xtest.spl Xtest', 'E759:')
755
756 " Both SAL and SOFOFROM/SOFOTO items
757 call writefile(['SOFOFROM abcd', 'SOFOTO ABCD', 'SAL CIA X'], 'Xtest.aff')
758 let output = execute('mkspell! Xtest.spl Xtest')
759 call assert_match('Both SAL and SOFO lines in Xtest.aff', output)
Bram Moolenaarc8ec5fe2020-08-24 20:28:56 +0200760
761 " use an alphabet flag when FLAG is num
Bram Moolenaarc8ec5fe2020-08-24 20:28:56 +0200762 call writefile(['FLAG num', 'SFX L Y 1', 'SFX L 0 re [^x]'], 'Xtest.aff')
763 let output = execute('mkspell! Xtest.spl Xtest')
764 call assert_match('Flag is not a number in Xtest.aff line 2: L', output)
765
766 " use number and alphabet flag when FLAG is num
Bram Moolenaarc8ec5fe2020-08-24 20:28:56 +0200767 call writefile(['FLAG num', 'SFX 4f Y 1', 'SFX 4f 0 re [^x]'], 'Xtest.aff')
768 let output = execute('mkspell! Xtest.spl Xtest')
769 call assert_match('Affix name too long in Xtest.aff line 2: 4f', output)
770
771 " use a single character flag when FLAG is long
Bram Moolenaarc8ec5fe2020-08-24 20:28:56 +0200772 call writefile(['FLAG long', 'SFX L Y 1', 'SFX L 0 re [^x]'], 'Xtest.aff')
773 let output = execute('mkspell! Xtest.spl Xtest')
774 call assert_match('Illegal flag in Xtest.aff line 2: L', output)
775
Bram Moolenaar64e2db62020-09-09 22:43:19 +0200776 " missing character in UPP entry. The character table is used only in a
777 " non-utf8 encoding
778 call writefile(['FOL abc', 'LOW abc', 'UPP A'], 'Xtest.aff')
779 let save_encoding = &encoding
780 set encoding=cp949
781 call assert_fails('mkspell! Xtest.spl Xtest', 'E761:')
782 let &encoding = save_encoding
783
784 " character range doesn't match between FOL and LOW entries
785 call writefile(["FOL \u0102bc", 'LOW abc', 'UPP ABC'], 'Xtest.aff')
786 let save_encoding = &encoding
787 set encoding=cp949
788 call assert_fails('mkspell! Xtest.spl Xtest', 'E762:')
789 let &encoding = save_encoding
790
791 " character range doesn't match between FOL and UPP entries
792 call writefile(["FOL \u0102bc", "LOW \u0102bc", 'UPP ABC'], 'Xtest.aff')
793 let save_encoding = &encoding
794 set encoding=cp949
795 call assert_fails('mkspell! Xtest.spl Xtest', 'E762:')
796 let &encoding = save_encoding
797
798 " additional characters in LOW and UPP entries
799 call writefile(["FOL ab", "LOW abc", 'UPP ABC'], 'Xtest.aff')
800 let save_encoding = &encoding
801 set encoding=cp949
802 call assert_fails('mkspell! Xtest.spl Xtest', 'E761:')
803 let &encoding = save_encoding
804
Bram Moolenaar96fdf432020-09-11 18:11:50 +0200805 " missing UPP entry
806 call writefile(["FOL abc", "LOW abc"], 'Xtest.aff')
807 let save_encoding = &encoding
808 set encoding=cp949
809 let output = execute('mkspell! Xtest.spl Xtest')
810 call assert_match('Missing FOL/LOW/UPP line in Xtest.aff', output)
811 let &encoding = save_encoding
812
Bram Moolenaarb9fc1922020-08-25 21:19:36 +0200813 " duplicate word in the .dic file
814 call writefile(['2', 'good', 'good', 'good'], 'Xtest.dic')
815 call writefile(['NAME vim'], 'Xtest.aff')
816 let output = execute('mkspell! Xtest.spl Xtest')
817 call assert_match('First duplicate word in Xtest.dic line 3: good', output)
818 call assert_match('2 duplicate word(s) in Xtest.dic', output)
819
Bram Moolenaar96fdf432020-09-11 18:11:50 +0200820 " use multiple .aff files with different values for COMPOUNDWORDMAX and
821 " MIDWORD (number and string)
Bram Moolenaar56564962022-10-10 22:39:42 +0100822 call writefile(['1', 'world'], 'Xtest_US.dic', 'D')
823 call writefile(['1', 'world'], 'Xtest_CA.dic', 'D')
824 call writefile(["COMPOUNDWORDMAX 3", "MIDWORD '-"], 'Xtest_US.aff', 'D')
825 call writefile(["COMPOUNDWORDMAX 4", "MIDWORD '="], 'Xtest_CA.aff', 'D')
Bram Moolenaar96fdf432020-09-11 18:11:50 +0200826 let output = execute('mkspell! Xtest.spl Xtest_US Xtest_CA')
827 call assert_match('COMPOUNDWORDMAX value differs from what is used in another .aff file', output)
828 call assert_match('MIDWORD value differs from what is used in another .aff file', output)
Bram Moolenaar96fdf432020-09-11 18:11:50 +0200829
Bram Moolenaarc8ec5fe2020-08-24 20:28:56 +0200830 call delete('Xtest.spl')
831 call delete('Xtest.sug')
832endfunc
833
Bram Moolenaarfc2a47f2020-08-20 15:41:55 +0200834func Test_spell_add_word()
835 set spellfile=
836 call assert_fails('spellgood abc', 'E764:')
837
838 set spellfile=Xtest.utf-8.add
839 call assert_fails('2spellgood abc', 'E765:')
840
841 edit Xtest.utf-8.add
842 call setline(1, 'sample')
843 call assert_fails('spellgood abc', 'E139:')
844 set spellfile&
845 %bw!
846endfunc
847
zeertzjq0dff3152024-07-29 20:28:14 +0200848func Test_spell_add_long_word()
849 set spell spellfile=./Xspellfile.add spelllang=en
850
851 let word = repeat('a', 9000)
852 let v:errmsg = ''
853 " Spell checking doesn't really work for such a long word,
854 " but this should not cause an E1510 error.
855 exe 'spellgood ' .. word
856 call assert_equal('', v:errmsg)
857 call assert_equal([word], readfile('./Xspellfile.add'))
858
859 set spell& spellfile= spelllang& encoding=utf-8
860 call delete('./Xspellfile.add')
861 call delete('./Xspellfile.add.spl')
862endfunc
863
Dominique Pelle5a6cfb32021-05-29 17:29:33 +0200864func Test_spellfile_verbose()
Bram Moolenaar56564962022-10-10 22:39:42 +0100865 call writefile(['1', 'one'], 'XtestVerbose.dic', 'D')
866 call writefile([], 'XtestVerbose.aff', 'D')
Dominique Pelle5a6cfb32021-05-29 17:29:33 +0200867 mkspell! XtestVerbose-utf8.spl XtestVerbose
868 set spell
869
870 " First time: the spl file should be read.
871 let a = execute('3verbose set spelllang=XtestVerbose-utf8.spl')
872 call assert_match('Reading spell file "XtestVerbose-utf8.spl"', a)
873
874 " Second time time: the spl file should not be read (already read).
875 let a = execute('3verbose set spelllang=XtestVerbose-utf8.spl')
876 call assert_notmatch('Reading spell file "XtestVerbose-utf8.spl"', a)
877
878 set spell& spelllang&
Dominique Pelle5a6cfb32021-05-29 17:29:33 +0200879 call delete('XtestVerbose-utf8.spl')
880endfunc
881
882" Test NOBREAK (see :help spell-NOBREAK)
883func Test_NOBREAK()
Bram Moolenaar56564962022-10-10 22:39:42 +0100884 call writefile(['3', 'one', 'two', 'three' ], 'XtestNOBREAK.dic', 'D')
885 call writefile(['NOBREAK' ], 'XtestNOBREAK.aff', 'D')
Dominique Pelle5a6cfb32021-05-29 17:29:33 +0200886
887 mkspell! XtestNOBREAK-utf8.spl XtestNOBREAK
888 set spell spelllang=XtestNOBREAK-utf8.spl
889
890 call assert_equal(['', ''], spellbadword('One two three onetwo onetwothree threetwoone'))
891
892 call assert_equal(['x', 'bad'], spellbadword('x'))
893 call assert_equal(['y', 'bad'], spellbadword('yone'))
894 call assert_equal(['z', 'bad'], spellbadword('onez'))
895 call assert_equal(['zero', 'bad'], spellbadword('Onetwozerothree'))
896
Dominique Pellebb162362021-05-31 20:04:07 +0200897 new
898 call setline(1, 'Onetwwothree')
899 norm! fw1z=
900 call assert_equal('Onetwothree', getline(1))
901 call setline(1, 'Onetwothre')
902 norm! fh1z=
903 call assert_equal('Onetwothree', getline(1))
904
905 bw!
Dominique Pelle5a6cfb32021-05-29 17:29:33 +0200906 set spell& spelllang&
Dominique Pelle5a6cfb32021-05-29 17:29:33 +0200907 call delete('XtestNOBREAK-utf8.spl')
908endfunc
909
Dominique Pelledc3275a2021-05-28 18:32:12 +0200910" Test CHECKCOMPOUNDPATTERN (see :help spell-CHECKCOMPOUNDPATTERN)
911func Test_spellfile_CHECKCOMPOUNDPATTERN()
912 call writefile(['4',
913 \ 'one/c',
914 \ 'two/c',
915 \ 'three/c',
Bram Moolenaar56564962022-10-10 22:39:42 +0100916 \ 'four'], 'XtestCHECKCOMPOUNDPATTERN.dic', 'D')
Dominique Pelledc3275a2021-05-28 18:32:12 +0200917 " Forbid compound words where first word ends with 'wo' and second starts with 'on'.
918 call writefile(['CHECKCOMPOUNDPATTERN 1',
919 \ 'CHECKCOMPOUNDPATTERN wo on',
Bram Moolenaar56564962022-10-10 22:39:42 +0100920 \ 'COMPOUNDFLAG c'], 'XtestCHECKCOMPOUNDPATTERN.aff', 'D')
Dominique Pelledc3275a2021-05-28 18:32:12 +0200921
Dominique Pelle5a6cfb32021-05-29 17:29:33 +0200922 mkspell! XtestCHECKCOMPOUNDPATTERN-utf8.spl XtestCHECKCOMPOUNDPATTERN
Dominique Pelledc3275a2021-05-28 18:32:12 +0200923 set spell spelllang=XtestCHECKCOMPOUNDPATTERN-utf8.spl
924
925 " Check valid words with and without valid compounds.
926 for goodword in ['one', 'two', 'three', 'four',
927 \ 'oneone', 'onetwo', 'onethree',
928 \ 'twotwo', 'twothree',
929 \ 'threeone', 'threetwo', 'threethree',
930 \ 'onetwothree', 'onethreetwo', 'twothreeone', 'oneoneone']
931 call assert_equal(['', ''], spellbadword(goodword), goodword)
932 endfor
933
934 " Compounds 'twoone' or 'threetwoone' should be forbidden by CHECKCOMPOUNPATTERN.
935 " 'four' does not have the 'c' flag in *.aff file so no compound.
936 " 'five' is not in the *.dic file.
937 for badword in ['five', 'onetwox',
938 \ 'twoone', 'threetwoone',
939 \ 'fourone', 'onefour']
940 call assert_equal([badword, 'bad'], spellbadword(badword))
941 endfor
942
943 set spell& spelllang&
Dominique Pelledc3275a2021-05-28 18:32:12 +0200944 call delete('XtestCHECKCOMPOUNDPATTERN-utf8.spl')
945endfunc
946
Dominique Pelle9c9472f2021-07-24 20:51:13 +0200947" Test NOCOMPOUNDSUGS (see :help spell-NOCOMPOUNDSUGS)
948func Test_spellfile_NOCOMPOUNDSUGS()
949 call writefile(['3',
950 \ 'one/c',
951 \ 'two/c',
Bram Moolenaar56564962022-10-10 22:39:42 +0100952 \ 'three/c'], 'XtestNOCOMPOUNDSUGS.dic', 'D')
Dominique Pelle9c9472f2021-07-24 20:51:13 +0200953
954 " pass 0 tests without NOCOMPOUNDSUGS, pass 1 tests with NOCOMPOUNDSUGS
955 for pass in [0, 1]
956 if pass == 0
Bram Moolenaar56564962022-10-10 22:39:42 +0100957 call writefile(['COMPOUNDFLAG c'], 'XtestNOCOMPOUNDSUGS.aff', 'D')
Dominique Pelle9c9472f2021-07-24 20:51:13 +0200958 else
959 call writefile(['NOCOMPOUNDSUGS',
Bram Moolenaar56564962022-10-10 22:39:42 +0100960 \ 'COMPOUNDFLAG c'], 'XtestNOCOMPOUNDSUGS.aff', 'D')
Dominique Pelle9c9472f2021-07-24 20:51:13 +0200961 endif
962
963 mkspell! XtestNOCOMPOUNDSUGS-utf8.spl XtestNOCOMPOUNDSUGS
964 set spell spelllang=XtestNOCOMPOUNDSUGS-utf8.spl
965
966 for goodword in ['one', 'two', 'three',
967 \ 'oneone', 'onetwo', 'onethree',
968 \ 'twoone', 'twotwo', 'twothree',
969 \ 'threeone', 'threetwo', 'threethree',
970 \ 'onetwothree', 'onethreetwo', 'twothreeone', 'oneoneone']
971 call assert_equal(['', ''], spellbadword(goodword), goodword)
972 endfor
973
974 for badword in ['four', 'onetwox', 'onexone']
975 call assert_equal([badword, 'bad'], spellbadword(badword))
976 endfor
977
978 if pass == 0
979 call assert_equal(['one', 'oneone'], spellsuggest('onne', 2))
980 call assert_equal(['onethree', 'one three'], spellsuggest('onethre', 2))
981 else
982 call assert_equal(['one', 'one one'], spellsuggest('onne', 2))
983 call assert_equal(['one three'], spellsuggest('onethre', 2))
984 endif
985 endfor
986
987 set spell& spelllang&
Dominique Pelle9c9472f2021-07-24 20:51:13 +0200988 call delete('XtestNOCOMPOUNDSUGS-utf8.spl')
989endfunc
990
Dominique Pelledc3275a2021-05-28 18:32:12 +0200991" Test COMMON (better suggestions with common words, see :help spell-COMMON)
992func Test_spellfile_COMMON()
993 call writefile(['7',
994 \ 'and',
995 \ 'ant',
996 \ 'end',
997 \ 'any',
998 \ 'tee',
999 \ 'the',
Bram Moolenaar56564962022-10-10 22:39:42 +01001000 \ 'ted'], 'XtestCOMMON.dic', 'D')
1001 call writefile(['COMMON the and'], 'XtestCOMMON.aff', 'D')
Dominique Pelledc3275a2021-05-28 18:32:12 +02001002
Dominique Pelle5a6cfb32021-05-29 17:29:33 +02001003 mkspell! XtestCOMMON-utf8.spl XtestCOMMON
Dominique Pelledc3275a2021-05-28 18:32:12 +02001004 set spell spelllang=XtestCOMMON-utf8.spl
1005
1006 " COMMON words 'and' and 'the' should be the top suggestions.
1007 call assert_equal(['and', 'ant'], spellsuggest('anr', 2))
1008 call assert_equal(['and', 'end'], spellsuggest('ond', 2))
1009 call assert_equal(['the', 'ted'], spellsuggest('tha', 2))
1010 call assert_equal(['the', 'tee'], spellsuggest('dhe', 2))
1011
1012 set spell& spelllang&
Dominique Pelledc3275a2021-05-28 18:32:12 +02001013 call delete('XtestCOMMON-utf8.spl')
1014endfunc
1015
Dominique Pellebfb2bb12021-08-14 21:11:51 +02001016" Test NOSUGGEST (see :help spell-COMMON)
1017func Test_spellfile_NOSUGGEST()
Bram Moolenaar56564962022-10-10 22:39:42 +01001018 call writefile(['2', 'foo/X', 'fog'], 'XtestNOSUGGEST.dic', 'D')
1019 call writefile(['NOSUGGEST X'], 'XtestNOSUGGEST.aff', 'D')
Dominique Pellebfb2bb12021-08-14 21:11:51 +02001020
1021 mkspell! XtestNOSUGGEST-utf8.spl XtestNOSUGGEST
1022 set spell spelllang=XtestNOSUGGEST-utf8.spl
1023
1024 for goodword in ['foo', 'Foo', 'FOO', 'fog', 'Fog', 'FOG']
1025 call assert_equal(['', ''], spellbadword(goodword), goodword)
1026 endfor
1027 for badword in ['foO', 'fOO', 'fooo', 'foog', 'foofog', 'fogfoo']
1028 call assert_equal([badword, 'bad'], spellbadword(badword))
1029 endfor
1030
1031 call assert_equal(['fog'], spellsuggest('fooo', 1))
1032 call assert_equal(['fog'], spellsuggest('fOo', 1))
1033 call assert_equal(['fog'], spellsuggest('foG', 1))
1034 call assert_equal(['fog'], spellsuggest('fogg', 1))
1035
1036 set spell& spelllang&
Dominique Pellebfb2bb12021-08-14 21:11:51 +02001037 call delete('XtestNOSUGGEST-utf8.spl')
1038endfunc
1039
1040
Dominique Pelle5a6cfb32021-05-29 17:29:33 +02001041" Test CIRCUMFIX (see: :help spell-CIRCUMFIX)
1042func Test_spellfile_CIRCUMFIX()
1043 " Example taken verbatim from https://github.com/hunspell/hunspell/tree/master/tests
1044 call writefile(['1',
Bram Moolenaar56564962022-10-10 22:39:42 +01001045 \ 'nagy/C po:adj'], 'XtestCIRCUMFIX.dic', 'D')
Dominique Pelle5a6cfb32021-05-29 17:29:33 +02001046 call writefile(['# circumfixes: ~ obligate prefix/suffix combinations',
1047 \ '# superlative in Hungarian: leg- (prefix) AND -bb (suffix)',
1048 \ '',
1049 \ 'CIRCUMFIX X',
1050 \ '',
1051 \ 'PFX A Y 1',
1052 \ 'PFX A 0 leg/X .',
1053 \ '',
1054 \ 'PFX B Y 1',
1055 \ 'PFX B 0 legesleg/X .',
1056 \ '',
1057 \ 'SFX C Y 3',
1058 \ 'SFX C 0 obb . is:COMPARATIVE',
1059 \ 'SFX C 0 obb/AX . is:SUPERLATIVE',
Bram Moolenaar56564962022-10-10 22:39:42 +01001060 \ 'SFX C 0 obb/BX . is:SUPERSUPERLATIVE'], 'XtestCIRCUMFIX.aff', 'D')
Dominique Pelle5a6cfb32021-05-29 17:29:33 +02001061
1062 mkspell! XtestCIRCUMFIX-utf8.spl XtestCIRCUMFIX
1063 set spell spelllang=XtestCIRCUMFIX-utf8.spl
1064
1065 " From https://catalog.ldc.upenn.edu/docs/LDC2008T01/acta04.pdf:
1066 " Hungarian English
1067 " --------- -------
1068 " nagy great
1069 " nagyobb greater
1070 " legnagyobb greatest
1071 " legeslegnagyob most greatest
1072 call assert_equal(['', ''], spellbadword('nagy nagyobb legnagyobb legeslegnagyobb'))
1073
1074 for badword in ['legnagy', 'legeslegnagy', 'legobb', 'legeslegobb']
1075 call assert_equal([badword, 'bad'], spellbadword(badword))
1076 endfor
1077
1078 set spell& spelllang&
Dominique Pelle5a6cfb32021-05-29 17:29:33 +02001079 call delete('XtestCIRCUMFIX-utf8.spl')
1080endfunc
1081
Dominique Pellebb162362021-05-31 20:04:07 +02001082" Test SFX that strips/chops characters
1083func Test_spellfile_SFX_strip()
1084 " Simplified conjugation of Italian verbs ending in -are (first conjugation).
1085 call writefile(['SFX A Y 4',
1086 \ 'SFX A are iamo [^icg]are',
1087 \ 'SFX A are hiamo [cg]are',
1088 \ 'SFX A re mo iare',
1089 \ 'SFX A re vamo are'],
Bram Moolenaar56564962022-10-10 22:39:42 +01001090 \ 'XtestSFX.aff', 'D')
Dominique Pellebb162362021-05-31 20:04:07 +02001091 " Examples of Italian verbs:
1092 " - cantare = to sing
1093 " - cercare = to search
1094 " - odiare = to hate
Bram Moolenaar56564962022-10-10 22:39:42 +01001095 call writefile(['3', 'cantare/A', 'cercare/A', 'odiare/A'], 'XtestSFX.dic', 'D')
Dominique Pellebb162362021-05-31 20:04:07 +02001096
1097 mkspell! XtestSFX-utf8.spl XtestSFX
1098 set spell spelllang=XtestSFX-utf8.spl
1099
1100 " To sing, we're singing, we were singing.
1101 call assert_equal(['', ''], spellbadword('cantare cantiamo cantavamo'))
1102
1103 " To search, we're searching, we were searching.
1104 call assert_equal(['', ''], spellbadword('cercare cerchiamo cercavamo'))
1105
1106 " To hate, we hate, we were hating.
1107 call assert_equal(['', ''], spellbadword('odiare odiamo odiavamo'))
1108
1109 for badword in ['canthiamo', 'cerciamo', 'cantarevamo', 'odiiamo']
1110 call assert_equal([badword, 'bad'], spellbadword(badword))
1111 endfor
1112
1113 call assert_equal(['cantiamo'], spellsuggest('canthiamo', 1))
1114 call assert_equal(['cerchiamo'], spellsuggest('cerciamo', 1))
1115 call assert_equal(['cantavamo'], spellsuggest('cantarevamo', 1))
1116 call assert_equal(['odiamo'], spellsuggest('odiiamo', 1))
1117
1118 set spell& spelllang&
Dominique Pellebb162362021-05-31 20:04:07 +02001119 call delete('XtestSFX-utf8.spl')
1120endfunc
1121
Bram Moolenaarc8ec5fe2020-08-24 20:28:56 +02001122" When 'spellfile' is not set, adding a new good word will automatically set
1123" the 'spellfile'
1124func Test_init_spellfile()
1125 let save_rtp = &rtp
1126 let save_encoding = &encoding
Bram Moolenaar56564962022-10-10 22:39:42 +01001127 call mkdir('Xrtp/spell', 'pR')
Bram Moolenaarc8ec5fe2020-08-24 20:28:56 +02001128 call writefile(['vim'], 'Xrtp/spell/Xtest.dic')
1129 silent mkspell Xrtp/spell/Xtest.utf-8.spl Xrtp/spell/Xtest.dic
1130 set runtimepath=./Xrtp
1131 set spelllang=Xtest
1132 set spell
1133 silent spellgood abc
1134 call assert_equal('./Xrtp/spell/Xtest.utf-8.add', &spellfile)
1135 call assert_equal(['abc'], readfile('Xrtp/spell/Xtest.utf-8.add'))
1136 call assert_true(filereadable('Xrtp/spell/Xtest.utf-8.spl'))
Bram Moolenaar56564962022-10-10 22:39:42 +01001137
Bram Moolenaarc8ec5fe2020-08-24 20:28:56 +02001138 set spell& spelllang& spellfile&
Bram Moolenaarc8ec5fe2020-08-24 20:28:56 +02001139 let &encoding = save_encoding
1140 let &rtp = save_rtp
1141 %bw!
1142endfunc
1143
Bram Moolenaarb9fc1922020-08-25 21:19:36 +02001144" Test for the 'mkspellmem' option
1145func Test_mkspellmem_opt()
1146 call assert_fails('set mkspellmem=1000', 'E474:')
1147 call assert_fails('set mkspellmem=1000,', 'E474:')
1148 call assert_fails('set mkspellmem=1000,50', 'E474:')
1149 call assert_fails('set mkspellmem=1000,50,', 'E474:')
1150 call assert_fails('set mkspellmem=1000,50,10,', 'E474:')
1151 call assert_fails('set mkspellmem=1000,50,0', 'E474:')
1152endfunc
1153
Bram Moolenaarbc49c5f2022-08-04 13:01:48 +01001154" 'spellfile' accepts '@' on top of 'isfname'.
1155def Test_spellfile_allow_at_character()
1156 mkdir('Xtest/the foo@bar,dir', 'p')
1157 &spellfile = './Xtest/the foo@bar,dir/Xspellfile.add'
1158 &spellfile = ''
1159 delete('Xtest', 'rf')
1160enddef
1161
Bram Moolenaar6669de12022-08-21 20:33:47 +01001162" this was using a NULL pointer
1163func Test_mkspell_empty_dic()
Bram Moolenaar56564962022-10-10 22:39:42 +01001164 call writefile(['1'], 'XtestEmpty.dic', 'D')
1165 call writefile(['SOFOFROM abcd', 'SOFOTO ABCD', 'SAL CIA X'], 'XtestEmpty.aff', 'D')
Bram Moolenaar6669de12022-08-21 20:33:47 +01001166 mkspell! XtestEmpty.spl XtestEmpty
1167
Bram Moolenaar6669de12022-08-21 20:33:47 +01001168 call delete('XtestEmpty.spl')
1169endfunc
1170
1171
Bram Moolenaar6d91bcb2020-08-12 18:50:36 +02001172" vim: shiftwidth=2 sts=2 expandtab