blob: b72974ed07e8d8b3c25ea3c13a80f59722dc685c [file] [log] [blame]
Bram Moolenaar08cc3742019-08-11 22:51:14 +02001" Test for commands that operate on the spellfile.
2
Bram Moolenaar08cc3742019-08-11 22:51:14 +02003CheckFeature spell
4CheckFeature syntax
5
6func Test_spell_normal()
7 new
8 call append(0, ['1 good', '2 goood', '3 goood'])
9 set spell spellfile=./Xspellfile.add spelllang=en
10 let oldlang=v:lang
11 lang C
12
13 " Test for zg
14 1
15 norm! ]s
16 call assert_equal('2 goood', getline('.'))
17 norm! zg
18 1
19 let a=execute('unsilent :norm! ]s')
20 call assert_equal('1 good', getline('.'))
21 call assert_equal('search hit BOTTOM, continuing at TOP', a[1:])
22 let cnt=readfile('./Xspellfile.add')
23 call assert_equal('goood', cnt[0])
24
Bram Moolenaar8a9bc952020-10-02 18:48:07 +020025 " zg should fail in operator-pending mode
26 call assert_beeps('norm! czg')
27
28 " zg fails in visual mode when not able to get the visual text
29 call assert_beeps('norm! ggVjzg')
30 norm! V
31
32 " zg fails for a non-identifier word
33 call append(line('$'), '###')
34 call assert_fails('norm! Gzg', 'E349:')
35 $d
36
Bram Moolenaar08cc3742019-08-11 22:51:14 +020037 " Test for zw
38 2
39 norm! $zw
40 1
41 norm! ]s
42 call assert_equal('2 goood', getline('.'))
43 let cnt=readfile('./Xspellfile.add')
44 call assert_equal('#oood', cnt[0])
45 call assert_equal('goood/!', cnt[1])
46
47 " Test for :spellrare
48 spellrare rare
49 let cnt=readfile('./Xspellfile.add')
50 call assert_equal(['#oood', 'goood/!', 'rare/?'], cnt)
51
52 " Make sure :spellundo works for rare words.
53 spellundo rare
54 let cnt=readfile('./Xspellfile.add')
55 call assert_equal(['#oood', 'goood/!', '#are/?'], cnt)
56
57 " Test for zg in visual mode
58 let a=execute('unsilent :norm! V$zg')
59 call assert_equal("Word '2 goood' added to ./Xspellfile.add", a[1:])
60 1
61 norm! ]s
62 call assert_equal('3 goood', getline('.'))
63 let cnt=readfile('./Xspellfile.add')
64 call assert_equal('2 goood', cnt[3])
65 " Remove "2 good" from spellfile
66 2
67 let a=execute('unsilent norm! V$zw')
68 call assert_equal("Word '2 goood' added to ./Xspellfile.add", a[1:])
69 let cnt=readfile('./Xspellfile.add')
70 call assert_equal('2 goood/!', cnt[4])
71
72 " Test for zG
73 let a=execute('unsilent norm! V$zG')
74 call assert_match("Word '2 goood' added to .*", a)
75 let fname=matchstr(a, 'to\s\+\zs\f\+$')
76 let cnt=readfile(fname)
77 call assert_equal('2 goood', cnt[0])
78
79 " Test for zW
80 let a=execute('unsilent norm! V$zW')
81 call assert_match("Word '2 goood' added to .*", a)
82 let cnt=readfile(fname)
83 call assert_equal('# goood', cnt[0])
84 call assert_equal('2 goood/!', cnt[1])
85
86 " Test for zuW
87 let a=execute('unsilent norm! V$zuW')
88 call assert_match("Word '2 goood' removed from .*", a)
89 let cnt=readfile(fname)
90 call assert_equal('# goood', cnt[0])
91 call assert_equal('# goood/!', cnt[1])
92
93 " Test for zuG
94 let a=execute('unsilent norm! $zG')
95 call assert_match("Word 'goood' added to .*", a)
96 let cnt=readfile(fname)
97 call assert_equal('# goood', cnt[0])
98 call assert_equal('# goood/!', cnt[1])
99 call assert_equal('goood', cnt[2])
100 let a=execute('unsilent norm! $zuG')
101 let cnt=readfile(fname)
102 call assert_match("Word 'goood' removed from .*", a)
103 call assert_equal('# goood', cnt[0])
104 call assert_equal('# goood/!', cnt[1])
105 call assert_equal('#oood', cnt[2])
106 " word not found in wordlist
107 let a=execute('unsilent norm! V$zuG')
108 let cnt=readfile(fname)
109 call assert_match("", a)
110 call assert_equal('# goood', cnt[0])
111 call assert_equal('# goood/!', cnt[1])
112 call assert_equal('#oood', cnt[2])
113
114 " Test for zug
115 call delete('./Xspellfile.add')
116 2
117 let a=execute('unsilent norm! $zg')
118 let cnt=readfile('./Xspellfile.add')
119 call assert_equal('goood', cnt[0])
120 let a=execute('unsilent norm! $zug')
121 call assert_match("Word 'goood' removed from \./Xspellfile.add", a)
122 let cnt=readfile('./Xspellfile.add')
123 call assert_equal('#oood', cnt[0])
124 " word not in wordlist
125 let a=execute('unsilent norm! V$zug')
126 call assert_match('', a)
127 let cnt=readfile('./Xspellfile.add')
128 call assert_equal('#oood', cnt[0])
129
130 " Test for zuw
131 call delete('./Xspellfile.add')
132 2
133 let a=execute('unsilent norm! Vzw')
134 let cnt=readfile('./Xspellfile.add')
135 call assert_equal('2 goood/!', cnt[0])
136 let a=execute('unsilent norm! Vzuw')
137 call assert_match("Word '2 goood' removed from \./Xspellfile.add", a)
138 let cnt=readfile('./Xspellfile.add')
139 call assert_equal('# goood/!', cnt[0])
140 " word not in wordlist
141 let a=execute('unsilent norm! $zug')
142 call assert_match('', a)
143 let cnt=readfile('./Xspellfile.add')
144 call assert_equal('# goood/!', cnt[0])
145
146 " add second entry to spellfile setting
147 set spellfile=./Xspellfile.add,./Xspellfile2.add
148 call delete('./Xspellfile.add')
149 2
150 let a=execute('unsilent norm! $2zg')
151 let cnt=readfile('./Xspellfile2.add')
152 call assert_match("Word 'goood' added to ./Xspellfile2.add", a)
153 call assert_equal('goood', cnt[0])
154
155 " Test for :spellgood!
156 let temp = execute(':spe!0/0')
157 call assert_match('Invalid region', temp)
158 let spellfile = matchstr(temp, 'Invalid region nr in \zs.*\ze line \d: 0')
159 call assert_equal(['# goood', '# goood/!', '#oood', '0/0'], readfile(spellfile))
160
161 " Test for :spellrare!
162 :spellrare! raare
163 call assert_equal(['# goood', '# goood/!', '#oood', '0/0', 'raare/?'], readfile(spellfile))
164 call delete(spellfile)
165
166 " clean up
167 exe "lang" oldlang
168 call delete("./Xspellfile.add")
169 call delete("./Xspellfile2.add")
170 call delete("./Xspellfile.add.spl")
171 call delete("./Xspellfile2.add.spl")
172
173 " zux -> no-op
174 2
175 norm! $zux
176 call assert_equal([], glob('Xspellfile.add',0,1))
177 call assert_equal([], glob('Xspellfile2.add',0,1))
178
Bram Moolenaarc0f88232020-08-16 21:51:49 +0200179 set spellfile= spell& spelllang&
Bram Moolenaar08cc3742019-08-11 22:51:14 +0200180 bw!
181endfunc
Bram Moolenaar6d91bcb2020-08-12 18:50:36 +0200182
Bram Moolenaarfc2a47f2020-08-20 15:41:55 +0200183" Spell file content test. Write 'content' to the spell file prefixed by the
184" spell file header and then enable spell checking. If 'emsg' is not empty,
185" then check for error.
186func Spellfile_Test(content, emsg)
187 let splfile = './Xtest/spell/Xtest.utf-8.spl'
188 " Add the spell file header and version (VIMspell2)
189 let v = 0z56494D7370656C6C32 + a:content
190 call writefile(v, splfile, 'b')
Bram Moolenaar64e2db62020-09-09 22:43:19 +0200191
192 " 'encoding' is set before each test to clear the previously loaded suggest
193 " file from memory.
194 set encoding=utf-8
195
Bram Moolenaarfc2a47f2020-08-20 15:41:55 +0200196 set runtimepath=./Xtest
197 set spelllang=Xtest
198 if a:emsg != ''
199 call assert_fails('set spell', a:emsg)
200 else
201 " FIXME: With some invalid spellfile contents, there are no error
202 " messages. So don't know how to check for the test result.
203 set spell
204 endif
205 set nospell spelllang& rtp&
206endfunc
207
208" Test for spell file format errors.
209" The spell file format is described in spellfile.c
Bram Moolenaarc0f88232020-08-16 21:51:49 +0200210func Test_spellfile_format_error()
211 let save_rtp = &rtp
Bram Moolenaar56564962022-10-10 22:39:42 +0100212 call mkdir('Xtest/spell', 'pR')
Bram Moolenaarfc2a47f2020-08-20 15:41:55 +0200213 let splfile = './Xtest/spell/Xtest.utf-8.spl'
Bram Moolenaarc0f88232020-08-16 21:51:49 +0200214
215 " empty spell file
Bram Moolenaarfc2a47f2020-08-20 15:41:55 +0200216 call writefile([], splfile)
Bram Moolenaarc0f88232020-08-16 21:51:49 +0200217 set runtimepath=./Xtest
218 set spelllang=Xtest
219 call assert_fails('set spell', 'E757:')
220 set nospell spelllang&
221
222 " invalid file ID
Bram Moolenaarfc2a47f2020-08-20 15:41:55 +0200223 call writefile(0z56494D, splfile, 'b')
Bram Moolenaarc0f88232020-08-16 21:51:49 +0200224 set runtimepath=./Xtest
225 set spelllang=Xtest
226 call assert_fails('set spell', 'E757:')
227 set nospell spelllang&
228
229 " missing version number
Bram Moolenaarfc2a47f2020-08-20 15:41:55 +0200230 call writefile(0z56494D7370656C6C, splfile, 'b')
Bram Moolenaarc0f88232020-08-16 21:51:49 +0200231 set runtimepath=./Xtest
232 set spelllang=Xtest
233 call assert_fails('set spell', 'E771:')
234 set nospell spelllang&
235
236 " invalid version number
Bram Moolenaarfc2a47f2020-08-20 15:41:55 +0200237 call writefile(0z56494D7370656C6C7A, splfile, 'b')
Bram Moolenaarc0f88232020-08-16 21:51:49 +0200238 set runtimepath=./Xtest
239 set spelllang=Xtest
240 call assert_fails('set spell', 'E772:')
241 set nospell spelllang&
242
243 " no sections
Bram Moolenaarfc2a47f2020-08-20 15:41:55 +0200244 call Spellfile_Test(0z, 'E758:')
Bram Moolenaarc0f88232020-08-16 21:51:49 +0200245
246 " missing section length
Bram Moolenaarfc2a47f2020-08-20 15:41:55 +0200247 call Spellfile_Test(0z00, 'E758:')
Bram Moolenaarc0f88232020-08-16 21:51:49 +0200248
249 " unsupported required section
Bram Moolenaarfc2a47f2020-08-20 15:41:55 +0200250 call Spellfile_Test(0z7A0100000004, 'E770:')
Bram Moolenaarc0f88232020-08-16 21:51:49 +0200251
252 " unsupported not-required section
Bram Moolenaarfc2a47f2020-08-20 15:41:55 +0200253 call Spellfile_Test(0z7A0000000004, 'E758:')
Bram Moolenaarc0f88232020-08-16 21:51:49 +0200254
255 " SN_REGION: invalid number of region names
Bram Moolenaarfc2a47f2020-08-20 15:41:55 +0200256 call Spellfile_Test(0z0000000000FF, 'E759:')
Bram Moolenaarc0f88232020-08-16 21:51:49 +0200257
258 " SN_CHARFLAGS: missing <charflagslen> length
Bram Moolenaarfc2a47f2020-08-20 15:41:55 +0200259 call Spellfile_Test(0z010000000004, 'E758:')
Bram Moolenaarc0f88232020-08-16 21:51:49 +0200260
261 " SN_CHARFLAGS: invalid <charflagslen> length
Bram Moolenaarfc2a47f2020-08-20 15:41:55 +0200262 call Spellfile_Test(0z0100000000010201, '')
Bram Moolenaarc0f88232020-08-16 21:51:49 +0200263
264 " SN_CHARFLAGS: charflagslen == 0 and folcharslen != 0
Bram Moolenaarfc2a47f2020-08-20 15:41:55 +0200265 call Spellfile_Test(0z01000000000400000101, 'E759:')
Bram Moolenaarc0f88232020-08-16 21:51:49 +0200266
267 " SN_CHARFLAGS: missing <folcharslen> length
Bram Moolenaarfc2a47f2020-08-20 15:41:55 +0200268 call Spellfile_Test(0z01000000000100, 'E758:')
Bram Moolenaarc0f88232020-08-16 21:51:49 +0200269
270 " SN_PREFCOND: invalid prefcondcnt
Bram Moolenaarfc2a47f2020-08-20 15:41:55 +0200271 call Spellfile_Test(0z03000000000100, 'E759:')
Bram Moolenaarc0f88232020-08-16 21:51:49 +0200272
273 " SN_PREFCOND: invalid condlen
Bram Moolenaarfc2a47f2020-08-20 15:41:55 +0200274 call Spellfile_Test(0z0300000000020001, 'E759:')
Bram Moolenaarc0f88232020-08-16 21:51:49 +0200275
276 " SN_REP: invalid repcount
Bram Moolenaarfc2a47f2020-08-20 15:41:55 +0200277 call Spellfile_Test(0z04000000000100, 'E758:')
Bram Moolenaarc0f88232020-08-16 21:51:49 +0200278
279 " SN_REP: missing rep
Bram Moolenaarfc2a47f2020-08-20 15:41:55 +0200280 call Spellfile_Test(0z0400000000020004, 'E758:')
Bram Moolenaarc0f88232020-08-16 21:51:49 +0200281
282 " SN_REP: zero repfromlen
Bram Moolenaarfc2a47f2020-08-20 15:41:55 +0200283 call Spellfile_Test(0z040000000003000100, 'E759:')
Bram Moolenaarc0f88232020-08-16 21:51:49 +0200284
285 " SN_REP: invalid reptolen
Bram Moolenaarfc2a47f2020-08-20 15:41:55 +0200286 call Spellfile_Test(0z0400000000050001014101, '')
Bram Moolenaarc0f88232020-08-16 21:51:49 +0200287
288 " SN_REP: zero reptolen
Bram Moolenaarfc2a47f2020-08-20 15:41:55 +0200289 call Spellfile_Test(0z0400000000050001014100, 'E759:')
290
291 " SN_SAL: missing salcount
292 call Spellfile_Test(0z05000000000102, 'E758:')
293
294 " SN_SAL: missing salfromlen
295 call Spellfile_Test(0z050000000003080001, 'E758:')
296
297 " SN_SAL: missing saltolen
298 call Spellfile_Test(0z0500000000050400010161, 'E758:')
299
300 " SN_WORDS: non-NUL terminated word
301 call Spellfile_Test(0z0D000000000376696D, 'E758:')
302
303 " SN_WORDS: very long word
304 let v = eval('0z0D000000012C' .. repeat('41', 300))
305 call Spellfile_Test(v, 'E759:')
306
307 " SN_SOFO: missing sofofromlen
308 call Spellfile_Test(0z06000000000100, 'E758:')
309
310 " SN_SOFO: missing sofotolen
311 call Spellfile_Test(0z06000000000400016100, 'E758:')
312
313 " SN_SOFO: missing sofoto
314 call Spellfile_Test(0z0600000000050001610000, 'E759:')
315
Bram Moolenaar64e2db62020-09-09 22:43:19 +0200316 " SN_SOFO: empty sofofrom and sofoto
317 call Spellfile_Test(0z06000000000400000000FF000000000000000000000000, '')
318
Bram Moolenaar96fdf432020-09-11 18:11:50 +0200319 " SN_SOFO: multi-byte characters in sofofrom and sofoto
320 call Spellfile_Test(0z0600000000080002CF810002CF82FF000000000000000000000000, '')
321
Bram Moolenaarfc2a47f2020-08-20 15:41:55 +0200322 " SN_COMPOUND: compmax is less than 2
323 call Spellfile_Test(0z08000000000101, 'E759:')
324
325 " SN_COMPOUND: missing compsylmax and other options
326 call Spellfile_Test(0z0800000000020401, 'E759:')
327
328 " SN_COMPOUND: missing compoptions
329 call Spellfile_Test(0z080000000005040101, 'E758:')
330
Bram Moolenaar64e2db62020-09-09 22:43:19 +0200331 " SN_COMPOUND: missing comppattern
332 call Spellfile_Test(0z08000000000704010100000001, 'E758:')
333
334 " SN_COMPOUND: incorrect comppatlen
335 call Spellfile_Test(0z080000000007040101000000020165, 'E758:')
336
Bram Moolenaarfc2a47f2020-08-20 15:41:55 +0200337 " SN_INFO: missing info
338 call Spellfile_Test(0z0F0000000005040101, '')
339
340 " SN_MIDWORD: missing midword
341 call Spellfile_Test(0z0200000000040102, '')
342
343 " SN_MAP: missing midword
344 call Spellfile_Test(0z0700000000040102, '')
345
Bram Moolenaar64e2db62020-09-09 22:43:19 +0200346 " SN_MAP: empty map string
347 call Spellfile_Test(0z070000000000FF000000000000000000000000, '')
348
349 " SN_MAP: duplicate multibyte character
350 call Spellfile_Test(0z070000000004DC81DC81, 'E783:')
351
Bram Moolenaarfc2a47f2020-08-20 15:41:55 +0200352 " SN_SYLLABLE: missing SYLLABLE item
353 call Spellfile_Test(0z0900000000040102, '')
354
355 " SN_SYLLABLE: More than SY_MAXLEN size
356 let v = eval('0z090000000022612F' .. repeat('62', 32))
357 call Spellfile_Test(v, '')
358
359 " LWORDTREE: missing
360 call Spellfile_Test(0zFF, 'E758:')
361
362 " LWORDTREE: missing tree node
363 call Spellfile_Test(0zFF00000004, 'E758:')
364
365 " LWORDTREE: missing tree node value
366 call Spellfile_Test(0zFF0000000402, 'E758:')
367
Bram Moolenaar64e2db62020-09-09 22:43:19 +0200368 " LWORDTREE: incorrect sibling node count
369 call Spellfile_Test(0zFF00000001040000000000000000, 'E759:')
370
Bram Moolenaarfc2a47f2020-08-20 15:41:55 +0200371 " KWORDTREE: missing tree node
372 call Spellfile_Test(0zFF0000000000000004, 'E758:')
373
374 " PREFIXTREE: missing tree node
375 call Spellfile_Test(0zFF000000000000000000000004, 'E758:')
376
Bram Moolenaar64e2db62020-09-09 22:43:19 +0200377 " PREFIXTREE: incorrect prefcondnr
378 call Spellfile_Test(0zFF000000000000000000000002010200000020, 'E759:')
379
380 " PREFIXTREE: invalid nodeidx
381 call Spellfile_Test(0zFF00000000000000000000000201010000, 'E759:')
382
Bram Moolenaarfc2a47f2020-08-20 15:41:55 +0200383 let &rtp = save_rtp
Bram Moolenaarfc2a47f2020-08-20 15:41:55 +0200384endfunc
385
386" Test for format errors in suggest file
387func Test_sugfile_format_error()
388 let save_rtp = &rtp
Bram Moolenaar56564962022-10-10 22:39:42 +0100389 call mkdir('Xtest/spell', 'pR')
Bram Moolenaarfc2a47f2020-08-20 15:41:55 +0200390 let splfile = './Xtest/spell/Xtest.utf-8.spl'
391 let sugfile = './Xtest/spell/Xtest.utf-8.sug'
392
393 " create an empty spell file with a suggest timestamp
394 call writefile(0z56494D7370656C6C320B00000000080000000000000044FF000000000000000000000000, splfile, 'b')
395
396 " 'encoding' is set before each test to clear the previously loaded suggest
397 " file from memory.
398
399 " empty suggest file
400 set encoding=utf-8
401 call writefile([], sugfile)
Bram Moolenaarc0f88232020-08-16 21:51:49 +0200402 set runtimepath=./Xtest
403 set spelllang=Xtest
Bram Moolenaarfc2a47f2020-08-20 15:41:55 +0200404 set spell
405 call assert_fails("let s = spellsuggest('abc')", 'E778:')
406 set nospell spelllang&
407
408 " zero suggest version
409 set encoding=utf-8
410 call writefile(0z56494D73756700, sugfile)
411 set runtimepath=./Xtest
412 set spelllang=Xtest
413 set spell
414 call assert_fails("let s = spellsuggest('abc')", 'E779:')
415 set nospell spelllang&
416
417 " unsupported suggest version
418 set encoding=utf-8
419 call writefile(0z56494D7375671F, sugfile)
420 set runtimepath=./Xtest
421 set spelllang=Xtest
422 set spell
423 call assert_fails("let s = spellsuggest('abc')", 'E780:')
424 set nospell spelllang&
425
426 " missing suggest timestamp
427 set encoding=utf-8
428 call writefile(0z56494D73756701, sugfile)
429 set runtimepath=./Xtest
430 set spelllang=Xtest
431 set spell
432 call assert_fails("let s = spellsuggest('abc')", 'E781:')
433 set nospell spelllang&
434
435 " incorrect suggest timestamp
436 set encoding=utf-8
437 call writefile(0z56494D7375670100000000000000FF, sugfile)
438 set runtimepath=./Xtest
439 set spelllang=Xtest
440 set spell
441 call assert_fails("let s = spellsuggest('abc')", 'E781:')
442 set nospell spelllang&
443
444 " missing suggest wordtree
445 set encoding=utf-8
446 call writefile(0z56494D737567010000000000000044, sugfile)
447 set runtimepath=./Xtest
448 set spelllang=Xtest
449 set spell
450 call assert_fails("let s = spellsuggest('abc')", 'E782:')
Bram Moolenaarc0f88232020-08-16 21:51:49 +0200451 set nospell spelllang&
452
Bram Moolenaarb9fc1922020-08-25 21:19:36 +0200453 " invalid suggest word count in SUGTABLE
454 set encoding=utf-8
455 call writefile(0z56494D7375670100000000000000440000000022, sugfile)
456 set runtimepath=./Xtest
457 set spelllang=Xtest
458 set spell
459 call assert_fails("let s = spellsuggest('abc')", 'E782:')
460 set nospell spelllang&
461
462 " missing sugline in SUGTABLE
463 set encoding=utf-8
464 call writefile(0z56494D7375670100000000000000440000000000000005, sugfile)
465 set runtimepath=./Xtest
466 set spelllang=Xtest
467 set spell
468 call assert_fails("let s = spellsuggest('abc')", 'E782:')
469 set nospell spelllang&
470
Bram Moolenaarc0f88232020-08-16 21:51:49 +0200471 let &rtp = save_rtp
Bram Moolenaarc0f88232020-08-16 21:51:49 +0200472endfunc
473
Bram Moolenaarfc2a47f2020-08-20 15:41:55 +0200474" Test for using :mkspell to create a spell file from a list of words
475func Test_wordlist_dic()
476 " duplicate encoding
477 let lines =<< trim [END]
478 # This is an example word list
479
480 /encoding=latin1
481 /encoding=latin1
482 example
483 [END]
Bram Moolenaar56564962022-10-10 22:39:42 +0100484 call writefile(lines, 'Xwordlist.dic', 'D')
Bram Moolenaarfc2a47f2020-08-20 15:41:55 +0200485 let output = execute('mkspell Xwordlist.spl Xwordlist.dic')
486 call assert_match('Duplicate /encoding= line ignored in Xwordlist.dic line 4: /encoding=latin1', output)
487
488 " multiple encoding for a word
489 let lines =<< trim [END]
490 example
491 /encoding=latin1
492 example
493 [END]
494 call writefile(lines, 'Xwordlist.dic')
495 let output = execute('mkspell! Xwordlist.spl Xwordlist.dic')
496 call assert_match('/encoding= line after word ignored in Xwordlist.dic line 2: /encoding=latin1', output)
497
498 " unsupported encoding for a word
499 let lines =<< trim [END]
500 /encoding=Xtest
501 example
502 [END]
503 call writefile(lines, 'Xwordlist.dic')
504 let output = execute('mkspell! Xwordlist.spl Xwordlist.dic')
505 call assert_match('Conversion in Xwordlist.dic not supported: from Xtest to utf-8', output)
506
507 " duplicate region
508 let lines =<< trim [END]
509 /regions=usca
510 /regions=usca
511 example
512 [END]
513 call writefile(lines, 'Xwordlist.dic')
514 let output = execute('mkspell! Xwordlist.spl Xwordlist.dic')
515 call assert_match('Duplicate /regions= line ignored in Xwordlist.dic line 2: regions=usca', output)
516
517 " maximum regions
518 let lines =<< trim [END]
519 /regions=uscauscauscauscausca
520 example
521 [END]
522 call writefile(lines, 'Xwordlist.dic')
523 let output = execute('mkspell! Xwordlist.spl Xwordlist.dic')
524 call assert_match('Too many regions in Xwordlist.dic line 1: uscauscauscauscausca', output)
525
526 " unsupported '/' value
527 let lines =<< trim [END]
528 /test=abc
529 example
530 [END]
531 call writefile(lines, 'Xwordlist.dic')
532 let output = execute('mkspell! Xwordlist.spl Xwordlist.dic')
533 call assert_match('/ line ignored in Xwordlist.dic line 1: /test=abc', output)
534
535 " unsupported flag
536 let lines =<< trim [END]
537 example/+
538 [END]
539 call writefile(lines, 'Xwordlist.dic')
540 let output = execute('mkspell! Xwordlist.spl Xwordlist.dic')
541 call assert_match('Unrecognized flags in Xwordlist.dic line 1: +', output)
542
543 " non-ascii word
544 call writefile(["ʀʀ"], 'Xwordlist.dic')
545 let output = execute('mkspell! -ascii Xwordlist.spl Xwordlist.dic')
546 call assert_match('Ignored 1 words with non-ASCII characters', output)
547
Bram Moolenaar64e2db62020-09-09 22:43:19 +0200548 " keep case of a word
549 let lines =<< trim [END]
550 example/=
551 [END]
552 call writefile(lines, 'Xwordlist.dic')
553 let output = execute('mkspell! Xwordlist.spl Xwordlist.dic')
554 call assert_match('Compressed keep-case:', output)
555
Bram Moolenaarfc2a47f2020-08-20 15:41:55 +0200556 call delete('Xwordlist.spl')
Bram Moolenaarfc2a47f2020-08-20 15:41:55 +0200557endfunc
558
559" Test for the :mkspell command
560func Test_mkspell()
561 call assert_fails('mkspell Xtest_us.spl', 'E751:')
Bram Moolenaar96fdf432020-09-11 18:11:50 +0200562 call assert_fails('mkspell Xtest.spl abc', 'E484:')
Bram Moolenaarfc2a47f2020-08-20 15:41:55 +0200563 call assert_fails('mkspell a b c d e f g h i j k', 'E754:')
564
Bram Moolenaar96fdf432020-09-11 18:11:50 +0200565 " create a .aff file but not the .dic file
566 call writefile([], 'Xtest.aff')
567 call assert_fails('mkspell Xtest.spl Xtest', 'E484:')
568 call delete('Xtest.aff')
569
Bram Moolenaarfc2a47f2020-08-20 15:41:55 +0200570 call writefile([], 'Xtest.spl')
571 call writefile([], 'Xtest.dic')
572 call assert_fails('mkspell Xtest.spl Xtest.dic', 'E13:')
573 call delete('Xtest.spl')
574 call delete('Xtest.dic')
575
576 call mkdir('Xtest.spl')
577 call assert_fails('mkspell! Xtest.spl Xtest.dic', 'E17:')
578 call delete('Xtest.spl', 'rf')
579
Dominique Pelle5a6cfb32021-05-29 17:29:33 +0200580 " can't write the .spl file as its directory does not exist
581 call writefile([], 'Xtest.aff')
582 call writefile([], 'Xtest.dic')
583 call assert_fails('mkspell DOES_NOT_EXIT/Xtest.spl Xtest.dic', 'E484:')
584 call delete('Xtest.aff')
585 call delete('Xtest.dic')
586
Bram Moolenaarfc2a47f2020-08-20 15:41:55 +0200587 call assert_fails('mkspell en en_US abc_xyz', 'E755:')
588endfunc
589
Bram Moolenaarc8ec5fe2020-08-24 20:28:56 +0200590" Tests for :mkspell with a .dic and .aff file
591func Test_aff_file_format_error()
Bram Moolenaarb9fc1922020-08-25 21:19:36 +0200592 " FIXME: For some reason, the :mkspell command below doesn't fail on the
593 " MS-Windows CI build. Disable this test on MS-Windows for now.
594 CheckNotMSWindows
595
Bram Moolenaarc8ec5fe2020-08-24 20:28:56 +0200596 " No word count in .dic file
Bram Moolenaar56564962022-10-10 22:39:42 +0100597 call writefile([], 'Xtest.dic', 'D')
598 call writefile([], 'Xtest.aff', 'D')
Bram Moolenaarc8ec5fe2020-08-24 20:28:56 +0200599 call assert_fails('mkspell! Xtest.spl Xtest', 'E760:')
600
Bram Moolenaarb9fc1922020-08-25 21:19:36 +0200601 " create a .dic file for the tests below
Bram Moolenaarc8ec5fe2020-08-24 20:28:56 +0200602 call writefile(['1', 'work'], 'Xtest.dic')
Bram Moolenaarb9fc1922020-08-25 21:19:36 +0200603
604 " Invalid encoding in .aff file
Bram Moolenaarc8ec5fe2020-08-24 20:28:56 +0200605 call writefile(['# comment', 'SET Xinvalidencoding'], 'Xtest.aff')
606 let output = execute('mkspell! Xtest.spl Xtest')
607 call assert_match('Conversion in Xtest.aff not supported: from xinvalidencoding', output)
608
609 " Invalid flag in .aff file
Bram Moolenaarc8ec5fe2020-08-24 20:28:56 +0200610 call writefile(['FLAG xxx'], 'Xtest.aff')
611 let output = execute('mkspell! Xtest.spl Xtest')
612 call assert_match('Invalid value for FLAG in Xtest.aff line 1: xxx', output)
613
614 " set FLAGS after using flag for an affix
Bram Moolenaarc8ec5fe2020-08-24 20:28:56 +0200615 call writefile(['SFX L Y 1', 'SFX L 0 re [^x]', 'FLAG long'], 'Xtest.aff')
616 let output = execute('mkspell! Xtest.spl Xtest')
617 call assert_match('FLAG after using flags in Xtest.aff line 3: long', output)
618
619 " INFO in affix file
620 let save_encoding = &encoding
621 call mkdir('Xrtp/spell', 'p')
622 call writefile(['1', 'work'], 'Xrtp/spell/Xtest.dic')
623 call writefile(['NAME klingon', 'VERSION 1.4', 'AUTHOR Spock'],
624 \ 'Xrtp/spell/Xtest.aff')
625 silent mkspell! Xrtp/spell/Xtest.utf-8.spl Xrtp/spell/Xtest
626 let save_rtp = &rtp
627 set runtimepath=./Xrtp
628 set spelllang=Xtest
629 set spell
630 let output = split(execute('spellinfo'), "\n")
631 call assert_equal("NAME klingon", output[1])
632 call assert_equal("VERSION 1.4", output[2])
633 call assert_equal("AUTHOR Spock", output[3])
634 let &rtp = save_rtp
635 call delete('Xrtp', 'rf')
636 set spell& spelllang& spellfile&
637 %bw!
638 " 'encoding' must be set again to clear the spell file in memory
639 let &encoding = save_encoding
640
641 " COMPOUNDFORBIDFLAG flag after PFX in an affix file
Bram Moolenaarc8ec5fe2020-08-24 20:28:56 +0200642 call writefile(['PFX L Y 1', 'PFX L 0 re x', 'COMPOUNDFLAG c', 'COMPOUNDFORBIDFLAG x'],
643 \ 'Xtest.aff')
644 let output = execute('mkspell! Xtest.spl Xtest')
645 call assert_match('Defining COMPOUNDFORBIDFLAG after PFX item may give wrong results in Xtest.aff line 4', output)
646
647 " COMPOUNDPERMITFLAG flag after PFX in an affix file
Bram Moolenaarc8ec5fe2020-08-24 20:28:56 +0200648 call writefile(['PFX L Y 1', 'PFX L 0 re x', 'COMPOUNDPERMITFLAG c'],
649 \ 'Xtest.aff')
650 let output = execute('mkspell! Xtest.spl Xtest')
651 call assert_match('Defining COMPOUNDPERMITFLAG after PFX item may give wrong results in Xtest.aff line 3', output)
652
653 " Wrong COMPOUNDRULES flag value in an affix file
Bram Moolenaarc8ec5fe2020-08-24 20:28:56 +0200654 call writefile(['COMPOUNDRULES a'], 'Xtest.aff')
655 let output = execute('mkspell! Xtest.spl Xtest')
656 call assert_match('Wrong COMPOUNDRULES value in Xtest.aff line 1: a', output)
657
658 " Wrong COMPOUNDWORDMAX flag value in an affix file
Bram Moolenaarc8ec5fe2020-08-24 20:28:56 +0200659 call writefile(['COMPOUNDWORDMAX 0'], 'Xtest.aff')
660 let output = execute('mkspell! Xtest.spl Xtest')
661 call assert_match('Wrong COMPOUNDWORDMAX value in Xtest.aff line 1: 0', output)
662
663 " Wrong COMPOUNDMIN flag value in an affix file
Bram Moolenaarc8ec5fe2020-08-24 20:28:56 +0200664 call writefile(['COMPOUNDMIN 0'], 'Xtest.aff')
665 let output = execute('mkspell! Xtest.spl Xtest')
666 call assert_match('Wrong COMPOUNDMIN value in Xtest.aff line 1: 0', output)
667
668 " Wrong COMPOUNDSYLMAX flag value in an affix file
Bram Moolenaarc8ec5fe2020-08-24 20:28:56 +0200669 call writefile(['COMPOUNDSYLMAX 0'], 'Xtest.aff')
670 let output = execute('mkspell! Xtest.spl Xtest')
671 call assert_match('Wrong COMPOUNDSYLMAX value in Xtest.aff line 1: 0', output)
672
673 " Wrong CHECKCOMPOUNDPATTERN flag value in an affix file
Bram Moolenaarc8ec5fe2020-08-24 20:28:56 +0200674 call writefile(['CHECKCOMPOUNDPATTERN 0'], 'Xtest.aff')
675 let output = execute('mkspell! Xtest.spl Xtest')
676 call assert_match('Wrong CHECKCOMPOUNDPATTERN value in Xtest.aff line 1: 0', output)
677
Dominique Pellebb162362021-05-31 20:04:07 +0200678 " Both compounding and NOBREAK specified
679 call writefile(['COMPOUNDFLAG c', 'NOBREAK'], 'Xtest.aff')
680 let output = execute('mkspell! Xtest.spl Xtest')
681 call assert_match('Warning: both compounding and NOBREAK specified', output)
682
Bram Moolenaarc8ec5fe2020-08-24 20:28:56 +0200683 " Duplicate affix entry in an affix file
Bram Moolenaarc8ec5fe2020-08-24 20:28:56 +0200684 call writefile(['PFX L Y 1', 'PFX L 0 re x', 'PFX L Y 1', 'PFX L 0 re x'],
685 \ 'Xtest.aff')
686 let output = execute('mkspell! Xtest.spl Xtest')
687 call assert_match('Duplicate affix in Xtest.aff line 3: L', output)
688
689 " Duplicate affix entry in an affix file
Bram Moolenaarc8ec5fe2020-08-24 20:28:56 +0200690 call writefile(['PFX L Y 1', 'PFX L Y 1'], 'Xtest.aff')
691 let output = execute('mkspell! Xtest.spl Xtest')
692 call assert_match('Unrecognized or duplicate item in Xtest.aff line 2: PFX', output)
693
694 " Different combining flags in an affix file
Bram Moolenaarc8ec5fe2020-08-24 20:28:56 +0200695 call writefile(['PFX L Y 1', 'PFX L 0 re x', 'PFX L N 1'], 'Xtest.aff')
696 let output = execute('mkspell! Xtest.spl Xtest')
697 call assert_match('Different combining flag in continued affix block in Xtest.aff line 3', output)
698
Dominique Pelle923dce22021-11-21 11:36:04 +0000699 " Try to reuse an affix used for BAD flag
Bram Moolenaarc8ec5fe2020-08-24 20:28:56 +0200700 call writefile(['BAD x', 'PFX x Y 1', 'PFX x 0 re x'], 'Xtest.aff')
701 let output = execute('mkspell! Xtest.spl Xtest')
702 call assert_match('Affix also used for BAD/RARE/KEEPCASE/NEEDAFFIX/NEEDCOMPOUND/NOSUGGEST in Xtest.aff line 2: x', output)
703
704 " Trailing characters in an affix entry
Bram Moolenaarc8ec5fe2020-08-24 20:28:56 +0200705 call writefile(['PFX L Y 1 Test', 'PFX L 0 re x'], 'Xtest.aff')
706 let output = execute('mkspell! Xtest.spl Xtest')
707 call assert_match('Trailing text in Xtest.aff line 1: Test', output)
708
709 " Trailing characters in an affix entry
Bram Moolenaarc8ec5fe2020-08-24 20:28:56 +0200710 call writefile(['PFX L Y 1', 'PFX L 0 re x Test'], 'Xtest.aff')
711 let output = execute('mkspell! Xtest.spl Xtest')
712 call assert_match('Trailing text in Xtest.aff line 2: Test', output)
713
714 " Incorrect combine flag in an affix entry
Bram Moolenaarc8ec5fe2020-08-24 20:28:56 +0200715 call writefile(['PFX L X 1', 'PFX L 0 re x'], 'Xtest.aff')
716 let output = execute('mkspell! Xtest.spl Xtest')
717 call assert_match('Expected Y or N in Xtest.aff line 1: X', output)
718
719 " Invalid count for REP item
Bram Moolenaarc8ec5fe2020-08-24 20:28:56 +0200720 call writefile(['REP a'], 'Xtest.aff')
721 let output = execute('mkspell! Xtest.spl Xtest')
722 call assert_match('Expected REP(SAL) count in Xtest.aff line 1', output)
723
724 " Trailing characters in REP item
Bram Moolenaarc8ec5fe2020-08-24 20:28:56 +0200725 call writefile(['REP 1', 'REP f ph test'], 'Xtest.aff')
726 let output = execute('mkspell! Xtest.spl Xtest')
727 call assert_match('Trailing text in Xtest.aff line 2: test', output)
728
729 " Invalid count for MAP item
Bram Moolenaarc8ec5fe2020-08-24 20:28:56 +0200730 call writefile(['MAP a'], 'Xtest.aff')
731 let output = execute('mkspell! Xtest.spl Xtest')
732 call assert_match('Expected MAP count in Xtest.aff line 1', output)
733
734 " Duplicate character in a MAP item
Bram Moolenaarc8ec5fe2020-08-24 20:28:56 +0200735 call writefile(['MAP 2', 'MAP xx', 'MAP yy'], 'Xtest.aff')
736 let output = execute('mkspell! Xtest.spl Xtest')
737 call assert_match('Duplicate character in MAP in Xtest.aff line 2', output)
738
739 " Use COMPOUNDSYLMAX without SYLLABLE
Bram Moolenaarc8ec5fe2020-08-24 20:28:56 +0200740 call writefile(['COMPOUNDSYLMAX 2'], 'Xtest.aff')
741 let output = execute('mkspell! Xtest.spl Xtest')
742 call assert_match('COMPOUNDSYLMAX used without SYLLABLE', output)
743
744 " Missing SOFOTO
Bram Moolenaarc8ec5fe2020-08-24 20:28:56 +0200745 call writefile(['SOFOFROM abcdef'], 'Xtest.aff')
746 let output = execute('mkspell! Xtest.spl Xtest')
747 call assert_match('Missing SOFOTO line in Xtest.aff', output)
748
Bram Moolenaarb9fc1922020-08-25 21:19:36 +0200749 " Length of SOFOFROM and SOFOTO differ
750 call writefile(['SOFOFROM abcde', 'SOFOTO ABCD'], 'Xtest.aff')
751 call assert_fails('mkspell! Xtest.spl Xtest', 'E759:')
752
753 " Both SAL and SOFOFROM/SOFOTO items
754 call writefile(['SOFOFROM abcd', 'SOFOTO ABCD', 'SAL CIA X'], 'Xtest.aff')
755 let output = execute('mkspell! Xtest.spl Xtest')
756 call assert_match('Both SAL and SOFO lines in Xtest.aff', output)
Bram Moolenaarc8ec5fe2020-08-24 20:28:56 +0200757
758 " use an alphabet flag when FLAG is num
Bram Moolenaarc8ec5fe2020-08-24 20:28:56 +0200759 call writefile(['FLAG num', 'SFX L Y 1', 'SFX L 0 re [^x]'], 'Xtest.aff')
760 let output = execute('mkspell! Xtest.spl Xtest')
761 call assert_match('Flag is not a number in Xtest.aff line 2: L', output)
762
763 " use number and alphabet flag when FLAG is num
Bram Moolenaarc8ec5fe2020-08-24 20:28:56 +0200764 call writefile(['FLAG num', 'SFX 4f Y 1', 'SFX 4f 0 re [^x]'], 'Xtest.aff')
765 let output = execute('mkspell! Xtest.spl Xtest')
766 call assert_match('Affix name too long in Xtest.aff line 2: 4f', output)
767
768 " use a single character flag when FLAG is long
Bram Moolenaarc8ec5fe2020-08-24 20:28:56 +0200769 call writefile(['FLAG long', 'SFX L Y 1', 'SFX L 0 re [^x]'], 'Xtest.aff')
770 let output = execute('mkspell! Xtest.spl Xtest')
771 call assert_match('Illegal flag in Xtest.aff line 2: L', output)
772
Bram Moolenaar64e2db62020-09-09 22:43:19 +0200773 " missing character in UPP entry. The character table is used only in a
774 " non-utf8 encoding
775 call writefile(['FOL abc', 'LOW abc', 'UPP A'], 'Xtest.aff')
776 let save_encoding = &encoding
777 set encoding=cp949
778 call assert_fails('mkspell! Xtest.spl Xtest', 'E761:')
779 let &encoding = save_encoding
780
781 " character range doesn't match between FOL and LOW entries
782 call writefile(["FOL \u0102bc", 'LOW abc', 'UPP ABC'], 'Xtest.aff')
783 let save_encoding = &encoding
784 set encoding=cp949
785 call assert_fails('mkspell! Xtest.spl Xtest', 'E762:')
786 let &encoding = save_encoding
787
788 " character range doesn't match between FOL and UPP entries
789 call writefile(["FOL \u0102bc", "LOW \u0102bc", 'UPP ABC'], 'Xtest.aff')
790 let save_encoding = &encoding
791 set encoding=cp949
792 call assert_fails('mkspell! Xtest.spl Xtest', 'E762:')
793 let &encoding = save_encoding
794
795 " additional characters in LOW and UPP entries
796 call writefile(["FOL ab", "LOW abc", 'UPP ABC'], 'Xtest.aff')
797 let save_encoding = &encoding
798 set encoding=cp949
799 call assert_fails('mkspell! Xtest.spl Xtest', 'E761:')
800 let &encoding = save_encoding
801
Bram Moolenaar96fdf432020-09-11 18:11:50 +0200802 " missing UPP entry
803 call writefile(["FOL abc", "LOW abc"], 'Xtest.aff')
804 let save_encoding = &encoding
805 set encoding=cp949
806 let output = execute('mkspell! Xtest.spl Xtest')
807 call assert_match('Missing FOL/LOW/UPP line in Xtest.aff', output)
808 let &encoding = save_encoding
809
Bram Moolenaarb9fc1922020-08-25 21:19:36 +0200810 " duplicate word in the .dic file
811 call writefile(['2', 'good', 'good', 'good'], 'Xtest.dic')
812 call writefile(['NAME vim'], 'Xtest.aff')
813 let output = execute('mkspell! Xtest.spl Xtest')
814 call assert_match('First duplicate word in Xtest.dic line 3: good', output)
815 call assert_match('2 duplicate word(s) in Xtest.dic', output)
816
Bram Moolenaar96fdf432020-09-11 18:11:50 +0200817 " use multiple .aff files with different values for COMPOUNDWORDMAX and
818 " MIDWORD (number and string)
Bram Moolenaar56564962022-10-10 22:39:42 +0100819 call writefile(['1', 'world'], 'Xtest_US.dic', 'D')
820 call writefile(['1', 'world'], 'Xtest_CA.dic', 'D')
821 call writefile(["COMPOUNDWORDMAX 3", "MIDWORD '-"], 'Xtest_US.aff', 'D')
822 call writefile(["COMPOUNDWORDMAX 4", "MIDWORD '="], 'Xtest_CA.aff', 'D')
Bram Moolenaar96fdf432020-09-11 18:11:50 +0200823 let output = execute('mkspell! Xtest.spl Xtest_US Xtest_CA')
824 call assert_match('COMPOUNDWORDMAX value differs from what is used in another .aff file', output)
825 call assert_match('MIDWORD value differs from what is used in another .aff file', output)
Bram Moolenaar96fdf432020-09-11 18:11:50 +0200826
Bram Moolenaarc8ec5fe2020-08-24 20:28:56 +0200827 call delete('Xtest.spl')
828 call delete('Xtest.sug')
829endfunc
830
Bram Moolenaarfc2a47f2020-08-20 15:41:55 +0200831func Test_spell_add_word()
832 set spellfile=
833 call assert_fails('spellgood abc', 'E764:')
834
835 set spellfile=Xtest.utf-8.add
836 call assert_fails('2spellgood abc', 'E765:')
837
838 edit Xtest.utf-8.add
839 call setline(1, 'sample')
840 call assert_fails('spellgood abc', 'E139:')
841 set spellfile&
842 %bw!
843endfunc
844
zeertzjq0dff3152024-07-29 20:28:14 +0200845func Test_spell_add_long_word()
846 set spell spellfile=./Xspellfile.add spelllang=en
847
848 let word = repeat('a', 9000)
849 let v:errmsg = ''
850 " Spell checking doesn't really work for such a long word,
851 " but this should not cause an E1510 error.
852 exe 'spellgood ' .. word
853 call assert_equal('', v:errmsg)
854 call assert_equal([word], readfile('./Xspellfile.add'))
855
856 set spell& spellfile= spelllang& encoding=utf-8
857 call delete('./Xspellfile.add')
858 call delete('./Xspellfile.add.spl')
859endfunc
860
Dominique Pelle5a6cfb32021-05-29 17:29:33 +0200861func Test_spellfile_verbose()
Bram Moolenaar56564962022-10-10 22:39:42 +0100862 call writefile(['1', 'one'], 'XtestVerbose.dic', 'D')
863 call writefile([], 'XtestVerbose.aff', 'D')
Dominique Pelle5a6cfb32021-05-29 17:29:33 +0200864 mkspell! XtestVerbose-utf8.spl XtestVerbose
865 set spell
866
867 " First time: the spl file should be read.
868 let a = execute('3verbose set spelllang=XtestVerbose-utf8.spl')
869 call assert_match('Reading spell file "XtestVerbose-utf8.spl"', a)
870
871 " Second time time: the spl file should not be read (already read).
872 let a = execute('3verbose set spelllang=XtestVerbose-utf8.spl')
873 call assert_notmatch('Reading spell file "XtestVerbose-utf8.spl"', a)
874
875 set spell& spelllang&
Dominique Pelle5a6cfb32021-05-29 17:29:33 +0200876 call delete('XtestVerbose-utf8.spl')
877endfunc
878
879" Test NOBREAK (see :help spell-NOBREAK)
880func Test_NOBREAK()
Bram Moolenaar56564962022-10-10 22:39:42 +0100881 call writefile(['3', 'one', 'two', 'three' ], 'XtestNOBREAK.dic', 'D')
882 call writefile(['NOBREAK' ], 'XtestNOBREAK.aff', 'D')
Dominique Pelle5a6cfb32021-05-29 17:29:33 +0200883
884 mkspell! XtestNOBREAK-utf8.spl XtestNOBREAK
885 set spell spelllang=XtestNOBREAK-utf8.spl
886
887 call assert_equal(['', ''], spellbadword('One two three onetwo onetwothree threetwoone'))
888
889 call assert_equal(['x', 'bad'], spellbadword('x'))
890 call assert_equal(['y', 'bad'], spellbadword('yone'))
891 call assert_equal(['z', 'bad'], spellbadword('onez'))
892 call assert_equal(['zero', 'bad'], spellbadword('Onetwozerothree'))
893
Dominique Pellebb162362021-05-31 20:04:07 +0200894 new
895 call setline(1, 'Onetwwothree')
896 norm! fw1z=
897 call assert_equal('Onetwothree', getline(1))
898 call setline(1, 'Onetwothre')
899 norm! fh1z=
900 call assert_equal('Onetwothree', getline(1))
901
902 bw!
Dominique Pelle5a6cfb32021-05-29 17:29:33 +0200903 set spell& spelllang&
Dominique Pelle5a6cfb32021-05-29 17:29:33 +0200904 call delete('XtestNOBREAK-utf8.spl')
905endfunc
906
Dominique Pelledc3275a2021-05-28 18:32:12 +0200907" Test CHECKCOMPOUNDPATTERN (see :help spell-CHECKCOMPOUNDPATTERN)
908func Test_spellfile_CHECKCOMPOUNDPATTERN()
909 call writefile(['4',
910 \ 'one/c',
911 \ 'two/c',
912 \ 'three/c',
Bram Moolenaar56564962022-10-10 22:39:42 +0100913 \ 'four'], 'XtestCHECKCOMPOUNDPATTERN.dic', 'D')
Dominique Pelledc3275a2021-05-28 18:32:12 +0200914 " Forbid compound words where first word ends with 'wo' and second starts with 'on'.
915 call writefile(['CHECKCOMPOUNDPATTERN 1',
916 \ 'CHECKCOMPOUNDPATTERN wo on',
Bram Moolenaar56564962022-10-10 22:39:42 +0100917 \ 'COMPOUNDFLAG c'], 'XtestCHECKCOMPOUNDPATTERN.aff', 'D')
Dominique Pelledc3275a2021-05-28 18:32:12 +0200918
Dominique Pelle5a6cfb32021-05-29 17:29:33 +0200919 mkspell! XtestCHECKCOMPOUNDPATTERN-utf8.spl XtestCHECKCOMPOUNDPATTERN
Dominique Pelledc3275a2021-05-28 18:32:12 +0200920 set spell spelllang=XtestCHECKCOMPOUNDPATTERN-utf8.spl
921
922 " Check valid words with and without valid compounds.
923 for goodword in ['one', 'two', 'three', 'four',
924 \ 'oneone', 'onetwo', 'onethree',
925 \ 'twotwo', 'twothree',
926 \ 'threeone', 'threetwo', 'threethree',
927 \ 'onetwothree', 'onethreetwo', 'twothreeone', 'oneoneone']
928 call assert_equal(['', ''], spellbadword(goodword), goodword)
929 endfor
930
931 " Compounds 'twoone' or 'threetwoone' should be forbidden by CHECKCOMPOUNPATTERN.
932 " 'four' does not have the 'c' flag in *.aff file so no compound.
933 " 'five' is not in the *.dic file.
934 for badword in ['five', 'onetwox',
935 \ 'twoone', 'threetwoone',
936 \ 'fourone', 'onefour']
937 call assert_equal([badword, 'bad'], spellbadword(badword))
938 endfor
939
940 set spell& spelllang&
Dominique Pelledc3275a2021-05-28 18:32:12 +0200941 call delete('XtestCHECKCOMPOUNDPATTERN-utf8.spl')
942endfunc
943
Dominique Pelle9c9472f2021-07-24 20:51:13 +0200944" Test NOCOMPOUNDSUGS (see :help spell-NOCOMPOUNDSUGS)
945func Test_spellfile_NOCOMPOUNDSUGS()
946 call writefile(['3',
947 \ 'one/c',
948 \ 'two/c',
Bram Moolenaar56564962022-10-10 22:39:42 +0100949 \ 'three/c'], 'XtestNOCOMPOUNDSUGS.dic', 'D')
Dominique Pelle9c9472f2021-07-24 20:51:13 +0200950
951 " pass 0 tests without NOCOMPOUNDSUGS, pass 1 tests with NOCOMPOUNDSUGS
952 for pass in [0, 1]
953 if pass == 0
Bram Moolenaar56564962022-10-10 22:39:42 +0100954 call writefile(['COMPOUNDFLAG c'], 'XtestNOCOMPOUNDSUGS.aff', 'D')
Dominique Pelle9c9472f2021-07-24 20:51:13 +0200955 else
956 call writefile(['NOCOMPOUNDSUGS',
Bram Moolenaar56564962022-10-10 22:39:42 +0100957 \ 'COMPOUNDFLAG c'], 'XtestNOCOMPOUNDSUGS.aff', 'D')
Dominique Pelle9c9472f2021-07-24 20:51:13 +0200958 endif
959
960 mkspell! XtestNOCOMPOUNDSUGS-utf8.spl XtestNOCOMPOUNDSUGS
961 set spell spelllang=XtestNOCOMPOUNDSUGS-utf8.spl
962
963 for goodword in ['one', 'two', 'three',
964 \ 'oneone', 'onetwo', 'onethree',
965 \ 'twoone', 'twotwo', 'twothree',
966 \ 'threeone', 'threetwo', 'threethree',
967 \ 'onetwothree', 'onethreetwo', 'twothreeone', 'oneoneone']
968 call assert_equal(['', ''], spellbadword(goodword), goodword)
969 endfor
970
971 for badword in ['four', 'onetwox', 'onexone']
972 call assert_equal([badword, 'bad'], spellbadword(badword))
973 endfor
974
975 if pass == 0
976 call assert_equal(['one', 'oneone'], spellsuggest('onne', 2))
977 call assert_equal(['onethree', 'one three'], spellsuggest('onethre', 2))
978 else
979 call assert_equal(['one', 'one one'], spellsuggest('onne', 2))
980 call assert_equal(['one three'], spellsuggest('onethre', 2))
981 endif
982 endfor
983
984 set spell& spelllang&
Dominique Pelle9c9472f2021-07-24 20:51:13 +0200985 call delete('XtestNOCOMPOUNDSUGS-utf8.spl')
986endfunc
987
Dominique Pelledc3275a2021-05-28 18:32:12 +0200988" Test COMMON (better suggestions with common words, see :help spell-COMMON)
989func Test_spellfile_COMMON()
990 call writefile(['7',
991 \ 'and',
992 \ 'ant',
993 \ 'end',
994 \ 'any',
995 \ 'tee',
996 \ 'the',
Bram Moolenaar56564962022-10-10 22:39:42 +0100997 \ 'ted'], 'XtestCOMMON.dic', 'D')
998 call writefile(['COMMON the and'], 'XtestCOMMON.aff', 'D')
Dominique Pelledc3275a2021-05-28 18:32:12 +0200999
Dominique Pelle5a6cfb32021-05-29 17:29:33 +02001000 mkspell! XtestCOMMON-utf8.spl XtestCOMMON
Dominique Pelledc3275a2021-05-28 18:32:12 +02001001 set spell spelllang=XtestCOMMON-utf8.spl
1002
1003 " COMMON words 'and' and 'the' should be the top suggestions.
1004 call assert_equal(['and', 'ant'], spellsuggest('anr', 2))
1005 call assert_equal(['and', 'end'], spellsuggest('ond', 2))
1006 call assert_equal(['the', 'ted'], spellsuggest('tha', 2))
1007 call assert_equal(['the', 'tee'], spellsuggest('dhe', 2))
1008
1009 set spell& spelllang&
Dominique Pelledc3275a2021-05-28 18:32:12 +02001010 call delete('XtestCOMMON-utf8.spl')
1011endfunc
1012
Dominique Pellebfb2bb12021-08-14 21:11:51 +02001013" Test NOSUGGEST (see :help spell-COMMON)
1014func Test_spellfile_NOSUGGEST()
Bram Moolenaar56564962022-10-10 22:39:42 +01001015 call writefile(['2', 'foo/X', 'fog'], 'XtestNOSUGGEST.dic', 'D')
1016 call writefile(['NOSUGGEST X'], 'XtestNOSUGGEST.aff', 'D')
Dominique Pellebfb2bb12021-08-14 21:11:51 +02001017
1018 mkspell! XtestNOSUGGEST-utf8.spl XtestNOSUGGEST
1019 set spell spelllang=XtestNOSUGGEST-utf8.spl
1020
1021 for goodword in ['foo', 'Foo', 'FOO', 'fog', 'Fog', 'FOG']
1022 call assert_equal(['', ''], spellbadword(goodword), goodword)
1023 endfor
1024 for badword in ['foO', 'fOO', 'fooo', 'foog', 'foofog', 'fogfoo']
1025 call assert_equal([badword, 'bad'], spellbadword(badword))
1026 endfor
1027
1028 call assert_equal(['fog'], spellsuggest('fooo', 1))
1029 call assert_equal(['fog'], spellsuggest('fOo', 1))
1030 call assert_equal(['fog'], spellsuggest('foG', 1))
1031 call assert_equal(['fog'], spellsuggest('fogg', 1))
1032
1033 set spell& spelllang&
Dominique Pellebfb2bb12021-08-14 21:11:51 +02001034 call delete('XtestNOSUGGEST-utf8.spl')
1035endfunc
1036
1037
Dominique Pelle5a6cfb32021-05-29 17:29:33 +02001038" Test CIRCUMFIX (see: :help spell-CIRCUMFIX)
1039func Test_spellfile_CIRCUMFIX()
1040 " Example taken verbatim from https://github.com/hunspell/hunspell/tree/master/tests
1041 call writefile(['1',
Bram Moolenaar56564962022-10-10 22:39:42 +01001042 \ 'nagy/C po:adj'], 'XtestCIRCUMFIX.dic', 'D')
Dominique Pelle5a6cfb32021-05-29 17:29:33 +02001043 call writefile(['# circumfixes: ~ obligate prefix/suffix combinations',
1044 \ '# superlative in Hungarian: leg- (prefix) AND -bb (suffix)',
1045 \ '',
1046 \ 'CIRCUMFIX X',
1047 \ '',
1048 \ 'PFX A Y 1',
1049 \ 'PFX A 0 leg/X .',
1050 \ '',
1051 \ 'PFX B Y 1',
1052 \ 'PFX B 0 legesleg/X .',
1053 \ '',
1054 \ 'SFX C Y 3',
1055 \ 'SFX C 0 obb . is:COMPARATIVE',
1056 \ 'SFX C 0 obb/AX . is:SUPERLATIVE',
Bram Moolenaar56564962022-10-10 22:39:42 +01001057 \ 'SFX C 0 obb/BX . is:SUPERSUPERLATIVE'], 'XtestCIRCUMFIX.aff', 'D')
Dominique Pelle5a6cfb32021-05-29 17:29:33 +02001058
1059 mkspell! XtestCIRCUMFIX-utf8.spl XtestCIRCUMFIX
1060 set spell spelllang=XtestCIRCUMFIX-utf8.spl
1061
1062 " From https://catalog.ldc.upenn.edu/docs/LDC2008T01/acta04.pdf:
1063 " Hungarian English
1064 " --------- -------
1065 " nagy great
1066 " nagyobb greater
1067 " legnagyobb greatest
1068 " legeslegnagyob most greatest
1069 call assert_equal(['', ''], spellbadword('nagy nagyobb legnagyobb legeslegnagyobb'))
1070
1071 for badword in ['legnagy', 'legeslegnagy', 'legobb', 'legeslegobb']
1072 call assert_equal([badword, 'bad'], spellbadword(badword))
1073 endfor
1074
1075 set spell& spelllang&
Dominique Pelle5a6cfb32021-05-29 17:29:33 +02001076 call delete('XtestCIRCUMFIX-utf8.spl')
1077endfunc
1078
Dominique Pellebb162362021-05-31 20:04:07 +02001079" Test SFX that strips/chops characters
1080func Test_spellfile_SFX_strip()
1081 " Simplified conjugation of Italian verbs ending in -are (first conjugation).
1082 call writefile(['SFX A Y 4',
1083 \ 'SFX A are iamo [^icg]are',
1084 \ 'SFX A are hiamo [cg]are',
1085 \ 'SFX A re mo iare',
1086 \ 'SFX A re vamo are'],
Bram Moolenaar56564962022-10-10 22:39:42 +01001087 \ 'XtestSFX.aff', 'D')
Dominique Pellebb162362021-05-31 20:04:07 +02001088 " Examples of Italian verbs:
1089 " - cantare = to sing
1090 " - cercare = to search
1091 " - odiare = to hate
Bram Moolenaar56564962022-10-10 22:39:42 +01001092 call writefile(['3', 'cantare/A', 'cercare/A', 'odiare/A'], 'XtestSFX.dic', 'D')
Dominique Pellebb162362021-05-31 20:04:07 +02001093
1094 mkspell! XtestSFX-utf8.spl XtestSFX
1095 set spell spelllang=XtestSFX-utf8.spl
1096
1097 " To sing, we're singing, we were singing.
1098 call assert_equal(['', ''], spellbadword('cantare cantiamo cantavamo'))
1099
1100 " To search, we're searching, we were searching.
1101 call assert_equal(['', ''], spellbadword('cercare cerchiamo cercavamo'))
1102
1103 " To hate, we hate, we were hating.
1104 call assert_equal(['', ''], spellbadword('odiare odiamo odiavamo'))
1105
1106 for badword in ['canthiamo', 'cerciamo', 'cantarevamo', 'odiiamo']
1107 call assert_equal([badword, 'bad'], spellbadword(badword))
1108 endfor
1109
1110 call assert_equal(['cantiamo'], spellsuggest('canthiamo', 1))
1111 call assert_equal(['cerchiamo'], spellsuggest('cerciamo', 1))
1112 call assert_equal(['cantavamo'], spellsuggest('cantarevamo', 1))
1113 call assert_equal(['odiamo'], spellsuggest('odiiamo', 1))
1114
1115 set spell& spelllang&
Dominique Pellebb162362021-05-31 20:04:07 +02001116 call delete('XtestSFX-utf8.spl')
1117endfunc
1118
Bram Moolenaarc8ec5fe2020-08-24 20:28:56 +02001119" When 'spellfile' is not set, adding a new good word will automatically set
1120" the 'spellfile'
1121func Test_init_spellfile()
1122 let save_rtp = &rtp
1123 let save_encoding = &encoding
Bram Moolenaar56564962022-10-10 22:39:42 +01001124 call mkdir('Xrtp/spell', 'pR')
Bram Moolenaarc8ec5fe2020-08-24 20:28:56 +02001125 call writefile(['vim'], 'Xrtp/spell/Xtest.dic')
1126 silent mkspell Xrtp/spell/Xtest.utf-8.spl Xrtp/spell/Xtest.dic
1127 set runtimepath=./Xrtp
1128 set spelllang=Xtest
1129 set spell
1130 silent spellgood abc
1131 call assert_equal('./Xrtp/spell/Xtest.utf-8.add', &spellfile)
1132 call assert_equal(['abc'], readfile('Xrtp/spell/Xtest.utf-8.add'))
1133 call assert_true(filereadable('Xrtp/spell/Xtest.utf-8.spl'))
Bram Moolenaar56564962022-10-10 22:39:42 +01001134
Bram Moolenaarc8ec5fe2020-08-24 20:28:56 +02001135 set spell& spelllang& spellfile&
Bram Moolenaarc8ec5fe2020-08-24 20:28:56 +02001136 let &encoding = save_encoding
1137 let &rtp = save_rtp
1138 %bw!
1139endfunc
1140
Bram Moolenaarb9fc1922020-08-25 21:19:36 +02001141" Test for the 'mkspellmem' option
1142func Test_mkspellmem_opt()
1143 call assert_fails('set mkspellmem=1000', 'E474:')
1144 call assert_fails('set mkspellmem=1000,', 'E474:')
1145 call assert_fails('set mkspellmem=1000,50', 'E474:')
1146 call assert_fails('set mkspellmem=1000,50,', 'E474:')
1147 call assert_fails('set mkspellmem=1000,50,10,', 'E474:')
1148 call assert_fails('set mkspellmem=1000,50,0', 'E474:')
1149endfunc
1150
Bram Moolenaarbc49c5f2022-08-04 13:01:48 +01001151" 'spellfile' accepts '@' on top of 'isfname'.
1152def Test_spellfile_allow_at_character()
1153 mkdir('Xtest/the foo@bar,dir', 'p')
Milly322ad0c2024-10-14 20:21:48 +02001154 &spellfile = './Xtest/the foo@bar\,dir/Xspellfile.add'
Bram Moolenaarbc49c5f2022-08-04 13:01:48 +01001155 &spellfile = ''
1156 delete('Xtest', 'rf')
1157enddef
1158
Bram Moolenaar6669de12022-08-21 20:33:47 +01001159" this was using a NULL pointer
1160func Test_mkspell_empty_dic()
Bram Moolenaar56564962022-10-10 22:39:42 +01001161 call writefile(['1'], 'XtestEmpty.dic', 'D')
1162 call writefile(['SOFOFROM abcd', 'SOFOTO ABCD', 'SAL CIA X'], 'XtestEmpty.aff', 'D')
Bram Moolenaar6669de12022-08-21 20:33:47 +01001163 mkspell! XtestEmpty.spl XtestEmpty
1164
Bram Moolenaar6669de12022-08-21 20:33:47 +01001165 call delete('XtestEmpty.spl')
1166endfunc
1167
1168
Bram Moolenaar6d91bcb2020-08-12 18:50:36 +02001169" vim: shiftwidth=2 sts=2 expandtab