1" Tests for popup windows 2 3source check.vim 4CheckFeature popupwin 5 6source screendump.vim 7 8func Test_simple_popup() 9 CheckScreendump 10 11 let lines =<< trim END 12 call setline(1, range(1, 100)) 13 hi PopupColor1 ctermbg=lightblue 14 hi PopupColor2 ctermbg=lightcyan 15 hi EndOfBuffer ctermbg=lightgrey 16 hi Comment ctermfg=red 17 call prop_type_add('comment', #{highlight: 'Comment'}) 18 let winid = popup_create('hello there', #{line: 3, col: 11, minwidth: 20, highlight: 'PopupColor1'}) 19 let winid2 = popup_create(['another one', 'another two', 'another three'], #{line: 3, col: 25, minwidth: 20}) 20 call setwinvar(winid2, '&wincolor', 'PopupColor2') 21 END 22 call writefile(lines, 'XtestPopup') 23 let buf = RunVimInTerminal('-S XtestPopup', #{rows: 10}) 24 call VerifyScreenDump(buf, 'Test_popupwin_01', {}) 25 26 " Add a tabpage 27 call term_sendkeys(buf, ":tabnew\<CR>") 28 call term_sendkeys(buf, ":let popupwin = popup_create([" 29 \ .. "#{text: 'other tab'}," 30 \ .. "#{text: 'a comment line', props: [#{" 31 \ .. "col: 3, length: 7, minwidth: 20, type: 'comment'" 32 \ .. "}]}," 33 \ .. "], #{line: 4, col: 9, minwidth: 20})\<CR>") 34 call VerifyScreenDump(buf, 'Test_popupwin_02', {}) 35 36 " switch back to first tabpage 37 call term_sendkeys(buf, "gt") 38 call VerifyScreenDump(buf, 'Test_popupwin_03', {}) 39 40 " close that tabpage 41 call term_sendkeys(buf, ":quit!\<CR>") 42 call VerifyScreenDump(buf, 'Test_popupwin_04', {}) 43 44 " set 'columns' to a small value, size must be recomputed 45 call term_sendkeys(buf, ":let cols = &columns\<CR>") 46 call term_sendkeys(buf, ":set columns=12\<CR>") 47 call VerifyScreenDump(buf, 'Test_popupwin_04a', {}) 48 call term_sendkeys(buf, ":let &columns = cols\<CR>") 49 50 " resize popup, show empty line at bottom 51 call term_sendkeys(buf, ":call popup_move(popupwin, #{minwidth: 15, maxwidth: 25, minheight: 3, maxheight: 5})\<CR>") 52 call term_sendkeys(buf, ":redraw\<CR>") 53 call VerifyScreenDump(buf, 'Test_popupwin_05', {}) 54 55 " show not fitting line at bottom 56 call term_sendkeys(buf, ":call setbufline(winbufnr(popupwin), 3, 'this line will not fit here')\<CR>") 57 call term_sendkeys(buf, ":redraw\<CR>") 58 call VerifyScreenDump(buf, 'Test_popupwin_06', {}) 59 60 " move popup over ruler 61 call term_sendkeys(buf, ":set cmdheight=2\<CR>") 62 call term_sendkeys(buf, ":call popup_move(popupwin, #{line: 7, col: 55})\<CR>") 63 call term_sendkeys(buf, ":\<CR>") 64 call VerifyScreenDump(buf, 'Test_popupwin_07', {}) 65 66 " clear all popups after moving the cursor a bit, so that ruler is updated 67 call term_sendkeys(buf, "axxx\<Esc>") 68 call TermWait(buf) 69 call term_sendkeys(buf, "0") 70 call TermWait(buf) 71 call term_sendkeys(buf, ":call popup_clear()\<CR>") 72 call VerifyScreenDump(buf, 'Test_popupwin_08', {}) 73 74 " clean up 75 call StopVimInTerminal(buf) 76 call delete('XtestPopup') 77endfunc 78 79func Test_popup_with_border_and_padding() 80 CheckScreendump 81 82 for iter in range(0, 1) 83 let lines =<< trim END 84 call setline(1, range(1, 100)) 85 call popup_create('hello border', #{line: 2, col: 3, border: []}) 86 call popup_create('hello padding', #{line: 2, col: 23, padding: []}) 87 call popup_create('hello both', #{line: 2, col: 43, border: [], padding: [], highlight: 'Normal'}) 88 call popup_create('border TL', #{line: 6, col: 3, border: [1, 0, 0, 4]}) 89 call popup_create('paddings', #{line: 6, col: 23, padding: range(1, 4)}) 90 call popup_create('wrapped longer text', #{line: 8, col: 55, padding: [0, 3, 0, 3], border: [0, 1, 0, 1]}) 91 call popup_create('right aligned text', #{line: 11, col: 56, wrap: 0, padding: [0, 3, 0, 3], border: [0, 1, 0, 1]}) 92 call popup_create('X', #{line: 2, col: 73}) 93 call popup_create('X', #{line: 3, col: 74}) 94 call popup_create('X', #{line: 4, col: 75}) 95 call popup_create('X', #{line: 5, col: 76}) 96 END 97 call insert(lines, iter == 1 ? '' : 'set enc=latin1') 98 call writefile(lines, 'XtestPopupBorder') 99 let buf = RunVimInTerminal('-S XtestPopupBorder', #{rows: 15}) 100 call VerifyScreenDump(buf, 'Test_popupwin_2' .. iter, {}) 101 102 call StopVimInTerminal(buf) 103 call delete('XtestPopupBorder') 104 endfor 105 106 let lines =<< trim END 107 call setline(1, range(1, 100)) 108 hi BlueColor ctermbg=lightblue 109 hi TopColor ctermbg=253 110 hi RightColor ctermbg=245 111 hi BottomColor ctermbg=240 112 hi LeftColor ctermbg=248 113 call popup_create('hello border', #{line: 2, col: 3, border: [], borderhighlight: ['BlueColor']}) 114 call popup_create(['hello border', 'and more'], #{line: 2, col: 23, border: [], borderhighlight: ['TopColor', 'RightColor', 'BottomColor', 'LeftColor']}) 115 call popup_create(['hello border', 'lines only'], #{line: 2, col: 43, border: [], borderhighlight: ['BlueColor'], borderchars: ['x']}) 116 call popup_create(['hello border', 'with corners'], #{line: 2, col: 60, border: [], borderhighlight: ['BlueColor'], borderchars: ['x', '#']}) 117 let winid = popup_create(['hello border', 'with numbers'], #{line: 6, col: 3, border: [], borderhighlight: ['BlueColor'], borderchars: ['0', '1', '2', '3', '4', '5', '6', '7']}) 118 call popup_create(['hello border', 'just blanks'], #{line: 7, col: 23, border: [], borderhighlight: ['BlueColor'], borderchars: [' ']}) 119 func MultiByte() 120 call popup_create(['hello'], #{line: 8, col: 43, border: [], borderchars: ['─', '│', '─', '│', '┌', '┐', '┘', '└']}) 121 endfunc 122 END 123 call writefile(lines, 'XtestPopupBorder') 124 let buf = RunVimInTerminal('-S XtestPopupBorder', #{rows: 12}) 125 call VerifyScreenDump(buf, 'Test_popupwin_22', {}) 126 127 " check that changing borderchars triggers a redraw 128 call term_sendkeys(buf, ":call popup_setoptions(winid, #{borderchars: ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h']})\<CR>") 129 call VerifyScreenDump(buf, 'Test_popupwin_23', {}) 130 131 " check multi-byte border only with 'ambiwidth' single 132 if &ambiwidth == 'single' 133 call term_sendkeys(buf, ":call MultiByte()\<CR>") 134 call VerifyScreenDump(buf, 'Test_popupwin_24', {}) 135 endif 136 137 call StopVimInTerminal(buf) 138 call delete('XtestPopupBorder') 139 140 let with_border_or_padding = #{ 141 \ line: 2, 142 \ core_line: 3, 143 \ col: 3, 144 \ core_col: 4, 145 \ width: 14, 146 \ core_width: 12, 147 \ height: 3, 148 \ core_height: 1, 149 \ firstline: 1, 150 \ lastline: 1, 151 \ scrollbar: 0, 152 \ visible: 1} 153 let winid = popup_create('hello border', #{line: 2, col: 3, border: []})", 154 call assert_equal(with_border_or_padding, winid->popup_getpos()) 155 let options = popup_getoptions(winid) 156 call assert_equal([], options.border) 157 call assert_false(has_key(options, "padding")) 158 159 let winid = popup_create('hello padding', #{line: 2, col: 3, padding: []}) 160 let with_border_or_padding.width = 15 161 let with_border_or_padding.core_width = 13 162 call assert_equal(with_border_or_padding, popup_getpos(winid)) 163 let options = popup_getoptions(winid) 164 call assert_false(has_key(options, "border")) 165 call assert_equal([], options.padding) 166 167 call popup_setoptions(winid, #{ 168 \ padding: [1, 2, 3, 4], 169 \ border: [4, 0, 7, 8], 170 \ borderhighlight: ['Top', 'Right', 'Bottom', 'Left'], 171 \ borderchars: ['1', '^', '2', '>', '3', 'v', '4', '<'], 172 \ }) 173 let options = popup_getoptions(winid) 174 call assert_equal([1, 0, 1, 1], options.border) 175 call assert_equal([1, 2, 3, 4], options.padding) 176 call assert_equal(['Top', 'Right', 'Bottom', 'Left'], options.borderhighlight) 177 call assert_equal(['1', '^', '2', '>', '3', 'v', '4', '<'], options.borderchars) 178 179 " Check that popup_setoptions() takes the output of popup_getoptions() 180 call popup_setoptions(winid, options) 181 call assert_equal(options, popup_getoptions(winid)) 182 183 " Check that range() doesn't crash 184 call popup_setoptions(winid, #{ 185 \ padding: range(1, 4), 186 \ border: range(5, 8), 187 \ borderhighlight: range(4), 188 \ borderchars: range(8), 189 \ }) 190 191 let winid = popup_create('hello both', #{line: 3, col: 8, border: [], padding: []}) 192 call assert_equal(#{ 193 \ line: 3, 194 \ core_line: 5, 195 \ col: 8, 196 \ core_col: 10, 197 \ width: 14, 198 \ core_width: 10, 199 \ height: 5, 200 \ scrollbar: 0, 201 \ core_height: 1, 202 \ firstline: 1, 203 \ lastline: 1, 204 \ visible: 1}, popup_getpos(winid)) 205 206 call popup_clear() 207endfunc 208 209func Test_popup_with_syntax_win_execute() 210 CheckScreendump 211 212 let lines =<< trim END 213 call setline(1, range(1, 100)) 214 hi PopupColor ctermbg=lightblue 215 let winid = popup_create([ 216 \ '#include <stdio.h>', 217 \ 'int main(void)', 218 \ '{', 219 \ ' printf(123);', 220 \ '}', 221 \], #{line: 3, col: 25, highlight: 'PopupColor'}) 222 call win_execute(winid, 'set syntax=cpp') 223 END 224 call writefile(lines, 'XtestPopup') 225 let buf = RunVimInTerminal('-S XtestPopup', #{rows: 10}) 226 call VerifyScreenDump(buf, 'Test_popupwin_10', {}) 227 228 " clean up 229 call StopVimInTerminal(buf) 230 call delete('XtestPopup') 231endfunc 232 233func Test_popup_with_syntax_setbufvar() 234 CheckScreendump 235 236 let lines =<< trim END 237 call setline(1, range(1, 100)) 238 hi PopupColor ctermbg=lightgrey 239 let winid = popup_create([ 240 \ '#include <stdio.h>', 241 \ 'int main(void)', 242 \ '{', 243 \ "\tprintf(567);", 244 \ '}', 245 \], #{line: 3, col: 21, highlight: 'PopupColor'}) 246 call setbufvar(winbufnr(winid), '&syntax', 'cpp') 247 END 248 call writefile(lines, 'XtestPopup') 249 let buf = RunVimInTerminal('-S XtestPopup', #{rows: 10}) 250 call VerifyScreenDump(buf, 'Test_popupwin_11', {}) 251 252 " clean up 253 call StopVimInTerminal(buf) 254 call delete('XtestPopup') 255endfunc 256 257func Test_popup_with_matches() 258 CheckScreendump 259 260 let lines =<< trim END 261 call setline(1, ['111 222 333', '444 555 666']) 262 let winid = popup_create([ 263 \ '111 222 333', 264 \ '444 555 666', 265 \], #{line: 3, col: 10, border: []}) 266 set hlsearch 267 hi VeryBlue ctermfg=blue guifg=blue 268 /666 269 call matchadd('ErrorMsg', '111') 270 call matchadd('VeryBlue', '444') 271 call win_execute(winid, "call matchadd('ErrorMsg', '111')") 272 call win_execute(winid, "call matchadd('VeryBlue', '555')") 273 END 274 call writefile(lines, 'XtestPopupMatches') 275 let buf = RunVimInTerminal('-S XtestPopupMatches', #{rows: 10}) 276 call VerifyScreenDump(buf, 'Test_popupwin_matches', {}) 277 278 " clean up 279 call StopVimInTerminal(buf) 280 call delete('XtestPopupMatches') 281endfunc 282 283func Test_popup_all_corners() 284 CheckScreendump 285 286 let lines =<< trim END 287 call setline(1, repeat([repeat('-', 60)], 15)) 288 set so=0 289 normal 2G3|r# 290 let winid1 = popup_create(['first', 'second'], #{ 291 \ line: 'cursor+1', 292 \ col: 'cursor', 293 \ pos: 'topleft', 294 \ border: [], 295 \ padding: [], 296 \ }) 297 normal 24|r@ 298 let winid1 = popup_create(['First', 'SeconD'], #{ 299 \ line: 'cursor+1', 300 \ col: 'cursor', 301 \ pos: 'topright', 302 \ border: [], 303 \ padding: [], 304 \ }) 305 normal 9G27|r% 306 let winid1 = popup_create(['fiRSt', 'seCOnd'], #{ 307 \ line: 'cursor-1', 308 \ col: 'cursor', 309 \ pos: 'botleft', 310 \ border: [], 311 \ padding: [], 312 \ }) 313 normal 48|r& 314 let winid1 = popup_create(['FIrsT', 'SEcoND'], #{ 315 \ line: 'cursor-1', 316 \ col: 'cursor', 317 \ pos: 'botright', 318 \ border: [], 319 \ padding: [], 320 \ }) 321 normal 1G51|r* 322 let winid1 = popup_create(['one', 'two'], #{ 323 \ line: 'cursor-1', 324 \ col: 'cursor', 325 \ pos: 'botleft', 326 \ border: [], 327 \ padding: [], 328 \ }) 329 END 330 call writefile(lines, 'XtestPopupCorners') 331 let buf = RunVimInTerminal('-S XtestPopupCorners', #{rows: 12}) 332 call VerifyScreenDump(buf, 'Test_popupwin_corners', {}) 333 334 " clean up 335 call StopVimInTerminal(buf) 336 call delete('XtestPopupCorners') 337endfunc 338 339func Test_popup_nospace() 340 CheckScreendump 341 342 let lines =<< trim END 343 call setline(1, repeat([repeat('-', 60)], 15)) 344 set so=0 345 346 " cursor in a line in top half, using "botleft" with popup that 347 " does fit 348 normal 5G2|r@ 349 let winid1 = popup_create(['one', 'two'], #{ 350 \ line: 'cursor-1', 351 \ col: 'cursor', 352 \ pos: 'botleft', 353 \ border: [], 354 \ }) 355 " cursor in a line in top half, using "botleft" with popup that 356 " doesn't fit: gets truncated 357 normal 5G9|r# 358 let winid1 = popup_create(['one', 'two', 'tee'], #{ 359 \ line: 'cursor-1', 360 \ col: 'cursor', 361 \ pos: 'botleft', 362 \ posinvert: 0, 363 \ border: [], 364 \ }) 365 " cursor in a line in top half, using "botleft" with popup that 366 " doesn't fit and 'posinvert' set: flips to below. 367 normal 5G16|r% 368 let winid1 = popup_create(['one', 'two', 'tee'], #{ 369 \ line: 'cursor-1', 370 \ col: 'cursor', 371 \ pos: 'botleft', 372 \ border: [], 373 \ }) 374 " cursor in a line in bottom half, using "botleft" with popup that 375 " doesn't fit: does not flip. 376 normal 8G23|r* 377 let winid1 = popup_create(['aaa', 'bbb', 'ccc', 'ddd', 'eee', 'fff'], #{ 378 \ line: 'cursor-1', 379 \ col: 'cursor', 380 \ pos: 'botleft', 381 \ border: [], 382 \ }) 383 384 " cursor in a line in bottom half, using "topleft" with popup that 385 " does fit 386 normal 8G30|r@ 387 let winid1 = popup_create(['one', 'two'], #{ 388 \ line: 'cursor+1', 389 \ col: 'cursor', 390 \ pos: 'topleft', 391 \ border: [], 392 \ }) 393 " cursor in a line in top half, using "topleft" with popup that 394 " doesn't fit: truncated 395 normal 8G37|r# 396 let winid1 = popup_create(['one', 'two', 'tee'], #{ 397 \ line: 'cursor+1', 398 \ col: 'cursor', 399 \ pos: 'topleft', 400 \ posinvert: 0, 401 \ border: [], 402 \ }) 403 " cursor in a line in top half, using "topleft" with popup that 404 " doesn't fit and "posinvert" set: flips to above. 405 normal 8G44|r% 406 let winid1 = popup_create(['one', 'two', 'tee', 'fou', 'fiv'], #{ 407 \ line: 'cursor+1', 408 \ col: 'cursor', 409 \ pos: 'topleft', 410 \ border: [], 411 \ }) 412 " cursor in a line in top half, using "topleft" with popup that 413 " doesn't fit: does not flip. 414 normal 5G51|r* 415 let winid1 = popup_create(['aaa', 'bbb', 'ccc', 'ddd', 'eee', 'fff'], #{ 416 \ line: 'cursor+1', 417 \ col: 'cursor', 418 \ pos: 'topleft', 419 \ border: [], 420 \ }) 421 END 422 call writefile(lines, 'XtestPopupNospace') 423 let buf = RunVimInTerminal('-S XtestPopupNospace', #{rows: 12}) 424 call VerifyScreenDump(buf, 'Test_popupwin_nospace', {}) 425 426 " clean up 427 call StopVimInTerminal(buf) 428 call delete('XtestPopupNospace') 429endfunc 430 431func Test_popup_firstline_dump() 432 CheckScreendump 433 434 let lines =<< trim END 435 call setline(1, range(1, 20)) 436 let winid = popup_create(['1111', '222222', '33333', '44', '5', '666666', '77777', '888', '9999999999999999'], #{ 437 \ maxheight: 4, 438 \ firstline: 3, 439 \ }) 440 END 441 call writefile(lines, 'XtestPopupFirstline') 442 let buf = RunVimInTerminal('-S XtestPopupFirstline', #{rows: 10}) 443 call VerifyScreenDump(buf, 'Test_popupwin_firstline_1', {}) 444 445 call term_sendkeys(buf, ":call popup_setoptions(winid, #{firstline: -1})\<CR>") 446 call term_sendkeys(buf, ":\<CR>") 447 call VerifyScreenDump(buf, 'Test_popupwin_firstline_2', {}) 448 449 " clean up 450 call StopVimInTerminal(buf) 451 call delete('XtestPopupFirstline') 452endfunc 453 454func Test_popup_firstline() 455 let winid = popup_create(['1111', '222222', '33333', '44444'], #{ 456 \ maxheight: 2, 457 \ firstline: 3, 458 \ }) 459 call assert_equal(3, popup_getoptions(winid).firstline) 460 call popup_setoptions(winid, #{firstline: 1}) 461 call assert_equal(1, popup_getoptions(winid).firstline) 462 eval winid->popup_close() 463 464 let winid = popup_create(['xxx']->repeat(50), #{ 465 \ maxheight: 3, 466 \ firstline: 11, 467 \ }) 468 redraw 469 call assert_equal(11, popup_getoptions(winid).firstline) 470 call assert_equal(11, popup_getpos(winid).firstline) 471 " check line() works with popup window 472 call assert_equal(11, line('.', winid)) 473 call assert_equal(50, line('$', winid)) 474 call assert_equal(0, line('$', 123456)) 475 476 " Normal command changes what is displayed but not "firstline" 477 call win_execute(winid, "normal! \<c-y>") 478 call assert_equal(11, popup_getoptions(winid).firstline) 479 call assert_equal(10, popup_getpos(winid).firstline) 480 481 " Making some property change applies "firstline" again 482 call popup_setoptions(winid, #{line: 4}) 483 call assert_equal(11, popup_getoptions(winid).firstline) 484 call assert_equal(11, popup_getpos(winid).firstline) 485 486 " Remove "firstline" property and scroll 487 call popup_setoptions(winid, #{firstline: 0}) 488 call win_execute(winid, "normal! \<c-y>") 489 call assert_equal(0, popup_getoptions(winid).firstline) 490 call assert_equal(10, popup_getpos(winid).firstline) 491 492 " Making some property change has no side effect 493 call popup_setoptions(winid, #{line: 3}) 494 call assert_equal(0, popup_getoptions(winid).firstline) 495 call assert_equal(10, popup_getpos(winid).firstline) 496 call popup_close(winid) 497 498 " CTRL-D scrolls down half a page 499 let winid = popup_create(['xxx']->repeat(50), #{ 500 \ maxheight: 8, 501 \ }) 502 redraw 503 call assert_equal(1, popup_getpos(winid).firstline) 504 call win_execute(winid, "normal! \<C-D>") 505 call assert_equal(5, popup_getpos(winid).firstline) 506 call win_execute(winid, "normal! \<C-D>") 507 call assert_equal(9, popup_getpos(winid).firstline) 508 call win_execute(winid, "normal! \<C-U>") 509 call assert_equal(5, popup_getpos(winid).firstline) 510 511 call win_execute(winid, "normal! \<C-F>") 512 call assert_equal(11, popup_getpos(winid).firstline) 513 call win_execute(winid, "normal! \<C-B>") 514 call assert_equal(5, popup_getpos(winid).firstline) 515 516 call popup_close(winid) 517endfunc 518 519func Test_popup_firstline_cursorline() 520 let winid = popup_create(['1111', '222222', '33333', '44444'], #{ 521 \ maxheight: 2, 522 \ firstline: 3, 523 \ cursorline: 1, 524 \ }) 525 call assert_equal(3, popup_getoptions(winid).firstline) 526 call assert_equal(3, getwininfo(winid)[0].topline) 527 call assert_equal(3, getcurpos(winid)[1]) 528 529 call popup_close(winid) 530endfunc 531 532func Test_popup_noscrolloff() 533 set scrolloff=5 534 let winid = popup_create(['xxx']->repeat(50), #{ 535 \ maxheight: 5, 536 \ firstline: 11, 537 \ }) 538 redraw 539 call assert_equal(11, popup_getoptions(winid).firstline) 540 call assert_equal(11, popup_getpos(winid).firstline) 541 542 call popup_setoptions(winid, #{firstline: 0}) 543 call win_execute(winid, "normal! \<c-y>") 544 call assert_equal(0, popup_getoptions(winid).firstline) 545 call assert_equal(10, popup_getpos(winid).firstline) 546 547 call popup_close(winid) 548endfunc 549 550func Test_popup_drag() 551 CheckScreendump 552 553 " create a popup that covers the command line 554 let lines =<< trim END 555 call setline(1, range(1, 20)) 556 split 557 vsplit 558 $wincmd w 559 vsplit 560 1wincmd w 561 let winid = popup_create(['1111', '222222', '33333'], #{ 562 \ drag: 1, 563 \ resize: 1, 564 \ border: [], 565 \ line: &lines - 4, 566 \ }) 567 func Dragit() 568 call feedkeys("\<F3>\<LeftMouse>\<F4>\<LeftDrag>\<LeftRelease>", "xt") 569 endfunc 570 map <silent> <F3> :call test_setmouse(&lines - 4, &columns / 2)<CR> 571 map <silent> <F4> :call test_setmouse(&lines - 8, &columns / 2 - 20)<CR> 572 func Resize() 573 call feedkeys("\<F5>\<LeftMouse>\<F6>\<LeftDrag>\<LeftRelease>", "xt") 574 endfunc 575 map <silent> <F5> :call test_setmouse(6, 21)<CR> 576 map <silent> <F6> :call test_setmouse(7, 25)<CR> 577 END 578 call writefile(lines, 'XtestPopupDrag') 579 let buf = RunVimInTerminal('-S XtestPopupDrag', #{rows: 10}) 580 call VerifyScreenDump(buf, 'Test_popupwin_drag_01', {}) 581 582 call term_sendkeys(buf, ":call Dragit()\<CR>") 583 call VerifyScreenDump(buf, 'Test_popupwin_drag_02', {}) 584 585 call term_sendkeys(buf, ":call Resize()\<CR>") 586 call VerifyScreenDump(buf, 'Test_popupwin_drag_03', {}) 587 588 " clean up 589 call StopVimInTerminal(buf) 590 call delete('XtestPopupDrag') 591endfunc 592 593func Test_popup_drag_termwin() 594 CheckUnix 595 CheckScreendump 596 CheckFeature terminal 597 598 " create a popup that covers the terminal window 599 let lines =<< trim END 600 set foldmethod=marker 601 call setline(1, range(100)) 602 for nr in range(7) 603 call setline(nr * 12 + 1, "fold {{{") 604 call setline(nr * 12 + 11, "end }}}") 605 endfor 606 %foldclose 607 set shell=/bin/sh noruler 608 unlet $PROMPT_COMMAND 609 let $PS1 = 'vim> ' 610 terminal ++rows=4 611 $wincmd w 612 let winid = popup_create(['1111', '2222'], #{ 613 \ drag: 1, 614 \ resize: 1, 615 \ border: [], 616 \ line: 3, 617 \ }) 618 func DragitLeft() 619 call feedkeys("\<F3>\<LeftMouse>\<F4>\<LeftDrag>\<LeftRelease>", "xt") 620 endfunc 621 func DragitDown() 622 call feedkeys("\<F4>\<LeftMouse>\<F5>\<LeftDrag>\<LeftRelease>", "xt") 623 endfunc 624 func DragitDownLeft() 625 call feedkeys("\<F5>\<LeftMouse>\<F6>\<LeftDrag>\<LeftRelease>", "xt") 626 endfunc 627 map <silent> <F3> :call test_setmouse(3, &columns / 2)<CR> 628 map <silent> <F4> :call test_setmouse(3, &columns / 2 - 20)<CR> 629 map <silent> <F5> :call test_setmouse(12, &columns / 2)<CR> 630 map <silent> <F6> :call test_setmouse(12, &columns / 2 - 20)<CR> 631 END 632 call writefile(lines, 'XtestPopupTerm') 633 let buf = RunVimInTerminal('-S XtestPopupTerm', #{rows: 16}) 634 call VerifyScreenDump(buf, 'Test_popupwin_term_01', {}) 635 636 call term_sendkeys(buf, ":call DragitLeft()\<CR>") 637 call VerifyScreenDump(buf, 'Test_popupwin_term_02', {}) 638 639 call term_sendkeys(buf, ":call DragitDown()\<CR>") 640 call VerifyScreenDump(buf, 'Test_popupwin_term_03', {}) 641 642 call term_sendkeys(buf, ":call DragitDownLeft()\<CR>") 643 call VerifyScreenDump(buf, 'Test_popupwin_term_04', {}) 644 645 " clean up 646 call StopVimInTerminal(buf) 647 call delete('XtestPopupTerm') 648endfunc 649 650func Test_popup_close_with_mouse() 651 CheckScreendump 652 653 let lines =<< trim END 654 call setline(1, range(1, 20)) 655 " With border, can click on X 656 let winid = popup_create('foobar', #{ 657 \ close: 'button', 658 \ border: [], 659 \ line: 1, 660 \ col: 1, 661 \ }) 662 func CloseMsg(id, result) 663 echomsg 'Popup closed with ' .. a:result 664 endfunc 665 let winid = popup_create('notification', #{ 666 \ close: 'click', 667 \ line: 3, 668 \ col: 15, 669 \ callback: 'CloseMsg', 670 \ }) 671 let winid = popup_create('no border here', #{ 672 \ close: 'button', 673 \ line: 5, 674 \ col: 3, 675 \ }) 676 let winid = popup_create('only padding', #{ 677 \ close: 'button', 678 \ padding: [], 679 \ line: 5, 680 \ col: 23, 681 \ }) 682 func CloseWithX() 683 call feedkeys("\<F3>\<LeftMouse>\<LeftRelease>", "xt") 684 endfunc 685 map <silent> <F3> :call test_setmouse(1, len('foobar') + 2)<CR> 686 func CloseWithClick() 687 call feedkeys("\<F4>\<LeftMouse>\<LeftRelease>", "xt") 688 endfunc 689 map <silent> <F4> :call test_setmouse(3, 17)<CR> 690 func CreateWithMenuFilter() 691 let winid = popup_create('barfoo', #{ 692 \ close: 'button', 693 \ filter: 'popup_filter_menu', 694 \ border: [], 695 \ line: 1, 696 \ col: 40, 697 \ }) 698 endfunc 699 END 700 call writefile(lines, 'XtestPopupClose') 701 let buf = RunVimInTerminal('-S XtestPopupClose', #{rows: 10}) 702 call VerifyScreenDump(buf, 'Test_popupwin_close_01', {}) 703 704 call term_sendkeys(buf, ":call CloseWithX()\<CR>") 705 call VerifyScreenDump(buf, 'Test_popupwin_close_02', {}) 706 707 call term_sendkeys(buf, ":call CloseWithClick()\<CR>") 708 call VerifyScreenDump(buf, 'Test_popupwin_close_03', {}) 709 710 call term_sendkeys(buf, ":call CreateWithMenuFilter()\<CR>") 711 call VerifyScreenDump(buf, 'Test_popupwin_close_04', {}) 712 713 " We have to send the actual mouse code, feedkeys() would be caught the 714 " filter. 715 call term_sendkeys(buf, "\<Esc>[<0;47;1M") 716 call VerifyScreenDump(buf, 'Test_popupwin_close_05', {}) 717 718 " clean up 719 call StopVimInTerminal(buf) 720 call delete('XtestPopupClose') 721endfunction 722 723func Test_popup_menu_wrap() 724 CheckScreendump 725 726 let lines =<< trim END 727 call setline(1, range(1, 20)) 728 call popup_create([ 729 \ 'one', 730 \ 'asdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfas', 731 \ 'three', 732 \ 'four', 733 \ ], #{ 734 \ pos: "botleft", 735 \ border: [], 736 \ padding: [0,1,0,1], 737 \ maxheight: 3, 738 \ cursorline: 1, 739 \ filter: 'popup_filter_menu', 740 \ }) 741 END 742 call writefile(lines, 'XtestPopupWrap') 743 let buf = RunVimInTerminal('-S XtestPopupWrap', #{rows: 10}) 744 call VerifyScreenDump(buf, 'Test_popupwin_wrap_1', {}) 745 746 call term_sendkeys(buf, "jj") 747 call VerifyScreenDump(buf, 'Test_popupwin_wrap_2', {}) 748 749 " clean up 750 call term_sendkeys(buf, "\<Esc>") 751 call StopVimInTerminal(buf) 752 call delete('XtestPopupWrap') 753endfunction 754 755func Test_popup_with_mask() 756 CheckScreendump 757 758 let lines =<< trim END 759 call setline(1, repeat([join(range(1, 42), '')], 13)) 760 hi PopupColor ctermbg=lightgrey 761 let winid = popup_create([ 762 \ 'some text', 763 \ 'another line', 764 \], #{ 765 \ line: 1, 766 \ col: 10, 767 \ posinvert: 0, 768 \ wrap: 0, 769 \ fixed: 1, 770 \ scrollbar: v:false, 771 \ zindex: 90, 772 \ padding: [], 773 \ highlight: 'PopupColor', 774 \ mask: [[1,1,1,1], [-5,-1,4,4], [7,9,2,3], [2,4,3,3]]}) 775 call popup_create([ 776 \ 'xxxxxxxxx', 777 \ 'yyyyyyyyy', 778 \], #{ 779 \ line: 3, 780 \ col: 18, 781 \ zindex: 20}) 782 let winidb = popup_create([ 783 \ 'just one line', 784 \], #{ 785 \ line: 7, 786 \ col: 10, 787 \ posinvert: 0, 788 \ wrap: 0, 789 \ fixed: 1, 790 \ scrollbar: v:false, 791 \ close: 'button', 792 \ zindex: 90, 793 \ padding: [], 794 \ border: [], 795 \ mask: [[1,2,1,1], [-5,-1,4,4], [7,9,2,3], [3,5,5,5],[-7,-4,5,5]]}) 796 END 797 call writefile(lines, 'XtestPopupMask') 798 let buf = RunVimInTerminal('-S XtestPopupMask', #{rows: 13}) 799 call VerifyScreenDump(buf, 'Test_popupwin_mask_1', {}) 800 801 call term_sendkeys(buf, ":call popup_move(winid, #{col: 11, line: 2})\<CR>") 802 call term_sendkeys(buf, ":call popup_move(winidb, #{col: 12})\<CR>") 803 call term_sendkeys(buf, ":\<CR>") 804 call VerifyScreenDump(buf, 'Test_popupwin_mask_2', {}) 805 806 call term_sendkeys(buf, ":call popup_move(winid, #{col: 65, line: 2})\<CR>") 807 call term_sendkeys(buf, ":call popup_move(winidb, #{col: 63})\<CR>") 808 call term_sendkeys(buf, ":\<CR>") 809 call VerifyScreenDump(buf, 'Test_popupwin_mask_3', {}) 810 811 call term_sendkeys(buf, ":call popup_move(winid, #{pos: 'topright', col: 12, line: 2})\<CR>") 812 call term_sendkeys(buf, ":call popup_move(winidb, #{pos: 'topright', col: 12})\<CR>") 813 call term_sendkeys(buf, ":\<CR>") 814 call VerifyScreenDump(buf, 'Test_popupwin_mask_4', {}) 815 816 call term_sendkeys(buf, ":call popup_move(winid, #{pos: 'topright', col: 12, line: 11})\<CR>") 817 call term_sendkeys(buf, ":call popup_move(winidb, #{pos: 'topleft', col: 42, line: 11})\<CR>") 818 call term_sendkeys(buf, ":\<CR>") 819 call VerifyScreenDump(buf, 'Test_popupwin_mask_5', {}) 820 821 " clean up 822 call StopVimInTerminal(buf) 823 call delete('XtestPopupMask') 824 825 " this was causing a crash 826 call popup_create('test', #{mask: [[0, 0, 0, 0]]}) 827 call popup_clear() 828 829 " this was causing an internal error 830 enew 831 set nowrap 832 call repeat('x', &columns)->setline(1) 833 call prop_type_add('textprop', {}) 834 call prop_add(1, 1, #{length: &columns, type: 'textprop'}) 835 vsplit 836 let opts = popup_create('', #{textprop: 'textprop'}) 837 \ ->popup_getoptions() 838 \ ->extend(#{mask: [[1, 1, 1, 1]]}) 839 call popup_create('', opts) 840 redraw 841 842 close! 843 bwipe! 844 call prop_type_delete('textprop') 845 call popup_clear() 846 set wrap& 847endfunc 848 849func Test_popup_select() 850 CheckScreendump 851 CheckFeature clipboard_working 852 853 " create a popup with some text to be selected 854 let lines =<< trim END 855 set clipboard=autoselect 856 call setline(1, range(1, 20)) 857 let winid = popup_create(['the word', 'some more', 'several words here', 'invisible', '5', '6', '7'], #{ 858 \ drag: 1, 859 \ border: [], 860 \ line: 3, 861 \ col: 10, 862 \ maxheight: 3, 863 \ }) 864 func Select1() 865 call feedkeys("\<F3>\<LeftMouse>\<F4>\<LeftDrag>\<LeftRelease>", "xt") 866 endfunc 867 map <silent> <F3> :call test_setmouse(4, 15)<CR> 868 map <silent> <F4> :call test_setmouse(6, 23)<CR> 869 END 870 call writefile(lines, 'XtestPopupSelect') 871 let buf = RunVimInTerminal('-S XtestPopupSelect', #{rows: 10}) 872 call term_sendkeys(buf, ":call Select1()\<CR>") 873 call VerifyScreenDump(buf, 'Test_popupwin_select_01', {}) 874 875 call term_sendkeys(buf, ":call popup_close(winid)\<CR>") 876 call term_sendkeys(buf, "\"*p") 877 " clean the command line, sometimes it still shows a command 878 call term_sendkeys(buf, ":\<esc>") 879 880 call VerifyScreenDump(buf, 'Test_popupwin_select_02', {}) 881 882 " clean up 883 call StopVimInTerminal(buf) 884 call delete('XtestPopupSelect') 885endfunc 886 887func Test_popup_in_tab() 888 " default popup is local to tab, not visible when in other tab 889 let winid = popup_create("text", {}) 890 let bufnr = winbufnr(winid) 891 call assert_equal(1, popup_getpos(winid).visible) 892 call assert_equal(0, popup_getoptions(winid).tabpage) 893 tabnew 894 call assert_equal(0, popup_getpos(winid).visible) 895 call assert_equal(1, popup_getoptions(winid).tabpage) 896 quit 897 call assert_equal(1, popup_getpos(winid).visible) 898 899 call assert_equal(1, bufexists(bufnr)) 900 call popup_clear() 901 " buffer is gone now 902 call assert_equal(0, bufexists(bufnr)) 903 904 " global popup is visible in any tab 905 let winid = popup_create("text", #{tabpage: -1}) 906 call assert_equal(1, popup_getpos(winid).visible) 907 call assert_equal(-1, popup_getoptions(winid).tabpage) 908 tabnew 909 call assert_equal(1, popup_getpos(winid).visible) 910 call assert_equal(-1, popup_getoptions(winid).tabpage) 911 quit 912 call assert_equal(1, popup_getpos(winid).visible) 913 call popup_clear() 914 915 " create popup in other tab 916 tabnew 917 let winid = popup_create("text", #{tabpage: 1}) 918 call assert_equal(0, popup_getpos(winid).visible) 919 call assert_equal(1, popup_getoptions(winid).tabpage) 920 quit 921 call assert_equal(1, popup_getpos(winid).visible) 922 call assert_equal(0, popup_getoptions(winid).tabpage) 923 call popup_clear() 924endfunc 925 926func Test_popup_valid_arguments() 927 call assert_equal(0, len(popup_list())) 928 929 " Zero value is like the property wasn't there 930 let winid = popup_create("text", #{col: 0}) 931 let pos = popup_getpos(winid) 932 call assert_inrange(&columns / 2 - 1, &columns / 2 + 1, pos.col) 933 call assert_equal([winid], popup_list()) 934 call popup_clear() 935 936 " using cursor column has minimum value of 1 937 let winid = popup_create("text", #{col: 'cursor-100'}) 938 let pos = popup_getpos(winid) 939 call assert_equal(1, pos.col) 940 call popup_clear() 941 942 " center 943 let winid = popup_create("text", #{pos: 'center'}) 944 let pos = popup_getpos(winid) 945 let around = (&columns - pos.width) / 2 946 call assert_inrange(around - 1, around + 1, pos.col) 947 let around = (&lines - pos.height) / 2 948 call assert_inrange(around - 1, around + 1, pos.line) 949 call popup_clear() 950endfunc 951 952func Test_popup_invalid_arguments() 953 call assert_fails('call popup_create(666, {})', 'E86:') 954 call popup_clear() 955 call assert_fails('call popup_create("text", "none")', 'E715:') 956 call popup_clear() 957 call assert_fails('call popup_create(test_null_string(), {})', 'E450:') 958 call assert_fails('call popup_create(test_null_list(), {})', 'E450:') 959 call popup_clear() 960 961 call assert_fails('call popup_create("text", #{col: "xxx"})', 'E475:') 962 call popup_clear() 963 call assert_fails('call popup_create("text", #{col: "cursor8"})', 'E15:') 964 call popup_clear() 965 call assert_fails('call popup_create("text", #{col: "cursor+x"})', 'E15:') 966 call popup_clear() 967 call assert_fails('call popup_create("text", #{col: "cursor+8x"})', 'E15:') 968 call popup_clear() 969 970 call assert_fails('call popup_create("text", #{line: "xxx"})', 'E475:') 971 call popup_clear() 972 call assert_fails('call popup_create("text", #{line: "cursor8"})', 'E15:') 973 call popup_clear() 974 call assert_fails('call popup_create("text", #{line: "cursor+x"})', 'E15:') 975 call popup_clear() 976 call assert_fails('call popup_create("text", #{line: "cursor+8x"})', 'E15:') 977 call popup_clear() 978 979 call assert_fails('call popup_create("text", #{pos: "there"})', 'E475:') 980 call popup_clear() 981 call assert_fails('call popup_create("text", #{padding: "none"})', 'E714:') 982 call popup_clear() 983 call assert_fails('call popup_create("text", #{border: "none"})', 'E714:') 984 call popup_clear() 985 call assert_fails('call popup_create("text", #{borderhighlight: "none"})', 'E714:') 986 call popup_clear() 987 call assert_fails('call popup_create("text", #{borderhighlight: test_null_list()})', 'E714:') 988 call popup_clear() 989 call assert_fails('call popup_create("text", #{borderchars: "none"})', 'E714:') 990 call popup_clear() 991 992 call assert_fails('call popup_create([#{text: "text"}, 666], {})', 'E715:') 993 call popup_clear() 994 call assert_fails('call popup_create([#{text: "text", props: "none"}], {})', 'E714:') 995 call popup_clear() 996 call assert_fails('call popup_create([#{text: "text", props: ["none"]}], {})', 'E715:') 997 call popup_clear() 998 call assert_fails('call popup_create([#{text: "text", props: range(3)}], {})', 'E715:') 999 call popup_clear() 1000 call assert_fails('call popup_create("text", #{mask: ["asdf"]})', 'E475:') 1001 call popup_clear() 1002 call assert_fails('call popup_create("text", #{mask: range(5)})', 'E475:') 1003 call popup_clear() 1004 call popup_create("text", #{mask: [range(4)]}) 1005 call popup_clear() 1006 call assert_fails('call popup_create("text", #{mask: test_null_list()})', 'E475:') 1007 call assert_fails('call popup_create("text", #{mapping: []})', 'E745:') 1008 call popup_clear() 1009 call assert_fails('call popup_create("text", #{tabpage : 4})', 'E997:') 1010 call popup_clear() 1011endfunc 1012 1013func Test_win_execute_closing_curwin() 1014 split 1015 let winid = popup_create('some text', {}) 1016 call assert_fails('call win_execute(winid, winnr() .. "close")', 'E994:') 1017 call popup_clear() 1018 1019 let winid = popup_create('some text', {}) 1020 call assert_fails('call win_execute(winid, printf("normal! :\<C-u>call popup_close(%d)\<CR>", winid))', 'E994:') 1021 call popup_clear() 1022endfunc 1023 1024func Test_win_execute_not_allowed() 1025 let winid = popup_create('some text', {}) 1026 call assert_fails('call win_execute(winid, "split")', 'E994:') 1027 call assert_fails('call win_execute(winid, "vsplit")', 'E994:') 1028 call assert_fails('call win_execute(winid, "close")', 'E994:') 1029 call assert_fails('call win_execute(winid, "bdelete")', 'E994:') 1030 call assert_fails('call win_execute(winid, "bwipe!")', 'E994:') 1031 call assert_fails('call win_execute(winid, "tabnew")', 'E994:') 1032 call assert_fails('call win_execute(winid, "tabnext")', 'E994:') 1033 call assert_fails('call win_execute(winid, "next")', 'E994:') 1034 call assert_fails('call win_execute(winid, "rewind")', 'E994:') 1035 call assert_fails('call win_execute(winid, "pedit filename")', 'E994:') 1036 call assert_fails('call win_execute(winid, "buf")', 'E994:') 1037 call assert_fails('call win_execute(winid, "bnext")', 'E994:') 1038 call assert_fails('call win_execute(winid, "bprev")', 'E994:') 1039 call assert_fails('call win_execute(winid, "bfirst")', 'E994:') 1040 call assert_fails('call win_execute(winid, "blast")', 'E994:') 1041 call assert_fails('call win_execute(winid, "edit")', 'E994:') 1042 call assert_fails('call win_execute(winid, "enew")', 'E994:') 1043 call assert_fails('call win_execute(winid, "help")', 'E994:') 1044 call assert_fails('call win_execute(winid, "1only")', 'E994:') 1045 call assert_fails('call win_execute(winid, "wincmd x")', 'E994:') 1046 call assert_fails('call win_execute(winid, "wincmd w")', 'E994:') 1047 call assert_fails('call win_execute(winid, "wincmd t")', 'E994:') 1048 call assert_fails('call win_execute(winid, "wincmd b")', 'E994:') 1049 call popup_clear() 1050endfunc 1051 1052func Test_popup_with_wrap() 1053 CheckScreendump 1054 1055 let lines =<< trim END 1056 call setline(1, range(1, 100)) 1057 let winid = popup_create( 1058 \ 'a long line that wont fit', 1059 \ #{line: 3, col: 20, maxwidth: 10, wrap: 1}) 1060 END 1061 call writefile(lines, 'XtestPopup') 1062 let buf = RunVimInTerminal('-S XtestPopup', #{rows: 10}) 1063 call VerifyScreenDump(buf, 'Test_popupwin_wrap', {}) 1064 1065 " clean up 1066 call StopVimInTerminal(buf) 1067 call delete('XtestPopup') 1068endfunc 1069 1070func Test_popup_without_wrap() 1071 CheckScreendump 1072 1073 let lines =<< trim END 1074 call setline(1, range(1, 100)) 1075 let winid = popup_create( 1076 \ 'a long line that wont fit', 1077 \ #{line: 3, col: 20, maxwidth: 10, wrap: 0}) 1078 END 1079 call writefile(lines, 'XtestPopup') 1080 let buf = RunVimInTerminal('-S XtestPopup', #{rows: 10}) 1081 call VerifyScreenDump(buf, 'Test_popupwin_nowrap', {}) 1082 1083 " clean up 1084 call StopVimInTerminal(buf) 1085 call delete('XtestPopup') 1086endfunc 1087 1088func Test_popup_with_showbreak() 1089 CheckScreendump 1090 1091 let lines =<< trim END 1092 set showbreak=>>\ 1093 call setline(1, range(1, 20)) 1094 let winid = popup_dialog( 1095 \ 'a long line here that wraps', 1096 \ #{filter: 'popup_filter_yesno', 1097 \ maxwidth: 12}) 1098 END 1099 call writefile(lines, 'XtestPopupShowbreak') 1100 let buf = RunVimInTerminal('-S XtestPopupShowbreak', #{rows: 10}) 1101 call VerifyScreenDump(buf, 'Test_popupwin_showbreak', {}) 1102 1103 " clean up 1104 call term_sendkeys(buf, "y") 1105 call StopVimInTerminal(buf) 1106 call delete('XtestPopupShowbreak') 1107endfunc 1108 1109func Test_popup_time() 1110 CheckFeature timers 1111 1112 topleft vnew 1113 call setline(1, 'hello') 1114 1115 let winid = popup_create('world', #{ 1116 \ line: 1, 1117 \ col: 1, 1118 \ minwidth: 20, 1119 \ time: 500, 1120 \}) 1121 redraw 1122 let line = join(map(range(1, 5), 'screenstring(1, v:val)'), '') 1123 call assert_equal('world', line) 1124 1125 call assert_equal(winid, popup_locate(1, 1)) 1126 call assert_equal(winid, popup_locate(1, 20)) 1127 call assert_equal(0, popup_locate(1, 21)) 1128 call assert_equal(0, popup_locate(2, 1)) 1129 1130 sleep 700m 1131 redraw 1132 let line = join(map(range(1, 5), '1->screenstring(v:val)'), '') 1133 call assert_equal('hello', line) 1134 1135 call popup_create('on the command line', #{ 1136 \ line: &lines, 1137 \ col: 10, 1138 \ minwidth: 20, 1139 \ time: 500, 1140 \}) 1141 redraw 1142 let line = join(map(range(1, 30), 'screenstring(&lines, v:val)'), '') 1143 call assert_match('.*on the command line.*', line) 1144 1145 sleep 700m 1146 redraw 1147 let line = join(map(range(1, 30), 'screenstring(&lines, v:val)'), '') 1148 call assert_notmatch('.*on the command line.*', line) 1149 1150 bwipe! 1151endfunc 1152 1153func Test_popup_hide() 1154 topleft vnew 1155 call setline(1, 'hello') 1156 1157 let winid = popup_create('world', #{ 1158 \ line: 1, 1159 \ col: 1, 1160 \ minwidth: 20, 1161 \}) 1162 redraw 1163 let line = join(map(range(1, 5), 'screenstring(1, v:val)'), '') 1164 call assert_equal('world', line) 1165 call assert_equal(1, popup_getpos(winid).visible) 1166 " buffer is still listed and active 1167 call assert_match(winbufnr(winid) .. 'u a.*\[Popup\]', execute('ls u')) 1168 1169 call popup_hide(winid) 1170 redraw 1171 let line = join(map(range(1, 5), 'screenstring(1, v:val)'), '') 1172 call assert_equal('hello', line) 1173 call assert_equal(0, popup_getpos(winid).visible) 1174 " buffer is still listed but hidden 1175 call assert_match(winbufnr(winid) .. 'u a.*\[Popup\]', execute('ls u')) 1176 1177 eval winid->popup_show() 1178 redraw 1179 let line = join(map(range(1, 5), 'screenstring(1, v:val)'), '') 1180 call assert_equal('world', line) 1181 call assert_equal(1, popup_getpos(winid).visible) 1182 1183 1184 call popup_close(winid) 1185 redraw 1186 let line = join(map(range(1, 5), 'screenstring(1, v:val)'), '') 1187 call assert_equal('hello', line) 1188 1189 " error is given for existing non-popup window 1190 call assert_fails('call popup_hide(win_getid())', 'E993:') 1191 1192 " no error non-existing window 1193 eval 1234234->popup_hide() 1194 call popup_show(41234234) 1195 1196 bwipe! 1197endfunc 1198 1199func Test_popup_move() 1200 topleft vnew 1201 call setline(1, 'hello') 1202 1203 let winid = popup_create('world', #{ 1204 \ line: 1, 1205 \ col: 1, 1206 \ minwidth: 20, 1207 \}) 1208 redraw 1209 let line = join(map(range(1, 6), 'screenstring(1, v:val)'), '') 1210 call assert_equal('world ', line) 1211 1212 call popup_move(winid, #{line: 2, col: 2}) 1213 redraw 1214 let line = join(map(range(1, 6), 'screenstring(1, v:val)'), '') 1215 call assert_equal('hello ', line) 1216 let line = join(map(range(1, 6), 'screenstring(2, v:val)'), '') 1217 call assert_equal('~world', line) 1218 1219 eval winid->popup_move(#{line: 1}) 1220 redraw 1221 let line = join(map(range(1, 6), 'screenstring(1, v:val)'), '') 1222 call assert_equal('hworld', line) 1223 1224 call assert_fails('call popup_move(winid, [])', 'E715:') 1225 call assert_fails('call popup_move(winid, test_null_dict())', 'E715:') 1226 1227 call popup_close(winid) 1228 1229 call assert_equal(0, popup_move(-1, {})) 1230 1231 bwipe! 1232endfunc 1233 1234func Test_popup_getpos() 1235 let winid = popup_create('hello', #{ 1236 \ line: 2, 1237 \ col: 3, 1238 \ minwidth: 10, 1239 \ minheight: 11, 1240 \}) 1241 redraw 1242 let res = popup_getpos(winid) 1243 call assert_equal(2, res.line) 1244 call assert_equal(3, res.col) 1245 call assert_equal(10, res.width) 1246 call assert_equal(11, res.height) 1247 call assert_equal(1, res.visible) 1248 1249 call popup_close(winid) 1250endfunc 1251 1252func Test_popup_width_longest() 1253 let tests = [ 1254 \ [['hello', 'this', 'window', 'displays', 'all of its text'], 15], 1255 \ [['hello', 'this', 'window', 'all of its text', 'displays'], 15], 1256 \ [['hello', 'this', 'all of its text', 'window', 'displays'], 15], 1257 \ [['hello', 'all of its text', 'this', 'window', 'displays'], 15], 1258 \ [['all of its text', 'hello', 'this', 'window', 'displays'], 15], 1259 \ ] 1260 1261 for test in tests 1262 let winid = popup_create(test[0], #{line: 2, col: 3}) 1263 redraw 1264 let position = popup_getpos(winid) 1265 call assert_equal(test[1], position.width) 1266 call popup_close(winid) 1267 endfor 1268endfunc 1269 1270func Test_popup_wraps() 1271 let tests = [ 1272 \ ['nowrap', 6, 1], 1273 \ ['a line that wraps once', 12, 2], 1274 \ ['a line that wraps two times', 12, 3], 1275 \ ] 1276 for test in tests 1277 let winid = popup_create(test[0], 1278 \ #{line: 2, col: 3, maxwidth: 12}) 1279 redraw 1280 let position = popup_getpos(winid) 1281 call assert_equal(test[1], position.width) 1282 call assert_equal(test[2], position.height) 1283 1284 call popup_close(winid) 1285 call assert_equal({}, popup_getpos(winid)) 1286 endfor 1287endfunc 1288 1289func Test_popup_getoptions() 1290 let winid = popup_create('hello', #{ 1291 \ line: 2, 1292 \ col: 3, 1293 \ minwidth: 10, 1294 \ minheight: 11, 1295 \ maxwidth: 20, 1296 \ maxheight: 21, 1297 \ zindex: 100, 1298 \ time: 5000, 1299 \ fixed: 1 1300 \}) 1301 redraw 1302 let res = popup_getoptions(winid) 1303 call assert_equal(2, res.line) 1304 call assert_equal(3, res.col) 1305 call assert_equal(10, res.minwidth) 1306 call assert_equal(11, res.minheight) 1307 call assert_equal(20, res.maxwidth) 1308 call assert_equal(21, res.maxheight) 1309 call assert_equal(100, res.zindex) 1310 call assert_equal(1, res.fixed) 1311 call assert_equal(1, res.mapping) 1312 if has('timers') 1313 call assert_equal(5000, res.time) 1314 endif 1315 call popup_close(winid) 1316 1317 let winid = popup_create('hello', {}) 1318 redraw 1319 let res = popup_getoptions(winid) 1320 call assert_equal(0, res.line) 1321 call assert_equal(0, res.col) 1322 call assert_equal(0, res.minwidth) 1323 call assert_equal(0, res.minheight) 1324 call assert_equal(0, res.maxwidth) 1325 call assert_equal(0, res.maxheight) 1326 call assert_equal(50, res.zindex) 1327 call assert_equal(0, res.fixed) 1328 if has('timers') 1329 call assert_equal(0, res.time) 1330 endif 1331 call popup_close(winid) 1332 call assert_equal({}, popup_getoptions(winid)) 1333endfunc 1334 1335func Test_popup_option_values() 1336 new 1337 " window-local 1338 setlocal number 1339 setlocal nowrap 1340 " buffer-local 1341 setlocal omnifunc=Something 1342 " global/buffer-local 1343 setlocal path=/there 1344 " global/window-local 1345 setlocal statusline=2 1346 1347 let winid = popup_create('hello', {}) 1348 call assert_equal(0, getwinvar(winid, '&number')) 1349 call assert_equal(1, getwinvar(winid, '&wrap')) 1350 call assert_equal('', getwinvar(winid, '&omnifunc')) 1351 call assert_equal(&g:path, getwinvar(winid, '&path')) 1352 call assert_equal(&g:statusline, getwinvar(winid, '&statusline')) 1353 1354 " 'scrolloff' is reset to zero 1355 call assert_equal(5, &scrolloff) 1356 call assert_equal(0, getwinvar(winid, '&scrolloff')) 1357 1358 call popup_close(winid) 1359 bwipe 1360endfunc 1361 1362func Test_popup_atcursor() 1363 topleft vnew 1364 call setline(1, [ 1365 \ 'xxxxxxxxxxxxxxxxx', 1366 \ 'xxxxxxxxxxxxxxxxx', 1367 \ 'xxxxxxxxxxxxxxxxx', 1368 \]) 1369 1370 call cursor(2, 2) 1371 redraw 1372 let winid = popup_atcursor('vim', {}) 1373 redraw 1374 let line = join(map(range(1, 17), 'screenstring(1, v:val)'), '') 1375 call assert_equal('xvimxxxxxxxxxxxxx', line) 1376 call popup_close(winid) 1377 1378 call cursor(3, 4) 1379 redraw 1380 let winid = 'vim'->popup_atcursor({}) 1381 redraw 1382 let line = join(map(range(1, 17), 'screenstring(2, v:val)'), '') 1383 call assert_equal('xxxvimxxxxxxxxxxx', line) 1384 call popup_close(winid) 1385 1386 call cursor(1, 1) 1387 redraw 1388 let winid = popup_create('vim', #{ 1389 \ line: 'cursor+2', 1390 \ col: 'cursor+1', 1391 \}) 1392 redraw 1393 let line = join(map(range(1, 17), 'screenstring(3, v:val)'), '') 1394 call assert_equal('xvimxxxxxxxxxxxxx', line) 1395 call popup_close(winid) 1396 1397 call cursor(3, 3) 1398 redraw 1399 let winid = popup_create('vim', #{ 1400 \ line: 'cursor-2', 1401 \ col: 'cursor-1', 1402 \}) 1403 redraw 1404 let line = join(map(range(1, 17), 'screenstring(1, v:val)'), '') 1405 call assert_equal('xvimxxxxxxxxxxxxx', line) 1406 call popup_close(winid) 1407 1408 " just enough room above 1409 call cursor(3, 3) 1410 redraw 1411 let winid = popup_atcursor(['vim', 'is great'], {}) 1412 redraw 1413 let pos = popup_getpos(winid) 1414 call assert_equal(1, pos.line) 1415 call popup_close(winid) 1416 1417 " not enough room above, popup goes below the cursor 1418 call cursor(3, 3) 1419 redraw 1420 let winid = popup_atcursor(['vim', 'is', 'great'], {}) 1421 redraw 1422 let pos = popup_getpos(winid) 1423 call assert_equal(4, pos.line) 1424 call popup_close(winid) 1425 1426 " cursor in first line, popup in line 2 1427 call cursor(1, 1) 1428 redraw 1429 let winid = popup_atcursor(['vim', 'is', 'great'], {}) 1430 redraw 1431 let pos = popup_getpos(winid) 1432 call assert_equal(2, pos.line) 1433 call popup_close(winid) 1434 1435 bwipe! 1436endfunc 1437 1438func Test_popup_atcursor_pos() 1439 CheckScreendump 1440 CheckFeature conceal 1441 1442 let lines =<< trim END 1443 call setline(1, repeat([repeat('-', 60)], 15)) 1444 set so=0 1445 1446 normal 9G3|r# 1447 let winid1 = popup_atcursor(['first', 'second'], #{ 1448 \ moved: [0, 0, 0], 1449 \ }) 1450 normal 9G21|r& 1451 let winid1 = popup_atcursor(['FIrsT', 'SEcoND'], #{ 1452 \ pos: 'botright', 1453 \ moved: [0, 0, 0], 1454 \ }) 1455 normal 3G27|r% 1456 let winid1 = popup_atcursor(['fiRSt', 'seCOnd'], #{ 1457 \ pos: 'topleft', 1458 \ moved: [0, 0, 0], 1459 \ }) 1460 normal 3G45|r@ 1461 let winid1 = popup_atcursor(['First', 'SeconD'], #{ 1462 \ pos: 'topright', 1463 \ moved: range(3), 1464 \ mousemoved: range(3), 1465 \ }) 1466 1467 normal 9G27|Rconcealed X 1468 syn match Hidden /concealed/ conceal 1469 set conceallevel=2 concealcursor=n 1470 redraw 1471 normal 0fX 1472 call popup_atcursor('mark', {}) 1473 END 1474 call writefile(lines, 'XtestPopupAtcursorPos') 1475 let buf = RunVimInTerminal('-S XtestPopupAtcursorPos', #{rows: 12}) 1476 call VerifyScreenDump(buf, 'Test_popupwin_atcursor_pos', {}) 1477 1478 " clean up 1479 call StopVimInTerminal(buf) 1480 call delete('XtestPopupAtcursorPos') 1481endfunc 1482 1483func Test_popup_beval() 1484 CheckScreendump 1485 CheckFeature balloon_eval_term 1486 1487 let lines =<< trim END 1488 call setline(1, range(1, 20)) 1489 call setline(5, 'here is some text to hover over') 1490 set balloonevalterm 1491 set balloonexpr=BalloonExpr() 1492 set balloondelay=100 1493 func BalloonExpr() 1494 let s:winid = [v:beval_text]->popup_beval({}) 1495 return '' 1496 endfunc 1497 func Hover() 1498 call test_setmouse(5, 15) 1499 call feedkeys("\<MouseMove>\<Ignore>", "xt") 1500 sleep 100m 1501 endfunc 1502 func MoveOntoPopup() 1503 call test_setmouse(4, 17) 1504 call feedkeys("\<F4>\<MouseMove>\<Ignore>", "xt") 1505 endfunc 1506 func MoveAway() 1507 call test_setmouse(5, 13) 1508 call feedkeys("\<F5>\<MouseMove>\<Ignore>", "xt") 1509 endfunc 1510 END 1511 call writefile(lines, 'XtestPopupBeval') 1512 let buf = RunVimInTerminal('-S XtestPopupBeval', #{rows: 10}) 1513 call TermWait(buf, 50) 1514 call term_sendkeys(buf, 'j') 1515 call term_sendkeys(buf, ":call Hover()\<CR>") 1516 call VerifyScreenDump(buf, 'Test_popupwin_beval_1', {}) 1517 1518 call term_sendkeys(buf, ":call MoveOntoPopup()\<CR>") 1519 call VerifyScreenDump(buf, 'Test_popupwin_beval_2', {}) 1520 1521 call term_sendkeys(buf, ":call MoveAway()\<CR>") 1522 call VerifyScreenDump(buf, 'Test_popupwin_beval_3', {}) 1523 1524 " clean up 1525 call StopVimInTerminal(buf) 1526 call delete('XtestPopupBeval') 1527endfunc 1528 1529func Test_popup_filter() 1530 new 1531 call setline(1, 'some text') 1532 1533 func MyPopupFilter(winid, c) 1534 if a:c == 'e' || a:c == "\<F9>" 1535 let g:eaten = a:c 1536 return 1 1537 endif 1538 if a:c == '0' 1539 let g:ignored = '0' 1540 return 0 1541 endif 1542 if a:c == 'x' 1543 call popup_close(a:winid) 1544 return 1 1545 endif 1546 return 0 1547 endfunc 1548 1549 let winid = 'something'->popup_create(#{filter: 'MyPopupFilter'}) 1550 redraw 1551 1552 " e is consumed by the filter 1553 let g:eaten = '' 1554 call feedkeys('e', 'xt') 1555 call assert_equal('e', g:eaten) 1556 call feedkeys("\<F9>", 'xt') 1557 call assert_equal("\<F9>", g:eaten) 1558 1559 " 0 is ignored by the filter 1560 let g:ignored = '' 1561 normal $ 1562 call assert_equal(9, getcurpos()[2]) 1563 call feedkeys('0', 'xt') 1564 call assert_equal('0', g:ignored) 1565 1566 if has('win32') && has('gui_running') 1567 echo "FIXME: this check is very flaky on MS-Windows GUI, the cursor doesn't move" 1568 else 1569 call assert_equal(1, getcurpos()[2]) 1570 endif 1571 1572 " x closes the popup 1573 call feedkeys('x', 'xt') 1574 call assert_equal("\<F9>", g:eaten) 1575 call assert_equal(-1, winbufnr(winid)) 1576 1577 unlet g:eaten 1578 unlet g:ignored 1579 delfunc MyPopupFilter 1580 call popup_clear() 1581endfunc 1582 1583" this tests that the filter is not used for :normal command 1584func Test_popup_filter_normal_cmd() 1585 CheckScreendump 1586 1587 let lines =<< trim END 1588 let text = range(1, 20)->map({_, v -> string(v)}) 1589 let g:winid = popup_create(text, #{maxheight: 5, minwidth: 3, filter: 'invalidfilter'}) 1590 call timer_start(0, {-> win_execute(g:winid, 'norm! 10Gzz')}) 1591 END 1592 call writefile(lines, 'XtestPopupNormal') 1593 let buf = RunVimInTerminal('-S XtestPopupNormal', #{rows: 10}) 1594 call TermWait(buf, 100) 1595 call VerifyScreenDump(buf, 'Test_popupwin_normal_cmd', {}) 1596 1597 call StopVimInTerminal(buf) 1598 call delete('XtestPopupNormal') 1599endfunc 1600 1601" test that cursor line highlight is updated after using win_execute() 1602func Test_popup_filter_win_execute() 1603 CheckScreendump 1604 1605 let lines =<< trim END 1606 let lines = range(1, &lines * 2)->map({_, v -> string(v)}) 1607 let g:id = popup_create(lines, #{ 1608 \ minheight: &lines - 5, 1609 \ maxheight: &lines - 5, 1610 \ cursorline: 1, 1611 \ }) 1612 redraw 1613 END 1614 call writefile(lines, 'XtestPopupWinExecute') 1615 let buf = RunVimInTerminal('-S XtestPopupWinExecute', #{rows: 14}) 1616 1617 call term_sendkeys(buf, ":call win_execute(g:id, ['normal 17Gzz'])\<CR>") 1618 call term_sendkeys(buf, ":\<CR>") 1619 1620 call VerifyScreenDump(buf, 'Test_popupwin_win_execute_cursorline', {}) 1621 1622 call StopVimInTerminal(buf) 1623 call delete('XtestPopupWinExecute') 1624endfunc 1625 1626func Test_popup_set_firstline() 1627 CheckScreendump 1628 1629 let lines =<< trim END 1630 let lines = range(1, 50)->map({_, v -> string(v)}) 1631 let g:id = popup_create(lines, #{ 1632 \ minwidth: 20, 1633 \ maxwidth: 20, 1634 \ minheight: &lines - 5, 1635 \ maxheight: &lines - 5, 1636 \ cursorline: 1, 1637 \ }) 1638 call popup_setoptions(g:id, #{firstline: 10}) 1639 redraw 1640 END 1641 call writefile(lines, 'XtestPopupWinSetFirstline') 1642 let buf = RunVimInTerminal('-S XtestPopupWinSetFirstline', #{rows: 16}) 1643 1644 call VerifyScreenDump(buf, 'Test_popupwin_set_firstline_1', {}) 1645 1646 call term_sendkeys(buf, ":call popup_setoptions(g:id, #{firstline: 5})\<CR>") 1647 call term_sendkeys(buf, ":\<CR>") 1648 call VerifyScreenDump(buf, 'Test_popupwin_set_firstline_2', {}) 1649 1650 call StopVimInTerminal(buf) 1651 call delete('XtestPopupWinSetFirstline') 1652endfunc 1653 1654" this tests that we don't get stuck with an error in "win_execute()" 1655func Test_popup_filter_win_execute_error() 1656 CheckScreendump 1657 1658 let lines =<< trim END 1659 let g:winid = popup_create('some text', {'filter': 'invalidfilter'}) 1660 call timer_start(0, {-> win_execute(g:winid, 'invalidCommand')}) 1661 END 1662 call writefile(lines, 'XtestPopupWinExecuteError') 1663 let buf = RunVimInTerminal('-S XtestPopupWinExecuteError', #{rows: 10, wait_for_ruler: 0}) 1664 1665 call WaitFor({-> term_getline(buf, 9) =~ 'Not an editor command: invalidCommand'}) 1666 call term_sendkeys(buf, "\<CR>") 1667 call WaitFor({-> term_getline(buf, 9) =~ 'Unknown function: invalidfilter'}) 1668 call term_sendkeys(buf, "\<CR>") 1669 call WaitFor({-> term_getline(buf, 9) =~ 'Not allowed in a popup window'}) 1670 call term_sendkeys(buf, "\<CR>") 1671 call term_sendkeys(buf, "\<CR>") 1672 call VerifyScreenDump(buf, 'Test_popupwin_win_execute', {}) 1673 1674 call StopVimInTerminal(buf) 1675 call delete('XtestPopupWinExecuteError') 1676endfunc 1677 1678func ShowDialog(key, result) 1679 let s:cb_res = 999 1680 let winid = popup_dialog('do you want to quit (Yes/no)?', #{ 1681 \ filter: 'popup_filter_yesno', 1682 \ callback: 'QuitCallback', 1683 \ }) 1684 redraw 1685 call feedkeys(a:key, "xt") 1686 call assert_equal(winid, s:cb_winid) 1687 call assert_equal(a:result, s:cb_res) 1688endfunc 1689 1690func Test_popup_dialog() 1691 func QuitCallback(id, res) 1692 let s:cb_winid = a:id 1693 let s:cb_res = a:res 1694 endfunc 1695 1696 let winid = ShowDialog("y", 1) 1697 let winid = ShowDialog("Y", 1) 1698 let winid = ShowDialog("n", 0) 1699 let winid = ShowDialog("N", 0) 1700 let winid = ShowDialog("x", 0) 1701 let winid = ShowDialog("X", 0) 1702 let winid = ShowDialog("\<Esc>", 0) 1703 let winid = ShowDialog("\<C-C>", -1) 1704 1705 delfunc QuitCallback 1706endfunc 1707 1708func ShowMenu(key, result) 1709 let s:cb_res = 999 1710 let winid = popup_menu(['one', 'two', 'something else'], #{ 1711 \ callback: 'QuitCallback', 1712 \ }) 1713 redraw 1714 call feedkeys(a:key, "xt") 1715 call assert_equal(winid, s:cb_winid) 1716 call assert_equal(a:result, s:cb_res) 1717endfunc 1718 1719func Test_popup_menu() 1720 func QuitCallback(id, res) 1721 let s:cb_winid = a:id 1722 let s:cb_res = a:res 1723 endfunc 1724 " mapping won't be used in popup 1725 map j k 1726 1727 let winid = ShowMenu(" ", 1) 1728 let winid = ShowMenu("j \<CR>", 2) 1729 let winid = ShowMenu("JjK \<CR>", 2) 1730 let winid = ShowMenu("jjjjjj ", 3) 1731 let winid = ShowMenu("kkk ", 1) 1732 let winid = ShowMenu("x", -1) 1733 let winid = ShowMenu("X", -1) 1734 let winid = ShowMenu("\<Esc>", -1) 1735 let winid = ShowMenu("\<C-C>", -1) 1736 1737 delfunc QuitCallback 1738 unmap j 1739endfunc 1740 1741func Test_popup_menu_screenshot() 1742 CheckScreendump 1743 1744 let lines =<< trim END 1745 call setline(1, range(1, 20)) 1746 hi PopupSelected ctermbg=lightblue 1747 call popup_menu(['one', 'two', 'another'], #{callback: 'MenuDone', title: ' make a choice from the list '}) 1748 func MenuDone(id, res) 1749 echomsg "selected " .. a:res 1750 endfunc 1751 END 1752 call writefile(lines, 'XtestPopupMenu') 1753 let buf = RunVimInTerminal('-S XtestPopupMenu', #{rows: 10}) 1754 call VerifyScreenDump(buf, 'Test_popupwin_menu_01', {}) 1755 1756 call term_sendkeys(buf, "jj") 1757 call VerifyScreenDump(buf, 'Test_popupwin_menu_02', {}) 1758 1759 call term_sendkeys(buf, " ") 1760 call VerifyScreenDump(buf, 'Test_popupwin_menu_03', {}) 1761 1762 " clean up 1763 call StopVimInTerminal(buf) 1764 call delete('XtestPopupMenu') 1765endfunc 1766 1767func Test_popup_menu_narrow() 1768 CheckScreendump 1769 1770 let lines =<< trim END 1771 call setline(1, range(1, 20)) 1772 hi PopupSelected ctermbg=green 1773 call popup_menu(['one', 'two', 'three'], #{callback: 'MenuDone'}) 1774 func MenuDone(id, res) 1775 echomsg "selected " .. a:res 1776 endfunc 1777 END 1778 call writefile(lines, 'XtestPopupNarrowMenu') 1779 let buf = RunVimInTerminal('-S XtestPopupNarrowMenu', #{rows: 10}) 1780 call VerifyScreenDump(buf, 'Test_popupwin_menu_04', {}) 1781 1782 " clean up 1783 call term_sendkeys(buf, "x") 1784 call StopVimInTerminal(buf) 1785 call delete('XtestPopupNarrowMenu') 1786endfunc 1787 1788func Test_popup_title() 1789 CheckScreendump 1790 1791 " Create a popup without title or border, a line of padding will be added to 1792 " put the title on. 1793 let lines =<< trim END 1794 call setline(1, range(1, 20)) 1795 let winid = popup_create(['one', 'two', 'another'], #{title: 'Title String'}) 1796 END 1797 call writefile(lines, 'XtestPopupTitle') 1798 let buf = RunVimInTerminal('-S XtestPopupTitle', #{rows: 10}) 1799 call VerifyScreenDump(buf, 'Test_popupwin_title', {}) 1800 1801 call term_sendkeys(buf, ":call popup_setoptions(winid, #{maxwidth: 20, title: 'a very long title that is not going to fit'})\<CR>") 1802 call term_sendkeys(buf, ":\<CR>") 1803 call VerifyScreenDump(buf, 'Test_popupwin_longtitle_1', {}) 1804 1805 call term_sendkeys(buf, ":call popup_setoptions(winid, #{border: []})\<CR>") 1806 call term_sendkeys(buf, ":\<CR>") 1807 call VerifyScreenDump(buf, 'Test_popupwin_longtitle_2', {}) 1808 1809 call term_sendkeys(buf, ":call popup_clear()\<CR>") 1810 call term_sendkeys(buf, ":call popup_create(['aaa', 'bbb'], #{title: 'Title', minwidth: 12, padding: [2, 2, 2, 2]})\<CR>") 1811 call term_sendkeys(buf, ":\<CR>") 1812 call VerifyScreenDump(buf, 'Test_popupwin_longtitle_3', {}) 1813 1814 call term_sendkeys(buf, ":call popup_clear()\<CR>") 1815 call term_sendkeys(buf, ":call popup_create(['aaa', 'bbb'], #{title: 'Title', minwidth: 12, border: [], padding: [2, 2, 2, 2]})\<CR>") 1816 call term_sendkeys(buf, ":\<CR>") 1817 call VerifyScreenDump(buf, 'Test_popupwin_longtitle_4', {}) 1818 1819 call term_sendkeys(buf, ":call popup_clear()\<CR>") 1820 call term_sendkeys(buf, ":call popup_menu(['This is a line', 'and another line'], #{title: '▶Äあいうえお◀', })\<CR>") 1821 call VerifyScreenDump(buf, 'Test_popupwin_multibytetitle', {}) 1822 call term_sendkeys(buf, "x") 1823 1824 " clean up 1825 call StopVimInTerminal(buf) 1826 call delete('XtestPopupTitle') 1827 1828 let winid = popup_create('something', #{title: 'Some Title'}) 1829 call assert_equal('Some Title', popup_getoptions(winid).title) 1830 call popup_setoptions(winid, #{title: 'Another Title'}) 1831 call assert_equal('Another Title', popup_getoptions(winid).title) 1832 1833 call popup_clear() 1834endfunc 1835 1836func Test_popup_close_callback() 1837 func PopupDone(id, result) 1838 let g:result = a:result 1839 endfunc 1840 let winid = popup_create('something', #{callback: 'PopupDone'}) 1841 redraw 1842 call popup_close(winid, 'done') 1843 call assert_equal('done', g:result) 1844endfunc 1845 1846func Test_popup_empty() 1847 let winid = popup_create('', #{padding: [2,2,2,2]}) 1848 redraw 1849 let pos = popup_getpos(winid) 1850 call assert_equal(5, pos.width) 1851 call assert_equal(5, pos.height) 1852 call popup_close(winid) 1853 1854 let winid = popup_create([], #{border: []}) 1855 redraw 1856 let pos = popup_getpos(winid) 1857 call assert_equal(3, pos.width) 1858 call assert_equal(3, pos.height) 1859 call popup_close(winid) 1860endfunc 1861 1862func Test_popup_never_behind() 1863 CheckScreendump 1864 1865 " +-----------------------------+ 1866 " | | | 1867 " | | | 1868 " | | | 1869 " | line1 | 1870 " |------------line2------------| 1871 " | line3 | 1872 " | line4 | 1873 " | | 1874 " | | 1875 " +-----------------------------+ 1876 let lines =<< trim END 1877 split 1878 vsplit 1879 let info_window1 = getwininfo()[0] 1880 let line = info_window1['height'] 1881 let col = info_window1['width'] 1882 call popup_create(['line1', 'line2', 'line3', 'line4'], #{ 1883 \ line : line, 1884 \ col : col, 1885 \ }) 1886 END 1887 call writefile(lines, 'XtestPopupBehind') 1888 let buf = RunVimInTerminal('-S XtestPopupBehind', #{rows: 10}) 1889 call term_sendkeys(buf, "\<C-W>w") 1890 call VerifyScreenDump(buf, 'Test_popupwin_behind', {}) 1891 1892 " clean up 1893 call StopVimInTerminal(buf) 1894 call delete('XtestPopupBehind') 1895endfunc 1896 1897func s:VerifyPosition(p, msg, line, col, width, height) 1898 call assert_equal(a:line, popup_getpos(a:p).line, a:msg . ' (l)') 1899 call assert_equal(a:col, popup_getpos(a:p).col, a:msg . ' (c)') 1900 call assert_equal(a:width, popup_getpos(a:p).width, a:msg . ' (w)') 1901 call assert_equal(a:height, popup_getpos(a:p).height, a:msg . ' (h)') 1902endfunc 1903 1904func Test_popup_position_adjust() 1905 " Anything placed past the last cell on the right of the screen is moved to 1906 " the left. 1907 " 1908 " When wrapping is disabled, we also shift to the left to display on the 1909 " screen, unless fixed is set. 1910 1911 " Entries for cases which don't vary based on wrapping. 1912 " Format is per tests described below 1913 let both_wrap_tests = [ 1914 \ ['a', 5, &columns, 5, &columns, 1, 1], 1915 \ ['b', 5, &columns + 1, 5, &columns, 1, 1], 1916 \ ['c', 5, &columns - 1, 5, &columns - 1, 1, 1], 1917 \ ['d', 5, &columns - 2, 5, &columns - 2, 1, 1], 1918 \ ['e', 5, &columns - 3, 5, &columns - 3, 1, 1]] 1919 1920 " these test groups are dicts with: 1921 " - comment: something to identify the group of tests by 1922 " - options: dict of options to merge with the row/col in tests 1923 " - tests: list of cases. Each one is a list with elements: 1924 " - text 1925 " - row 1926 " - col 1927 " - expected row 1928 " - expected col 1929 " - expected width 1930 " - expected height 1931 let tests = [ 1932 \ #{ 1933 \ comment: 'left-aligned with wrapping', 1934 \ options: #{ 1935 \ wrap: 1, 1936 \ pos: 'botleft', 1937 \ }, 1938 \ tests: both_wrap_tests + [ 1939 \ ['aa', 5, &columns, 4, &columns, 1, 2], 1940 \ ['bb', 5, &columns + 1, 4, &columns, 1, 2], 1941 \ ['cc', 5, &columns - 1, 5, &columns - 1, 2, 1], 1942 \ ['dd', 5, &columns - 2, 5, &columns - 2, 2, 1], 1943 \ ['ee', 5, &columns - 3, 5, &columns - 3, 2, 1], 1944 \ 1945 \ ['aaa', 5, &columns, 3, &columns, 1, 3], 1946 \ ['bbb', 5, &columns + 1, 3, &columns, 1, 3], 1947 \ ['ccc', 5, &columns - 1, 4, &columns - 1, 2, 2], 1948 \ ['ddd', 5, &columns - 2, 5, &columns - 2, 3, 1], 1949 \ ['eee', 5, &columns - 3, 5, &columns - 3, 3, 1], 1950 \ 1951 \ ['aaaa', 5, &columns, 2, &columns, 1, 4], 1952 \ ['bbbb', 5, &columns + 1, 2, &columns, 1, 4], 1953 \ ['cccc', 5, &columns - 1, 4, &columns - 1, 2, 2], 1954 \ ['dddd', 5, &columns - 2, 4, &columns - 2, 3, 2], 1955 \ ['eeee', 5, &columns - 3, 5, &columns - 3, 4, 1], 1956 \ ['eeee', 5, &columns - 4, 5, &columns - 4, 4, 1], 1957 \ ], 1958 \ }, 1959 \ #{ 1960 \ comment: 'left aligned without wrapping', 1961 \ options: #{ 1962 \ wrap: 0, 1963 \ pos: 'botleft', 1964 \ }, 1965 \ tests: both_wrap_tests + [ 1966 \ ['aa', 5, &columns, 5, &columns - 1, 2, 1], 1967 \ ['bb', 5, &columns + 1, 5, &columns - 1, 2, 1], 1968 \ ['cc', 5, &columns - 1, 5, &columns - 1, 2, 1], 1969 \ ['dd', 5, &columns - 2, 5, &columns - 2, 2, 1], 1970 \ ['ee', 5, &columns - 3, 5, &columns - 3, 2, 1], 1971 \ 1972 \ ['aaa', 5, &columns, 5, &columns - 2, 3, 1], 1973 \ ['bbb', 5, &columns + 1, 5, &columns - 2, 3, 1], 1974 \ ['ccc', 5, &columns - 1, 5, &columns - 2, 3, 1], 1975 \ ['ddd', 5, &columns - 2, 5, &columns - 2, 3, 1], 1976 \ ['eee', 5, &columns - 3, 5, &columns - 3, 3, 1], 1977 \ 1978 \ ['aaaa', 5, &columns, 5, &columns - 3, 4, 1], 1979 \ ['bbbb', 5, &columns + 1, 5, &columns - 3, 4, 1], 1980 \ ['cccc', 5, &columns - 1, 5, &columns - 3, 4, 1], 1981 \ ['dddd', 5, &columns - 2, 5, &columns - 3, 4, 1], 1982 \ ['eeee', 5, &columns - 3, 5, &columns - 3, 4, 1], 1983 \ ], 1984 \ }, 1985 \ #{ 1986 \ comment: 'left aligned with fixed position', 1987 \ options: #{ 1988 \ wrap: 0, 1989 \ fixed: 1, 1990 \ pos: 'botleft', 1991 \ }, 1992 \ tests: both_wrap_tests + [ 1993 \ ['aa', 5, &columns, 5, &columns, 1, 1], 1994 \ ['bb', 5, &columns + 1, 5, &columns, 1, 1], 1995 \ ['cc', 5, &columns - 1, 5, &columns - 1, 2, 1], 1996 \ ['dd', 5, &columns - 2, 5, &columns - 2, 2, 1], 1997 \ ['ee', 5, &columns - 3, 5, &columns - 3, 2, 1], 1998 \ 1999 \ ['aaa', 5, &columns, 5, &columns, 1, 1], 2000 \ ['bbb', 5, &columns + 1, 5, &columns, 1, 1], 2001 \ ['ccc', 5, &columns - 1, 5, &columns - 1, 2, 1], 2002 \ ['ddd', 5, &columns - 2, 5, &columns - 2, 3, 1], 2003 \ ['eee', 5, &columns - 3, 5, &columns - 3, 3, 1], 2004 \ 2005 \ ['aaaa', 5, &columns, 5, &columns, 1, 1], 2006 \ ['bbbb', 5, &columns + 1, 5, &columns, 1, 1], 2007 \ ['cccc', 5, &columns - 1, 5, &columns - 1, 2, 1], 2008 \ ['dddd', 5, &columns - 2, 5, &columns - 2, 3, 1], 2009 \ ['eeee', 5, &columns - 3, 5, &columns - 3, 4, 1], 2010 \ ], 2011 \ }, 2012 \ ] 2013 2014 for test_group in tests 2015 for test in test_group.tests 2016 let [ text, line, col, e_line, e_col, e_width, e_height ] = test 2017 let options = #{ 2018 \ line: line, 2019 \ col: col, 2020 \ } 2021 call extend(options, test_group.options) 2022 2023 let p = popup_create(text, options) 2024 2025 let msg = string(extend(options, #{text: text})) 2026 call s:VerifyPosition(p, msg, e_line, e_col, e_width, e_height) 2027 call popup_close(p) 2028 endfor 2029 endfor 2030 2031 call popup_clear() 2032 %bwipe! 2033endfunc 2034 2035func Test_adjust_left_past_screen_width() 2036 " width of screen 2037 let X = join(map(range(&columns), {->'X'}), '') 2038 2039 let p = popup_create(X, #{line: 1, col: 1, wrap: 0}) 2040 call s:VerifyPosition(p, 'full width topleft', 1, 1, &columns, 1) 2041 2042 redraw 2043 let line = join(map(range(1, &columns + 1), 'screenstring(1, v:val)'), '') 2044 call assert_equal(X, line) 2045 2046 call popup_close(p) 2047 redraw 2048 2049 " Same if placed on the right hand side 2050 let p = popup_create(X, #{line: 1, col: &columns, wrap: 0}) 2051 call s:VerifyPosition(p, 'full width topright', 1, 1, &columns, 1) 2052 2053 redraw 2054 let line = join(map(range(1, &columns + 1), 'screenstring(1, v:val)'), '') 2055 call assert_equal(X, line) 2056 2057 call popup_close(p) 2058 redraw 2059 2060 " Extend so > window width 2061 let X .= 'x' 2062 2063 let p = popup_create(X, #{line: 1, col: 1, wrap: 0}) 2064 call s:VerifyPosition(p, 'full width + 1 topleft', 1, 1, &columns, 1) 2065 2066 redraw 2067 let line = join(map(range(1, &columns + 1), 'screenstring(1, v:val)'), '') 2068 call assert_equal(X[ : -2 ], line) 2069 2070 call popup_close(p) 2071 redraw 2072 2073 " Shifted then truncated (the x is not visible) 2074 let p = popup_create(X, #{line: 1, col: &columns - 3, wrap: 0}) 2075 call s:VerifyPosition(p, 'full width + 1 topright', 1, 1, &columns, 1) 2076 2077 redraw 2078 let line = join(map(range(1, &columns + 1), 'screenstring(1, v:val)'), '') 2079 call assert_equal(X[ : -2 ], line) 2080 2081 call popup_close(p) 2082 redraw 2083 2084 " Not shifted, just truncated 2085 let p = popup_create(X, 2086 \ #{line: 1, col: 2, wrap: 0, fixed: 1}) 2087 call s:VerifyPosition(p, 'full width + 1 fixed', 1, 2, &columns - 1, 1) 2088 2089 redraw 2090 let line = join(map(range(1, &columns + 1), 'screenstring(1, v:val)'), '') 2091 let e_line = ' ' . X[ 1 : -2 ] 2092 call assert_equal(e_line, line) 2093 2094 call popup_close(p) 2095 redraw 2096 2097 call popup_clear() 2098 %bwipe! 2099endfunc 2100 2101func Test_popup_moved() 2102 new 2103 call test_override('char_avail', 1) 2104 call setline(1, ['one word to move around', 'a WORD.and->some thing']) 2105 2106 exe "normal gg0/word\<CR>" 2107 let winid = popup_atcursor('text', #{moved: 'any'}) 2108 redraw 2109 call assert_equal(1, popup_getpos(winid).visible) 2110 call assert_equal([1, 4, 4], popup_getoptions(winid).moved) 2111 " trigger the check for last_cursormoved by going into insert mode 2112 call feedkeys("li\<Esc>", 'xt') 2113 call assert_equal({}, popup_getpos(winid)) 2114 call popup_clear() 2115 2116 exe "normal gg0/word\<CR>" 2117 let winid = popup_atcursor('text', #{moved: 'word'}) 2118 redraw 2119 call assert_equal(1, popup_getpos(winid).visible) 2120 call assert_equal([1, 4, 7], popup_getoptions(winid).moved) 2121 call feedkeys("hi\<Esc>", 'xt') 2122 call assert_equal({}, popup_getpos(winid)) 2123 call popup_clear() 2124 2125 exe "normal gg0/word\<CR>" 2126 let winid = popup_atcursor('text', #{moved: 'word'}) 2127 redraw 2128 call assert_equal(1, popup_getpos(winid).visible) 2129 call assert_equal([1, 4, 7], popup_getoptions(winid).moved) 2130 call feedkeys("li\<Esc>", 'xt') 2131 call assert_equal(1, popup_getpos(winid).visible) 2132 call feedkeys("ei\<Esc>", 'xt') 2133 call assert_equal(1, popup_getpos(winid).visible) 2134 call feedkeys("eli\<Esc>", 'xt') 2135 call assert_equal({}, popup_getpos(winid)) 2136 call popup_clear() 2137 2138 " WORD is the default 2139 exe "normal gg0/WORD\<CR>" 2140 let winid = popup_atcursor('text', {}) 2141 redraw 2142 call assert_equal(1, popup_getpos(winid).visible) 2143 call assert_equal([2, 2, 15], popup_getoptions(winid).moved) 2144 call feedkeys("eli\<Esc>", 'xt') 2145 call assert_equal(1, popup_getpos(winid).visible) 2146 call feedkeys("wi\<Esc>", 'xt') 2147 call assert_equal(1, popup_getpos(winid).visible) 2148 call feedkeys("Eli\<Esc>", 'xt') 2149 call assert_equal({}, popup_getpos(winid)) 2150 call popup_clear() 2151 2152 exe "normal gg0/word\<CR>" 2153 let winid = popup_atcursor('text', #{moved: [5, 10]}) 2154 redraw 2155 call assert_equal(1, popup_getpos(winid).visible) 2156 call feedkeys("eli\<Esc>", 'xt') 2157 call feedkeys("ei\<Esc>", 'xt') 2158 call assert_equal(1, popup_getpos(winid).visible) 2159 call feedkeys("eli\<Esc>", 'xt') 2160 call assert_equal({}, popup_getpos(winid)) 2161 call popup_clear() 2162 2163 bwipe! 2164 call test_override('ALL', 0) 2165endfunc 2166 2167func Test_notifications() 2168 CheckFeature timers 2169 CheckScreendump 2170 2171 let lines =<< trim END 2172 call setline(1, range(1, 20)) 2173 hi Notification ctermbg=lightblue 2174 call popup_notification('first notification', {}) 2175 END 2176 call writefile(lines, 'XtestNotifications') 2177 let buf = RunVimInTerminal('-S XtestNotifications', #{rows: 10}) 2178 call VerifyScreenDump(buf, 'Test_popupwin_notify_01', {}) 2179 2180 " second one goes below the first one 2181 call term_sendkeys(buf, ":hi link PopupNotification Notification\<CR>") 2182 call term_sendkeys(buf, ":call popup_notification('another important notification', {})\<CR>") 2183 call VerifyScreenDump(buf, 'Test_popupwin_notify_02', {}) 2184 2185 " clean up 2186 call StopVimInTerminal(buf) 2187 call delete('XtestNotifications') 2188endfunc 2189 2190func Test_popup_scrollbar() 2191 CheckScreendump 2192 2193 let lines =<< trim END 2194 call setline(1, range(1, 20)) 2195 hi ScrollThumb ctermbg=blue 2196 hi ScrollBar ctermbg=red 2197 let winid = popup_create(['one', 'two', 'three', 'four', 'five', 2198 \ 'six', 'seven', 'eight', 'nine'], #{ 2199 \ minwidth: 8, 2200 \ maxheight: 4, 2201 \ }) 2202 func ScrollUp() 2203 call feedkeys("\<F3>\<ScrollWheelUp>", "xt") 2204 endfunc 2205 func ScrollDown() 2206 call feedkeys("\<F3>\<ScrollWheelDown>", "xt") 2207 endfunc 2208 func ClickTop() 2209 call feedkeys("\<F4>\<LeftMouse>", "xt") 2210 endfunc 2211 func ClickBot() 2212 call popup_setoptions(g:winid, #{border: [], close: 'button'}) 2213 call feedkeys("\<F5>\<LeftMouse>", "xt") 2214 endfunc 2215 func Popup_filter(winid, key) 2216 if a:key == 'j' 2217 silent! this_throws_an_error_but_is_ignored 2218 let line = popup_getoptions(a:winid).firstline 2219 let nlines = line('$', a:winid) 2220 let newline = line < nlines ? (line + 1) : nlines 2221 call popup_setoptions(a:winid, #{firstline: newline}) 2222 return v:true 2223 elseif a:key == 'x' 2224 call popup_close(a:winid) 2225 return v:true 2226 endif 2227 endfunc 2228 2229 def CreatePopup(text: list<string>) 2230 popup_create(text, { 2231 \ minwidth: 30, 2232 \ maxwidth: 30, 2233 \ minheight: 4, 2234 \ maxheight: 4, 2235 \ firstline: 1, 2236 \ lastline: 4, 2237 \ wrap: true, 2238 \ scrollbar: true, 2239 \ mapping: false, 2240 \ filter: Popup_filter, 2241 \ }) 2242 enddef 2243 2244 func PopupScroll() 2245 call popup_clear() 2246 let text =<< trim END 2247 1 2248 2 2249 3 2250 4 2251 long line long line long line long line long line long line 2252 long line long line long line long line long line long line 2253 long line long line long line long line long line long line 2254 END 2255 call CreatePopup(text) 2256 endfunc 2257 map <silent> <F3> :call test_setmouse(5, 36)<CR> 2258 map <silent> <F4> :call test_setmouse(4, 42)<CR> 2259 map <silent> <F5> :call test_setmouse(7, 42)<CR> 2260 END 2261 call writefile(lines, 'XtestPopupScroll') 2262 let buf = RunVimInTerminal('-S XtestPopupScroll', #{rows: 10}) 2263 call VerifyScreenDump(buf, 'Test_popupwin_scroll_1', {}) 2264 2265 call term_sendkeys(buf, ":call popup_setoptions(winid, #{firstline: 2})\<CR>") 2266 call term_sendkeys(buf, ":\<CR>") 2267 call VerifyScreenDump(buf, 'Test_popupwin_scroll_2', {}) 2268 2269 call term_sendkeys(buf, ":call popup_setoptions(winid, #{firstline: 6})\<CR>") 2270 call term_sendkeys(buf, ":\<CR>") 2271 call VerifyScreenDump(buf, 'Test_popupwin_scroll_3', {}) 2272 2273 call term_sendkeys(buf, ":call popup_setoptions(winid, #{firstline: 9})\<CR>") 2274 call term_sendkeys(buf, ":\<CR>") 2275 call VerifyScreenDump(buf, 'Test_popupwin_scroll_4', {}) 2276 2277 call term_sendkeys(buf, ":call popup_setoptions(winid, #{scrollbarhighlight: 'ScrollBar', thumbhighlight: 'ScrollThumb', firstline: 5})\<CR>") 2278 " this scrolls two lines (half the window height) 2279 call term_sendkeys(buf, ":call ScrollUp()\<CR>") 2280 call VerifyScreenDump(buf, 'Test_popupwin_scroll_5', {}) 2281 2282 call term_sendkeys(buf, ":call ScrollDown()\<CR>") 2283 call VerifyScreenDump(buf, 'Test_popupwin_scroll_6', {}) 2284 2285 call term_sendkeys(buf, ":call ScrollDown()\<CR>") 2286 " wait a bit, otherwise it fails sometimes (double click recognized?) 2287 sleep 100m 2288 call term_sendkeys(buf, ":call ScrollDown()\<CR>") 2289 call VerifyScreenDump(buf, 'Test_popupwin_scroll_7', {}) 2290 2291 call term_sendkeys(buf, ":call ClickTop()\<CR>") 2292 sleep 100m 2293 call term_sendkeys(buf, ":call ClickTop()\<CR>") 2294 call VerifyScreenDump(buf, 'Test_popupwin_scroll_8', {}) 2295 2296 call term_sendkeys(buf, ":call ClickBot()\<CR>") 2297 call VerifyScreenDump(buf, 'Test_popupwin_scroll_9', {}) 2298 2299 " remove the minwidth and maxheight 2300 call term_sendkeys(buf, ":call popup_setoptions(winid, #{maxheight: 0, minwidth: 0})\<CR>") 2301 call term_sendkeys(buf, ":\<CR>") 2302 call VerifyScreenDump(buf, 'Test_popupwin_scroll_10', {}) 2303 2304 " check size with non-wrapping lines 2305 call term_sendkeys(buf, ":call PopupScroll()\<CR>") 2306 call VerifyScreenDump(buf, 'Test_popupwin_scroll_11', {}) 2307 2308 " check size with wrapping lines 2309 call term_sendkeys(buf, "j") 2310 call VerifyScreenDump(buf, 'Test_popupwin_scroll_12', {}) 2311 2312 " clean up 2313 call term_sendkeys(buf, "x") 2314 call StopVimInTerminal(buf) 2315 call delete('XtestPopupScroll') 2316endfunc 2317 2318func Test_popup_too_high_scrollbar() 2319 CheckScreendump 2320 2321 let lines =<< trim END 2322 call setline(1, range(1, 20)->map({i, v -> repeat(v, 10)})) 2323 set scrolloff=0 2324 func ShowPopup() 2325 let winid = popup_atcursor(['one', 'two', 'three', 'four', 'five', 2326 \ 'six', 'seven', 'eight', 'nine', 'ten', 'eleven', 'twelve'], #{ 2327 \ minwidth: 8, 2328 \ border: [], 2329 \ }) 2330 endfunc 2331 normal 3G$ 2332 call ShowPopup() 2333 END 2334 call writefile(lines, 'XtestPopupToohigh') 2335 let buf = RunVimInTerminal('-S XtestPopupToohigh', #{rows: 10}) 2336 call VerifyScreenDump(buf, 'Test_popupwin_toohigh_1', {}) 2337 2338 call term_sendkeys(buf, ":call popup_clear()\<CR>") 2339 call term_sendkeys(buf, "8G$") 2340 call term_sendkeys(buf, ":call ShowPopup()\<CR>") 2341 call VerifyScreenDump(buf, 'Test_popupwin_toohigh_2', {}) 2342 2343 call term_sendkeys(buf, ":call popup_clear()\<CR>") 2344 call term_sendkeys(buf, "gg$") 2345 call term_sendkeys(buf, ":call ShowPopup()\<CR>") 2346 call VerifyScreenDump(buf, 'Test_popupwin_toohigh_3', {}) 2347 2348 " clean up 2349 call StopVimInTerminal(buf) 2350 call delete('XtestPopupToohigh') 2351endfunc 2352 2353func Test_popup_fitting_scrollbar() 2354 " this was causing a crash, divide by zero 2355 let winid = popup_create([ 2356 \ 'one', 'two', 'longer line that wraps', 'four', 'five'], #{ 2357 \ scrollbar: 1, 2358 \ maxwidth: 10, 2359 \ maxheight: 5, 2360 \ firstline: 2}) 2361 redraw 2362 call popup_clear() 2363endfunc 2364 2365func Test_popup_settext() 2366 CheckScreendump 2367 2368 let lines =<< trim END 2369 let opts = #{wrap: 0} 2370 let p = popup_create('test', opts) 2371 eval p->popup_settext('this is a text') 2372 END 2373 2374 call writefile(lines, 'XtestPopupSetText') 2375 let buf = RunVimInTerminal('-S XtestPopupSetText', #{rows: 10}) 2376 call VerifyScreenDump(buf, 'Test_popup_settext_01', {}) 2377 2378 " Setting to empty string clears it 2379 call term_sendkeys(buf, ":call popup_settext(p, '')\<CR>") 2380 call VerifyScreenDump(buf, 'Test_popup_settext_02', {}) 2381 2382 " Setting a list 2383 call term_sendkeys(buf, ":call popup_settext(p, ['a','b','c'])\<CR>") 2384 call VerifyScreenDump(buf, 'Test_popup_settext_03', {}) 2385 2386 " Shrinking with a list 2387 call term_sendkeys(buf, ":call popup_settext(p, ['a'])\<CR>") 2388 call VerifyScreenDump(buf, 'Test_popup_settext_04', {}) 2389 2390 " Growing with a list 2391 call term_sendkeys(buf, ":call popup_settext(p, ['a','b','c'])\<CR>") 2392 call VerifyScreenDump(buf, 'Test_popup_settext_03', {}) 2393 2394 " Empty list clears 2395 call term_sendkeys(buf, ":call popup_settext(p, [])\<CR>") 2396 call VerifyScreenDump(buf, 'Test_popup_settext_05', {}) 2397 2398 " Dicts 2399 call term_sendkeys(buf, ":call popup_settext(p, [#{text: 'aaaa'}, #{text: 'bbbb'}, #{text: 'cccc'}])\<CR>") 2400 call VerifyScreenDump(buf, 'Test_popup_settext_06', {}) 2401 2402 " range() (doesn't work) 2403 call term_sendkeys(buf, ":call popup_settext(p, range(4, 8))\<CR>") 2404 call VerifyScreenDump(buf, 'Test_popup_settext_07', {}) 2405 2406 " clean up 2407 call StopVimInTerminal(buf) 2408 call delete('XtestPopupSetText') 2409endfunc 2410 2411func Test_popup_settext_getline() 2412 let id = popup_create('', #{ tabpage: 0 }) 2413 call popup_settext(id, ['a','b']) 2414 call assert_equal(2, line('$', id)) " OK :) 2415 call popup_close(id) 2416 2417 let id = popup_create('', #{ tabpage: -1 }) 2418 call popup_settext(id, ['a','b']) 2419 call assert_equal(2, line('$', id)) " Fails :( 2420 call popup_close(id) 2421endfunc 2422 2423func Test_popup_settext_null() 2424 let id = popup_create('', #{ tabpage: 0 }) 2425 call popup_settext(id, test_null_list()) 2426 call popup_close(id) 2427 2428 let id = popup_create('', #{ tabpage: 0 }) 2429 call popup_settext(id, test_null_string()) 2430 call popup_close(id) 2431endfunc 2432 2433func Test_popup_hidden() 2434 new 2435 2436 let winid = popup_atcursor('text', #{hidden: 1}) 2437 redraw 2438 call assert_equal(0, popup_getpos(winid).visible) 2439 call popup_close(winid) 2440 2441 let winid = popup_create('text', #{hidden: 1}) 2442 redraw 2443 call assert_equal(0, popup_getpos(winid).visible) 2444 call popup_close(winid) 2445 2446 func QuitCallback(id, res) 2447 let s:cb_winid = a:id 2448 let s:cb_res = a:res 2449 endfunc 2450 let winid = 'make a choice'->popup_dialog(#{hidden: 1, 2451 \ filter: 'popup_filter_yesno', 2452 \ callback: 'QuitCallback', 2453 \ }) 2454 redraw 2455 call assert_equal(0, popup_getpos(winid).visible) 2456 call assert_equal(function('popup_filter_yesno'), popup_getoptions(winid).filter) 2457 call assert_equal(function('QuitCallback'), popup_getoptions(winid).callback) 2458 exe "normal anot used by filter\<Esc>" 2459 call assert_equal('not used by filter', getline(1)) 2460 2461 call popup_show(winid) 2462 call feedkeys('y', "xt") 2463 call assert_equal(1, s:cb_res) 2464 2465 bwipe! 2466 delfunc QuitCallback 2467endfunc 2468 2469" Test options not checked elsewhere 2470func Test_set_get_options() 2471 let winid = popup_create('some text', #{highlight: 'Beautiful'}) 2472 let options = popup_getoptions(winid) 2473 call assert_equal(1, options.wrap) 2474 call assert_equal(0, options.drag) 2475 call assert_equal('Beautiful', options.highlight) 2476 2477 call popup_setoptions(winid, #{wrap: 0, drag: 1, highlight: 'Another'}) 2478 let options = popup_getoptions(winid) 2479 call assert_equal(0, options.wrap) 2480 call assert_equal(1, options.drag) 2481 call assert_equal('Another', options.highlight) 2482 2483 call assert_fails('call popup_setoptions(winid, [])', 'E715:') 2484 call assert_fails('call popup_setoptions(winid, test_null_dict())', 'E715:') 2485 2486 call popup_close(winid) 2487 call assert_equal(0, popup_setoptions(winid, options.wrap)) 2488endfunc 2489 2490func Test_popupwin_garbage_collect() 2491 func MyPopupFilter(x, winid, c) 2492 " NOP 2493 endfunc 2494 2495 let winid = popup_create('something', #{filter: function('MyPopupFilter', [{}])}) 2496 call test_garbagecollect_now() 2497 redraw 2498 " Must not crash caused by invalid memory access 2499 call feedkeys('j', 'xt') 2500 call assert_true(v:true) 2501 2502 call popup_close(winid) 2503 delfunc MyPopupFilter 2504endfunc 2505 2506func Test_popupwin_filter_mode() 2507 func MyPopupFilter(winid, c) 2508 let s:typed = a:c 2509 if a:c == ':' || a:c == "\r" || a:c == 'v' 2510 " can start cmdline mode, get out, and start/stop Visual mode 2511 return 0 2512 endif 2513 return 1 2514 endfunc 2515 2516 " Normal, Visual and Insert mode 2517 let winid = popup_create('something', #{filter: 'MyPopupFilter', filtermode: 'nvi'}) 2518 redraw 2519 call feedkeys('x', 'xt') 2520 call assert_equal('x', s:typed) 2521 2522 call feedkeys(":let g:foo = 'foo'\<CR>", 'xt') 2523 call assert_equal(':', s:typed) 2524 call assert_equal('foo', g:foo) 2525 2526 let @x = 'something' 2527 call feedkeys('v$"xy', 'xt') 2528 call assert_equal('y', s:typed) 2529 call assert_equal('something', @x) " yank command is filtered out 2530 call feedkeys('v', 'xt') " end Visual mode 2531 2532 call popup_close(winid) 2533 2534 " only Normal mode 2535 let winid = popup_create('something', #{filter: 'MyPopupFilter', filtermode: 'n'}) 2536 redraw 2537 call feedkeys('x', 'xt') 2538 call assert_equal('x', s:typed) 2539 2540 call feedkeys(":let g:foo = 'foo'\<CR>", 'xt') 2541 call assert_equal(':', s:typed) 2542 call assert_equal('foo', g:foo) 2543 2544 let @x = 'something' 2545 call feedkeys('v$"xy', 'xt') 2546 call assert_equal('v', s:typed) 2547 call assert_notequal('something', @x) 2548 2549 call popup_close(winid) 2550 2551 " default: all modes 2552 let winid = popup_create('something', #{filter: 'MyPopupFilter'}) 2553 redraw 2554 call feedkeys('x', 'xt') 2555 call assert_equal('x', s:typed) 2556 2557 let g:foo = 'bar' 2558 call feedkeys(":let g:foo = 'foo'\<CR>", 'xt') 2559 call assert_equal("\r", s:typed) 2560 call assert_equal('bar', g:foo) 2561 2562 let @x = 'something' 2563 call feedkeys('v$"xy', 'xt') 2564 call assert_equal('y', s:typed) 2565 call assert_equal('something', @x) " yank command is filtered out 2566 call feedkeys('v', 'xt') " end Visual mode 2567 2568 call popup_close(winid) 2569 delfunc MyPopupFilter 2570endfunc 2571 2572func Test_popupwin_filter_mouse() 2573 func MyPopupFilter(winid, c) 2574 let g:got_mousepos = getmousepos() 2575 return 0 2576 endfunc 2577 2578 call setline(1, ['.'->repeat(25)]->repeat(10)) 2579 let winid = popup_create(['short', 'long line that will wrap', 'other'], #{ 2580 \ line: 2, 2581 \ col: 4, 2582 \ maxwidth: 12, 2583 \ padding: [], 2584 \ border: [], 2585 \ filter: 'MyPopupFilter', 2586 \ }) 2587 redraw 2588 " 123456789012345678901 2589 " 1 ..................... 2590 " 2 ...+--------------+.. 2591 " 3 ...| |.. 2592 " 4 ...| short |.. 2593 " 5 ...| long line th |.. 2594 " 6 ...| at will wrap |.. 2595 " 7 ...| other |.. 2596 " 8 ...| |.. 2597 " 9 ...+--------------+.. 2598 " 10 ..................... 2599 let tests = [] 2600 2601 func AddItemOutsidePopup(tests, row, col) 2602 eval a:tests->add(#{clickrow: a:row, clickcol: a:col, result: #{ 2603 \ screenrow: a:row, screencol: a:col, 2604 \ winid: win_getid(), winrow: a:row, wincol: a:col, 2605 \ line: a:row, column: a:col, 2606 \ }}) 2607 endfunc 2608 func AddItemInPopupBorder(tests, winid, row, col) 2609 eval a:tests->add(#{clickrow: a:row, clickcol: a:col, result: #{ 2610 \ screenrow: a:row, screencol: a:col, 2611 \ winid: a:winid, winrow: a:row - 1, wincol: a:col - 3, 2612 \ line: 0, column: 0, 2613 \ }}) 2614 endfunc 2615 func AddItemInPopupText(tests, winid, row, col, textline, textcol) 2616 eval a:tests->add(#{clickrow: a:row, clickcol: a:col, result: #{ 2617 \ screenrow: a:row, screencol: a:col, 2618 \ winid: a:winid, winrow: a:row - 1, wincol: a:col - 3, 2619 \ line: a:textline, column: a:textcol, 2620 \ }}) 2621 endfunc 2622 2623 " above and below popup 2624 for c in range(1, 21) 2625 call AddItemOutsidePopup(tests, 1, c) 2626 call AddItemOutsidePopup(tests, 10, c) 2627 endfor 2628 " left and right of popup 2629 for r in range(1, 10) 2630 call AddItemOutsidePopup(tests, r, 3) 2631 call AddItemOutsidePopup(tests, r, 20) 2632 endfor 2633 " top and bottom in popup 2634 for c in range(4, 19) 2635 call AddItemInPopupBorder(tests, winid, 2, c) 2636 call AddItemInPopupBorder(tests, winid, 3, c) 2637 call AddItemInPopupBorder(tests, winid, 8, c) 2638 call AddItemInPopupBorder(tests, winid, 9, c) 2639 endfor 2640 " left and right margin in popup 2641 for r in range(2, 9) 2642 call AddItemInPopupBorder(tests, winid, r, 4) 2643 call AddItemInPopupBorder(tests, winid, r, 5) 2644 call AddItemInPopupBorder(tests, winid, r, 18) 2645 call AddItemInPopupBorder(tests, winid, r, 19) 2646 endfor 2647 " text "short" 2648 call AddItemInPopupText(tests, winid, 4, 6, 1, 1) 2649 call AddItemInPopupText(tests, winid, 4, 10, 1, 5) 2650 call AddItemInPopupText(tests, winid, 4, 11, 1, 6) 2651 call AddItemInPopupText(tests, winid, 4, 17, 1, 6) 2652 " text "long line th" 2653 call AddItemInPopupText(tests, winid, 5, 6, 2, 1) 2654 call AddItemInPopupText(tests, winid, 5, 10, 2, 5) 2655 call AddItemInPopupText(tests, winid, 5, 17, 2, 12) 2656 " text "at will wrap" 2657 call AddItemInPopupText(tests, winid, 6, 6, 2, 13) 2658 call AddItemInPopupText(tests, winid, 6, 10, 2, 17) 2659 call AddItemInPopupText(tests, winid, 6, 17, 2, 24) 2660 " text "other" 2661 call AddItemInPopupText(tests, winid, 7, 6, 3, 1) 2662 call AddItemInPopupText(tests, winid, 7, 10, 3, 5) 2663 call AddItemInPopupText(tests, winid, 7, 11, 3, 6) 2664 call AddItemInPopupText(tests, winid, 7, 17, 3, 6) 2665 2666 for item in tests 2667 call test_setmouse(item.clickrow, item.clickcol) 2668 call feedkeys("\<LeftMouse>", 'xt') 2669 call assert_equal(item.result, g:got_mousepos) 2670 endfor 2671 2672 call popup_close(winid) 2673 enew! 2674 delfunc MyPopupFilter 2675endfunc 2676 2677func Test_popupwin_with_buffer() 2678 call writefile(['some text', 'in a buffer'], 'XsomeFile') 2679 let buf = bufadd('XsomeFile') 2680 call assert_equal(0, bufloaded(buf)) 2681 2682 setlocal number 2683 call setbufvar(buf, "&wrapmargin", 13) 2684 2685 let winid = popup_create(buf, {}) 2686 call assert_notequal(0, winid) 2687 let pos = popup_getpos(winid) 2688 call assert_equal(2, pos.height) 2689 call assert_equal(1, bufloaded(buf)) 2690 2691 " window-local option is set to default, buffer-local is not 2692 call assert_equal(0, getwinvar(winid, '&number')) 2693 call assert_equal(13, getbufvar(buf, '&wrapmargin')) 2694 2695 call popup_close(winid) 2696 call assert_equal({}, popup_getpos(winid)) 2697 call assert_equal(1, bufloaded(buf)) 2698 exe 'bwipe! ' .. buf 2699 setlocal nonumber 2700 2701 edit test_popupwin.vim 2702 let winid = popup_create(bufnr(''), {}) 2703 redraw 2704 call popup_close(winid) 2705 call delete('XsomeFile') 2706endfunc 2707 2708func Test_popupwin_terminal_buffer() 2709 CheckFeature terminal 2710 CheckUnix 2711 " Starting a terminal to run a shell in is considered flaky. 2712 let g:test_is_flaky = 1 2713 2714 let origwin = win_getid() 2715 2716 " open help window to test that :help below fails 2717 help 2718 2719 let termbuf = term_start(&shell, #{hidden: 1}) 2720 let winid = popup_create(termbuf, #{minwidth: 40, minheight: 10, border: []}) 2721 " Wait for shell to start 2722 call WaitForAssert({-> assert_equal("run", job_status(term_getjob(termbuf)))}) 2723 " Wait for a prompt (see border char first, then space after prompt) 2724 call WaitForAssert({ -> assert_equal(' ', screenstring(screenrow(), screencol() - 1))}) 2725 2726 " When typing a character, the cursor is after it. 2727 call feedkeys("x", 'xt') 2728 call term_wait(termbuf) 2729 redraw 2730 call WaitForAssert({ -> assert_equal('x', screenstring(screenrow(), screencol() - 1))}) 2731 call feedkeys("\<BS>", 'xt') 2732 2733 " Check this doesn't crash 2734 call assert_equal(winnr(), winnr('j')) 2735 call assert_equal(winnr(), winnr('k')) 2736 call assert_equal(winnr(), winnr('h')) 2737 call assert_equal(winnr(), winnr('l')) 2738 2739 " Cannot quit while job is running 2740 call assert_fails('call feedkeys("\<C-W>:quit\<CR>", "xt")', 'E948:') 2741 2742 " Cannot enter Terminal-Normal mode. (TODO: but it works...) 2743 call feedkeys("xxx\<C-W>N", 'xt') 2744 call assert_fails('call feedkeys("gf", "xt")', 'E863:') 2745 call feedkeys("a\<C-U>", 'xt') 2746 2747 " Cannot escape from terminal window 2748 call assert_fails('tab drop xxx', 'E863:') 2749 call assert_fails('help', 'E994:') 2750 2751 " Cannot open a second one. 2752 let termbuf2 = term_start(&shell, #{hidden: 1}) 2753 call assert_fails('call popup_create(termbuf2, #{})', 'E861:') 2754 call term_sendkeys(termbuf2, "exit\<CR>") 2755 2756 " Exiting shell closes popup window 2757 call feedkeys("exit\<CR>", 'xt') 2758 " Wait for shell to exit 2759 call WaitForAssert({-> assert_equal("dead", job_status(term_getjob(termbuf)))}) 2760 2761 helpclose 2762 call feedkeys(":quit\<CR>", 'xt') 2763 call assert_equal(origwin, win_getid()) 2764endfunc 2765 2766func Test_popupwin_close_prevwin() 2767 CheckFeature terminal 2768 call Popupwin_close_prevwin() 2769endfunc 2770 2771def Popupwin_close_prevwin() 2772 assert_equal(1, winnr('$')) 2773 split 2774 wincmd b 2775 assert_equal(2, winnr()) 2776 var buf = term_start(&shell, {hidden: 1}) 2777 popup_create(buf, {}) 2778 TermWait(buf, 100) 2779 popup_clear(true) 2780 assert_equal(2, winnr()) 2781 2782 quit 2783 exe 'bwipe! ' .. buf 2784enddef 2785 2786func Test_popupwin_with_buffer_and_filter() 2787 new Xwithfilter 2788 call setline(1, range(100)) 2789 let bufnr = bufnr() 2790 hide 2791 2792 func BufferFilter(win, key) 2793 if a:key == 'G' 2794 " recursive use of "G" does not cause problems. 2795 call win_execute(a:win, 'normal! G') 2796 return 1 2797 endif 2798 return 0 2799 endfunc 2800 2801 let winid = popup_create(bufnr, #{maxheight: 5, filter: 'BufferFilter'}) 2802 call assert_equal(1, popup_getpos(winid).firstline) 2803 redraw 2804 call feedkeys("G", 'xt') 2805 call assert_equal(99, popup_getpos(winid).firstline) 2806 2807 call popup_close(winid) 2808 exe 'bwipe! ' .. bufnr 2809endfunc 2810 2811func Test_popupwin_width() 2812 let winid = popup_create(repeat(['short', 'long long long line', 'medium width'], 50), #{ 2813 \ maxwidth: 40, 2814 \ maxheight: 10, 2815 \ }) 2816 for top in range(1, 20) 2817 eval winid->popup_setoptions(#{firstline: top}) 2818 redraw 2819 call assert_equal(19, popup_getpos(winid).width) 2820 endfor 2821 call popup_clear() 2822endfunc 2823 2824func Test_popupwin_buf_close() 2825 let buf = bufadd('Xtestbuf') 2826 call bufload(buf) 2827 call setbufline(buf, 1, ['just', 'some', 'lines']) 2828 let winid = popup_create(buf, {}) 2829 redraw 2830 call assert_equal(3, popup_getpos(winid).height) 2831 let bufinfo = getbufinfo(buf)[0] 2832 call assert_equal(1, bufinfo.changed) 2833 call assert_equal(0, bufinfo.hidden) 2834 call assert_equal(0, bufinfo.listed) 2835 call assert_equal(1, bufinfo.loaded) 2836 call assert_equal([], bufinfo.windows) 2837 call assert_equal([winid], bufinfo.popups) 2838 2839 call popup_close(winid) 2840 call assert_equal({}, popup_getpos(winid)) 2841 let bufinfo = getbufinfo(buf)[0] 2842 call assert_equal(1, bufinfo.changed) 2843 call assert_equal(1, bufinfo.hidden) 2844 call assert_equal(0, bufinfo.listed) 2845 call assert_equal(1, bufinfo.loaded) 2846 call assert_equal([], bufinfo.windows) 2847 call assert_equal([], bufinfo.popups) 2848 exe 'bwipe! ' .. buf 2849endfunc 2850 2851func Test_popup_menu_with_maxwidth() 2852 CheckScreendump 2853 2854 let lines =<< trim END 2855 call setline(1, range(1, 10)) 2856 hi ScrollThumb ctermbg=blue 2857 hi ScrollBar ctermbg=red 2858 func PopupMenu(lines, line, col, scrollbar = 0) 2859 return popup_menu(a:lines, #{ 2860 \ maxwidth: 10, 2861 \ maxheight: 3, 2862 \ pos : 'topleft', 2863 \ col : a:col, 2864 \ line : a:line, 2865 \ scrollbar : a:scrollbar, 2866 \ }) 2867 endfunc 2868 call PopupMenu(['x'], 1, 1) 2869 call PopupMenu(['123456789|'], 1, 16) 2870 call PopupMenu(['123456789|' .. ' '], 7, 1) 2871 call PopupMenu([repeat('123456789|', 100)], 7, 16) 2872 call PopupMenu(repeat(['123456789|' .. ' '], 5), 1, 33, 1) 2873 END 2874 call writefile(lines, 'XtestPopupMenuMaxWidth') 2875 let buf = RunVimInTerminal('-S XtestPopupMenuMaxWidth', #{rows: 13}) 2876 call VerifyScreenDump(buf, 'Test_popupwin_menu_maxwidth_1', {}) 2877 2878 " close the menu popupwin. 2879 call term_sendkeys(buf, " ") 2880 call term_sendkeys(buf, " ") 2881 call term_sendkeys(buf, " ") 2882 call term_sendkeys(buf, " ") 2883 call term_sendkeys(buf, " ") 2884 2885 " clean up 2886 call StopVimInTerminal(buf) 2887 call delete('XtestPopupMenuMaxWidth') 2888endfunc 2889 2890func Test_popup_menu_with_scrollbar() 2891 CheckScreendump 2892 2893 let lines =<< trim END 2894 call setline(1, range(1, 20)) 2895 hi ScrollThumb ctermbg=blue 2896 hi ScrollBar ctermbg=red 2897 eval ['one', 'two', 'three', 'four', 'five', 2898 \ 'six', 'seven', 'eight', 'nine'] 2899 \ ->popup_menu(#{ 2900 \ minwidth: 8, 2901 \ maxheight: 3, 2902 \ }) 2903 END 2904 call writefile(lines, 'XtestPopupMenuScroll') 2905 let buf = RunVimInTerminal('-S XtestPopupMenuScroll', #{rows: 10}) 2906 2907 call term_sendkeys(buf, "j") 2908 call VerifyScreenDump(buf, 'Test_popupwin_menu_scroll_1', {}) 2909 2910 call term_sendkeys(buf, "jjj") 2911 call VerifyScreenDump(buf, 'Test_popupwin_menu_scroll_2', {}) 2912 2913 " if the cursor is the bottom line, it stays at the bottom line. 2914 call term_sendkeys(buf, repeat("j", 20)) 2915 call VerifyScreenDump(buf, 'Test_popupwin_menu_scroll_3', {}) 2916 2917 call term_sendkeys(buf, "kk") 2918 call VerifyScreenDump(buf, 'Test_popupwin_menu_scroll_4', {}) 2919 2920 call term_sendkeys(buf, "k") 2921 call VerifyScreenDump(buf, 'Test_popupwin_menu_scroll_5', {}) 2922 2923 " if the cursor is in the top line, it stays in the top line. 2924 call term_sendkeys(buf, repeat("k", 20)) 2925 call VerifyScreenDump(buf, 'Test_popupwin_menu_scroll_6', {}) 2926 2927 " close the menu popupwin. 2928 call term_sendkeys(buf, " ") 2929 2930 " clean up 2931 call StopVimInTerminal(buf) 2932 call delete('XtestPopupMenuScroll') 2933endfunc 2934 2935func Test_popup_menu_filter() 2936 CheckScreendump 2937 2938 let lines =<< trim END 2939 function! MyFilter(winid, key) abort 2940 if a:key == "0" 2941 call win_execute(a:winid, "call setpos('.', [0, 1, 1, 0])") 2942 return 1 2943 endif 2944 if a:key == "G" 2945 call win_execute(a:winid, "call setpos('.', [0, line('$'), 1, 0])") 2946 return 1 2947 endif 2948 if a:key == "j" 2949 call win_execute(a:winid, "call setpos('.', [0, line('.') + 1, 1, 0])") 2950 return 1 2951 endif 2952 if a:key == "k" 2953 call win_execute(a:winid, "call setpos('.', [0, line('.') - 1, 1, 0])") 2954 return 1 2955 endif 2956 if a:key == ':' 2957 call popup_close(a:winid) 2958 return 0 2959 endif 2960 return 0 2961 endfunction 2962 call popup_menu(['111', '222', '333', '444', '555', '666', '777', '888', '999'], #{ 2963 \ maxheight : 3, 2964 \ filter : 'MyFilter' 2965 \ }) 2966 END 2967 call writefile(lines, 'XtestPopupMenuFilter') 2968 let buf = RunVimInTerminal('-S XtestPopupMenuFilter', #{rows: 10}) 2969 2970 call term_sendkeys(buf, "j") 2971 call VerifyScreenDump(buf, 'Test_popupwin_menu_filter_1', {}) 2972 2973 call term_sendkeys(buf, "k") 2974 call VerifyScreenDump(buf, 'Test_popupwin_menu_filter_2', {}) 2975 2976 call term_sendkeys(buf, "G") 2977 call VerifyScreenDump(buf, 'Test_popupwin_menu_filter_3', {}) 2978 2979 call term_sendkeys(buf, "0") 2980 call VerifyScreenDump(buf, 'Test_popupwin_menu_filter_4', {}) 2981 2982 " check that when the popup is closed in the filter the screen is redrawn 2983 call term_sendkeys(buf, ":") 2984 call VerifyScreenDump(buf, 'Test_popupwin_menu_filter_5', {}) 2985 call term_sendkeys(buf, "\<CR>") 2986 2987 " clean up 2988 call StopVimInTerminal(buf) 2989 call delete('XtestPopupMenuFilter') 2990endfunc 2991 2992func Test_popup_cursorline() 2993 CheckScreendump 2994 2995 let winid = popup_create('some text', {}) 2996 call assert_equal(0, popup_getoptions(winid).cursorline) 2997 call popup_close(winid) 2998 2999 let winid = popup_create('some text', #{ cursorline: 1, }) 3000 call assert_equal(1, popup_getoptions(winid).cursorline) 3001 call popup_close(winid) 3002 3003 let winid = popup_create('some text', #{ cursorline: v:true, }) 3004 call assert_equal(1, popup_getoptions(winid).cursorline) 3005 call popup_close(winid) 3006 3007 let winid = popup_create('some text', #{ cursorline: 0, }) 3008 call assert_equal(0, popup_getoptions(winid).cursorline) 3009 call popup_close(winid) 3010 3011 let winid = popup_menu('some text', {}) 3012 call assert_equal(1, popup_getoptions(winid).cursorline) 3013 call popup_close(winid) 3014 3015 let winid = popup_menu('some text', #{ cursorline: 1, }) 3016 call assert_equal(1, popup_getoptions(winid).cursorline) 3017 call popup_close(winid) 3018 3019 let winid = popup_menu('some text', #{ cursorline: 0, }) 3020 call assert_equal(0, popup_getoptions(winid).cursorline) 3021 call popup_close(winid) 3022 3023 " --------- 3024 " Pattern 1 3025 " --------- 3026 let lines =<< trim END 3027 call popup_create(['111', '222', '333'], #{ cursorline : 0 }) 3028 END 3029 call writefile(lines, 'XtestPopupCursorLine') 3030 let buf = RunVimInTerminal('-S XtestPopupCursorLine', #{rows: 10}) 3031 call VerifyScreenDump(buf, 'Test_popupwin_cursorline_1', {}) 3032 call term_sendkeys(buf, ":call popup_clear()\<cr>") 3033 call StopVimInTerminal(buf) 3034 3035 " --------- 3036 " Pattern 2 3037 " --------- 3038 let lines =<< trim END 3039 call popup_create(['111', '222', '333'], #{ cursorline : 1 }) 3040 END 3041 call writefile(lines, 'XtestPopupCursorLine') 3042 let buf = RunVimInTerminal('-S XtestPopupCursorLine', #{rows: 10}) 3043 call VerifyScreenDump(buf, 'Test_popupwin_cursorline_2', {}) 3044 call term_sendkeys(buf, ":call popup_clear()\<cr>") 3045 call StopVimInTerminal(buf) 3046 3047 " --------- 3048 " Pattern 3 3049 " --------- 3050 let lines =<< trim END 3051 function! MyFilter(winid, key) abort 3052 if a:key == "j" 3053 call win_execute(a:winid, "call setpos('.', [0, line('.') + 1, 1, 0]) | redraw") 3054 return 1 3055 endif 3056 if a:key == 'x' 3057 call popup_close(a:winid) 3058 return 1 3059 endif 3060 return 0 3061 endfunction 3062 call popup_menu(['111', '222', '333'], #{ 3063 \ cursorline : 0, 3064 \ maxheight : 2, 3065 \ filter : 'MyFilter', 3066 \ }) 3067 END 3068 call writefile(lines, 'XtestPopupCursorLine') 3069 let buf = RunVimInTerminal('-S XtestPopupCursorLine', #{rows: 10}) 3070 call VerifyScreenDump(buf, 'Test_popupwin_cursorline_3', {}) 3071 call term_sendkeys(buf, "j") 3072 call term_sendkeys(buf, "j") 3073 call VerifyScreenDump(buf, 'Test_popupwin_cursorline_4', {}) 3074 call term_sendkeys(buf, "x") 3075 call StopVimInTerminal(buf) 3076 3077 " --------- 3078 " Pattern 4 3079 " --------- 3080 let lines =<< trim END 3081 function! MyFilter(winid, key) abort 3082 if a:key == "j" 3083 call win_execute(a:winid, "call setpos('.', [0, line('.') + 1, 1, 0]) | redraw") 3084 return 1 3085 endif 3086 if a:key == 'x' 3087 call popup_close(a:winid) 3088 return 1 3089 endif 3090 return 0 3091 endfunction 3092 call popup_menu(['111', '222', '333'], #{ 3093 \ cursorline : 1, 3094 \ maxheight : 2, 3095 \ filter : 'MyFilter', 3096 \ }) 3097 END 3098 call writefile(lines, 'XtestPopupCursorLine') 3099 let buf = RunVimInTerminal('-S XtestPopupCursorLine', #{rows: 10}) 3100 call VerifyScreenDump(buf, 'Test_popupwin_cursorline_5', {}) 3101 call term_sendkeys(buf, "j") 3102 call term_sendkeys(buf, "j") 3103 call VerifyScreenDump(buf, 'Test_popupwin_cursorline_6', {}) 3104 call term_sendkeys(buf, "x") 3105 call StopVimInTerminal(buf) 3106 3107 " --------- 3108 " Cursor in second line when creating the popup 3109 " --------- 3110 let lines =<< trim END 3111 let winid = popup_create(['111', '222', '333'], #{ 3112 \ cursorline : 1, 3113 \ }) 3114 call win_execute(winid, "2") 3115 END 3116 call writefile(lines, 'XtestPopupCursorLine') 3117 let buf = RunVimInTerminal('-S XtestPopupCursorLine', #{rows: 10}) 3118 call VerifyScreenDump(buf, 'Test_popupwin_cursorline_7', {}) 3119 call StopVimInTerminal(buf) 3120 3121 call delete('XtestPopupCursorLine') 3122 3123 " --------- 3124 " Use current buffer for popupmenu 3125 " --------- 3126 let lines =<< trim END 3127 call setline(1, ['one', 'two', 'three']) 3128 let winid = popup_create(bufnr('%'), #{ 3129 \ cursorline : 1, 3130 \ }) 3131 call win_execute(winid, "2") 3132 END 3133 call writefile(lines, 'XtestPopupCursorLine') 3134 let buf = RunVimInTerminal('-S XtestPopupCursorLine', #{rows: 10}) 3135 call VerifyScreenDump(buf, 'Test_popupwin_cursorline_8', {}) 3136 call StopVimInTerminal(buf) 3137 3138 call delete('XtestPopupCursorLine') 3139endfunc 3140 3141def Test_popup_cursorline_vim9() 3142 var winid = popup_create('some text', { cursorline: true, }) 3143 assert_equal(1, popup_getoptions(winid).cursorline) 3144 popup_close(winid) 3145 3146 assert_fails("popup_create('some text', { cursorline: 2, })", 'E1023:') 3147 popup_clear() 3148enddef 3149 3150func Test_previewpopup() 3151 CheckScreendump 3152 CheckFeature quickfix 3153 3154 call writefile([ 3155 \ "!_TAG_FILE_ENCODING\tutf-8\t//", 3156 \ "another\tXtagfile\t/^this is another", 3157 \ "theword\tXtagfile\t/^theword"], 3158 \ 'Xtags') 3159 call writefile(range(1,20) 3160 \ + ['theword is here'] 3161 \ + range(22, 27) 3162 \ + ['this is another place'] 3163 \ + range(29, 40), 3164 \ "Xtagfile") 3165 call writefile(range(1,10) 3166 \ + ['searched word is here'] 3167 \ + range(12, 20), 3168 \ "Xheader.h") 3169 let lines =<< trim END 3170 set tags=Xtags 3171 call setline(1, [ 3172 \ 'one', 3173 \ '#include "Xheader.h"', 3174 \ 'three', 3175 \ 'four', 3176 \ 'five', 3177 \ 'six', 3178 \ 'seven', 3179 \ 'find theword somewhere', 3180 \ 'nine', 3181 \ 'this is another word', 3182 \ 'very long line where the word is also another']) 3183 set previewpopup=height:4,width:40 3184 hi OtherColor ctermbg=lightcyan guibg=lightcyan 3185 set path=. 3186 END 3187 call writefile(lines, 'XtestPreviewPopup') 3188 let buf = RunVimInTerminal('-S XtestPreviewPopup', #{rows: 14}) 3189 3190 call term_sendkeys(buf, "/theword\<CR>\<C-W>}") 3191 call term_sendkeys(buf, ":\<CR>") 3192 call VerifyScreenDump(buf, 'Test_popupwin_previewpopup_1', {}) 3193 3194 call term_sendkeys(buf, ":set previewpopup+=highlight:OtherColor\<CR>") 3195 call term_sendkeys(buf, "/another\<CR>\<C-W>}") 3196 call VerifyScreenDump(buf, 'Test_popupwin_previewpopup_2', {}) 3197 3198 call term_sendkeys(buf, ":call popup_move(popup_findpreview(), #{col: 15})\<CR>") 3199 call term_sendkeys(buf, ":\<CR>") 3200 call VerifyScreenDump(buf, 'Test_popupwin_previewpopup_3', {}) 3201 3202 call term_sendkeys(buf, "/another\<CR>\<C-W>}") 3203 call VerifyScreenDump(buf, 'Test_popupwin_previewpopup_4', {}) 3204 3205 call term_sendkeys(buf, ":silent cd ..\<CR>:\<CR>") 3206 call VerifyScreenDump(buf, 'Test_popupwin_previewpopup_5', {}) 3207 call term_sendkeys(buf, ":silent cd testdir\<CR>") 3208 3209 call term_sendkeys(buf, ":set previewpopup-=highlight:OtherColor\<CR>") 3210 call term_sendkeys(buf, ":pclose\<CR>") 3211 call term_sendkeys(buf, ":\<BS>") 3212 call VerifyScreenDump(buf, 'Test_popupwin_previewpopup_6', {}) 3213 3214 call term_sendkeys(buf, ":pedit +/theword Xtagfile\<CR>") 3215 call term_sendkeys(buf, ":\<CR>") 3216 call VerifyScreenDump(buf, 'Test_popupwin_previewpopup_7', {}) 3217 3218 call term_sendkeys(buf, ":pclose\<CR>") 3219 call term_sendkeys(buf, ":psearch searched\<CR>") 3220 call term_sendkeys(buf, ":\<CR>") 3221 call VerifyScreenDump(buf, 'Test_popupwin_previewpopup_8', {}) 3222 3223 call term_sendkeys(buf, "\<C-W>p") 3224 call VerifyScreenDump(buf, 'Test_popupwin_previewpopup_9', {}) 3225 3226 call term_sendkeys(buf, ":call win_execute(popup_findpreview(), 'call popup_clear()')\<CR>") 3227 call VerifyScreenDump(buf, 'Test_popupwin_previewpopup_10', {}) 3228 3229 call StopVimInTerminal(buf) 3230 call delete('Xtags') 3231 call delete('Xtagfile') 3232 call delete('XtestPreviewPopup') 3233 call delete('Xheader.h') 3234endfunc 3235 3236func Get_popupmenu_lines() 3237 let lines =<< trim END 3238 set completeopt+=preview,popup 3239 set completefunc=CompleteFuncDict 3240 hi InfoPopup ctermbg=yellow 3241 3242 func CompleteFuncDict(findstart, base) 3243 if a:findstart 3244 if col('.') > 10 3245 return col('.') - 10 3246 endif 3247 return 0 3248 endif 3249 3250 return { 3251 \ 'words': [ 3252 \ { 3253 \ 'word': 'aword', 3254 \ 'abbr': 'wrd', 3255 \ 'menu': 'extra text', 3256 \ 'info': 'words are cool', 3257 \ 'kind': 'W', 3258 \ 'user_data': 'test' 3259 \ }, 3260 \ { 3261 \ 'word': 'anotherword', 3262 \ 'abbr': 'anotwrd', 3263 \ 'menu': 'extra text', 3264 \ 'info': "other words are\ncooler than this and some more text\nto make wrap", 3265 \ 'kind': 'W', 3266 \ 'user_data': 'notest' 3267 \ }, 3268 \ { 3269 \ 'word': 'noinfo', 3270 \ 'abbr': 'noawrd', 3271 \ 'menu': 'extra text', 3272 \ 'info': "lets\nshow\na\nscrollbar\nhere", 3273 \ 'kind': 'W', 3274 \ 'user_data': 'notest' 3275 \ }, 3276 \ { 3277 \ 'word': 'thatword', 3278 \ 'abbr': 'thatwrd', 3279 \ 'menu': 'extra text', 3280 \ 'info': 'that word is cool', 3281 \ 'kind': 'W', 3282 \ 'user_data': 'notest' 3283 \ }, 3284 \ ] 3285 \ } 3286 endfunc 3287 call setline(1, 'text text text text text text text ') 3288 func ChangeColor() 3289 let id = popup_findinfo() 3290 if buflisted(winbufnr(id)) 3291 call setline(1, 'buffer is listed') 3292 endif 3293 eval id->popup_setoptions(#{highlight: 'InfoPopup'}) 3294 endfunc 3295 3296 func InfoHidden() 3297 set completepopup=height:4,border:off,align:menu 3298 set completeopt-=popup completeopt+=popuphidden 3299 au CompleteChanged * call HandleChange() 3300 endfunc 3301 3302 let s:counter = 0 3303 func HandleChange() 3304 let s:counter += 1 3305 let selected = complete_info(['selected']).selected 3306 if selected <= 0 3307 " First time: do nothing, info remains hidden 3308 return 3309 endif 3310 if selected == 1 3311 " Second time: show info right away 3312 let id = popup_findinfo() 3313 if id 3314 call popup_settext(id, 'immediate info ' .. s:counter) 3315 call popup_show(id) 3316 endif 3317 else 3318 " Third time: show info after a short delay 3319 call timer_start(100, 'ShowInfo') 3320 endif 3321 endfunc 3322 3323 func ShowInfo(...) 3324 let id = popup_findinfo() 3325 if id 3326 call popup_settext(id, 'async info ' .. s:counter) 3327 call popup_show(id) 3328 endif 3329 endfunc 3330 3331 func OpenOtherPopups() 3332 call popup_create([ 3333 \ 'popup below', 3334 \ 'popup below', 3335 \ 'popup below', 3336 \ 'popup below', 3337 \ ], #{ 3338 \ line: 'cursor', 3339 \ col: 'cursor+3', 3340 \ highlight: 'ErrorMsg', 3341 \ minwidth: 17, 3342 \ zindex: 50, 3343 \ }) 3344 call popup_create([ 3345 \ 'popup on top', 3346 \ 'popup on top', 3347 \ 'popup on top', 3348 \ ], #{ 3349 \ line: 'cursor+3', 3350 \ col: 'cursor-10', 3351 \ highlight: 'Search', 3352 \ minwidth: 10, 3353 \ zindex: 200, 3354 \ }) 3355 endfunc 3356 3357 " Check that no autocommands are triggered for the info popup 3358 au WinEnter * if win_gettype() == 'popup' | call setline(2, 'WinEnter') | endif 3359 au WinLeave * if win_gettype() == 'popup' | call setline(2, 'WinLeave') | endif 3360 END 3361 return lines 3362endfunc 3363 3364func Test_popupmenu_info_border() 3365 CheckScreendump 3366 CheckFeature quickfix 3367 3368 let lines = Get_popupmenu_lines() 3369 call add(lines, 'set completepopup=height:4,highlight:InfoPopup') 3370 call writefile(lines, 'XtestInfoPopup') 3371 3372 let buf = RunVimInTerminal('-S XtestInfoPopup', #{rows: 14}) 3373 call TermWait(buf, 25) 3374 3375 call term_sendkeys(buf, "A\<C-X>\<C-U>") 3376 call VerifyScreenDump(buf, 'Test_popupwin_infopopup_1', {}) 3377 3378 call term_sendkeys(buf, "\<C-N>") 3379 call VerifyScreenDump(buf, 'Test_popupwin_infopopup_2', {}) 3380 3381 call term_sendkeys(buf, "\<C-N>") 3382 call VerifyScreenDump(buf, 'Test_popupwin_infopopup_3', {}) 3383 3384 call term_sendkeys(buf, "\<C-N>\<C-N>") 3385 call VerifyScreenDump(buf, 'Test_popupwin_infopopup_4', {}) 3386 3387 " info on the left with scrollbar 3388 call term_sendkeys(buf, "test text test text\<C-X>\<C-U>") 3389 call term_sendkeys(buf, "\<C-N>\<C-N>") 3390 call VerifyScreenDump(buf, 'Test_popupwin_infopopup_5', {}) 3391 3392 " Test that the popupmenu's scrollbar and infopopup do not overlap 3393 call term_sendkeys(buf, "\<Esc>") 3394 call term_sendkeys(buf, ":set pumheight=3\<CR>") 3395 call term_sendkeys(buf, "cc\<C-X>\<C-U>") 3396 call VerifyScreenDump(buf, 'Test_popupwin_infopopup_6', {}) 3397 3398 " Hide the info popup, cycle through buffers, make sure it didn't get 3399 " deleted. 3400 call term_sendkeys(buf, "\<Esc>") 3401 call term_sendkeys(buf, ":set hidden\<CR>") 3402 call term_sendkeys(buf, ":bn\<CR>") 3403 call term_sendkeys(buf, ":bn\<CR>") 3404 call term_sendkeys(buf, "otest text test text\<C-X>\<C-U>") 3405 call VerifyScreenDump(buf, 'Test_popupwin_infopopup_7', {}) 3406 3407 " Test that when the option is changed the popup changes. 3408 call term_sendkeys(buf, "\<Esc>") 3409 call term_sendkeys(buf, ":set completepopup=border:off\<CR>") 3410 call term_sendkeys(buf, "a\<C-X>\<C-U>") 3411 call VerifyScreenDump(buf, 'Test_popupwin_infopopup_8', {}) 3412 3413 call term_sendkeys(buf, " \<Esc>") 3414 call term_sendkeys(buf, ":set completepopup+=width:10\<CR>") 3415 call term_sendkeys(buf, "a\<C-X>\<C-U>") 3416 call VerifyScreenDump(buf, 'Test_popupwin_infopopup_9', {}) 3417 3418 call term_sendkeys(buf, "\<Esc>") 3419 call StopVimInTerminal(buf) 3420 call delete('XtestInfoPopup') 3421endfunc 3422 3423func Test_popupmenu_info_noborder() 3424 CheckScreendump 3425 CheckFeature quickfix 3426 3427 let lines = Get_popupmenu_lines() 3428 call add(lines, 'set completepopup=height:4,border:off') 3429 call writefile(lines, 'XtestInfoPopupNb') 3430 3431 let buf = RunVimInTerminal('-S XtestInfoPopupNb', #{rows: 14}) 3432 call TermWait(buf, 25) 3433 3434 call term_sendkeys(buf, "A\<C-X>\<C-U>") 3435 call VerifyScreenDump(buf, 'Test_popupwin_infopopup_nb_1', {}) 3436 3437 call StopVimInTerminal(buf) 3438 call delete('XtestInfoPopupNb') 3439endfunc 3440 3441func Test_popupmenu_info_align_menu() 3442 CheckScreendump 3443 CheckFeature quickfix 3444 3445 let lines = Get_popupmenu_lines() 3446 call add(lines, 'set completepopup=height:4,border:off,align:menu') 3447 call writefile(lines, 'XtestInfoPopupNb') 3448 3449 let buf = RunVimInTerminal('-S XtestInfoPopupNb', #{rows: 14}) 3450 call TermWait(buf, 25) 3451 3452 call term_sendkeys(buf, "A\<C-X>\<C-U>") 3453 call term_sendkeys(buf, "\<C-N>") 3454 call term_sendkeys(buf, "\<C-N>") 3455 call term_sendkeys(buf, "\<C-N>") 3456 call VerifyScreenDump(buf, 'Test_popupwin_infopopup_align_1', {}) 3457 3458 call term_sendkeys(buf, "test text test text test\<C-X>\<C-U>") 3459 call term_sendkeys(buf, "\<C-N>") 3460 call VerifyScreenDump(buf, 'Test_popupwin_infopopup_align_2', {}) 3461 3462 call term_sendkeys(buf, "\<Esc>") 3463 call term_sendkeys(buf, ":call ChangeColor()\<CR>") 3464 call term_sendkeys(buf, ":call setline(2, ['x']->repeat(10))\<CR>") 3465 call term_sendkeys(buf, "Gotest text test text\<C-X>\<C-U>") 3466 call VerifyScreenDump(buf, 'Test_popupwin_infopopup_align_3', {}) 3467 3468 call StopVimInTerminal(buf) 3469 call delete('XtestInfoPopupNb') 3470endfunc 3471 3472func Test_popupmenu_info_hidden() 3473 CheckScreendump 3474 CheckFeature quickfix 3475 3476 let lines = Get_popupmenu_lines() 3477 call add(lines, 'call InfoHidden()') 3478 call writefile(lines, 'XtestInfoPopupHidden') 3479 3480 let buf = RunVimInTerminal('-S XtestInfoPopupHidden', #{rows: 14}) 3481 call TermWait(buf, 25) 3482 3483 call term_sendkeys(buf, "A\<C-X>\<C-U>") 3484 call VerifyScreenDump(buf, 'Test_popupwin_infopopup_hidden_1', {}) 3485 3486 call term_sendkeys(buf, "\<C-N>") 3487 call VerifyScreenDump(buf, 'Test_popupwin_infopopup_hidden_2', {}) 3488 3489 call term_sendkeys(buf, "\<C-N>") 3490 call VerifyScreenDump(buf, 'Test_popupwin_infopopup_hidden_3', {}) 3491 3492 call term_sendkeys(buf, "\<Esc>") 3493 call StopVimInTerminal(buf) 3494 call delete('XtestInfoPopupHidden') 3495endfunc 3496 3497func Test_popupmenu_info_too_wide() 3498 CheckScreendump 3499 CheckFeature quickfix 3500 3501 let lines =<< trim END 3502 call setline(1, range(10)) 3503 3504 set completeopt+=preview,popup 3505 set completepopup=align:menu 3506 set omnifunc=OmniFunc 3507 hi InfoPopup ctermbg=lightgrey 3508 3509 func OmniFunc(findstart, base) 3510 if a:findstart 3511 return 0 3512 endif 3513 3514 let menuText = 'some long text to make sure the menu takes up all of the width of the window' 3515 return #{ 3516 \ words: [ 3517 \ #{ 3518 \ word: 'scrap', 3519 \ menu: menuText, 3520 \ info: "other words are\ncooler than this and some more text\nto make wrap", 3521 \ }, 3522 \ #{ 3523 \ word: 'scappier', 3524 \ menu: menuText, 3525 \ info: 'words are cool', 3526 \ }, 3527 \ #{ 3528 \ word: 'scrappier2', 3529 \ menu: menuText, 3530 \ info: 'words are cool', 3531 \ }, 3532 \ ] 3533 \ } 3534 endfunc 3535 END 3536 3537 call writefile(lines, 'XtestInfoPopupWide') 3538 let buf = RunVimInTerminal('-S XtestInfoPopupWide', #{rows: 8}) 3539 call TermWait(buf, 25) 3540 3541 call term_sendkeys(buf, "Ascr\<C-X>\<C-O>") 3542 call VerifyScreenDump(buf, 'Test_popupwin_infopopup_wide_1', {}) 3543 3544 call term_sendkeys(buf, "\<Esc>") 3545 call StopVimInTerminal(buf) 3546 call delete('XtestInfoPopupWide') 3547endfunc 3548 3549func Test_popupmenu_masking() 3550 " Test that popup windows that are opened while popup menu is open are 3551 " properly displayed. 3552 CheckScreendump 3553 CheckFeature quickfix 3554 3555 let lines = Get_popupmenu_lines() 3556 call add(lines, 'inoremap <C-A> <Cmd>call OpenOtherPopups()<CR>') 3557 call writefile(lines, 'XtestPopupmenuMasking') 3558 3559 let buf = RunVimInTerminal('-S XtestPopupmenuMasking', #{rows: 14}) 3560 call TermWait(buf, 25) 3561 3562 call term_sendkeys(buf, "A\<C-X>\<C-U>\<C-A>") 3563 call VerifyScreenDump(buf, 'Test_popupwin_popupmenu_masking_1', {}) 3564 3565 call term_sendkeys(buf, "\<Esc>") 3566 call VerifyScreenDump(buf, 'Test_popupwin_popupmenu_masking_2', {}) 3567 3568 call StopVimInTerminal(buf) 3569 call delete('XtestPopupmenuMasking') 3570endfunc 3571 3572func Test_popupwin_recycle_bnr() 3573 let bufnr = popup_notification('nothing wrong', {})->winbufnr() 3574 call popup_clear() 3575 let winid = 'nothing wrong'->popup_notification({}) 3576 call assert_equal(bufnr, winbufnr(winid)) 3577 call popup_clear() 3578endfunc 3579 3580func Test_popupwin_getoptions_tablocal() 3581 topleft split 3582 let win1 = popup_create('nothing', #{maxheight: 8}) 3583 let win2 = popup_create('something', #{maxheight: 10}) 3584 let win3 = popup_create('something', #{maxheight: 15}) 3585 call assert_equal(8, popup_getoptions(win1).maxheight) 3586 call assert_equal(10, popup_getoptions(win2).maxheight) 3587 call assert_equal(15, popup_getoptions(win3).maxheight) 3588 call popup_clear() 3589 quit 3590endfunc 3591 3592func Test_popupwin_cancel() 3593 let win1 = popup_create('one', #{line: 5, filter: {... -> 0}}) 3594 let win2 = popup_create('two', #{line: 10, filter: {... -> 0}}) 3595 let win3 = popup_create('three', #{line: 15, filter: {... -> 0}}) 3596 call assert_equal(5, popup_getpos(win1).line) 3597 call assert_equal(10, popup_getpos(win2).line) 3598 call assert_equal(15, popup_getpos(win3).line) 3599 " TODO: this also works without patch 8.1.2110 3600 call feedkeys("\<C-C>", 'xt') 3601 call assert_equal(5, popup_getpos(win1).line) 3602 call assert_equal(10, popup_getpos(win2).line) 3603 call assert_equal({}, popup_getpos(win3)) 3604 call feedkeys("\<C-C>", 'xt') 3605 call assert_equal(5, popup_getpos(win1).line) 3606 call assert_equal({}, popup_getpos(win2)) 3607 call assert_equal({}, popup_getpos(win3)) 3608 call feedkeys("\<C-C>", 'xt') 3609 call assert_equal({}, popup_getpos(win1)) 3610 call assert_equal({}, popup_getpos(win2)) 3611 call assert_equal({}, popup_getpos(win3)) 3612endfunc 3613 3614func Test_popupwin_filter_redraw() 3615 " Create two popups with a filter that closes the popup when typing "0". 3616 " Both popups should close, even though the redraw also calls 3617 " popup_reset_handled() 3618 3619 func CloseFilter(winid, key) 3620 if a:key == '0' 3621 call popup_close(a:winid) 3622 redraw 3623 endif 3624 return 0 " pass the key 3625 endfunc 3626 3627 let id1 = popup_create('first one', #{ 3628 \ line: 1, 3629 \ col: 1, 3630 \ filter: 'CloseFilter', 3631 \ }) 3632 let id2 = popup_create('second one', #{ 3633 \ line: 9, 3634 \ col: 1, 3635 \ filter: 'CloseFilter', 3636 \ }) 3637 call assert_equal(1, popup_getpos(id1).line) 3638 call assert_equal(9, popup_getpos(id2).line) 3639 3640 call feedkeys('0', 'xt') 3641 call assert_equal({}, popup_getpos(id1)) 3642 call assert_equal({}, popup_getpos(id2)) 3643 3644 call popup_clear() 3645 delfunc CloseFilter 3646endfunc 3647 3648func Test_popupwin_double_width() 3649 CheckScreendump 3650 3651 let lines =<< trim END 3652 call setline(1, 'x你好世界你好世你好世界你好') 3653 call setline(2, '你好世界你好世你好世界你好') 3654 call setline(3, 'x你好世界你好世你好世界你好') 3655 call popup_create('你好,世界 - 你好,世界xxxxx', #{line: 1, col: 3, maxwidth: 14}) 3656 END 3657 call writefile(lines, 'XtestPopupWide') 3658 3659 let buf = RunVimInTerminal('-S XtestPopupWide', #{rows: 10}) 3660 call VerifyScreenDump(buf, 'Test_popupwin_doublewidth_1', {}) 3661 3662 call StopVimInTerminal(buf) 3663 call delete('XtestPopupWide') 3664endfunc 3665 3666func Test_popupwin_sign() 3667 CheckScreendump 3668 3669 let lines =<< trim END 3670 call setline(1, range(10)) 3671 call sign_define('Current', { 3672 \ 'text': '>>', 3673 \ 'texthl': 'WarningMsg', 3674 \ 'linehl': 'Error', 3675 \ }) 3676 call sign_define('Other', { 3677 \ 'text': '#!', 3678 \ 'texthl': 'Error', 3679 \ 'linehl': 'Search', 3680 \ }) 3681 let winid = popup_create(['hello', 'bright', 'world'], { 3682 \ 'minwidth': 20, 3683 \ }) 3684 call setwinvar(winid, "&signcolumn", "yes") 3685 let winbufnr = winbufnr(winid) 3686 3687 " add sign to current buffer, shows 3688 call sign_place(1, 'Selected', 'Current', bufnr('%'), {'lnum': 1}) 3689 " add sign to current buffer, does not show 3690 call sign_place(2, 'PopUpSelected', 'Other', bufnr('%'), {'lnum': 2}) 3691 3692 " add sign to popup buffer, shows 3693 call sign_place(3, 'PopUpSelected', 'Other', winbufnr, {'lnum': 1}) 3694 " add sign to popup buffer, does not show 3695 call sign_place(4, 'Selected', 'Current', winbufnr, {'lnum': 2}) 3696 3697 func SetOptions() 3698 call setwinvar(g:winid, '&number', 1) 3699 call setwinvar(g:winid, '&foldcolumn', 2) 3700 call popup_settext(g:winid, 'a longer line to check the width') 3701 endfunc 3702 END 3703 call writefile(lines, 'XtestPopupSign') 3704 3705 let buf = RunVimInTerminal('-S XtestPopupSign', #{rows: 10}) 3706 call VerifyScreenDump(buf, 'Test_popupwin_sign_1', {}) 3707 3708 " set more options to check the width is adjusted 3709 call term_sendkeys(buf, ":call SetOptions()\<CR>") 3710 call VerifyScreenDump(buf, 'Test_popupwin_sign_2', {}) 3711 3712 call StopVimInTerminal(buf) 3713 call delete('XtestPopupSign') 3714endfunc 3715 3716func Test_popupwin_bufnr() 3717 let popwin = popup_create(['blah'], #{}) 3718 let popbuf = winbufnr(popwin) 3719 split asdfasdf 3720 let newbuf = bufnr() 3721 call assert_true(newbuf > popbuf, 'New buffer number is higher') 3722 call assert_equal(newbuf, bufnr('$')) 3723 call popup_clear() 3724 let popwin = popup_create(['blah'], #{}) 3725 " reuses previous buffer number 3726 call assert_equal(popbuf, winbufnr(popwin)) 3727 call assert_equal(newbuf, bufnr('$')) 3728 3729 call popup_clear() 3730 bwipe! 3731endfunc 3732 3733func Test_popupwin_filter_input_multibyte() 3734 func MyPopupFilter(winid, c) 3735 let g:bytes = range(a:c->strlen())->map({i -> char2nr(a:c[i])}) 3736 return 0 3737 endfunc 3738 let winid = popup_create('', #{mapping: 0, filter: 'MyPopupFilter'}) 3739 3740 " UTF-8: E3 80 80, including K_SPECIAL(0x80) 3741 call feedkeys("\u3000", 'xt') 3742 call assert_equal([0xe3, 0x80, 0x80], g:bytes) 3743 3744 " UTF-8: E3 80 9B, including CSI(0x9B) 3745 call feedkeys("\u301b", 'xt') 3746 call assert_equal([0xe3, 0x80, 0x9b], g:bytes) 3747 3748 if has('unix') 3749 " with modifyOtherKeys <M-S-a> does not include a modifier sequence 3750 if has('gui_running') 3751 call feedkeys("\x9b\xfc\x08A", 'Lx!') 3752 else 3753 call feedkeys("\<Esc>[27;4;65~", 'Lx!') 3754 endif 3755 call assert_equal([0xc3, 0x81], g:bytes) 3756 endif 3757 3758 call popup_clear() 3759 delfunc MyPopupFilter 3760 unlet g:bytes 3761endfunc 3762 3763func Test_popupwin_filter_close_ctrl_c() 3764 CheckScreendump 3765 3766 let lines =<< trim END 3767 vsplit 3768 set laststatus=2 3769 set statusline=%!Statusline() 3770 3771 function Statusline() abort 3772 return '%<%f %h%m%r%=%-14.(%l,%c%V%) %P' 3773 endfunction 3774 3775 call popup_create('test test test test...', {'filter': {-> 0}}) 3776 END 3777 call writefile(lines, 'XtestPopupCtrlC') 3778 3779 let buf = RunVimInTerminal('-S XtestPopupCtrlC', #{rows: 10}) 3780 3781 call term_sendkeys(buf, "\<C-C>") 3782 call VerifyScreenDump(buf, 'Test_popupwin_ctrl_c', {}) 3783 3784 call StopVimInTerminal(buf) 3785 call delete('XtestPopupCtrlC') 3786endfunc 3787 3788func Test_popupwin_filter_close_wrong_name() 3789 CheckScreendump 3790 3791 let lines =<< trim END 3792 call popup_create('one two three...', {'filter': 'NoSuchFunc'}) 3793 END 3794 call writefile(lines, 'XtestPopupWrongName') 3795 3796 let buf = RunVimInTerminal('-S XtestPopupWrongName', #{rows: 10}) 3797 3798 call term_sendkeys(buf, "j") 3799 call VerifyScreenDump(buf, 'Test_popupwin_wrong_name', {}) 3800 3801 call StopVimInTerminal(buf) 3802 call delete('XtestPopupWrongName') 3803endfunc 3804 3805func Test_popupwin_filter_close_three_errors() 3806 CheckScreendump 3807 3808 let lines =<< trim END 3809 set cmdheight=2 3810 call popup_create('one two three...', {'filter': 'filter'}) 3811 END 3812 call writefile(lines, 'XtestPopupThreeErrors') 3813 3814 let buf = RunVimInTerminal('-S XtestPopupThreeErrors', #{rows: 10}) 3815 3816 call term_sendkeys(buf, "jj") 3817 call VerifyScreenDump(buf, 'Test_popupwin_three_errors_1', {}) 3818 call term_sendkeys(buf, "j") 3819 call VerifyScreenDump(buf, 'Test_popupwin_three_errors_2', {}) 3820 3821 call StopVimInTerminal(buf) 3822 call delete('XtestPopupThreeErrors') 3823endfunc 3824 3825func Test_popupwin_latin1_encoding() 3826 CheckScreendump 3827 CheckUnix 3828 3829 " When 'encoding' is a single-byte encoding a terminal window will mess up 3830 " the display. Check that showing a popup on top of that doesn't crash. 3831 let lines =<< trim END 3832 set encoding=latin1 3833 terminal cat Xmultibyte 3834 call popup_create(['one', 'two', 'three', 'four'], #{line: 1, col: 10}) 3835 redraw 3836 " wait for "cat" to finish 3837 while execute('ls!') !~ 'finished' 3838 sleep 10m 3839 endwhile 3840 echo "Done" 3841 END 3842 call writefile(lines, 'XtestPopupLatin') 3843 call writefile([repeat("\u3042 ", 120)], 'Xmultibyte') 3844 3845 let buf = RunVimInTerminal('-S XtestPopupLatin', #{rows: 10}) 3846 call WaitForAssert({-> assert_match('Done', term_getline(buf, 10))}) 3847 3848 call term_sendkeys(buf, ":q\<CR>") 3849 call StopVimInTerminal(buf) 3850 call delete('XtestPopupLatin') 3851 call delete('Xmultibyte') 3852endfunc 3853 3854func Test_popupwin_atcursor_far_right() 3855 new 3856 3857 " this was getting stuck 3858 set signcolumn=yes 3859 call setline(1, repeat('=', &columns)) 3860 normal! ggg$ 3861 let winid = popup_atcursor(repeat('x', 500), #{moved: 'any', border: []}) 3862 3863 " 'signcolumn' was getting reset 3864 call setwinvar(winid, '&signcolumn', 'yes') 3865 call popup_setoptions(winid, {'zindex': 1000}) 3866 call assert_equal('yes', getwinvar(winid, '&signcolumn')) 3867 3868 call popup_close(winid) 3869 bwipe! 3870 set signcolumn& 3871endfunc 3872 3873func Test_popupwin_splitmove() 3874 vsplit 3875 let win2 = win_getid() 3876 let popup_winid = popup_dialog('hello', {}) 3877 call assert_fails('call win_splitmove(popup_winid, win2)', 'E957:') 3878 call assert_fails('call win_splitmove(win2, popup_winid)', 'E957:') 3879 3880 call popup_clear() 3881 bwipe 3882endfunc 3883 3884func Test_popupwin_exiting_terminal() 3885 CheckFeature terminal 3886 3887 " Tests that when creating a popup right after closing a terminal window does 3888 " not make the popup the current window. 3889 let winid = win_getid() 3890 try 3891 augroup Test_popupwin_exiting_terminal 3892 autocmd! 3893 autocmd WinEnter * :call popup_create('test', {}) 3894 augroup END 3895 let bnr = term_start(&shell, #{term_finish: 'close'}) 3896 call term_sendkeys(bnr, "exit\r\n") 3897 call WaitForAssert({-> assert_equal(winid, win_getid())}) 3898 finally 3899 call popup_clear(1) 3900 augroup Test_popupwin_exiting_terminal 3901 autocmd! 3902 augroup END 3903 endtry 3904endfunc 3905 3906func Test_popup_filter_menu() 3907 let colors = ['red', 'green', 'blue'] 3908 call popup_menu(colors, #{callback: {_, result -> assert_equal('green', colors[result - 1])}}) 3909 call feedkeys("\<c-n>\<c-n>\<c-p>\<cr>", 'xt') 3910endfunc 3911 3912func Test_popup_getoptions_other_tab() 3913 new 3914 call setline(1, 'some text') 3915 call prop_type_add('textprop', {}) 3916 call prop_add(1, 1, #{type: 'textprop', length: 1}) 3917 let id = popup_create('TEST', #{textprop: 'textprop', highlight: 'ErrorMsg', tabpage: 1}) 3918 tab sp 3919 call assert_equal(['textprop', 'textpropid', 'textpropwin'], popup_getoptions(id)->keys()->filter({_, v -> v =~ 'textprop'})) 3920 3921 tabclose 3922 call popup_close(id) 3923 bwipe! 3924 call prop_type_delete('textprop') 3925endfunc 3926 3927 3928func Test_popup_setoptions_other_tab() 3929 new Xfile 3930 let winid = win_getid() 3931 call setline(1, 'some text') 3932 call prop_type_add('textprop', {}) 3933 call prop_add(1, 1, #{type: 'textprop', length: 1}) 3934 let id = popup_create('TEST', #{textprop: 'textprop'}) 3935 tab sp 3936 call popup_setoptions(id, #{textprop: 'textprop', textpropwin: winid}) 3937 call assert_equal(winid, popup_getoptions(id).textpropwin) 3938 3939 tabclose 3940 call popup_close(id) 3941 bwipe! Xfile 3942 call prop_type_delete('textprop') 3943endfunc 3944 3945func Test_popup_prop_not_visible() 3946 CheckScreendump 3947 3948 let lines =<< trim END 3949 vim9script 3950 set nowrap stal=2 3951 rightbelow :31vnew 3952 setline(1, ['', 'some text', '', 'other text']) 3953 prop_type_add('someprop', {}) 3954 prop_add(2, 9, {type: 'someprop', length: 5}) 3955 popup_create('attached to "some"', { 3956 textprop: 'someprop', 3957 highlight: 'ErrorMsg', 3958 line: -1, 3959 wrap: false, 3960 fixed: true, 3961 }) 3962 prop_type_add('otherprop', {}) 3963 prop_add(4, 10, {type: 'otherprop', length: 5}) 3964 popup_create('attached to "other"', { 3965 textprop: 'otherprop', 3966 highlight: 'ErrorMsg', 3967 line: -1, 3968 wrap: false, 3969 fixed: false, 3970 }) 3971 END 3972 call writefile(lines, 'XtestPropNotVisble') 3973 let buf = RunVimInTerminal('-S XtestPropNotVisble', #{rows: 10}) 3974 call VerifyScreenDump(buf, 'Test_popup_prop_not_visible_01', {}) 3975 3976 call term_sendkeys(buf, ":vert resize -14\<CR>") 3977 call VerifyScreenDump(buf, 'Test_popup_prop_not_visible_02', {}) 3978 3979 call term_sendkeys(buf, ":vert resize -8\<CR>") 3980 call VerifyScreenDump(buf, 'Test_popup_prop_not_visible_03', {}) 3981 3982 " clean up 3983 call StopVimInTerminal(buf) 3984 call delete('XtestPropNotVisble') 3985endfunction 3986 3987func Test_bufdel_skips_popupwin_buffer() 3988 let id = popup_create("Some text", {}) 3989 %bd 3990 call popup_close(id) 3991endfunc 3992 3993 3994" vim: shiftwidth=2 sts=2 3995