spell_spec.lua (24803B)
1 -- Test for scenarios involving 'spell' 2 3 local t = require('test.testutil') 4 local n = require('test.functional.testnvim')() 5 local Screen = require('test.functional.ui.screen') 6 7 local clear = n.clear 8 local exec = n.exec 9 local feed = n.feed 10 local insert = n.insert 11 local api = n.api 12 local is_os = t.is_os 13 14 describe("'spell'", function() 15 local screen 16 17 before_each(function() 18 clear() 19 screen = Screen.new(80, 8) 20 screen:set_default_attr_ids({ 21 [0] = { bold = true, foreground = Screen.colors.Blue }, 22 [1] = { special = Screen.colors.Red, undercurl = true }, 23 [2] = { special = Screen.colors.Blue, undercurl = true }, 24 [3] = { foreground = tonumber('0x6a0dad') }, 25 [4] = { foreground = Screen.colors.Magenta }, 26 [5] = { bold = true, foreground = Screen.colors.SeaGreen }, 27 [6] = { foreground = Screen.colors.Red }, 28 [7] = { foreground = Screen.colors.Blue }, 29 [8] = { foreground = Screen.colors.Blue, special = Screen.colors.Red, undercurl = true }, 30 [9] = { bold = true }, 31 [10] = { background = Screen.colors.LightGrey, foreground = Screen.colors.DarkBlue }, 32 }) 33 end) 34 35 it('joins long lines #7937', function() 36 if is_os('openbsd') then 37 pending('FIXME #12104', function() end) 38 return 39 end 40 exec('set spell') 41 insert([[ 42 Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod 43 tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, 44 quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo 45 consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse 46 cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat 47 non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. 48 ]]) 49 feed('ggJJJJJJ0') 50 screen:expect([[ 51 {1:^Lorem} {1:ipsum} dolor sit {1:amet}, {1:consectetur} {1:adipiscing} {1:elit}, {1:sed} do {1:eiusmod} {1:tempor} {1:i}| 52 {1:ncididunt} {1:ut} {1:labore} et {1:dolore} {1:magna} {1:aliqua}. {1:Ut} {1:enim} ad minim {1:veniam}, {1:quis} {1:nostru}| 53 {1:d} {1:exercitation} {1:ullamco} {1:laboris} {1:nisi} {1:ut} {1:aliquip} ex ea {1:commodo} {1:consequat}. {1:Duis} {1:aut}| 54 {1:e} {1:irure} dolor in {1:reprehenderit} in {1:voluptate} {1:velit} {1:esse} {1:cillum} {1:dolore} {1:eu} {1:fugiat} {1:n}| 55 {1:ulla} {1:pariatur}. {1:Excepteur} {1:sint} {1:occaecat} {1:cupidatat} non {1:proident}, {1:sunt} in culpa {1:qui}| 56 {1:officia} {1:deserunt} {1:mollit} {1:anim} id est {1:laborum}. | 57 {0:~ }| 58 | 59 ]]) 60 end) 61 62 -- oldtest: Test_spell_screendump() 63 it('has correct highlight at start of line', function() 64 exec([=[ 65 call setline(1, [ 66 \"This is some text without any spell errors. Everything", 67 \"should just be black, nothing wrong here.", 68 \"", 69 \"This line has a sepll error. and missing caps.", 70 \"And and this is the the duplication.", 71 \"with missing caps here.", 72 \]) 73 set spell spelllang=en_nz 74 ]=]) 75 screen:expect([[ 76 ^This is some text without any spell errors. Everything | 77 should just be black, nothing wrong here. | 78 | 79 This line has a {1:sepll} error. {2:and} missing caps. | 80 {1:And and} this is {1:the the} duplication. | 81 {2:with} missing caps here. | 82 {0:~ }| 83 | 84 ]]) 85 end) 86 87 -- oldtest: Test_spell_screendump_spellcap() 88 it('SpellCap highlight at start of line', function() 89 exec([=[ 90 call setline(1, [ 91 \" This line has a sepll error. and missing caps and trailing spaces. ", 92 \"another missing cap here.", 93 \"", 94 \"and here.", 95 \" ", 96 \"and here." 97 \]) 98 set spell spelllang=en 99 ]=]) 100 screen:expect([[ 101 ^ This line has a {1:sepll} error. {2:and} missing caps and trailing spaces. | 102 {2:another} missing cap here. | 103 | 104 {2:and} here. | 105 | 106 {2:and} here. | 107 {0:~ }| 108 | 109 ]]) 110 -- After adding word missing Cap in next line is updated 111 feed('3GANot<Esc>') 112 screen:expect([[ 113 This line has a {1:sepll} error. {2:and} missing caps and trailing spaces. | 114 {2:another} missing cap here. | 115 No^t | 116 and here. | 117 | 118 {2:and} here. | 119 {0:~ }| 120 | 121 ]]) 122 -- Deleting a full stop removes missing Cap in next line 123 feed('5Gdd<C-L>k$x') 124 screen:expect([[ 125 This line has a {1:sepll} error. {2:and} missing caps and trailing spaces. | 126 {2:another} missing cap here. | 127 Not | 128 and her^e | 129 and here. | 130 {0:~ }|*2 131 | 132 ]]) 133 -- Undo also updates the next line (go to command line to remove message) 134 feed('u:<Esc>') 135 screen:expect([[ 136 This line has a {1:sepll} error. {2:and} missing caps and trailing spaces. | 137 {2:another} missing cap here. | 138 Not | 139 and here^. | 140 {2:and} here. | 141 {0:~ }|*2 142 | 143 ]]) 144 -- Folding an empty line does not remove Cap in next line 145 feed('uzfk:<Esc>') 146 screen:expect([[ 147 This line has a {1:sepll} error. {2:and} missing caps and trailing spaces. | 148 {2:another} missing cap here. | 149 Not | 150 {10:^+-- 2 lines: and here.·························································}| 151 {2:and} here. | 152 {0:~ }|*2 153 | 154 ]]) 155 -- Folding the end of a sentence does not remove Cap in next line 156 -- and editing a line does not remove Cap in current line 157 feed('Jzfkk$x') 158 screen:expect([[ 159 This line has a {1:sepll} error. {2:and} missing caps and trailing spaces. | 160 {2:another} missing cap her^e | 161 {10:+-- 2 lines: Not·······························································}| 162 {2:and} here. | 163 {0:~ }|*3 164 | 165 ]]) 166 -- Cap is correctly applied in the first row of a window 167 feed('<C-E><C-L>') 168 screen:expect([[ 169 {2:another} missing cap her^e | 170 {10:+-- 2 lines: Not·······························································}| 171 {2:and} here. | 172 {0:~ }|*4 173 | 174 ]]) 175 -- Adding an empty line does not remove Cap in "mod_bot" area 176 feed('zbO<Esc>') 177 screen:expect([[ 178 This line has a {1:sepll} error. {2:and} missing caps and trailing spaces. | 179 ^ | 180 {2:another} missing cap here | 181 {10:+-- 2 lines: Not·······························································}| 182 {2:and} here. | 183 {0:~ }|*2 184 | 185 ]]) 186 -- Multiple empty lines does not remove Cap in the line after 187 feed('O<Esc><C-L>') 188 screen:expect([[ 189 This line has a {1:sepll} error. {2:and} missing caps and trailing spaces. | 190 ^ | 191 | 192 {2:another} missing cap here | 193 {10:+-- 2 lines: Not·······························································}| 194 {2:and} here. | 195 {0:~ }| 196 | 197 ]]) 198 end) 199 200 -- oldtest: Test_spell_compatible() 201 it([[redraws properly when using "C" and "$" is in 'cpo']], function() 202 exec([=[ 203 call setline(1, [ 204 \ "test "->repeat(20), 205 \ "", 206 \ "end", 207 \ ]) 208 set spell cpo+=$ 209 ]=]) 210 feed('51|C') 211 screen:expect([[ 212 {2:test} test test test test test test test test test ^test test test test test test | 213 test test test test$ | 214 | 215 {2:end} | 216 {0:~ }|*3 217 {9:-- INSERT --} | 218 ]]) 219 feed('x') 220 screen:expect([[ 221 {2:test} test test test test test test test test test x^est test test test test test | 222 test test test test$ | 223 | 224 {2:end} | 225 {0:~ }|*3 226 {9:-- INSERT --} | 227 ]]) 228 end) 229 230 it('extmarks, "noplainbuffer" and syntax #20385 #23398', function() 231 exec('set filetype=c') 232 exec('syntax on') 233 exec('set spell') 234 insert([[ 235 #include <stdbool.h> 236 bool func(void); 237 // I am a speling mistakke]]) 238 feed('ge') 239 screen:expect([[ 240 {3:#include }{4:<stdbool.h>} | 241 {5:bool} func({5:void}); | 242 {7:// I am a }{8:spelin^g}{7: }{8:mistakke} | 243 {0:~ }|*4 244 | 245 ]]) 246 feed(']s') 247 screen:expect([[ 248 {3:#include }{4:<stdbool.h>} | 249 {5:bool} func({5:void}); | 250 {7:// I am a }{8:speling}{7: }{8:^mistakke} | 251 {0:~ }|*4 252 | 253 ]]) 254 feed(']s') 255 screen:expect([[ 256 {3:#include }{4:<stdbool.h>} | 257 {5:bool} func({5:void}); | 258 {7:// I am a }{8:^speling}{7: }{8:mistakke} | 259 {0:~ }|*4 260 {6:search hit BOTTOM, continuing at TOP} | 261 ]]) 262 exec('echo ""') 263 local ns = api.nvim_create_namespace('spell') 264 -- extmark with spell=true enables spell 265 local id = api.nvim_buf_set_extmark(0, ns, 1, 4, { end_row = 1, end_col = 10, spell = true }) 266 screen:expect([[ 267 {3:#include }{4:<stdbool.h>} | 268 {5:bool} {1:func}({5:void}); | 269 {7:// I am a }{8:^speling}{7: }{8:mistakke} | 270 {0:~ }|*4 271 | 272 ]]) 273 feed('[s') 274 screen:expect([[ 275 {3:#include }{4:<stdbool.h>} | 276 {5:bool} {1:^func}({5:void}); | 277 {7:// I am a }{8:speling}{7: }{8:mistakke} | 278 {0:~ }|*4 279 | 280 ]]) 281 api.nvim_buf_del_extmark(0, ns, id) 282 -- extmark with spell=false disables spell 283 id = api.nvim_buf_set_extmark(0, ns, 2, 18, { end_row = 2, end_col = 26, spell = false }) 284 screen:expect([[ 285 {3:#include }{4:<stdbool.h>} | 286 {5:bool} ^func({5:void}); | 287 {7:// I am a }{8:speling}{7: mistakke} | 288 {0:~ }|*4 289 | 290 ]]) 291 feed('[s') 292 screen:expect([[ 293 {3:#include }{4:<stdbool.h>} | 294 {5:bool} func({5:void}); | 295 {7:// I am a }{8:^speling}{7: mistakke} | 296 {0:~ }|*4 297 {6:search hit TOP, continuing at BOTTOM} | 298 ]]) 299 exec('echo ""') 300 api.nvim_buf_del_extmark(0, ns, id) 301 screen:expect([[ 302 {3:#include }{4:<stdbool.h>} | 303 {5:bool} func({5:void}); | 304 {7:// I am a }{8:^speling}{7: }{8:mistakke} | 305 {0:~ }|*4 306 | 307 ]]) 308 feed(']s') 309 screen:expect([[ 310 {3:#include }{4:<stdbool.h>} | 311 {5:bool} func({5:void}); | 312 {7:// I am a }{8:speling}{7: }{8:^mistakke} | 313 {0:~ }|*4 314 | 315 ]]) 316 -- "noplainbuffer" shouldn't change spellchecking behavior with syntax enabled 317 exec('set spelloptions+=noplainbuffer') 318 screen:expect_unchanged() 319 feed('[s') 320 screen:expect([[ 321 {3:#include }{4:<stdbool.h>} | 322 {5:bool} func({5:void}); | 323 {7:// I am a }{8:^speling}{7: }{8:mistakke} | 324 {0:~ }|*4 325 | 326 ]]) 327 -- no spellchecking with "noplainbuffer" and syntax disabled 328 exec('syntax off') 329 screen:expect([[ 330 #include <stdbool.h> | 331 bool func(void); | 332 // I am a ^speling mistakke | 333 {0:~ }|*4 334 | 335 ]]) 336 feed(']s') 337 screen:expect([[ 338 #include <stdbool.h> | 339 bool func(void); | 340 // I am a ^speling mistakke | 341 {0:~ }|*4 342 {6:search hit BOTTOM, continuing at TOP} | 343 ]]) 344 exec('echo ""') 345 -- everything is spellchecked without "noplainbuffer" with syntax disabled 346 exec('set spelloptions&') 347 screen:expect([[ 348 #include <{1:stdbool}.h> | 349 {1:bool} {1:func}(void); | 350 // I am a {1:^speling} {1:mistakke} | 351 {0:~ }|*4 352 | 353 ]]) 354 feed('[s') 355 screen:expect([[ 356 #include <{1:stdbool}.h> | 357 {1:bool} {1:^func}(void); | 358 // I am a {1:speling} {1:mistakke} | 359 {0:~ }|*4 360 | 361 ]]) 362 end) 363 364 it('and syntax does not clear extmark highlighting at the start of a word', function() 365 screen:try_resize(43, 3) 366 exec([[ 367 set spell 368 syntax match Constant "^.*$" 369 call setline(1, "This is some text without any spell errors.") 370 ]]) 371 local ns = api.nvim_create_namespace('spell') 372 api.nvim_buf_set_extmark(0, ns, 0, 0, { hl_group = 'WarningMsg', end_col = 43 }) 373 screen:expect([[ 374 {6:^This is some text without any spell errors.}| 375 {0:~ }| 376 | 377 ]]) 378 end) 379 380 it('overrides syntax when Visual selection is active', function() 381 screen:try_resize(43, 3) 382 screen:set_default_attr_ids({ 383 [0] = { bold = true, foreground = Screen.colors.Blue }, 384 [1] = { foreground = Screen.colors.Blue }, 385 [2] = { foreground = Screen.colors.Red }, 386 [3] = { foreground = Screen.colors.Blue, underline = true }, 387 [4] = { foreground = Screen.colors.Red, underline = true }, 388 [5] = { bold = true }, 389 }) 390 exec([[ 391 hi! Comment guibg=NONE guifg=Blue gui=NONE guisp=NONE 392 hi! SpellBad guibg=NONE guifg=Red gui=NONE guisp=NONE 393 hi! Visual guibg=NONE guifg=NONE gui=underline guisp=NONE 394 syn match Comment "//.*" 395 call setline(1, '// Here is a misspeld word.') 396 set spell 397 ]]) 398 screen:expect([[ 399 {1:^// Here is a }{2:misspeld}{1: word.} | 400 {0:~ }| 401 | 402 ]]) 403 feed('V') 404 screen:expect([[ 405 {1:^/}{3:/ Here is a }{4:misspeld}{3: word.} | 406 {0:~ }| 407 {5:-- VISUAL LINE --} | 408 ]]) 409 end) 410 411 it("global value works properly for 'spelloptions'", function() 412 screen:try_resize(43, 3) 413 exec('set spell') 414 -- :setglobal applies to future buffers but not current buffer 415 exec('setglobal spelloptions=camel') 416 insert('Here is TheCamelWord being spellchecked') 417 screen:expect([[ 418 Here is {1:TheCamelWord} being spellchecke^d | 419 {0:~ }| 420 | 421 ]]) 422 exec('enew') 423 insert('There is TheCamelWord being spellchecked') 424 screen:expect([[ 425 There is TheCamelWord being spellchecke^d | 426 {0:~ }| 427 | 428 ]]) 429 -- :setlocal applies to current buffer but not future buffers 430 exec('setlocal spelloptions=') 431 screen:expect([[ 432 There is {1:TheCamelWord} being spellchecke^d | 433 {0:~ }| 434 | 435 ]]) 436 exec('enew') 437 insert('What is TheCamelWord being spellchecked') 438 screen:expect([[ 439 What is TheCamelWord being spellchecke^d | 440 {0:~ }| 441 | 442 ]]) 443 -- :set applies to both current buffer and future buffers 444 exec('set spelloptions=') 445 screen:expect([[ 446 What is {1:TheCamelWord} being spellchecke^d | 447 {0:~ }| 448 | 449 ]]) 450 exec('enew') 451 insert('Where is TheCamelWord being spellchecked') 452 screen:expect([[ 453 Where is {1:TheCamelWord} being spellchecke^d | 454 {0:~ }| 455 | 456 ]]) 457 end) 458 end)