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 9" test length zero 10 11func Test_proptype_global() 12 call prop_type_add('comment', {'highlight': 'Directory', 'priority': 123, 'start_incl': 1, 'end_incl': 1}) 13 let proptypes = prop_type_list() 14 call assert_equal(1, len(proptypes)) 15 call assert_equal('comment', proptypes[0]) 16 17 let proptype = prop_type_get('comment') 18 call assert_equal('Directory', proptype['highlight']) 19 call assert_equal(123, proptype['priority']) 20 call assert_equal(1, proptype['start_incl']) 21 call assert_equal(1, proptype['end_incl']) 22 23 call prop_type_delete('comment') 24 call assert_equal(0, len(prop_type_list())) 25 26 call prop_type_add('one', {}) 27 call assert_equal(1, len(prop_type_list())) 28 let proptype = 'one'->prop_type_get() 29 call assert_false(has_key(proptype, 'highlight')) 30 call assert_equal(0, proptype['priority']) 31 call assert_equal(0, proptype['start_incl']) 32 call assert_equal(0, proptype['end_incl']) 33 34 call prop_type_add('two', {}) 35 call assert_equal(2, len(prop_type_list())) 36 call prop_type_delete('one') 37 call assert_equal(1, len(prop_type_list())) 38 call prop_type_delete('two') 39 call assert_equal(0, len(prop_type_list())) 40endfunc 41 42func Test_proptype_buf() 43 let bufnr = bufnr('') 44 call prop_type_add('comment', {'bufnr': bufnr, 'highlight': 'Directory', 'priority': 123, 'start_incl': 1, 'end_incl': 1}) 45 let proptypes = prop_type_list({'bufnr': bufnr}) 46 call assert_equal(1, len(proptypes)) 47 call assert_equal('comment', proptypes[0]) 48 49 let proptype = prop_type_get('comment', {'bufnr': bufnr}) 50 call assert_equal('Directory', proptype['highlight']) 51 call assert_equal(123, proptype['priority']) 52 call assert_equal(1, proptype['start_incl']) 53 call assert_equal(1, proptype['end_incl']) 54 55 call prop_type_delete('comment', {'bufnr': bufnr}) 56 call assert_equal(0, len({'bufnr': bufnr}->prop_type_list())) 57 58 call prop_type_add('one', {'bufnr': bufnr}) 59 let proptype = prop_type_get('one', {'bufnr': bufnr}) 60 call assert_false(has_key(proptype, 'highlight')) 61 call assert_equal(0, proptype['priority']) 62 call assert_equal(0, proptype['start_incl']) 63 call assert_equal(0, proptype['end_incl']) 64 65 call prop_type_add('two', {'bufnr': bufnr}) 66 call assert_equal(2, len(prop_type_list({'bufnr': bufnr}))) 67 call prop_type_delete('one', {'bufnr': bufnr}) 68 call assert_equal(1, len(prop_type_list({'bufnr': bufnr}))) 69 call prop_type_delete('two', {'bufnr': bufnr}) 70 call assert_equal(0, len(prop_type_list({'bufnr': bufnr}))) 71 72 call assert_fails("call prop_type_add('one', {'bufnr': 98764})", "E158:") 73endfunc 74 75func AddPropTypes() 76 call prop_type_add('one', {}) 77 call prop_type_add('two', {}) 78 call prop_type_add('three', {}) 79 call prop_type_add('whole', {}) 80endfunc 81 82func DeletePropTypes() 83 call prop_type_delete('one') 84 call prop_type_delete('two') 85 call prop_type_delete('three') 86 call prop_type_delete('whole') 87endfunc 88 89func SetupPropsInFirstLine() 90 call setline(1, 'one two three') 91 call prop_add(1, 1, {'length': 3, 'id': 11, 'type': 'one'}) 92 eval 1->prop_add(5, {'length': 3, 'id': 12, 'type': 'two'}) 93 call prop_add(1, 9, {'length': 5, 'id': 13, 'type': 'three'}) 94 call prop_add(1, 1, {'length': 13, 'id': 14, 'type': 'whole'}) 95endfunc 96 97func Get_expected_props() 98 return [ 99 \ {'col': 1, 'length': 13, 'id': 14, 'type': 'whole', 'start': 1, 'end': 1}, 100 \ {'col': 1, 'length': 3, 'id': 11, 'type': 'one', 'start': 1, 'end': 1}, 101 \ {'col': 5, 'length': 3, 'id': 12, 'type': 'two', 'start': 1, 'end': 1}, 102 \ {'col': 9, 'length': 5, 'id': 13, 'type': 'three', 'start': 1, 'end': 1}, 103 \ ] 104endfunc 105 106func Test_prop_add() 107 new 108 call AddPropTypes() 109 call SetupPropsInFirstLine() 110 let expected_props = Get_expected_props() 111 call assert_equal(expected_props, prop_list(1)) 112 call assert_fails("call prop_add(10, 1, {'length': 1, 'id': 14, 'type': 'whole'})", 'E966:') 113 call assert_fails("call prop_add(1, 22, {'length': 1, 'id': 14, 'type': 'whole'})", 'E964:') 114 115 " Insert a line above, text props must still be there. 116 call append(0, 'empty') 117 call assert_equal(expected_props, prop_list(2)) 118 " Delete a line above, text props must still be there. 119 1del 120 call assert_equal(expected_props, prop_list(1)) 121 122 " Prop without length or end column is zero length 123 call prop_clear(1) 124 call prop_add(1, 5, {'type': 'two'}) 125 let expected = [{'col': 5, 'length': 0, 'type': 'two', 'id': 0, 'start': 1, 'end': 1}] 126 call assert_equal(expected, prop_list(1)) 127 128 call assert_fails("call prop_add(1, 5, {'type': 'two', 'bufnr': 234343})", 'E158:') 129 130 call DeletePropTypes() 131 bwipe! 132endfunc 133 134func Test_prop_remove() 135 new 136 call AddPropTypes() 137 call SetupPropsInFirstLine() 138 let props = Get_expected_props() 139 call assert_equal(props, prop_list(1)) 140 141 " remove by id 142 call assert_equal(1, {'id': 12}->prop_remove(1)) 143 unlet props[2] 144 call assert_equal(props, prop_list(1)) 145 146 " remove by type 147 call assert_equal(1, prop_remove({'type': 'one'}, 1)) 148 unlet props[1] 149 call assert_equal(props, prop_list(1)) 150 151 " remove from unknown buffer 152 call assert_fails("call prop_remove({'type': 'one', 'bufnr': 123456}, 1)", 'E158:') 153 154 call DeletePropTypes() 155 bwipe! 156endfunc 157 158func SetupOneLine() 159 call setline(1, 'xonex xtwoxx') 160 normal gg0 161 call AddPropTypes() 162 call prop_add(1, 2, {'length': 3, 'id': 11, 'type': 'one'}) 163 call prop_add(1, 8, {'length': 3, 'id': 12, 'type': 'two'}) 164 let expected = [ 165 \ {'col': 2, 'length': 3, 'id': 11, 'type': 'one', 'start': 1, 'end': 1}, 166 \ {'col': 8, 'length': 3, 'id': 12, 'type': 'two', 'start': 1, 'end': 1}, 167 \] 168 call assert_equal(expected, prop_list(1)) 169 return expected 170endfunc 171 172func Test_prop_add_remove_buf() 173 new 174 let bufnr = bufnr('') 175 call AddPropTypes() 176 for lnum in range(1, 4) 177 call setline(lnum, 'one two three') 178 endfor 179 wincmd w 180 for lnum in range(1, 4) 181 call prop_add(lnum, 1, {'length': 3, 'id': 11, 'type': 'one', 'bufnr': bufnr}) 182 call prop_add(lnum, 5, {'length': 3, 'id': 12, 'type': 'two', 'bufnr': bufnr}) 183 call prop_add(lnum, 11, {'length': 3, 'id': 13, 'type': 'three', 'bufnr': bufnr}) 184 endfor 185 186 let props = [ 187 \ {'col': 1, 'length': 3, 'id': 11, 'type': 'one', 'start': 1, 'end': 1}, 188 \ {'col': 5, 'length': 3, 'id': 12, 'type': 'two', 'start': 1, 'end': 1}, 189 \ {'col': 11, 'length': 3, 'id': 13, 'type': 'three', 'start': 1, 'end': 1}, 190 \] 191 call assert_equal(props, prop_list(1, {'bufnr': bufnr})) 192 193 " remove by id 194 let before_props = deepcopy(props) 195 unlet props[1] 196 197 call prop_remove({'id': 12, 'bufnr': bufnr}, 1) 198 call assert_equal(props, prop_list(1, {'bufnr': bufnr})) 199 call assert_equal(before_props, prop_list(2, {'bufnr': bufnr})) 200 call assert_equal(before_props, prop_list(3, {'bufnr': bufnr})) 201 call assert_equal(before_props, prop_list(4, {'bufnr': bufnr})) 202 203 call prop_remove({'id': 12, 'bufnr': bufnr}, 3, 4) 204 call assert_equal(props, prop_list(1, {'bufnr': bufnr})) 205 call assert_equal(before_props, prop_list(2, {'bufnr': bufnr})) 206 call assert_equal(props, prop_list(3, {'bufnr': bufnr})) 207 call assert_equal(props, prop_list(4, {'bufnr': bufnr})) 208 209 call prop_remove({'id': 12, 'bufnr': bufnr}) 210 for lnum in range(1, 4) 211 call assert_equal(props, prop_list(lnum, {'bufnr': bufnr})) 212 endfor 213 214 " remove by type 215 let before_props = deepcopy(props) 216 unlet props[0] 217 218 call prop_remove({'type': 'one', 'bufnr': bufnr}, 1) 219 call assert_equal(props, prop_list(1, {'bufnr': bufnr})) 220 call assert_equal(before_props, prop_list(2, {'bufnr': bufnr})) 221 call assert_equal(before_props, prop_list(3, {'bufnr': bufnr})) 222 call assert_equal(before_props, prop_list(4, {'bufnr': bufnr})) 223 224 call prop_remove({'type': 'one', 'bufnr': bufnr}, 3, 4) 225 call assert_equal(props, prop_list(1, {'bufnr': bufnr})) 226 call assert_equal(before_props, prop_list(2, {'bufnr': bufnr})) 227 call assert_equal(props, prop_list(3, {'bufnr': bufnr})) 228 call assert_equal(props, prop_list(4, {'bufnr': bufnr})) 229 230 call prop_remove({'type': 'one', 'bufnr': bufnr}) 231 for lnum in range(1, 4) 232 call assert_equal(props, prop_list(lnum, {'bufnr': bufnr})) 233 endfor 234 235 call DeletePropTypes() 236 wincmd w 237 bwipe! 238endfunc 239 240func Test_prop_backspace() 241 new 242 set bs=2 243 let expected = SetupOneLine() " 'xonex xtwoxx' 244 245 exe "normal 0li\<BS>\<Esc>fxli\<BS>\<Esc>" 246 call assert_equal('one xtwoxx', getline(1)) 247 let expected[0].col = 1 248 let expected[1].col = 6 249 call assert_equal(expected, prop_list(1)) 250 251 call DeletePropTypes() 252 bwipe! 253 set bs& 254endfunc 255 256func Test_prop_replace() 257 new 258 set bs=2 259 let expected = SetupOneLine() " 'xonex xtwoxx' 260 261 exe "normal 0Ryyy\<Esc>" 262 call assert_equal('yyyex xtwoxx', getline(1)) 263 call assert_equal(expected, prop_list(1)) 264 265 exe "normal ftRyy\<BS>" 266 call assert_equal('yyyex xywoxx', getline(1)) 267 call assert_equal(expected, prop_list(1)) 268 269 exe "normal 0fwRyy\<BS>" 270 call assert_equal('yyyex xyyoxx', getline(1)) 271 call assert_equal(expected, prop_list(1)) 272 273 exe "normal 0foRyy\<BS>\<BS>" 274 call assert_equal('yyyex xyyoxx', getline(1)) 275 call assert_equal(expected, prop_list(1)) 276 277 call DeletePropTypes() 278 bwipe! 279 set bs& 280endfunc 281 282func Test_prop_open_line() 283 new 284 285 " open new line, props stay in top line 286 let expected = SetupOneLine() " 'xonex xtwoxx' 287 exe "normal o\<Esc>" 288 call assert_equal('xonex xtwoxx', getline(1)) 289 call assert_equal('', getline(2)) 290 call assert_equal(expected, prop_list(1)) 291 call DeletePropTypes() 292 293 " move all props to next line 294 let expected = SetupOneLine() " 'xonex xtwoxx' 295 exe "normal 0i\<CR>\<Esc>" 296 call assert_equal('', getline(1)) 297 call assert_equal('xonex xtwoxx', getline(2)) 298 call assert_equal(expected, prop_list(2)) 299 call DeletePropTypes() 300 301 " split just before prop, move all props to next line 302 let expected = SetupOneLine() " 'xonex xtwoxx' 303 exe "normal 0li\<CR>\<Esc>" 304 call assert_equal('x', getline(1)) 305 call assert_equal('onex xtwoxx', getline(2)) 306 let expected[0].col -= 1 307 let expected[1].col -= 1 308 call assert_equal(expected, prop_list(2)) 309 call DeletePropTypes() 310 311 " split inside prop, split first prop 312 let expected = SetupOneLine() " 'xonex xtwoxx' 313 exe "normal 0lli\<CR>\<Esc>" 314 call assert_equal('xo', getline(1)) 315 call assert_equal('nex xtwoxx', getline(2)) 316 let exp_first = [deepcopy(expected[0])] 317 let exp_first[0].length = 1 318 call assert_equal(exp_first, prop_list(1)) 319 let expected[0].col = 1 320 let expected[0].length = 2 321 let expected[1].col -= 2 322 call assert_equal(expected, prop_list(2)) 323 call DeletePropTypes() 324 325 " split just after first prop, second prop move to next line 326 let expected = SetupOneLine() " 'xonex xtwoxx' 327 exe "normal 0fea\<CR>\<Esc>" 328 call assert_equal('xone', getline(1)) 329 call assert_equal('x xtwoxx', getline(2)) 330 let exp_first = expected[0:0] 331 call assert_equal(exp_first, prop_list(1)) 332 let expected = expected[1:1] 333 let expected[0].col -= 4 334 call assert_equal(expected, prop_list(2)) 335 call DeletePropTypes() 336 337 bwipe! 338 set bs& 339endfunc 340 341func Test_prop_clear() 342 new 343 call AddPropTypes() 344 call SetupPropsInFirstLine() 345 call assert_equal(Get_expected_props(), prop_list(1)) 346 347 eval 1->prop_clear() 348 call assert_equal([], 1->prop_list()) 349 350 call DeletePropTypes() 351 bwipe! 352endfunc 353 354func Test_prop_clear_buf() 355 new 356 call AddPropTypes() 357 call SetupPropsInFirstLine() 358 let bufnr = bufnr('') 359 wincmd w 360 call assert_equal(Get_expected_props(), prop_list(1, {'bufnr': bufnr})) 361 362 call prop_clear(1, 1, {'bufnr': bufnr}) 363 call assert_equal([], prop_list(1, {'bufnr': bufnr})) 364 365 wincmd w 366 call DeletePropTypes() 367 bwipe! 368endfunc 369 370func Test_prop_setline() 371 new 372 call AddPropTypes() 373 call SetupPropsInFirstLine() 374 call assert_equal(Get_expected_props(), prop_list(1)) 375 376 call setline(1, 'foobar') 377 call assert_equal([], prop_list(1)) 378 379 call DeletePropTypes() 380 bwipe! 381endfunc 382 383func Test_prop_setbufline() 384 new 385 call AddPropTypes() 386 call SetupPropsInFirstLine() 387 let bufnr = bufnr('') 388 wincmd w 389 call assert_equal(Get_expected_props(), prop_list(1, {'bufnr': bufnr})) 390 391 call setbufline(bufnr, 1, 'foobar') 392 call assert_equal([], prop_list(1, {'bufnr': bufnr})) 393 394 wincmd w 395 call DeletePropTypes() 396 bwipe! 397endfunc 398 399func Test_prop_substitute() 400 new 401 " Set first line to 'one two three' 402 call AddPropTypes() 403 call SetupPropsInFirstLine() 404 let expected_props = Get_expected_props() 405 call assert_equal(expected_props, prop_list(1)) 406 407 " Change "n" in "one" to XX: 'oXXe two three' 408 s/n/XX/ 409 let expected_props[0].length += 1 410 let expected_props[1].length += 1 411 let expected_props[2].col += 1 412 let expected_props[3].col += 1 413 call assert_equal(expected_props, prop_list(1)) 414 415 " Delete "t" in "two" and "three" to XX: 'oXXe wo hree' 416 s/t//g 417 let expected_props[0].length -= 2 418 let expected_props[2].length -= 1 419 let expected_props[3].length -= 1 420 let expected_props[3].col -= 1 421 call assert_equal(expected_props, prop_list(1)) 422 423 " Split the line by changing w to line break: 'oXXe ', 'o hree' 424 " The long prop is split and spans both lines. 425 " The props on "two" and "three" move to the next line. 426 s/w/\r/ 427 let new_props = [ 428 \ copy(expected_props[0]), 429 \ copy(expected_props[2]), 430 \ copy(expected_props[3]), 431 \ ] 432 let expected_props[0].length = 5 433 unlet expected_props[3] 434 unlet expected_props[2] 435 call assert_equal(expected_props, prop_list(1)) 436 437 let new_props[0].length = 6 438 let new_props[1].col = 1 439 let new_props[1].length = 1 440 let new_props[2].col = 3 441 call assert_equal(new_props, prop_list(2)) 442 443 call DeletePropTypes() 444 bwipe! 445endfunc 446 447func Test_prop_change_indent() 448 call prop_type_add('comment', {'highlight': 'Directory'}) 449 new 450 call setline(1, [' xxx', 'yyyyy']) 451 call prop_add(2, 2, {'length': 2, 'type': 'comment'}) 452 let expect = {'col': 2, 'length': 2, 'type': 'comment', 'start': 1, 'end': 1, 'id': 0} 453 call assert_equal([expect], prop_list(2)) 454 455 set shiftwidth=3 456 normal 2G>> 457 call assert_equal(' yyyyy', getline(2)) 458 let expect.col += 3 459 call assert_equal([expect], prop_list(2)) 460 461 normal 2G== 462 call assert_equal(' yyyyy', getline(2)) 463 let expect.col = 6 464 call assert_equal([expect], prop_list(2)) 465 466 call prop_clear(2) 467 call prop_add(2, 2, {'length': 5, 'type': 'comment'}) 468 let expect.col = 2 469 let expect.length = 5 470 call assert_equal([expect], prop_list(2)) 471 472 normal 2G<< 473 call assert_equal(' yyyyy', getline(2)) 474 let expect.length = 2 475 call assert_equal([expect], prop_list(2)) 476 477 set shiftwidth& 478 call prop_type_delete('comment') 479endfunc 480 481" Setup a three line prop in lines 2 - 4. 482" Add short props in line 1 and 5. 483func Setup_three_line_prop() 484 new 485 call setline(1, ['one', 'twotwo', 'three', 'fourfour', 'five']) 486 call prop_add(1, 2, {'length': 1, 'type': 'comment'}) 487 call prop_add(2, 4, {'end_lnum': 4, 'end_col': 5, 'type': 'comment'}) 488 call prop_add(5, 2, {'length': 1, 'type': 'comment'}) 489endfunc 490 491func Test_prop_multiline() 492 eval 'comment'->prop_type_add({'highlight': 'Directory'}) 493 new 494 call setline(1, ['xxxxxxx', 'yyyyyyyyy', 'zzzzzzzz']) 495 496 " start halfway line 1, end halfway line 3 497 call prop_add(1, 3, {'end_lnum': 3, 'end_col': 5, 'type': 'comment'}) 498 let expect1 = {'col': 3, 'length': 6, 'type': 'comment', 'start': 1, 'end': 0, 'id': 0} 499 call assert_equal([expect1], prop_list(1)) 500 let expect2 = {'col': 1, 'length': 10, 'type': 'comment', 'start': 0, 'end': 0, 'id': 0} 501 call assert_equal([expect2], prop_list(2)) 502 let expect3 = {'col': 1, 'length': 4, 'type': 'comment', 'start': 0, 'end': 1, 'id': 0} 503 call assert_equal([expect3], prop_list(3)) 504 call prop_clear(1, 3) 505 506 " include all three lines 507 call prop_add(1, 1, {'end_lnum': 3, 'end_col': 999, 'type': 'comment'}) 508 let expect1.col = 1 509 let expect1.length = 8 510 call assert_equal([expect1], prop_list(1)) 511 call assert_equal([expect2], prop_list(2)) 512 let expect3.length = 9 513 call assert_equal([expect3], prop_list(3)) 514 call prop_clear(1, 3) 515 516 bwipe! 517 518 " Test deleting the first line of a multi-line prop. 519 call Setup_three_line_prop() 520 let expect_short = {'col': 2, 'length': 1, 'type': 'comment', 'start': 1, 'end': 1, 'id': 0} 521 call assert_equal([expect_short], prop_list(1)) 522 let expect2 = {'col': 4, 'length': 4, 'type': 'comment', 'start': 1, 'end': 0, 'id': 0} 523 call assert_equal([expect2], prop_list(2)) 524 2del 525 call assert_equal([expect_short], prop_list(1)) 526 let expect2 = {'col': 1, 'length': 6, 'type': 'comment', 'start': 1, 'end': 0, 'id': 0} 527 call assert_equal([expect2], prop_list(2)) 528 bwipe! 529 530 " Test deleting the last line of a multi-line prop. 531 call Setup_three_line_prop() 532 let expect3 = {'col': 1, 'length': 6, 'type': 'comment', 'start': 0, 'end': 0, 'id': 0} 533 call assert_equal([expect3], prop_list(3)) 534 let expect4 = {'col': 1, 'length': 4, 'type': 'comment', 'start': 0, 'end': 1, 'id': 0} 535 call assert_equal([expect4], prop_list(4)) 536 4del 537 let expect3.end = 1 538 call assert_equal([expect3], prop_list(3)) 539 call assert_equal([expect_short], prop_list(4)) 540 bwipe! 541 542 " Test appending a line below the multi-line text prop start. 543 call Setup_three_line_prop() 544 let expect2 = {'col': 4, 'length': 4, 'type': 'comment', 'start': 1, 'end': 0, 'id': 0} 545 call assert_equal([expect2], prop_list(2)) 546 call append(2, "new line") 547 call assert_equal([expect2], prop_list(2)) 548 let expect3 = {'col': 1, 'length': 9, 'type': 'comment', 'start': 0, 'end': 0, 'id': 0} 549 call assert_equal([expect3], prop_list(3)) 550 bwipe! 551 552 call prop_type_delete('comment') 553endfunc 554 555func Test_prop_byteoff() 556 call prop_type_add('comment', {'highlight': 'Directory'}) 557 new 558 call setline(1, ['line1', 'second line', '']) 559 set ff=unix 560 call assert_equal(19, line2byte(3)) 561 call prop_add(1, 1, {'end_col': 3, 'type': 'comment'}) 562 call assert_equal(19, line2byte(3)) 563 564 bwipe! 565 call prop_type_delete('comment') 566endfunc 567 568func Test_prop_undo() 569 new 570 call prop_type_add('comment', {'highlight': 'Directory'}) 571 call setline(1, ['oneone', 'twotwo', 'three']) 572 " Set 'undolevels' to break changes into undo-able pieces. 573 set ul& 574 575 call prop_add(1, 3, {'end_col': 5, 'type': 'comment'}) 576 let expected = [{'col': 3, 'length': 2, 'id': 0, 'type': 'comment', 'start': 1, 'end': 1} ] 577 call assert_equal(expected, prop_list(1)) 578 579 " Insert a character, then undo. 580 exe "normal 0lllix\<Esc>" 581 set ul& 582 let expected[0].length = 3 583 call assert_equal(expected, prop_list(1)) 584 undo 585 let expected[0].length = 2 586 call assert_equal(expected, prop_list(1)) 587 588 " Delete a character, then undo 589 exe "normal 0lllx" 590 set ul& 591 let expected[0].length = 1 592 call assert_equal(expected, prop_list(1)) 593 undo 594 let expected[0].length = 2 595 call assert_equal(expected, prop_list(1)) 596 597 " Delete the line, then undo 598 1d 599 set ul& 600 call assert_equal([], prop_list(1)) 601 undo 602 call assert_equal(expected, prop_list(1)) 603 604 " Insert a character, delete two characters, then undo with "U" 605 exe "normal 0lllix\<Esc>" 606 set ul& 607 let expected[0].length = 3 608 call assert_equal(expected, prop_list(1)) 609 exe "normal 0lllxx" 610 set ul& 611 let expected[0].length = 1 612 call assert_equal(expected, prop_list(1)) 613 normal U 614 let expected[0].length = 2 615 call assert_equal(expected, prop_list(1)) 616 617 " substitute a word, then undo 618 call setline(1, 'the number 123 is highlighted.') 619 call prop_add(1, 12, {'length': 3, 'type': 'comment'}) 620 let expected = [{'col': 12, 'length': 3, 'id': 0, 'type': 'comment', 'start': 1, 'end': 1} ] 621 call assert_equal(expected, prop_list(1)) 622 set ul& 623 1s/number/foo 624 let expected[0].col = 9 625 call assert_equal(expected, prop_list(1)) 626 undo 627 let expected[0].col = 12 628 call assert_equal(expected, prop_list(1)) 629 call prop_clear(1) 630 631 " substitute with backslash 632 call setline(1, 'the number 123 is highlighted.') 633 call prop_add(1, 12, {'length': 3, 'type': 'comment'}) 634 let expected = [{'col': 12, 'length': 3, 'id': 0, 'type': 'comment', 'start': 1, 'end': 1} ] 635 call assert_equal(expected, prop_list(1)) 636 1s/the/\The 637 call assert_equal(expected, prop_list(1)) 638 1s/^/\\ 639 let expected[0].col += 1 640 call assert_equal(expected, prop_list(1)) 641 1s/^/\~ 642 let expected[0].col += 1 643 call assert_equal(expected, prop_list(1)) 644 1s/123/12\\3 645 let expected[0].length += 1 646 call assert_equal(expected, prop_list(1)) 647 call prop_clear(1) 648 649 bwipe! 650 call prop_type_delete('comment') 651endfunc 652 653" screenshot test with textprop highlighting 654func Test_textprop_screenshot_various() 655 CheckScreendump 656 " The Vim running in the terminal needs to use utf-8. 657 if g:orig_encoding != 'utf-8' 658 throw 'Skipped: not using utf-8' 659 endif 660 call writefile([ 661 \ "call setline(1, [" 662 \ .. "'One two'," 663 \ .. "'Numbér 123 änd thœn 4¾7.'," 664 \ .. "'--aa--bb--cc--dd--'," 665 \ .. "'// comment with error in it'," 666 \ .. "'first line'," 667 \ .. "' second line '," 668 \ .. "'third line'," 669 \ .. "' fourth line'," 670 \ .. "])", 671 \ "hi NumberProp ctermfg=blue", 672 \ "hi LongProp ctermbg=yellow", 673 \ "hi BackgroundProp ctermbg=lightgrey", 674 \ "hi UnderlineProp cterm=underline", 675 \ "call prop_type_add('number', {'highlight': 'NumberProp'})", 676 \ "call prop_type_add('long', {'highlight': 'NumberProp'})", 677 \ "call prop_type_change('long', {'highlight': 'LongProp'})", 678 \ "call prop_type_add('start', {'highlight': 'NumberProp', 'start_incl': 1})", 679 \ "call prop_type_add('end', {'highlight': 'NumberProp', 'end_incl': 1})", 680 \ "call prop_type_add('both', {'highlight': 'NumberProp', 'start_incl': 1, 'end_incl': 1})", 681 \ "call prop_type_add('background', {'highlight': 'NumberProp', 'combine': 1})", 682 \ "eval 'background'->prop_type_change({'highlight': 'BackgroundProp'})", 683 \ "call prop_type_add('error', {'highlight': 'UnderlineProp', 'combine': 1})", 684 \ "call prop_add(1, 4, {'end_lnum': 3, 'end_col': 3, 'type': 'long'})", 685 \ "call prop_add(2, 9, {'length': 3, 'type': 'number'})", 686 \ "call prop_add(2, 24, {'length': 4, 'type': 'number'})", 687 \ "call prop_add(3, 3, {'length': 2, 'type': 'number'})", 688 \ "call prop_add(3, 7, {'length': 2, 'type': 'start'})", 689 \ "call prop_add(3, 11, {'length': 2, 'type': 'end'})", 690 \ "call prop_add(3, 15, {'length': 2, 'type': 'both'})", 691 \ "call prop_add(4, 12, {'length': 10, 'type': 'background'})", 692 \ "call prop_add(4, 17, {'length': 5, 'type': 'error'})", 693 \ "call prop_add(5, 7, {'length': 4, 'type': 'long'})", 694 \ "call prop_add(6, 1, {'length': 8, 'type': 'long'})", 695 \ "call prop_add(8, 1, {'length': 1, 'type': 'long'})", 696 \ "call prop_add(8, 11, {'length': 4, 'type': 'long'})", 697 \ "set number cursorline", 698 \ "hi clear SpellBad", 699 \ "set spell", 700 \ "syn match Comment '//.*'", 701 \ "hi Comment ctermfg=green", 702 \ "normal 3G0llix\<Esc>lllix\<Esc>lllix\<Esc>lllix\<Esc>lllix\<Esc>lllix\<Esc>lllix\<Esc>lllix\<Esc>", 703 \ "normal 3G0lli\<BS>\<Esc>", 704 \ "normal 6G0i\<BS>\<Esc>", 705 \ "normal 3J", 706 \ "normal 3G", 707 \], 'XtestProp') 708 let buf = RunVimInTerminal('-S XtestProp', {'rows': 8}) 709 call VerifyScreenDump(buf, 'Test_textprop_01', {}) 710 711 " clean up 712 call StopVimInTerminal(buf) 713 call delete('XtestProp') 714endfunc 715 716func RunTestVisualBlock(width, dump) 717 call writefile([ 718 \ "call setline(1, [" 719 \ .. "'xxxxxxxxx 123 x'," 720 \ .. "'xxxxxxxx 123 x'," 721 \ .. "'xxxxxxx 123 x'," 722 \ .. "'xxxxxx 123 x'," 723 \ .. "'xxxxx 123 x'," 724 \ .. "'xxxx 123 xx'," 725 \ .. "'xxx 123 xxx'," 726 \ .. "'xx 123 xxxx'," 727 \ .. "'x 123 xxxxx'," 728 \ .. "' 123 xxxxxx'," 729 \ .. "])", 730 \ "hi SearchProp ctermbg=yellow", 731 \ "call prop_type_add('search', {'highlight': 'SearchProp'})", 732 \ "call prop_add(1, 11, {'length': 3, 'type': 'search'})", 733 \ "call prop_add(2, 10, {'length': 3, 'type': 'search'})", 734 \ "call prop_add(3, 9, {'length': 3, 'type': 'search'})", 735 \ "call prop_add(4, 8, {'length': 3, 'type': 'search'})", 736 \ "call prop_add(5, 7, {'length': 3, 'type': 'search'})", 737 \ "call prop_add(6, 6, {'length': 3, 'type': 'search'})", 738 \ "call prop_add(7, 5, {'length': 3, 'type': 'search'})", 739 \ "call prop_add(8, 4, {'length': 3, 'type': 'search'})", 740 \ "call prop_add(9, 3, {'length': 3, 'type': 'search'})", 741 \ "call prop_add(10, 2, {'length': 3, 'type': 'search'})", 742 \ "normal 1G6|\<C-V>" .. repeat('l', a:width - 1) .. "10jx", 743 \], 'XtestPropVis') 744 let buf = RunVimInTerminal('-S XtestPropVis', {'rows': 12}) 745 call VerifyScreenDump(buf, 'Test_textprop_vis_' .. a:dump, {}) 746 747 " clean up 748 call StopVimInTerminal(buf) 749 call delete('XtestPropVis') 750endfunc 751 752" screenshot test with Visual block mode operations 753func Test_textprop_screenshot_visual() 754 CheckScreendump 755 756 " Delete two columns while text props are three chars wide. 757 call RunTestVisualBlock(2, '01') 758 759 " Same, but delete four columns 760 call RunTestVisualBlock(4, '02') 761endfunc 762 763func Test_textprop_after_tab() 764 CheckScreendump 765 766 let lines =<< trim END 767 call setline(1, [ 768 \ "\txxx", 769 \ "x\txxx", 770 \ ]) 771 hi SearchProp ctermbg=yellow 772 call prop_type_add('search', {'highlight': 'SearchProp'}) 773 call prop_add(1, 2, {'length': 3, 'type': 'search'}) 774 call prop_add(2, 3, {'length': 3, 'type': 'search'}) 775 END 776 call writefile(lines, 'XtestPropTab') 777 let buf = RunVimInTerminal('-S XtestPropTab', {'rows': 6}) 778 call VerifyScreenDump(buf, 'Test_textprop_tab', {}) 779 780 " clean up 781 call StopVimInTerminal(buf) 782 call delete('XtestPropTab') 783endfunc 784 785func Test_textprop_with_syntax() 786 CheckScreendump 787 788 let lines =<< trim END 789 call setline(1, [ 790 \ "(abc)", 791 \ ]) 792 syn match csParens "[()]" display 793 hi! link csParens MatchParen 794 795 call prop_type_add('TPTitle', #{ highlight: 'Title' }) 796 call prop_add(1, 2, #{type: 'TPTitle', end_col: 5}) 797 END 798 call writefile(lines, 'XtestPropSyn') 799 let buf = RunVimInTerminal('-S XtestPropSyn', {'rows': 6}) 800 call VerifyScreenDump(buf, 'Test_textprop_syn_1', {}) 801 802 " clean up 803 call StopVimInTerminal(buf) 804 call delete('XtestPropSyn') 805endfunc 806 807" Adding a text property to a new buffer should not fail 808func Test_textprop_empty_buffer() 809 call prop_type_add('comment', {'highlight': 'Search'}) 810 new 811 call prop_add(1, 1, {'type': 'comment'}) 812 close 813 call prop_type_delete('comment') 814endfunc 815 816" Adding a text property with invalid highlight should be ignored. 817func Test_textprop_invalid_highlight() 818 call assert_fails("call prop_type_add('dni', {'highlight': 'DoesNotExist'})", 'E970:') 819 new 820 call setline(1, ['asdf','asdf']) 821 call prop_add(1, 1, {'length': 4, 'type': 'dni'}) 822 redraw 823 bwipe! 824 call prop_type_delete('dni') 825endfunc 826 827" Adding a text property to an empty buffer and then editing another 828func Test_textprop_empty_buffer_next() 829 call prop_type_add("xxx", {}) 830 call prop_add(1, 1, {"type": "xxx"}) 831 next X 832 call prop_type_delete('xxx') 833endfunc 834 835func Test_textprop_remove_from_buf() 836 new 837 let buf = bufnr('') 838 call prop_type_add('one', {'bufnr': buf}) 839 call prop_add(1, 1, {'type': 'one', 'id': 234}) 840 file x 841 edit y 842 call prop_remove({'id': 234, 'bufnr': buf}, 1) 843 call prop_type_delete('one', {'bufnr': buf}) 844 bwipe! x 845 close 846endfunc 847 848func Test_textprop_in_unloaded_buf() 849 edit Xaaa 850 call setline(1, 'aaa') 851 write 852 edit Xbbb 853 call setline(1, 'bbb') 854 write 855 let bnr = bufnr('') 856 edit Xaaa 857 858 call prop_type_add('ErrorMsg', #{highlight:'ErrorMsg'}) 859 call assert_fails("call prop_add(1, 1, #{end_lnum: 1, endcol: 2, type: 'ErrorMsg', bufnr: bnr})", 'E275:') 860 exe 'buf ' .. bnr 861 call assert_equal('bbb', getline(1)) 862 call assert_equal(0, prop_list(1)->len()) 863 864 bwipe! Xaaa 865 bwipe! Xbbb 866 cal delete('Xaaa') 867 cal delete('Xbbb') 868endfunc 869