1" Tests for defining text property types and adding text properties to the 2" buffer. 3 4if !has('textprop') 5 finish 6endif 7 8source screendump.vim 9 10" test length zero 11 12func Test_proptype_global() 13 call prop_type_add('comment', {'highlight': 'Directory', 'priority': 123, 'start_incl': 1, 'end_incl': 1}) 14 let proptypes = prop_type_list() 15 call assert_equal(1, len(proptypes)) 16 call assert_equal('comment', proptypes[0]) 17 18 let proptype = prop_type_get('comment') 19 call assert_equal('Directory', proptype['highlight']) 20 call assert_equal(123, proptype['priority']) 21 call assert_equal(1, proptype['start_incl']) 22 call assert_equal(1, proptype['end_incl']) 23 24 call prop_type_delete('comment') 25 call assert_equal(0, len(prop_type_list())) 26 27 call prop_type_add('one', {}) 28 call assert_equal(1, len(prop_type_list())) 29 let proptype = prop_type_get('one') 30 call assert_false(has_key(proptype, 'highlight')) 31 call assert_equal(0, proptype['priority']) 32 call assert_equal(0, proptype['start_incl']) 33 call assert_equal(0, proptype['end_incl']) 34 35 call prop_type_add('two', {}) 36 call assert_equal(2, len(prop_type_list())) 37 call prop_type_delete('one') 38 call assert_equal(1, len(prop_type_list())) 39 call prop_type_delete('two') 40 call assert_equal(0, len(prop_type_list())) 41endfunc 42 43func Test_proptype_buf() 44 let bufnr = bufnr('') 45 call prop_type_add('comment', {'bufnr': bufnr, 'highlight': 'Directory', 'priority': 123, 'start_incl': 1, 'end_incl': 1}) 46 let proptypes = prop_type_list({'bufnr': bufnr}) 47 call assert_equal(1, len(proptypes)) 48 call assert_equal('comment', proptypes[0]) 49 50 let proptype = prop_type_get('comment', {'bufnr': bufnr}) 51 call assert_equal('Directory', proptype['highlight']) 52 call assert_equal(123, proptype['priority']) 53 call assert_equal(1, proptype['start_incl']) 54 call assert_equal(1, proptype['end_incl']) 55 56 call prop_type_delete('comment', {'bufnr': bufnr}) 57 call assert_equal(0, len(prop_type_list({'bufnr': bufnr}))) 58 59 call prop_type_add('one', {'bufnr': bufnr}) 60 let proptype = prop_type_get('one', {'bufnr': bufnr}) 61 call assert_false(has_key(proptype, 'highlight')) 62 call assert_equal(0, proptype['priority']) 63 call assert_equal(0, proptype['start_incl']) 64 call assert_equal(0, proptype['end_incl']) 65 66 call prop_type_add('two', {'bufnr': bufnr}) 67 call assert_equal(2, len(prop_type_list({'bufnr': bufnr}))) 68 call prop_type_delete('one', {'bufnr': bufnr}) 69 call assert_equal(1, len(prop_type_list({'bufnr': bufnr}))) 70 call prop_type_delete('two', {'bufnr': bufnr}) 71 call assert_equal(0, len(prop_type_list({'bufnr': bufnr}))) 72endfunc 73 74func AddPropTypes() 75 call prop_type_add('one', {}) 76 call prop_type_add('two', {}) 77 call prop_type_add('three', {}) 78 call prop_type_add('whole', {}) 79endfunc 80 81func DeletePropTypes() 82 call prop_type_delete('one') 83 call prop_type_delete('two') 84 call prop_type_delete('three') 85 call prop_type_delete('whole') 86endfunc 87 88func SetupPropsInFirstLine() 89 call setline(1, 'one two three') 90 call prop_add(1, 1, {'length': 3, 'id': 11, 'type': 'one'}) 91 call prop_add(1, 5, {'length': 3, 'id': 12, 'type': 'two'}) 92 call prop_add(1, 9, {'length': 5, 'id': 13, 'type': 'three'}) 93 call prop_add(1, 1, {'length': 13, 'id': 14, 'type': 'whole'}) 94endfunc 95 96func Get_expected_props() 97 return [ 98 \ {'col': 1, 'length': 13, 'id': 14, 'type': 'whole', 'start': 1, 'end': 1}, 99 \ {'col': 1, 'length': 3, 'id': 11, 'type': 'one', 'start': 1, 'end': 1}, 100 \ {'col': 5, 'length': 3, 'id': 12, 'type': 'two', 'start': 1, 'end': 1}, 101 \ {'col': 9, 'length': 5, 'id': 13, 'type': 'three', 'start': 1, 'end': 1}, 102 \ ] 103endfunc 104 105func Test_prop_add() 106 new 107 call AddPropTypes() 108 call SetupPropsInFirstLine() 109 let expected_props = Get_expected_props() 110 call assert_equal(expected_props, prop_list(1)) 111 call assert_fails("call prop_add(10, 1, {'length': 1, 'id': 14, 'type': 'whole'})", 'E966:') 112 call assert_fails("call prop_add(1, 22, {'length': 1, 'id': 14, 'type': 'whole'})", 'E964:') 113 114 " Insert a line above, text props must still be there. 115 call append(0, 'empty') 116 call assert_equal(expected_props, prop_list(2)) 117 " Delete a line above, text props must still be there. 118 1del 119 call assert_equal(expected_props, prop_list(1)) 120 121 " Prop without length or end column is zero length 122 call prop_clear(1) 123 call prop_add(1, 5, {'type': 'two'}) 124 let expected = [{'col': 5, 'length': 0, 'type': 'two', 'id': 0, 'start': 1, 'end': 1}] 125 call assert_equal(expected, prop_list(1)) 126 127 call DeletePropTypes() 128 bwipe! 129endfunc 130 131func Test_prop_remove() 132 new 133 call AddPropTypes() 134 call SetupPropsInFirstLine() 135 let props = Get_expected_props() 136 call assert_equal(props, prop_list(1)) 137 138 " remove by id 139 call prop_remove({'id': 12}, 1) 140 unlet props[2] 141 call assert_equal(props, prop_list(1)) 142 143 " remove by type 144 call prop_remove({'type': 'one'}, 1) 145 unlet props[1] 146 call assert_equal(props, prop_list(1)) 147 148 call DeletePropTypes() 149 bwipe! 150endfunc 151 152func SetupOneLine() 153 call setline(1, 'xonex xtwoxx') 154 call AddPropTypes() 155 call prop_add(1, 2, {'length': 3, 'id': 11, 'type': 'one'}) 156 call prop_add(1, 8, {'length': 3, 'id': 12, 'type': 'two'}) 157 let expected = [ 158 \ {'col': 2, 'length': 3, 'id': 11, 'type': 'one', 'start': 1, 'end': 1}, 159 \ {'col': 8, 'length': 3, 'id': 12, 'type': 'two', 'start': 1, 'end': 1}, 160 \] 161 call assert_equal(expected, prop_list(1)) 162 return expected 163endfunc 164 165func Test_prop_add_remove_buf() 166 new 167 let bufnr = bufnr('') 168 call AddPropTypes() 169 call setline(1, 'one two three') 170 wincmd w 171 call prop_add(1, 1, {'length': 3, 'id': 11, 'type': 'one', 'bufnr': bufnr}) 172 call prop_add(1, 5, {'length': 3, 'id': 12, 'type': 'two', 'bufnr': bufnr}) 173 call prop_add(1, 11, {'length': 3, 'id': 13, 'type': 'three', 'bufnr': bufnr}) 174 175 let props = [ 176 \ {'col': 1, 'length': 3, 'id': 11, 'type': 'one', 'start': 1, 'end': 1}, 177 \ {'col': 5, 'length': 3, 'id': 12, 'type': 'two', 'start': 1, 'end': 1}, 178 \ {'col': 11, 'length': 3, 'id': 13, 'type': 'three', 'start': 1, 'end': 1}, 179 \] 180 call assert_equal(props, prop_list(1, {'bufnr': bufnr})) 181 182 " remove by id 183 call prop_remove({'id': 12, 'bufnr': bufnr}, 1) 184 unlet props[1] 185 call assert_equal(props, prop_list(1, {'bufnr': bufnr})) 186 187 " remove by type 188 call prop_remove({'type': 'one', 'bufnr': bufnr}, 1) 189 unlet props[0] 190 call assert_equal(props, prop_list(1, {'bufnr': bufnr})) 191 192 call DeletePropTypes() 193 wincmd w 194 bwipe! 195endfunc 196 197func Test_prop_backspace() 198 new 199 set bs=2 200 let expected = SetupOneLine() " 'xonex xtwoxx' 201 202 exe "normal 0li\<BS>\<Esc>fxli\<BS>\<Esc>" 203 call assert_equal('one xtwoxx', getline(1)) 204 let expected[0].col = 1 205 let expected[1].col = 6 206 call assert_equal(expected, prop_list(1)) 207 208 call DeletePropTypes() 209 bwipe! 210 set bs& 211endfunc 212 213func Test_prop_replace() 214 new 215 set bs=2 216 let expected = SetupOneLine() " 'xonex xtwoxx' 217 218 exe "normal 0Ryyy\<Esc>" 219 call assert_equal('yyyex xtwoxx', getline(1)) 220 call assert_equal(expected, prop_list(1)) 221 222 exe "normal ftRyy\<BS>" 223 call assert_equal('yyyex xywoxx', getline(1)) 224 call assert_equal(expected, prop_list(1)) 225 226 exe "normal 0fwRyy\<BS>" 227 call assert_equal('yyyex xyyoxx', getline(1)) 228 call assert_equal(expected, prop_list(1)) 229 230 exe "normal 0foRyy\<BS>\<BS>" 231 call assert_equal('yyyex xyyoxx', getline(1)) 232 call assert_equal(expected, prop_list(1)) 233 234 call DeletePropTypes() 235 bwipe! 236 set bs& 237endfunc 238 239func Test_prop_clear() 240 new 241 call AddPropTypes() 242 call SetupPropsInFirstLine() 243 call assert_equal(Get_expected_props(), prop_list(1)) 244 245 call prop_clear(1) 246 call assert_equal([], prop_list(1)) 247 248 call DeletePropTypes() 249 bwipe! 250endfunc 251 252func Test_prop_clear_buf() 253 new 254 call AddPropTypes() 255 call SetupPropsInFirstLine() 256 let bufnr = bufnr('') 257 wincmd w 258 call assert_equal(Get_expected_props(), prop_list(1, {'bufnr': bufnr})) 259 260 call prop_clear(1, 1, {'bufnr': bufnr}) 261 call assert_equal([], prop_list(1, {'bufnr': bufnr})) 262 263 wincmd w 264 call DeletePropTypes() 265 bwipe! 266endfunc 267 268func Test_prop_setline() 269 new 270 call AddPropTypes() 271 call SetupPropsInFirstLine() 272 call assert_equal(Get_expected_props(), prop_list(1)) 273 274 call setline(1, 'foobar') 275 call assert_equal([], prop_list(1)) 276 277 call DeletePropTypes() 278 bwipe! 279endfunc 280 281func Test_prop_setbufline() 282 new 283 call AddPropTypes() 284 call SetupPropsInFirstLine() 285 let bufnr = bufnr('') 286 wincmd w 287 call assert_equal(Get_expected_props(), prop_list(1, {'bufnr': bufnr})) 288 289 call setbufline(bufnr, 1, 'foobar') 290 call assert_equal([], prop_list(1, {'bufnr': bufnr})) 291 292 wincmd w 293 call DeletePropTypes() 294 bwipe! 295endfunc 296 297func Test_prop_substitute() 298 new 299 " Set first line to 'one two three' 300 call AddPropTypes() 301 call SetupPropsInFirstLine() 302 let expected_props = Get_expected_props() 303 call assert_equal(expected_props, prop_list(1)) 304 305 " Change "n" in "one" to XX: 'oXXe two three' 306 s/n/XX/ 307 let expected_props[0].length += 1 308 let expected_props[1].length += 1 309 let expected_props[2].col += 1 310 let expected_props[3].col += 1 311 call assert_equal(expected_props, prop_list(1)) 312 313 " Delete "t" in "two" and "three" to XX: 'oXXe wo hree' 314 s/t//g 315 let expected_props[0].length -= 2 316 let expected_props[2].length -= 1 317 let expected_props[3].length -= 1 318 let expected_props[3].col -= 1 319 call assert_equal(expected_props, prop_list(1)) 320 321 " Split the line by changing w to line break: 'oXXe ', 'o hree' 322 " The long prop is split and spans both lines. 323 " The props on "two" and "three" move to the next line. 324 s/w/\r/ 325 let new_props = [ 326 \ copy(expected_props[0]), 327 \ copy(expected_props[2]), 328 \ copy(expected_props[3]), 329 \ ] 330 let expected_props[0].length = 5 331 unlet expected_props[3] 332 unlet expected_props[2] 333 call assert_equal(expected_props, prop_list(1)) 334 335 let new_props[0].length = 6 336 let new_props[1].col = 1 337 let new_props[1].length = 1 338 let new_props[2].col = 3 339 call assert_equal(new_props, prop_list(2)) 340 341 call DeletePropTypes() 342 bwipe! 343endfunc 344 345func Test_prop_change_indent() 346 call prop_type_add('comment', {'highlight': 'Directory'}) 347 new 348 call setline(1, [' xxx', 'yyyyy']) 349 call prop_add(2, 2, {'length': 2, 'type': 'comment'}) 350 let expect = {'col': 2, 'length': 2, 'type': 'comment', 'start': 1, 'end': 1, 'id': 0} 351 call assert_equal([expect], prop_list(2)) 352 353 set shiftwidth=3 354 normal 2G>> 355 call assert_equal(' yyyyy', getline(2)) 356 let expect.col += 3 357 call assert_equal([expect], prop_list(2)) 358 359 normal 2G== 360 call assert_equal(' yyyyy', getline(2)) 361 let expect.col = 6 362 call assert_equal([expect], prop_list(2)) 363 364 call prop_clear(2) 365 call prop_add(2, 2, {'length': 5, 'type': 'comment'}) 366 let expect.col = 2 367 let expect.length = 5 368 call assert_equal([expect], prop_list(2)) 369 370 normal 2G<< 371 call assert_equal(' yyyyy', getline(2)) 372 let expect.length = 2 373 call assert_equal([expect], prop_list(2)) 374 375 set shiftwidth& 376 call prop_type_delete('comment') 377endfunc 378 379" Setup a three line prop in lines 2 - 4. 380" Add short props in line 1 and 5. 381func Setup_three_line_prop() 382 new 383 call setline(1, ['one', 'twotwo', 'three', 'fourfour', 'five']) 384 call prop_add(1, 2, {'length': 1, 'type': 'comment'}) 385 call prop_add(2, 4, {'end_lnum': 4, 'end_col': 5, 'type': 'comment'}) 386 call prop_add(5, 2, {'length': 1, 'type': 'comment'}) 387endfunc 388 389func Test_prop_multiline() 390 call prop_type_add('comment', {'highlight': 'Directory'}) 391 new 392 call setline(1, ['xxxxxxx', 'yyyyyyyyy', 'zzzzzzzz']) 393 394 " start halfway line 1, end halfway line 3 395 call prop_add(1, 3, {'end_lnum': 3, 'end_col': 5, 'type': 'comment'}) 396 let expect1 = {'col': 3, 'length': 6, 'type': 'comment', 'start': 1, 'end': 0, 'id': 0} 397 call assert_equal([expect1], prop_list(1)) 398 let expect2 = {'col': 1, 'length': 10, 'type': 'comment', 'start': 0, 'end': 0, 'id': 0} 399 call assert_equal([expect2], prop_list(2)) 400 let expect3 = {'col': 1, 'length': 4, 'type': 'comment', 'start': 0, 'end': 1, 'id': 0} 401 call assert_equal([expect3], prop_list(3)) 402 call prop_clear(1, 3) 403 404 " include all three lines 405 call prop_add(1, 1, {'end_lnum': 3, 'end_col': 999, 'type': 'comment'}) 406 let expect1.col = 1 407 let expect1.length = 8 408 call assert_equal([expect1], prop_list(1)) 409 call assert_equal([expect2], prop_list(2)) 410 let expect3.length = 9 411 call assert_equal([expect3], prop_list(3)) 412 call prop_clear(1, 3) 413 414 bwipe! 415 416 " Test deleting the first line of a multi-line prop. 417 call Setup_three_line_prop() 418 let expect_short = {'col': 2, 'length': 1, 'type': 'comment', 'start': 1, 'end': 1, 'id': 0} 419 call assert_equal([expect_short], prop_list(1)) 420 let expect2 = {'col': 4, 'length': 4, 'type': 'comment', 'start': 1, 'end': 0, 'id': 0} 421 call assert_equal([expect2], prop_list(2)) 422 2del 423 call assert_equal([expect_short], prop_list(1)) 424 let expect2 = {'col': 1, 'length': 6, 'type': 'comment', 'start': 1, 'end': 0, 'id': 0} 425 call assert_equal([expect2], prop_list(2)) 426 bwipe! 427 428 " Test deleting the last line of a multi-line prop. 429 call Setup_three_line_prop() 430 let expect3 = {'col': 1, 'length': 6, 'type': 'comment', 'start': 0, 'end': 0, 'id': 0} 431 call assert_equal([expect3], prop_list(3)) 432 let expect4 = {'col': 1, 'length': 4, 'type': 'comment', 'start': 0, 'end': 1, 'id': 0} 433 call assert_equal([expect4], prop_list(4)) 434 4del 435 let expect3.end = 1 436 call assert_equal([expect3], prop_list(3)) 437 call assert_equal([expect_short], prop_list(4)) 438 bwipe! 439 440 " Test appending a line below the multi-line text prop start. 441 call Setup_three_line_prop() 442 let expect2 = {'col': 4, 'length': 4, 'type': 'comment', 'start': 1, 'end': 0, 'id': 0} 443 call assert_equal([expect2], prop_list(2)) 444 call append(2, "new line") 445 call assert_equal([expect2], prop_list(2)) 446 let expect3 = {'col': 1, 'length': 9, 'type': 'comment', 'start': 0, 'end': 0, 'id': 0} 447 call assert_equal([expect3], prop_list(3)) 448 bwipe! 449 450 call prop_type_delete('comment') 451endfunc 452 453func Test_prop_byteoff() 454 call prop_type_add('comment', {'highlight': 'Directory'}) 455 new 456 call setline(1, ['line1', 'second line', '']) 457 set ff=unix 458 call assert_equal(19, line2byte(3)) 459 call prop_add(1, 1, {'end_col': 3, 'type': 'comment'}) 460 call assert_equal(19, line2byte(3)) 461 462 bwipe! 463 call prop_type_delete('comment') 464endfunc 465 466func Test_prop_undo() 467 new 468 call prop_type_add('comment', {'highlight': 'Directory'}) 469 call setline(1, ['oneone', 'twotwo', 'three']) 470 " Set 'undolevels' to break changes into undo-able pieces. 471 set ul& 472 473 call prop_add(1, 3, {'end_col': 5, 'type': 'comment'}) 474 let expected = [{'col': 3, 'length': 2, 'id': 0, 'type': 'comment', 'start': 1, 'end': 1} ] 475 call assert_equal(expected, prop_list(1)) 476 477 " Insert a character, then undo. 478 exe "normal 0lllix\<Esc>" 479 set ul& 480 let expected[0].length = 3 481 call assert_equal(expected, prop_list(1)) 482 undo 483 let expected[0].length = 2 484 call assert_equal(expected, prop_list(1)) 485 486 " Delete a character, then undo 487 exe "normal 0lllx" 488 set ul& 489 let expected[0].length = 1 490 call assert_equal(expected, prop_list(1)) 491 undo 492 let expected[0].length = 2 493 call assert_equal(expected, prop_list(1)) 494 495 " Delete the line, then undo 496 1d 497 set ul& 498 call assert_equal([], prop_list(1)) 499 undo 500 call assert_equal(expected, prop_list(1)) 501 502 " Insert a character, delete two characters, then undo with "U" 503 exe "normal 0lllix\<Esc>" 504 set ul& 505 let expected[0].length = 3 506 call assert_equal(expected, prop_list(1)) 507 exe "normal 0lllxx" 508 set ul& 509 let expected[0].length = 1 510 call assert_equal(expected, prop_list(1)) 511 normal U 512 let expected[0].length = 2 513 call assert_equal(expected, prop_list(1)) 514 515 bwipe! 516 call prop_type_delete('comment') 517endfunc 518 519" screenshot test with textprop highlighting 520funct Test_textprop_screenshots() 521 " The Vim running in the terminal needs to use utf-8. 522 if !CanRunVimInTerminal() || g:orig_encoding != 'utf-8' 523 return 524 endif 525 call writefile([ 526 \ "call setline(1, ['One two', 'Numbér 123 änd thœn 4¾7.', '--aa--bb--cc--dd--'])", 527 \ "hi NumberProp ctermfg=blue", 528 \ "hi LongProp ctermbg=yellow", 529 \ "call prop_type_add('number', {'highlight': 'NumberProp'})", 530 \ "call prop_type_add('long', {'highlight': 'LongProp'})", 531 \ "call prop_type_add('start', {'highlight': 'NumberProp', 'start_incl': 1})", 532 \ "call prop_type_add('end', {'highlight': 'NumberProp', 'end_incl': 1})", 533 \ "call prop_type_add('both', {'highlight': 'NumberProp', 'start_incl': 1, 'end_incl': 1})", 534 \ "call prop_add(1, 4, {'end_lnum': 3, 'end_col': 3, 'type': 'long'})", 535 \ "call prop_add(2, 9, {'length': 3, 'type': 'number'})", 536 \ "call prop_add(2, 24, {'length': 4, 'type': 'number'})", 537 \ "call prop_add(3, 3, {'length': 2, 'type': 'number'})", 538 \ "call prop_add(3, 7, {'length': 2, 'type': 'start'})", 539 \ "call prop_add(3, 11, {'length': 2, 'type': 'end'})", 540 \ "call prop_add(3, 15, {'length': 2, 'type': 'both'})", 541 \ "set number", 542 \ "hi clear SpellBad", 543 \ "set spell", 544 \ "normal 3G0llix\<Esc>lllix\<Esc>lllix\<Esc>lllix\<Esc>lllix\<Esc>lllix\<Esc>lllix\<Esc>lllix\<Esc>", 545 \ "normal 3G0lli\<BS>\<Esc>", 546 \], 'XtestProp') 547 let buf = RunVimInTerminal('-S XtestProp', {'rows': 6}) 548 call VerifyScreenDump(buf, 'Test_textprop_01', {}) 549 550 " clean up 551 call StopVimInTerminal(buf) 552 call delete('XtestProp') 553endfunc 554