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