1" Tests for defining text property types and adding text properties to the 2" buffer. 3 4source check.vim 5CheckFeature textprop 6 7source screendump.vim 8 9func Test_proptype_global() 10 call prop_type_add('comment', {'highlight': 'Directory', 'priority': 123, 'start_incl': 1, 'end_incl': 1}) 11 let proptypes = prop_type_list() 12 call assert_equal(1, len(proptypes)) 13 call assert_equal('comment', proptypes[0]) 14 15 let proptype = prop_type_get('comment') 16 call assert_equal('Directory', proptype['highlight']) 17 call assert_equal(123, proptype['priority']) 18 call assert_equal(1, proptype['start_incl']) 19 call assert_equal(1, proptype['end_incl']) 20 21 call prop_type_delete('comment') 22 call assert_equal(0, len(prop_type_list())) 23 24 call prop_type_add('one', {}) 25 call assert_equal(1, len(prop_type_list())) 26 let proptype = 'one'->prop_type_get() 27 call assert_false(has_key(proptype, 'highlight')) 28 call assert_equal(0, proptype['priority']) 29 call assert_equal(0, proptype['start_incl']) 30 call assert_equal(0, proptype['end_incl']) 31 32 call prop_type_add('two', {}) 33 call assert_equal(2, len(prop_type_list())) 34 call prop_type_delete('one') 35 call assert_equal(1, len(prop_type_list())) 36 call prop_type_delete('two') 37 call assert_equal(0, len(prop_type_list())) 38endfunc 39 40func Test_proptype_buf() 41 let bufnr = bufnr('') 42 call prop_type_add('comment', {'bufnr': bufnr, 'highlight': 'Directory', 'priority': 123, 'start_incl': 1, 'end_incl': 1}) 43 let proptypes = prop_type_list({'bufnr': bufnr}) 44 call assert_equal(1, len(proptypes)) 45 call assert_equal('comment', proptypes[0]) 46 47 let proptype = prop_type_get('comment', {'bufnr': bufnr}) 48 call assert_equal('Directory', proptype['highlight']) 49 call assert_equal(123, proptype['priority']) 50 call assert_equal(1, proptype['start_incl']) 51 call assert_equal(1, proptype['end_incl']) 52 53 call prop_type_delete('comment', {'bufnr': bufnr}) 54 call assert_equal(0, len({'bufnr': bufnr}->prop_type_list())) 55 56 call prop_type_add('one', {'bufnr': bufnr}) 57 let proptype = prop_type_get('one', {'bufnr': bufnr}) 58 call assert_false(has_key(proptype, 'highlight')) 59 call assert_equal(0, proptype['priority']) 60 call assert_equal(0, proptype['start_incl']) 61 call assert_equal(0, proptype['end_incl']) 62 63 call prop_type_add('two', {'bufnr': bufnr}) 64 call assert_equal(2, len(prop_type_list({'bufnr': bufnr}))) 65 call prop_type_delete('one', {'bufnr': bufnr}) 66 call assert_equal(1, len(prop_type_list({'bufnr': bufnr}))) 67 call prop_type_delete('two', {'bufnr': bufnr}) 68 call assert_equal(0, len(prop_type_list({'bufnr': bufnr}))) 69 70 call assert_fails("call prop_type_add('one', {'bufnr': 98764})", "E158:") 71endfunc 72 73func AddPropTypes() 74 call prop_type_add('one', {}) 75 call prop_type_add('two', {}) 76 call prop_type_add('three', {}) 77 call prop_type_add('whole', {}) 78endfunc 79 80func DeletePropTypes() 81 call prop_type_delete('one') 82 call prop_type_delete('two') 83 call prop_type_delete('three') 84 call prop_type_delete('whole') 85endfunc 86 87func SetupPropsInFirstLine() 88 call setline(1, 'one two three') 89 call prop_add(1, 1, {'length': 3, 'id': 11, 'type': 'one'}) 90 eval 1->prop_add(5, {'length': 3, 'id': 12, 'type': 'two'}) 91 call prop_add(1, 9, {'length': 5, 'id': 13, 'type': 'three'}) 92 call prop_add(1, 1, {'length': 13, 'id': 14, 'type': 'whole'}) 93endfunc 94 95func Get_expected_props() 96 return [ 97 \ {'col': 1, 'length': 13, 'id': 14, 'type': 'whole', 'start': 1, 'end': 1}, 98 \ {'col': 1, 'length': 3, 'id': 11, 'type': 'one', 'start': 1, 'end': 1}, 99 \ {'col': 5, 'length': 3, 'id': 12, 'type': 'two', 'start': 1, 'end': 1}, 100 \ {'col': 9, 'length': 5, 'id': 13, 'type': 'three', 'start': 1, 'end': 1}, 101 \ ] 102endfunc 103 104func Test_prop_find() 105 new 106 call setline(1, ['one one one', 'twotwo', 'three', 'fourfour', 'five', 'sixsix']) 107 108 " Add two text props on lines 1 and 5, and one spanning lines 2 to 4. 109 call prop_type_add('prop_name', {'highlight': 'Directory'}) 110 call prop_add(1, 5, {'type': 'prop_name', 'id': 10, 'length': 3}) 111 call prop_add(2, 4, {'type': 'prop_name', 'id': 11, 'end_lnum': 4, 'end_col': 9}) 112 call prop_add(5, 4, {'type': 'prop_name', 'id': 12, 'length': 1}) 113 114 let expected = [ 115 \ {'lnum': 1, 'col': 5, 'length': 3, 'id': 10, 'type': 'prop_name', 'start': 1, 'end': 1}, 116 \ {'lnum': 2, 'col': 4, 'id': 11, 'type': 'prop_name', 'start': 1, 'end': 0}, 117 \ {'lnum': 5, 'col': 4, 'length': 1, 'id': 12, 'type': 'prop_name', 'start': 1, 'end': 1} 118 \ ] 119 120 " Starting at line 5 col 1 this should find the prop at line 5 col 4. 121 call cursor(5,1) 122 let result = prop_find({'type': 'prop_name'}, 'f') 123 call assert_equal(expected[2], result) 124 125 " With skipstart left at false (default), this should find the prop at line 126 " 5 col 4. 127 let result = prop_find({'type': 'prop_name', 'lnum': 5, 'col': 4}, 'b') 128 call assert_equal(expected[2], result) 129 130 " With skipstart set to true, this should skip the prop at line 5 col 4. 131 let result = prop_find({'type': 'prop_name', 'lnum': 5, 'col': 4, 'skipstart': 1}, 'b') 132 unlet result.length 133 call assert_equal(expected[1], result) 134 135 " Search backwards from line 1 col 10 to find the prop on the same line. 136 let result = prop_find({'type': 'prop_name', 'lnum': 1, 'col': 10}, 'b') 137 call assert_equal(expected[0], result) 138 139 " with skipstart set to false, if the start position is anywhere between the 140 " start and end lines of a text prop (searching forward or backward), the 141 " result should be the prop on the first line (the line with 'start' set to 1). 142 call cursor(3,1) 143 let result = prop_find({'type': 'prop_name'}, 'f') 144 unlet result.length 145 call assert_equal(expected[1], result) 146 let result = prop_find({'type': 'prop_name'}, 'b') 147 unlet result.length 148 call assert_equal(expected[1], result) 149 150 " with skipstart set to true, if the start position is anywhere between the 151 " start and end lines of a text prop (searching forward or backward), all lines 152 " of the prop will be skipped. 153 let result = prop_find({'type': 'prop_name', 'skipstart': 1}, 'b') 154 call assert_equal(expected[0], result) 155 let result = prop_find({'type': 'prop_name', 'skipstart': 1}, 'f') 156 call assert_equal(expected[2], result) 157 158 " Use skipstart to search through all props with type name 'prop_name'. 159 " First forward... 160 let lnum = 1 161 let col = 1 162 let i = 0 163 for exp in expected 164 let result = prop_find({'type': 'prop_name', 'lnum': lnum, 'col': col, 'skipstart': 1}, 'f') 165 if !has_key(exp, "length") 166 unlet result.length 167 endif 168 call assert_equal(exp, result) 169 let lnum = result.lnum 170 let col = result.col 171 let i = i + 1 172 endfor 173 174 " ...then backwards. 175 let lnum = 6 176 let col = 4 177 let i = 2 178 while i >= 0 179 let result = prop_find({'type': 'prop_name', 'lnum': lnum, 'col': col, 'skipstart': 1}, 'b') 180 if !has_key(expected[i], "length") 181 unlet result.length 182 endif 183 call assert_equal(expected[i], result) 184 let lnum = result.lnum 185 let col = result.col 186 let i = i - 1 187 endwhile 188 189 " Starting from line 6 col 1 search backwards for prop with id 10. 190 call cursor(6,1) 191 let result = prop_find({'id': 10, 'skipstart': 1}, 'b') 192 call assert_equal(expected[0], result) 193 194 " Starting from line 1 col 1 search forwards for prop with id 12. 195 call cursor(1,1) 196 let result = prop_find({'id': 12}, 'f') 197 call assert_equal(expected[2], result) 198 199 " Search for a prop with an unknown id. 200 let result = prop_find({'id': 999}, 'f') 201 call assert_equal({}, result) 202 203 " Search backwards from the proceeding position of the prop with id 11 204 " (at line num 2 col 4). This should return an empty dict. 205 let result = prop_find({'id': 11, 'lnum': 2, 'col': 3}, 'b') 206 call assert_equal({}, result) 207 208 " When lnum is given and col is omitted, use column 1. 209 let result = prop_find({'type': 'prop_name', 'lnum': 1}, 'f') 210 call assert_equal(expected[0], result) 211 212 call prop_clear(1,6) 213 call prop_type_delete('prop_name') 214 215 bwipe! 216endfunc 217 218def Test_prop_find2() 219 # Multiple props per line, start on the first, should find the second. 220 new 221 ['the quikc bronw fox jumsp over the layz dog']->repeat(2)->setline(1) 222 prop_type_add('misspell', #{highlight: 'ErrorMsg'}) 223 for lnum in [1, 2] 224 for col in [8, 14, 24, 38] 225 prop_add(lnum, col, #{type: 'misspell', length: 2}) 226 endfor 227 endfor 228 cursor(1, 8) 229 let expected = {'lnum': 1, 'id': 0, 'col': 14, 'end': 1, 'type': 'misspell', 'length': 2, 'start': 1} 230 let result = prop_find(#{type: 'misspell', skipstart: true}, 'f') 231 assert_equal(expected, result) 232 233 prop_type_delete('misspell') 234 bwipe! 235enddef 236 237func Test_prop_find_smaller_len_than_match_col() 238 new 239 call prop_type_add('test', {'highlight': 'ErrorMsg'}) 240 call setline(1, ['xxxx', 'x']) 241 call prop_add(1, 4, {'type': 'test'}) 242 call assert_equal({'id': 0, 'lnum': 1, 'col': 4, 'type': 'test', 'length': 0, 'start': 1, 'end': 1}, 243 \ prop_find({'type': 'test', 'lnum': 2, 'col': 1}, 'b')) 244 bwipe! 245 call prop_type_delete('test') 246endfunc 247 248func Test_prop_add() 249 new 250 call AddPropTypes() 251 call SetupPropsInFirstLine() 252 let expected_props = Get_expected_props() 253 call assert_equal(expected_props, prop_list(1)) 254 call assert_fails("call prop_add(10, 1, {'length': 1, 'id': 14, 'type': 'whole'})", 'E966:') 255 call assert_fails("call prop_add(1, 22, {'length': 1, 'id': 14, 'type': 'whole'})", 'E964:') 256 257 " Insert a line above, text props must still be there. 258 call append(0, 'empty') 259 call assert_equal(expected_props, prop_list(2)) 260 " Delete a line above, text props must still be there. 261 1del 262 call assert_equal(expected_props, prop_list(1)) 263 264 " Prop without length or end column is zero length 265 call prop_clear(1) 266 call prop_type_add('included', {'start_incl': 1, 'end_incl': 1}) 267 call prop_add(1, 5, #{type: 'included'}) 268 let expected = [#{col: 5, length: 0, type: 'included', id: 0, start: 1, end: 1}] 269 call assert_equal(expected, prop_list(1)) 270 271 " Inserting text makes the prop bigger. 272 exe "normal 5|ixx\<Esc>" 273 let expected = [#{col: 5, length: 2, type: 'included', id: 0, start: 1, end: 1}] 274 call assert_equal(expected, prop_list(1)) 275 276 call assert_fails("call prop_add(1, 5, {'type': 'two', 'bufnr': 234343})", 'E158:') 277 278 call DeletePropTypes() 279 call prop_type_delete('included') 280 bwipe! 281endfunc 282 283func Test_prop_remove() 284 new 285 call AddPropTypes() 286 call SetupPropsInFirstLine() 287 let props = Get_expected_props() 288 call assert_equal(props, prop_list(1)) 289 290 " remove by id 291 call assert_equal(1, {'id': 12}->prop_remove(1)) 292 unlet props[2] 293 call assert_equal(props, prop_list(1)) 294 295 " remove by type 296 call assert_equal(1, prop_remove({'type': 'one'}, 1)) 297 unlet props[1] 298 call assert_equal(props, prop_list(1)) 299 300 " remove from unknown buffer 301 call assert_fails("call prop_remove({'type': 'one', 'bufnr': 123456}, 1)", 'E158:') 302 303 call DeletePropTypes() 304 bwipe! 305 306 new 307 call AddPropTypes() 308 call SetupPropsInFirstLine() 309 call prop_add(1, 6, {'length': 2, 'id': 11, 'type': 'three'}) 310 let props = Get_expected_props() 311 call insert(props, {'col': 6, 'length': 2, 'id': 11, 'type': 'three', 'start': 1, 'end': 1}, 3) 312 call assert_equal(props, prop_list(1)) 313 call assert_equal(1, prop_remove({'type': 'three', 'id': 11, 'both': 1, 'all': 1}, 1)) 314 unlet props[3] 315 call assert_equal(props, prop_list(1)) 316 317 call assert_fails("call prop_remove({'id': 11, 'both': 1})", 'E860') 318 call assert_fails("call prop_remove({'type': 'three', 'both': 1})", 'E860') 319 320 call DeletePropTypes() 321 bwipe! 322endfunc 323 324func SetupOneLine() 325 call setline(1, 'xonex xtwoxx') 326 normal gg0 327 call AddPropTypes() 328 call prop_add(1, 2, {'length': 3, 'id': 11, 'type': 'one'}) 329 call prop_add(1, 8, {'length': 3, 'id': 12, 'type': 'two'}) 330 let expected = [ 331 \ {'col': 2, 'length': 3, 'id': 11, 'type': 'one', 'start': 1, 'end': 1}, 332 \ {'col': 8, 'length': 3, 'id': 12, 'type': 'two', 'start': 1, 'end': 1}, 333 \] 334 call assert_equal(expected, prop_list(1)) 335 return expected 336endfunc 337 338func Test_prop_add_remove_buf() 339 new 340 let bufnr = bufnr('') 341 call AddPropTypes() 342 for lnum in range(1, 4) 343 call setline(lnum, 'one two three') 344 endfor 345 wincmd w 346 for lnum in range(1, 4) 347 call prop_add(lnum, 1, {'length': 3, 'id': 11, 'type': 'one', 'bufnr': bufnr}) 348 call prop_add(lnum, 5, {'length': 3, 'id': 12, 'type': 'two', 'bufnr': bufnr}) 349 call prop_add(lnum, 11, {'length': 3, 'id': 13, 'type': 'three', 'bufnr': bufnr}) 350 endfor 351 352 let props = [ 353 \ {'col': 1, 'length': 3, 'id': 11, 'type': 'one', 'start': 1, 'end': 1}, 354 \ {'col': 5, 'length': 3, 'id': 12, 'type': 'two', 'start': 1, 'end': 1}, 355 \ {'col': 11, 'length': 3, 'id': 13, 'type': 'three', 'start': 1, 'end': 1}, 356 \] 357 call assert_equal(props, prop_list(1, {'bufnr': bufnr})) 358 359 " remove by id 360 let before_props = deepcopy(props) 361 unlet props[1] 362 363 call prop_remove({'id': 12, 'bufnr': bufnr}, 1) 364 call assert_equal(props, prop_list(1, {'bufnr': bufnr})) 365 call assert_equal(before_props, prop_list(2, {'bufnr': bufnr})) 366 call assert_equal(before_props, prop_list(3, {'bufnr': bufnr})) 367 call assert_equal(before_props, prop_list(4, {'bufnr': bufnr})) 368 369 call prop_remove({'id': 12, 'bufnr': bufnr}, 3, 4) 370 call assert_equal(props, prop_list(1, {'bufnr': bufnr})) 371 call assert_equal(before_props, prop_list(2, {'bufnr': bufnr})) 372 call assert_equal(props, prop_list(3, {'bufnr': bufnr})) 373 call assert_equal(props, prop_list(4, {'bufnr': bufnr})) 374 375 call prop_remove({'id': 12, 'bufnr': bufnr}) 376 for lnum in range(1, 4) 377 call assert_equal(props, prop_list(lnum, {'bufnr': bufnr})) 378 endfor 379 380 " remove by type 381 let before_props = deepcopy(props) 382 unlet props[0] 383 384 call prop_remove({'type': 'one', 'bufnr': bufnr}, 1) 385 call assert_equal(props, prop_list(1, {'bufnr': bufnr})) 386 call assert_equal(before_props, prop_list(2, {'bufnr': bufnr})) 387 call assert_equal(before_props, prop_list(3, {'bufnr': bufnr})) 388 call assert_equal(before_props, prop_list(4, {'bufnr': bufnr})) 389 390 call prop_remove({'type': 'one', 'bufnr': bufnr}, 3, 4) 391 call assert_equal(props, prop_list(1, {'bufnr': bufnr})) 392 call assert_equal(before_props, prop_list(2, {'bufnr': bufnr})) 393 call assert_equal(props, prop_list(3, {'bufnr': bufnr})) 394 call assert_equal(props, prop_list(4, {'bufnr': bufnr})) 395 396 call prop_remove({'type': 'one', 'bufnr': bufnr}) 397 for lnum in range(1, 4) 398 call assert_equal(props, prop_list(lnum, {'bufnr': bufnr})) 399 endfor 400 401 call DeletePropTypes() 402 wincmd w 403 bwipe! 404endfunc 405 406func Test_prop_backspace() 407 new 408 set bs=2 409 let expected = SetupOneLine() " 'xonex xtwoxx' 410 411 exe "normal 0li\<BS>\<Esc>fxli\<BS>\<Esc>" 412 call assert_equal('one xtwoxx', getline(1)) 413 let expected[0].col = 1 414 let expected[1].col = 6 415 call assert_equal(expected, prop_list(1)) 416 417 call DeletePropTypes() 418 bwipe! 419 set bs& 420endfunc 421 422func Test_prop_replace() 423 new 424 set bs=2 425 let expected = SetupOneLine() " 'xonex xtwoxx' 426 427 exe "normal 0Ryyy\<Esc>" 428 call assert_equal('yyyex xtwoxx', getline(1)) 429 call assert_equal(expected, prop_list(1)) 430 431 exe "normal ftRyy\<BS>" 432 call assert_equal('yyyex xywoxx', getline(1)) 433 call assert_equal(expected, prop_list(1)) 434 435 exe "normal 0fwRyy\<BS>" 436 call assert_equal('yyyex xyyoxx', getline(1)) 437 call assert_equal(expected, prop_list(1)) 438 439 exe "normal 0foRyy\<BS>\<BS>" 440 call assert_equal('yyyex xyyoxx', getline(1)) 441 call assert_equal(expected, prop_list(1)) 442 443 call DeletePropTypes() 444 bwipe! 445 set bs& 446endfunc 447 448func Test_prop_open_line() 449 new 450 451 " open new line, props stay in top line 452 let expected = SetupOneLine() " 'xonex xtwoxx' 453 exe "normal o\<Esc>" 454 call assert_equal('xonex xtwoxx', getline(1)) 455 call assert_equal('', getline(2)) 456 call assert_equal(expected, prop_list(1)) 457 call DeletePropTypes() 458 459 " move all props to next line 460 let expected = SetupOneLine() " 'xonex xtwoxx' 461 exe "normal 0i\<CR>\<Esc>" 462 call assert_equal('', getline(1)) 463 call assert_equal('xonex xtwoxx', getline(2)) 464 call assert_equal(expected, prop_list(2)) 465 call DeletePropTypes() 466 467 " split just before prop, move all props to next line 468 let expected = SetupOneLine() " 'xonex xtwoxx' 469 exe "normal 0li\<CR>\<Esc>" 470 call assert_equal('x', getline(1)) 471 call assert_equal('onex xtwoxx', getline(2)) 472 let expected[0].col -= 1 473 let expected[1].col -= 1 474 call assert_equal(expected, prop_list(2)) 475 call DeletePropTypes() 476 477 " split inside prop, split first prop 478 let expected = SetupOneLine() " 'xonex xtwoxx' 479 exe "normal 0lli\<CR>\<Esc>" 480 call assert_equal('xo', getline(1)) 481 call assert_equal('nex xtwoxx', getline(2)) 482 let exp_first = [deepcopy(expected[0])] 483 let exp_first[0].length = 1 484 let exp_first[0].end = 0 485 call assert_equal(exp_first, prop_list(1)) 486 let expected[0].col = 1 487 let expected[0].length = 2 488 let expected[0].start = 0 489 let expected[1].col -= 2 490 call assert_equal(expected, prop_list(2)) 491 call DeletePropTypes() 492 493 " split just after first prop, second prop move to next line 494 let expected = SetupOneLine() " 'xonex xtwoxx' 495 exe "normal 0fea\<CR>\<Esc>" 496 call assert_equal('xone', getline(1)) 497 call assert_equal('x xtwoxx', getline(2)) 498 let exp_first = expected[0:0] 499 call assert_equal(exp_first, prop_list(1)) 500 let expected = expected[1:1] 501 let expected[0].col -= 4 502 call assert_equal(expected, prop_list(2)) 503 call DeletePropTypes() 504 505 bwipe! 506 set bs& 507endfunc 508 509func Test_prop_clear() 510 new 511 call AddPropTypes() 512 call SetupPropsInFirstLine() 513 call assert_equal(Get_expected_props(), prop_list(1)) 514 515 eval 1->prop_clear() 516 call assert_equal([], 1->prop_list()) 517 518 call DeletePropTypes() 519 bwipe! 520endfunc 521 522func Test_prop_clear_buf() 523 new 524 call AddPropTypes() 525 call SetupPropsInFirstLine() 526 let bufnr = bufnr('') 527 wincmd w 528 call assert_equal(Get_expected_props(), prop_list(1, {'bufnr': bufnr})) 529 530 call prop_clear(1, 1, {'bufnr': bufnr}) 531 call assert_equal([], prop_list(1, {'bufnr': bufnr})) 532 533 wincmd w 534 call DeletePropTypes() 535 bwipe! 536endfunc 537 538func Test_prop_setline() 539 new 540 call AddPropTypes() 541 call SetupPropsInFirstLine() 542 call assert_equal(Get_expected_props(), prop_list(1)) 543 544 call setline(1, 'foobar') 545 call assert_equal([], prop_list(1)) 546 547 call DeletePropTypes() 548 bwipe! 549endfunc 550 551func Test_prop_setbufline() 552 new 553 call AddPropTypes() 554 call SetupPropsInFirstLine() 555 let bufnr = bufnr('') 556 wincmd w 557 call assert_equal(Get_expected_props(), prop_list(1, {'bufnr': bufnr})) 558 559 call setbufline(bufnr, 1, 'foobar') 560 call assert_equal([], prop_list(1, {'bufnr': bufnr})) 561 562 wincmd w 563 call DeletePropTypes() 564 bwipe! 565endfunc 566 567func Test_prop_substitute() 568 new 569 " Set first line to 'one two three' 570 call AddPropTypes() 571 call SetupPropsInFirstLine() 572 let expected_props = Get_expected_props() 573 call assert_equal(expected_props, prop_list(1)) 574 575 " Change "n" in "one" to XX: 'oXXe two three' 576 s/n/XX/ 577 let expected_props[0].length += 1 578 let expected_props[1].length += 1 579 let expected_props[2].col += 1 580 let expected_props[3].col += 1 581 call assert_equal(expected_props, prop_list(1)) 582 583 " Delete "t" in "two" and "three" to XX: 'oXXe wo hree' 584 s/t//g 585 let expected_props[0].length -= 2 586 let expected_props[2].length -= 1 587 let expected_props[3].length -= 1 588 let expected_props[3].col -= 1 589 call assert_equal(expected_props, prop_list(1)) 590 591 " Split the line by changing w to line break: 'oXXe ', 'o hree' 592 " The long prop is split and spans both lines. 593 " The props on "two" and "three" move to the next line. 594 s/w/\r/ 595 let new_props = [ 596 \ copy(expected_props[0]), 597 \ copy(expected_props[2]), 598 \ copy(expected_props[3]), 599 \ ] 600 let expected_props[0].length = 5 601 let expected_props[0].end = 0 602 unlet expected_props[3] 603 unlet expected_props[2] 604 call assert_equal(expected_props, prop_list(1)) 605 606 let new_props[0].length = 6 607 let new_props[0].start = 0 608 let new_props[1].col = 1 609 let new_props[1].length = 1 610 let new_props[2].col = 3 611 call assert_equal(new_props, prop_list(2)) 612 613 call DeletePropTypes() 614 bwipe! 615endfunc 616 617func Test_prop_change_indent() 618 call prop_type_add('comment', {'highlight': 'Directory'}) 619 new 620 call setline(1, [' xxx', 'yyyyy']) 621 call prop_add(2, 2, {'length': 2, 'type': 'comment'}) 622 let expect = {'col': 2, 'length': 2, 'type': 'comment', 'start': 1, 'end': 1, 'id': 0} 623 call assert_equal([expect], prop_list(2)) 624 625 set shiftwidth=3 626 normal 2G>> 627 call assert_equal(' yyyyy', getline(2)) 628 let expect.col += 3 629 call assert_equal([expect], prop_list(2)) 630 631 normal 2G== 632 call assert_equal(' yyyyy', getline(2)) 633 let expect.col = 6 634 call assert_equal([expect], prop_list(2)) 635 636 call prop_clear(2) 637 call prop_add(2, 2, {'length': 5, 'type': 'comment'}) 638 let expect.col = 2 639 let expect.length = 5 640 call assert_equal([expect], prop_list(2)) 641 642 normal 2G<< 643 call assert_equal(' yyyyy', getline(2)) 644 let expect.length = 2 645 call assert_equal([expect], prop_list(2)) 646 647 set shiftwidth& 648 call prop_type_delete('comment') 649endfunc 650 651" Setup a three line prop in lines 2 - 4. 652" Add short props in line 1 and 5. 653func Setup_three_line_prop() 654 new 655 call setline(1, ['one', 'twotwo', 'three', 'fourfour', 'five']) 656 call prop_add(1, 2, {'length': 1, 'type': 'comment'}) 657 call prop_add(2, 4, {'end_lnum': 4, 'end_col': 5, 'type': 'comment'}) 658 call prop_add(5, 2, {'length': 1, 'type': 'comment'}) 659endfunc 660 661func Test_prop_multiline() 662 eval 'comment'->prop_type_add({'highlight': 'Directory'}) 663 new 664 call setline(1, ['xxxxxxx', 'yyyyyyyyy', 'zzzzzzzz']) 665 666 " start halfway line 1, end halfway line 3 667 call prop_add(1, 3, {'end_lnum': 3, 'end_col': 5, 'type': 'comment'}) 668 let expect1 = {'col': 3, 'length': 6, 'type': 'comment', 'start': 1, 'end': 0, 'id': 0} 669 call assert_equal([expect1], prop_list(1)) 670 let expect2 = {'col': 1, 'length': 10, 'type': 'comment', 'start': 0, 'end': 0, 'id': 0} 671 call assert_equal([expect2], prop_list(2)) 672 let expect3 = {'col': 1, 'length': 4, 'type': 'comment', 'start': 0, 'end': 1, 'id': 0} 673 call assert_equal([expect3], prop_list(3)) 674 call prop_clear(1, 3) 675 676 " include all three lines 677 call prop_add(1, 1, {'end_lnum': 3, 'end_col': 999, 'type': 'comment'}) 678 let expect1.col = 1 679 let expect1.length = 8 680 call assert_equal([expect1], prop_list(1)) 681 call assert_equal([expect2], prop_list(2)) 682 let expect3.length = 9 683 call assert_equal([expect3], prop_list(3)) 684 call prop_clear(1, 3) 685 686 bwipe! 687 688 " Test deleting the first line of a multi-line prop. 689 call Setup_three_line_prop() 690 let expect_short = {'col': 2, 'length': 1, 'type': 'comment', 'start': 1, 'end': 1, 'id': 0} 691 call assert_equal([expect_short], prop_list(1)) 692 let expect2 = {'col': 4, 'length': 4, 'type': 'comment', 'start': 1, 'end': 0, 'id': 0} 693 call assert_equal([expect2], prop_list(2)) 694 2del 695 call assert_equal([expect_short], prop_list(1)) 696 let expect2 = {'col': 1, 'length': 6, 'type': 'comment', 'start': 1, 'end': 0, 'id': 0} 697 call assert_equal([expect2], prop_list(2)) 698 bwipe! 699 700 " Test deleting the last line of a multi-line prop. 701 call Setup_three_line_prop() 702 let expect3 = {'col': 1, 'length': 6, 'type': 'comment', 'start': 0, 'end': 0, 'id': 0} 703 call assert_equal([expect3], prop_list(3)) 704 let expect4 = {'col': 1, 'length': 4, 'type': 'comment', 'start': 0, 'end': 1, 'id': 0} 705 call assert_equal([expect4], prop_list(4)) 706 4del 707 let expect3.end = 1 708 call assert_equal([expect3], prop_list(3)) 709 call assert_equal([expect_short], prop_list(4)) 710 bwipe! 711 712 " Test appending a line below the multi-line text prop start. 713 call Setup_three_line_prop() 714 let expect2 = {'col': 4, 'length': 4, 'type': 'comment', 'start': 1, 'end': 0, 'id': 0} 715 call assert_equal([expect2], prop_list(2)) 716 call append(2, "new line") 717 call assert_equal([expect2], prop_list(2)) 718 let expect3 = {'col': 1, 'length': 9, 'type': 'comment', 'start': 0, 'end': 0, 'id': 0} 719 call assert_equal([expect3], prop_list(3)) 720 bwipe! 721 722 call prop_type_delete('comment') 723endfunc 724 725func Test_prop_line2byte() 726 call prop_type_add('comment', {'highlight': 'Directory'}) 727 new 728 call setline(1, ['line1', 'second line', '']) 729 set ff=unix 730 call assert_equal(19, line2byte(3)) 731 call prop_add(1, 1, {'end_col': 3, 'type': 'comment'}) 732 call assert_equal(19, line2byte(3)) 733 734 bwipe! 735 call prop_type_delete('comment') 736endfunc 737 738func Test_prop_byte2line() 739 new 740 set ff=unix 741 call setline(1, ['one one', 'two two', 'three three', 'four four', 'five']) 742 call assert_equal(4, byte2line(line2byte(4))) 743 call assert_equal(5, byte2line(line2byte(5))) 744 745 call prop_type_add('prop', {'highlight': 'Directory'}) 746 call prop_add(3, 1, {'length': 5, 'type': 'prop'}) 747 call assert_equal(4, byte2line(line2byte(4))) 748 call assert_equal(5, byte2line(line2byte(5))) 749 750 bwipe! 751 call prop_type_delete('prop') 752endfunc 753 754func Test_prop_undo() 755 new 756 call prop_type_add('comment', {'highlight': 'Directory'}) 757 call setline(1, ['oneone', 'twotwo', 'three']) 758 " Set 'undolevels' to break changes into undo-able pieces. 759 set ul& 760 761 call prop_add(1, 3, {'end_col': 5, 'type': 'comment'}) 762 let expected = [{'col': 3, 'length': 2, 'id': 0, 'type': 'comment', 'start': 1, 'end': 1} ] 763 call assert_equal(expected, prop_list(1)) 764 765 " Insert a character, then undo. 766 exe "normal 0lllix\<Esc>" 767 set ul& 768 let expected[0].length = 3 769 call assert_equal(expected, prop_list(1)) 770 undo 771 let expected[0].length = 2 772 call assert_equal(expected, prop_list(1)) 773 774 " Delete a character, then undo 775 exe "normal 0lllx" 776 set ul& 777 let expected[0].length = 1 778 call assert_equal(expected, prop_list(1)) 779 undo 780 let expected[0].length = 2 781 call assert_equal(expected, prop_list(1)) 782 783 " Delete the line, then undo 784 1d 785 set ul& 786 call assert_equal([], prop_list(1)) 787 undo 788 call assert_equal(expected, prop_list(1)) 789 790 " Insert a character, delete two characters, then undo with "U" 791 exe "normal 0lllix\<Esc>" 792 set ul& 793 let expected[0].length = 3 794 call assert_equal(expected, prop_list(1)) 795 exe "normal 0lllxx" 796 set ul& 797 let expected[0].length = 1 798 call assert_equal(expected, prop_list(1)) 799 normal U 800 let expected[0].length = 2 801 call assert_equal(expected, prop_list(1)) 802 803 " substitute a word, then undo 804 call setline(1, 'the number 123 is highlighted.') 805 call prop_add(1, 12, {'length': 3, 'type': 'comment'}) 806 let expected = [{'col': 12, 'length': 3, 'id': 0, 'type': 'comment', 'start': 1, 'end': 1} ] 807 call assert_equal(expected, prop_list(1)) 808 set ul& 809 1s/number/foo 810 let expected[0].col = 9 811 call assert_equal(expected, prop_list(1)) 812 undo 813 let expected[0].col = 12 814 call assert_equal(expected, prop_list(1)) 815 call prop_clear(1) 816 817 " substitute with backslash 818 call setline(1, 'the number 123 is highlighted.') 819 call prop_add(1, 12, {'length': 3, 'type': 'comment'}) 820 let expected = [{'col': 12, 'length': 3, 'id': 0, 'type': 'comment', 'start': 1, 'end': 1} ] 821 call assert_equal(expected, prop_list(1)) 822 1s/the/\The 823 call assert_equal(expected, prop_list(1)) 824 1s/^/\\ 825 let expected[0].col += 1 826 call assert_equal(expected, prop_list(1)) 827 1s/^/\~ 828 let expected[0].col += 1 829 call assert_equal(expected, prop_list(1)) 830 1s/123/12\\3 831 let expected[0].length += 1 832 call assert_equal(expected, prop_list(1)) 833 call prop_clear(1) 834 835 bwipe! 836 call prop_type_delete('comment') 837endfunc 838 839func Test_prop_delete_text() 840 new 841 call prop_type_add('comment', {'highlight': 'Directory'}) 842 call setline(1, ['oneone', 'twotwo', 'three']) 843 844 " zero length property 845 call prop_add(1, 3, {'type': 'comment'}) 846 let expected = [{'col': 3, 'length': 0, 'id': 0, 'type': 'comment', 'start': 1, 'end': 1} ] 847 call assert_equal(expected, prop_list(1)) 848 849 " delete one char moves the property 850 normal! x 851 let expected = [{'col': 2, 'length': 0, 'id': 0, 'type': 'comment', 'start': 1, 'end': 1} ] 852 call assert_equal(expected, prop_list(1)) 853 854 " delete char of the property has no effect 855 normal! lx 856 let expected = [{'col': 2, 'length': 0, 'id': 0, 'type': 'comment', 'start': 1, 'end': 1} ] 857 call assert_equal(expected, prop_list(1)) 858 859 " delete more chars moves property to first column, is not deleted 860 normal! 0xxxx 861 let expected = [{'col': 1, 'length': 0, 'id': 0, 'type': 'comment', 'start': 1, 'end': 1} ] 862 call assert_equal(expected, prop_list(1)) 863 864 bwipe! 865 call prop_type_delete('comment') 866endfunc 867 868" screenshot test with textprop highlighting 869func Test_textprop_screenshot_various() 870 CheckScreendump 871 " The Vim running in the terminal needs to use utf-8. 872 if g:orig_encoding != 'utf-8' 873 throw 'Skipped: not using utf-8' 874 endif 875 call writefile([ 876 \ "call setline(1, [" 877 \ .. "'One two'," 878 \ .. "'Numbér 123 änd thœn 4¾7.'," 879 \ .. "'--aa--bb--cc--dd--'," 880 \ .. "'// comment with error in it'," 881 \ .. "'first line'," 882 \ .. "' second line '," 883 \ .. "'third line'," 884 \ .. "' fourth line'," 885 \ .. "])", 886 \ "hi NumberProp ctermfg=blue", 887 \ "hi LongProp ctermbg=yellow", 888 \ "hi BackgroundProp ctermbg=lightgrey", 889 \ "hi UnderlineProp cterm=underline", 890 \ "call prop_type_add('number', {'highlight': 'NumberProp'})", 891 \ "call prop_type_add('long', {'highlight': 'NumberProp'})", 892 \ "call prop_type_change('long', {'highlight': 'LongProp'})", 893 \ "call prop_type_add('start', {'highlight': 'NumberProp', 'start_incl': 1})", 894 \ "call prop_type_add('end', {'highlight': 'NumberProp', 'end_incl': 1})", 895 \ "call prop_type_add('both', {'highlight': 'NumberProp', 'start_incl': 1, 'end_incl': 1})", 896 \ "call prop_type_add('background', {'highlight': 'BackgroundProp', 'combine': 0})", 897 \ "call prop_type_add('backgroundcomb', {'highlight': 'NumberProp', 'combine': 1})", 898 \ "eval 'backgroundcomb'->prop_type_change({'highlight': 'BackgroundProp'})", 899 \ "call prop_type_add('error', {'highlight': 'UnderlineProp'})", 900 \ "call prop_add(1, 4, {'end_lnum': 3, 'end_col': 3, 'type': 'long'})", 901 \ "call prop_add(2, 9, {'length': 3, 'type': 'number'})", 902 \ "call prop_add(2, 24, {'length': 4, 'type': 'number'})", 903 \ "call prop_add(3, 3, {'length': 2, 'type': 'number'})", 904 \ "call prop_add(3, 7, {'length': 2, 'type': 'start'})", 905 \ "call prop_add(3, 11, {'length': 2, 'type': 'end'})", 906 \ "call prop_add(3, 15, {'length': 2, 'type': 'both'})", 907 \ "call prop_add(4, 6, {'length': 3, 'type': 'background'})", 908 \ "call prop_add(4, 12, {'length': 10, 'type': 'backgroundcomb'})", 909 \ "call prop_add(4, 17, {'length': 5, 'type': 'error'})", 910 \ "call prop_add(5, 7, {'length': 4, 'type': 'long'})", 911 \ "call prop_add(6, 1, {'length': 8, 'type': 'long'})", 912 \ "call prop_add(8, 1, {'length': 1, 'type': 'long'})", 913 \ "call prop_add(8, 11, {'length': 4, 'type': 'long'})", 914 \ "set number cursorline", 915 \ "hi clear SpellBad", 916 \ "set spell", 917 \ "syn match Comment '//.*'", 918 \ "hi Comment ctermfg=green", 919 \ "normal 3G0llix\<Esc>lllix\<Esc>lllix\<Esc>lllix\<Esc>lllix\<Esc>lllix\<Esc>lllix\<Esc>lllix\<Esc>", 920 \ "normal 3G0lli\<BS>\<Esc>", 921 \ "normal 6G0i\<BS>\<Esc>", 922 \ "normal 3J", 923 \ "normal 3G", 924 \], 'XtestProp') 925 let buf = RunVimInTerminal('-S XtestProp', {'rows': 8}) 926 call VerifyScreenDump(buf, 'Test_textprop_01', {}) 927 928 " clean up 929 call StopVimInTerminal(buf) 930 call delete('XtestProp') 931endfunc 932 933func RunTestVisualBlock(width, dump) 934 call writefile([ 935 \ "call setline(1, [" 936 \ .. "'xxxxxxxxx 123 x'," 937 \ .. "'xxxxxxxx 123 x'," 938 \ .. "'xxxxxxx 123 x'," 939 \ .. "'xxxxxx 123 x'," 940 \ .. "'xxxxx 123 x'," 941 \ .. "'xxxx 123 xx'," 942 \ .. "'xxx 123 xxx'," 943 \ .. "'xx 123 xxxx'," 944 \ .. "'x 123 xxxxx'," 945 \ .. "' 123 xxxxxx'," 946 \ .. "])", 947 \ "hi SearchProp ctermbg=yellow", 948 \ "call prop_type_add('search', {'highlight': 'SearchProp'})", 949 \ "call prop_add(1, 11, {'length': 3, 'type': 'search'})", 950 \ "call prop_add(2, 10, {'length': 3, 'type': 'search'})", 951 \ "call prop_add(3, 9, {'length': 3, 'type': 'search'})", 952 \ "call prop_add(4, 8, {'length': 3, 'type': 'search'})", 953 \ "call prop_add(5, 7, {'length': 3, 'type': 'search'})", 954 \ "call prop_add(6, 6, {'length': 3, 'type': 'search'})", 955 \ "call prop_add(7, 5, {'length': 3, 'type': 'search'})", 956 \ "call prop_add(8, 4, {'length': 3, 'type': 'search'})", 957 \ "call prop_add(9, 3, {'length': 3, 'type': 'search'})", 958 \ "call prop_add(10, 2, {'length': 3, 'type': 'search'})", 959 \ "normal 1G6|\<C-V>" .. repeat('l', a:width - 1) .. "10jx", 960 \], 'XtestPropVis') 961 let buf = RunVimInTerminal('-S XtestPropVis', {'rows': 12}) 962 call VerifyScreenDump(buf, 'Test_textprop_vis_' .. a:dump, {}) 963 964 " clean up 965 call StopVimInTerminal(buf) 966 call delete('XtestPropVis') 967endfunc 968 969" screenshot test with Visual block mode operations 970func Test_textprop_screenshot_visual() 971 CheckScreendump 972 973 " Delete two columns while text props are three chars wide. 974 call RunTestVisualBlock(2, '01') 975 976 " Same, but delete four columns 977 call RunTestVisualBlock(4, '02') 978endfunc 979 980func Test_textprop_after_tab() 981 CheckScreendump 982 983 let lines =<< trim END 984 call setline(1, [ 985 \ "\txxx", 986 \ "x\txxx", 987 \ ]) 988 hi SearchProp ctermbg=yellow 989 call prop_type_add('search', {'highlight': 'SearchProp'}) 990 call prop_add(1, 2, {'length': 3, 'type': 'search'}) 991 call prop_add(2, 3, {'length': 3, 'type': 'search'}) 992 END 993 call writefile(lines, 'XtestPropTab') 994 let buf = RunVimInTerminal('-S XtestPropTab', {'rows': 6}) 995 call VerifyScreenDump(buf, 'Test_textprop_tab', {}) 996 997 " clean up 998 call StopVimInTerminal(buf) 999 call delete('XtestPropTab') 1000endfunc 1001 1002func Test_textprop_with_syntax() 1003 CheckScreendump 1004 1005 let lines =<< trim END 1006 call setline(1, [ 1007 \ "(abc)", 1008 \ ]) 1009 syn match csParens "[()]" display 1010 hi! link csParens MatchParen 1011 1012 call prop_type_add('TPTitle', #{ highlight: 'Title' }) 1013 call prop_add(1, 2, #{type: 'TPTitle', end_col: 5}) 1014 END 1015 call writefile(lines, 'XtestPropSyn') 1016 let buf = RunVimInTerminal('-S XtestPropSyn', {'rows': 6}) 1017 call VerifyScreenDump(buf, 'Test_textprop_syn_1', {}) 1018 1019 " clean up 1020 call StopVimInTerminal(buf) 1021 call delete('XtestPropSyn') 1022endfunc 1023 1024" Adding a text property to a new buffer should not fail 1025func Test_textprop_empty_buffer() 1026 call prop_type_add('comment', {'highlight': 'Search'}) 1027 new 1028 call prop_add(1, 1, {'type': 'comment'}) 1029 close 1030 call prop_type_delete('comment') 1031endfunc 1032 1033" Adding a text property with invalid highlight should be ignored. 1034func Test_textprop_invalid_highlight() 1035 call assert_fails("call prop_type_add('dni', {'highlight': 'DoesNotExist'})", 'E970:') 1036 new 1037 call setline(1, ['asdf','asdf']) 1038 call prop_add(1, 1, {'length': 4, 'type': 'dni'}) 1039 redraw 1040 bwipe! 1041 call prop_type_delete('dni') 1042endfunc 1043 1044" Adding a text property to an empty buffer and then editing another 1045func Test_textprop_empty_buffer_next() 1046 call prop_type_add("xxx", {}) 1047 call prop_add(1, 1, {"type": "xxx"}) 1048 next X 1049 call prop_type_delete('xxx') 1050endfunc 1051 1052func Test_textprop_remove_from_buf() 1053 new 1054 let buf = bufnr('') 1055 call prop_type_add('one', {'bufnr': buf}) 1056 call prop_add(1, 1, {'type': 'one', 'id': 234}) 1057 file x 1058 edit y 1059 call prop_remove({'id': 234, 'bufnr': buf}, 1) 1060 call prop_type_delete('one', {'bufnr': buf}) 1061 bwipe! x 1062 close 1063endfunc 1064 1065func Test_textprop_in_unloaded_buf() 1066 edit Xaaa 1067 call setline(1, 'aaa') 1068 write 1069 edit Xbbb 1070 call setline(1, 'bbb') 1071 write 1072 let bnr = bufnr('') 1073 edit Xaaa 1074 1075 call prop_type_add('ErrorMsg', #{highlight:'ErrorMsg'}) 1076 call assert_fails("call prop_add(1, 1, #{end_lnum: 1, endcol: 2, type: 'ErrorMsg', bufnr: bnr})", 'E275:') 1077 exe 'buf ' .. bnr 1078 call assert_equal('bbb', getline(1)) 1079 call assert_equal(0, prop_list(1)->len()) 1080 1081 bwipe! Xaaa 1082 bwipe! Xbbb 1083 cal delete('Xaaa') 1084 cal delete('Xbbb') 1085endfunc 1086 1087func Test_proptype_substitute2() 1088 new 1089 " text_prop.vim 1090 call setline(1, [ 1091 \ 'The num 123 is smaller than 4567.', 1092 \ '123 The number 123 is smaller than 4567.', 1093 \ '123 The number 123 is smaller than 4567.']) 1094 1095 call prop_type_add('number', {'highlight': 'ErrorMsg'}) 1096 1097 call prop_add(1, 12, {'length': 3, 'type': 'number'}) 1098 call prop_add(2, 1, {'length': 3, 'type': 'number'}) 1099 call prop_add(3, 36, {'length': 4, 'type': 'number'}) 1100 set ul& 1101 let expected = [{'id': 0, 'col': 13, 'end': 1, 'type': 'number', 'length': 3, 'start': 1}, 1102 \ {'id': 0, 'col': 1, 'end': 1, 'type': 'number', 'length': 3, 'start': 1}, 1103 \ {'id': 0, 'col': 50, 'end': 1, 'type': 'number', 'length': 4, 'start': 1}] 1104 " Add some text in between 1105 %s/\s\+/ /g 1106 call assert_equal(expected, prop_list(1) + prop_list(2) + prop_list(3)) 1107 1108 " remove some text 1109 :1s/[a-z]\{3\}//g 1110 let expected = [{'id': 0, 'col': 10, 'end': 1, 'type': 'number', 'length': 3, 'start': 1}] 1111 call assert_equal(expected, prop_list(1)) 1112 bwipe! 1113endfunc 1114 1115func SaveOptions() 1116 let d = #{tabstop: &tabstop, 1117 \ softtabstop: &softtabstop, 1118 \ shiftwidth: &shiftwidth, 1119 \ expandtab: &expandtab, 1120 \ foldmethod: '"' .. &foldmethod .. '"', 1121 \ } 1122 return d 1123endfunc 1124 1125func RestoreOptions(dict) 1126 for name in keys(a:dict) 1127 exe 'let &' .. name .. ' = ' .. a:dict[name] 1128 endfor 1129endfunc 1130 1131func Test_textprop_noexpandtab() 1132 new 1133 let save_dict = SaveOptions() 1134 1135 set tabstop=8 1136 set softtabstop=4 1137 set shiftwidth=4 1138 set noexpandtab 1139 set foldmethod=marker 1140 1141 call feedkeys("\<esc>\<esc>0Ca\<cr>\<esc>\<up>", "tx") 1142 call prop_type_add('test', {'highlight': 'ErrorMsg'}) 1143 call prop_add(1, 1, {'end_col': 2, 'type': 'test'}) 1144 call feedkeys("0i\<tab>", "tx") 1145 call prop_remove({'type': 'test'}) 1146 call prop_add(1, 2, {'end_col': 3, 'type': 'test'}) 1147 call feedkeys("A\<left>\<tab>", "tx") 1148 call prop_remove({'type': 'test'}) 1149 try 1150 " It is correct that this does not pass 1151 call prop_add(1, 6, {'end_col': 7, 'type': 'test'}) 1152 " Has already collapsed here, start_col:6 does not result in an error 1153 call feedkeys("A\<left>\<tab>", "tx") 1154 catch /^Vim\%((\a\+)\)\=:E964/ 1155 endtry 1156 call prop_remove({'type': 'test'}) 1157 call prop_type_delete('test') 1158 1159 call RestoreOptions(save_dict) 1160 bwipe! 1161endfunc 1162 1163func Test_textprop_noexpandtab_redraw() 1164 new 1165 let save_dict = SaveOptions() 1166 1167 set tabstop=8 1168 set softtabstop=4 1169 set shiftwidth=4 1170 set noexpandtab 1171 set foldmethod=marker 1172 1173 call feedkeys("\<esc>\<esc>0Ca\<cr>\<space>\<esc>\<up>", "tx") 1174 call prop_type_add('test', {'highlight': 'ErrorMsg'}) 1175 call prop_add(1, 1, {'end_col': 2, 'type': 'test'}) 1176 call feedkeys("0i\<tab>", "tx") 1177 " Internally broken at the next line 1178 call feedkeys("A\<left>\<tab>", "tx") 1179 redraw 1180 " Index calculation failed internally on next line 1181 call prop_add(1, 1, {'end_col': 2, 'type': 'test'}) 1182 call prop_remove({'type': 'test', 'all': v:true}) 1183 call prop_type_delete('test') 1184 call prop_type_delete('test') 1185 1186 call RestoreOptions(save_dict) 1187 bwipe! 1188endfunc 1189 1190func Test_textprop_ins_str() 1191 new 1192 call setline(1, 'just some text') 1193 call prop_type_add('test', {'highlight': 'ErrorMsg'}) 1194 call prop_add(1, 1, {'end_col': 2, 'type': 'test'}) 1195 call assert_equal([{'id': 0, 'col': 1, 'end': 1, 'type': 'test', 'length': 1, 'start': 1}], prop_list(1)) 1196 1197 call feedkeys("foi\<F8>\<Esc>", "tx") 1198 call assert_equal('just s<F8>ome text', getline(1)) 1199 call assert_equal([{'id': 0, 'col': 1, 'end': 1, 'type': 'test', 'length': 1, 'start': 1}], prop_list(1)) 1200 1201 bwipe! 1202 call prop_remove({'type': 'test'}) 1203 call prop_type_delete('test') 1204endfunc 1205 1206func Test_find_prop_later_in_line() 1207 new 1208 call prop_type_add('test', {'highlight': 'ErrorMsg'}) 1209 call setline(1, 'just some text') 1210 call prop_add(1, 1, {'length': 4, 'type': 'test'}) 1211 call prop_add(1, 10, {'length': 3, 'type': 'test'}) 1212 1213 call assert_equal({'id': 0, 'lnum': 1, 'col': 10, 'end': 1, 'type': 'test', 'length': 3, 'start': 1}, 1214 \ prop_find(#{type: 'test', lnum: 1, col: 6})) 1215 1216 bwipe! 1217 call prop_type_delete('test') 1218endfunc 1219 1220func Test_find_zerowidth_prop_sol() 1221 new 1222 call prop_type_add('test', {'highlight': 'ErrorMsg'}) 1223 call setline(1, 'just some text') 1224 call prop_add(1, 1, {'length': 0, 'type': 'test'}) 1225 1226 call assert_equal({'id': 0, 'lnum': 1, 'col': 1, 'end': 1, 'type': 'test', 'length': 0, 'start': 1}, 1227 \ prop_find(#{type: 'test', lnum: 1})) 1228 1229 bwipe! 1230 call prop_type_delete('test') 1231endfunc 1232 1233" Test for passing invalid arguments to prop_xxx() functions 1234func Test_prop_func_invalid_args() 1235 call assert_fails('call prop_clear(1, 2, [])', 'E715:') 1236 call assert_fails('call prop_clear(-1, 2)', 'E16:') 1237 call assert_fails('call prop_find(test_null_dict())', 'E474:') 1238 call assert_fails('call prop_find({"bufnr" : []})', 'E730:') 1239 call assert_fails('call prop_find({})', 'E968:') 1240 call assert_fails('call prop_find({}, "x")', 'E474:') 1241 call assert_fails('call prop_find({"lnum" : -2})', 'E16:') 1242 call assert_fails('call prop_list(1, [])', 'E715:') 1243 call assert_fails('call prop_list(-1, {})', 'E16:') 1244 call assert_fails('call prop_remove([])', 'E474:') 1245 call assert_fails('call prop_remove({}, -2)', 'E16:') 1246 call assert_fails('call prop_remove({})', 'E968:') 1247 call assert_fails('call prop_type_add([], {})', 'E730:') 1248 call assert_fails("call prop_type_change('long', {'xyz' : 10})", 'E971:') 1249 call assert_fails("call prop_type_delete([])", 'E730:') 1250 call assert_fails("call prop_type_delete('xyz', [])", 'E715:') 1251 call assert_fails("call prop_type_get([])", 'E730:') 1252 call assert_fails("call prop_type_get('', [])", 'E474:') 1253 call assert_fails("call prop_type_list([])", 'E715:') 1254endfunc 1255 1256func Test_split_join() 1257 new 1258 call prop_type_add('test', {'highlight': 'ErrorMsg'}) 1259 call setline(1, 'just some text') 1260 call prop_add(1, 6, {'length': 4, 'type': 'test'}) 1261 1262 " Split in middle of "some" 1263 execute "normal! 8|i\<CR>" 1264 call assert_equal([{'id': 0, 'col': 6, 'end': 0, 'type': 'test', 'length': 2, 'start': 1}], 1265 \ prop_list(1)) 1266 call assert_equal([{'id': 0, 'col': 1, 'end': 1, 'type': 'test', 'length': 2, 'start': 0}], 1267 \ prop_list(2)) 1268 1269 " Join the two lines back together 1270 normal! 1GJ 1271 call assert_equal([{'id': 0, 'col': 6, 'end': 1, 'type': 'test', 'length': 5, 'start': 1}], prop_list(1)) 1272 1273 bwipe! 1274 call prop_type_delete('test') 1275endfunc 1276 1277" vim: shiftwidth=2 sts=2 expandtab 1278