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_noscrolloff() 520 set scrolloff=5 521 let winid = popup_create(['xxx']->repeat(50), #{ 522 \ maxheight: 5, 523 \ firstline: 11, 524 \ }) 525 redraw 526 call assert_equal(11, popup_getoptions(winid).firstline) 527 call assert_equal(11, popup_getpos(winid).firstline) 528 529 call popup_setoptions(winid, #{firstline: 0}) 530 call win_execute(winid, "normal! \<c-y>") 531 call assert_equal(0, popup_getoptions(winid).firstline) 532 call assert_equal(10, popup_getpos(winid).firstline) 533 534 call popup_close(winid) 535endfunc 536 537func Test_popup_drag() 538 CheckScreendump 539 540 " create a popup that covers the command line 541 let lines =<< trim END 542 call setline(1, range(1, 20)) 543 split 544 vsplit 545 $wincmd w 546 vsplit 547 1wincmd w 548 let winid = popup_create(['1111', '222222', '33333'], #{ 549 \ drag: 1, 550 \ resize: 1, 551 \ border: [], 552 \ line: &lines - 4, 553 \ }) 554 func Dragit() 555 call feedkeys("\<F3>\<LeftMouse>\<F4>\<LeftDrag>\<LeftRelease>", "xt") 556 endfunc 557 map <silent> <F3> :call test_setmouse(&lines - 4, &columns / 2)<CR> 558 map <silent> <F4> :call test_setmouse(&lines - 8, &columns / 2 - 20)<CR> 559 func Resize() 560 call feedkeys("\<F5>\<LeftMouse>\<F6>\<LeftDrag>\<LeftRelease>", "xt") 561 endfunc 562 map <silent> <F5> :call test_setmouse(6, 21)<CR> 563 map <silent> <F6> :call test_setmouse(7, 25)<CR> 564 END 565 call writefile(lines, 'XtestPopupDrag') 566 let buf = RunVimInTerminal('-S XtestPopupDrag', #{rows: 10}) 567 call VerifyScreenDump(buf, 'Test_popupwin_drag_01', {}) 568 569 call term_sendkeys(buf, ":call Dragit()\<CR>") 570 call VerifyScreenDump(buf, 'Test_popupwin_drag_02', {}) 571 572 call term_sendkeys(buf, ":call Resize()\<CR>") 573 call VerifyScreenDump(buf, 'Test_popupwin_drag_03', {}) 574 575 " clean up 576 call StopVimInTerminal(buf) 577 call delete('XtestPopupDrag') 578endfunc 579 580func Test_popup_close_with_mouse() 581 CheckScreendump 582 583 let lines =<< trim END 584 call setline(1, range(1, 20)) 585 " With border, can click on X 586 let winid = popup_create('foobar', #{ 587 \ close: 'button', 588 \ border: [], 589 \ line: 1, 590 \ col: 1, 591 \ }) 592 func CloseMsg(id, result) 593 echomsg 'Popup closed with ' .. a:result 594 endfunc 595 let winid = popup_create('notification', #{ 596 \ close: 'click', 597 \ line: 3, 598 \ col: 15, 599 \ callback: 'CloseMsg', 600 \ }) 601 let winid = popup_create('no border here', #{ 602 \ close: 'button', 603 \ line: 5, 604 \ col: 3, 605 \ }) 606 let winid = popup_create('only padding', #{ 607 \ close: 'button', 608 \ padding: [], 609 \ line: 5, 610 \ col: 23, 611 \ }) 612 func CloseWithX() 613 call feedkeys("\<F3>\<LeftMouse>\<LeftRelease>", "xt") 614 endfunc 615 map <silent> <F3> :call test_setmouse(1, len('foobar') + 2)<CR> 616 func CloseWithClick() 617 call feedkeys("\<F4>\<LeftMouse>\<LeftRelease>", "xt") 618 endfunc 619 map <silent> <F4> :call test_setmouse(3, 17)<CR> 620 func CreateWithMenuFilter() 621 let winid = popup_create('barfoo', #{ 622 \ close: 'button', 623 \ filter: 'popup_filter_menu', 624 \ border: [], 625 \ line: 1, 626 \ col: 40, 627 \ }) 628 endfunc 629 END 630 call writefile(lines, 'XtestPopupClose') 631 let buf = RunVimInTerminal('-S XtestPopupClose', #{rows: 10}) 632 call VerifyScreenDump(buf, 'Test_popupwin_close_01', {}) 633 634 call term_sendkeys(buf, ":call CloseWithX()\<CR>") 635 call VerifyScreenDump(buf, 'Test_popupwin_close_02', {}) 636 637 call term_sendkeys(buf, ":call CloseWithClick()\<CR>") 638 call VerifyScreenDump(buf, 'Test_popupwin_close_03', {}) 639 640 call term_sendkeys(buf, ":call CreateWithMenuFilter()\<CR>") 641 call VerifyScreenDump(buf, 'Test_popupwin_close_04', {}) 642 643 " We have to send the actual mouse code, feedkeys() would be caught the 644 " filter. 645 call term_sendkeys(buf, "\<Esc>[<0;47;1M") 646 call VerifyScreenDump(buf, 'Test_popupwin_close_05', {}) 647 648 " clean up 649 call StopVimInTerminal(buf) 650 call delete('XtestPopupClose') 651endfunction 652 653func Test_popup_menu_wrap() 654 CheckScreendump 655 656 let lines =<< trim END 657 call setline(1, range(1, 20)) 658 call popup_create([ 659 \ 'one', 660 \ 'asdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfasdfas', 661 \ 'three', 662 \ 'four', 663 \ ], #{ 664 \ pos: "botleft", 665 \ border: [], 666 \ padding: [0,1,0,1], 667 \ maxheight: 3, 668 \ cursorline: 1, 669 \ filter: 'popup_filter_menu', 670 \ }) 671 END 672 call writefile(lines, 'XtestPopupWrap') 673 let buf = RunVimInTerminal('-S XtestPopupWrap', #{rows: 10}) 674 call VerifyScreenDump(buf, 'Test_popupwin_wrap_1', {}) 675 676 call term_sendkeys(buf, "jj") 677 call VerifyScreenDump(buf, 'Test_popupwin_wrap_2', {}) 678 679 " clean up 680 call term_sendkeys(buf, "\<Esc>") 681 call StopVimInTerminal(buf) 682 call delete('XtestPopupWrap') 683endfunction 684 685func Test_popup_with_mask() 686 CheckScreendump 687 688 let lines =<< trim END 689 call setline(1, repeat([join(range(1, 42), '')], 13)) 690 hi PopupColor ctermbg=lightgrey 691 let winid = popup_create([ 692 \ 'some text', 693 \ 'another line', 694 \], #{ 695 \ line: 1, 696 \ col: 10, 697 \ posinvert: 0, 698 \ wrap: 0, 699 \ fixed: 1, 700 \ zindex: 90, 701 \ padding: [], 702 \ highlight: 'PopupColor', 703 \ mask: [[1,1,1,1], [-5,-1,4,4], [7,9,2,3], [2,4,3,3]]}) 704 call popup_create([ 705 \ 'xxxxxxxxx', 706 \ 'yyyyyyyyy', 707 \], #{ 708 \ line: 3, 709 \ col: 18, 710 \ zindex: 20}) 711 let winidb = popup_create([ 712 \ 'just one line', 713 \], #{ 714 \ line: 7, 715 \ col: 10, 716 \ posinvert: 0, 717 \ wrap: 0, 718 \ fixed: 1, 719 \ close: 'button', 720 \ zindex: 90, 721 \ padding: [], 722 \ border: [], 723 \ mask: [[1,2,1,1], [-5,-1,4,4], [7,9,2,3], [3,5,5,5],[-7,-4,5,5]]}) 724 END 725 call writefile(lines, 'XtestPopupMask') 726 let buf = RunVimInTerminal('-S XtestPopupMask', #{rows: 13}) 727 call VerifyScreenDump(buf, 'Test_popupwin_mask_1', {}) 728 729 call term_sendkeys(buf, ":call popup_move(winid, #{col: 11, line: 2})\<CR>") 730 call term_sendkeys(buf, ":call popup_move(winidb, #{col: 12})\<CR>") 731 call term_sendkeys(buf, ":\<CR>") 732 call VerifyScreenDump(buf, 'Test_popupwin_mask_2', {}) 733 734 call term_sendkeys(buf, ":call popup_move(winid, #{col: 65, line: 2})\<CR>") 735 call term_sendkeys(buf, ":call popup_move(winidb, #{col: 63})\<CR>") 736 call term_sendkeys(buf, ":\<CR>") 737 call VerifyScreenDump(buf, 'Test_popupwin_mask_3', {}) 738 739 call term_sendkeys(buf, ":call popup_move(winid, #{pos: 'topright', col: 12, line: 2})\<CR>") 740 call term_sendkeys(buf, ":call popup_move(winidb, #{pos: 'topright', col: 12})\<CR>") 741 call term_sendkeys(buf, ":\<CR>") 742 call VerifyScreenDump(buf, 'Test_popupwin_mask_4', {}) 743 744 call term_sendkeys(buf, ":call popup_move(winid, #{pos: 'topright', col: 12, line: 11})\<CR>") 745 call term_sendkeys(buf, ":call popup_move(winidb, #{pos: 'topleft', col: 42, line: 11})\<CR>") 746 call term_sendkeys(buf, ":\<CR>") 747 call VerifyScreenDump(buf, 'Test_popupwin_mask_5', {}) 748 749 " clean up 750 call StopVimInTerminal(buf) 751 call delete('XtestPopupMask') 752endfunc 753 754func Test_popup_select() 755 CheckScreendump 756 CheckFeature clipboard_working 757 758 " create a popup with some text to be selected 759 let lines =<< trim END 760 set clipboard=autoselect 761 call setline(1, range(1, 20)) 762 let winid = popup_create(['the word', 'some more', 'several words here', 'invisible', '5', '6', '7'], #{ 763 \ drag: 1, 764 \ border: [], 765 \ line: 3, 766 \ col: 10, 767 \ maxheight: 3, 768 \ }) 769 func Select1() 770 call feedkeys("\<F3>\<LeftMouse>\<F4>\<LeftDrag>\<LeftRelease>", "xt") 771 endfunc 772 map <silent> <F3> :call test_setmouse(4, 15)<CR> 773 map <silent> <F4> :call test_setmouse(6, 23)<CR> 774 END 775 call writefile(lines, 'XtestPopupSelect') 776 let buf = RunVimInTerminal('-S XtestPopupSelect', #{rows: 10}) 777 call term_sendkeys(buf, ":call Select1()\<CR>") 778 call VerifyScreenDump(buf, 'Test_popupwin_select_01', {}) 779 780 call term_sendkeys(buf, ":call popup_close(winid)\<CR>") 781 call term_sendkeys(buf, "\"*p") 782 " clean the command line, sometimes it still shows a command 783 call term_sendkeys(buf, ":\<esc>") 784 785 call VerifyScreenDump(buf, 'Test_popupwin_select_02', {}) 786 787 " clean up 788 call StopVimInTerminal(buf) 789 call delete('XtestPopupSelect') 790endfunc 791 792func Test_popup_in_tab() 793 " default popup is local to tab, not visible when in other tab 794 let winid = popup_create("text", {}) 795 let bufnr = winbufnr(winid) 796 call assert_equal(1, popup_getpos(winid).visible) 797 call assert_equal(0, popup_getoptions(winid).tabpage) 798 tabnew 799 call assert_equal(0, popup_getpos(winid).visible) 800 call assert_equal(1, popup_getoptions(winid).tabpage) 801 quit 802 call assert_equal(1, popup_getpos(winid).visible) 803 804 call assert_equal(1, bufexists(bufnr)) 805 call popup_clear() 806 " buffer is gone now 807 call assert_equal(0, bufexists(bufnr)) 808 809 " global popup is visible in any tab 810 let winid = popup_create("text", #{tabpage: -1}) 811 call assert_equal(1, popup_getpos(winid).visible) 812 call assert_equal(-1, popup_getoptions(winid).tabpage) 813 tabnew 814 call assert_equal(1, popup_getpos(winid).visible) 815 call assert_equal(-1, popup_getoptions(winid).tabpage) 816 quit 817 call assert_equal(1, popup_getpos(winid).visible) 818 call popup_clear() 819 820 " create popup in other tab 821 tabnew 822 let winid = popup_create("text", #{tabpage: 1}) 823 call assert_equal(0, popup_getpos(winid).visible) 824 call assert_equal(1, popup_getoptions(winid).tabpage) 825 quit 826 call assert_equal(1, popup_getpos(winid).visible) 827 call assert_equal(0, popup_getoptions(winid).tabpage) 828 call popup_clear() 829endfunc 830 831func Test_popup_valid_arguments() 832 call assert_equal(0, len(popup_list())) 833 834 " Zero value is like the property wasn't there 835 let winid = popup_create("text", #{col: 0}) 836 let pos = popup_getpos(winid) 837 call assert_inrange(&columns / 2 - 1, &columns / 2 + 1, pos.col) 838 call assert_equal([winid], popup_list()) 839 call popup_clear() 840 841 " using cursor column has minimum value of 1 842 let winid = popup_create("text", #{col: 'cursor-100'}) 843 let pos = popup_getpos(winid) 844 call assert_equal(1, pos.col) 845 call popup_clear() 846 847 " center 848 let winid = popup_create("text", #{pos: 'center'}) 849 let pos = popup_getpos(winid) 850 let around = (&columns - pos.width) / 2 851 call assert_inrange(around - 1, around + 1, pos.col) 852 let around = (&lines - pos.height) / 2 853 call assert_inrange(around - 1, around + 1, pos.line) 854 call popup_clear() 855endfunc 856 857func Test_popup_invalid_arguments() 858 call assert_fails('call popup_create(666, {})', 'E86:') 859 call popup_clear() 860 call assert_fails('call popup_create("text", "none")', 'E715:') 861 call popup_clear() 862 call assert_fails('call popup_create(test_null_string(), {})', 'E450:') 863 call assert_fails('call popup_create(test_null_list(), {})', 'E450:') 864 call popup_clear() 865 866 call assert_fails('call popup_create("text", #{col: "xxx"})', 'E475:') 867 call popup_clear() 868 call assert_fails('call popup_create("text", #{col: "cursor8"})', 'E15:') 869 call popup_clear() 870 call assert_fails('call popup_create("text", #{col: "cursor+x"})', 'E15:') 871 call popup_clear() 872 call assert_fails('call popup_create("text", #{col: "cursor+8x"})', 'E15:') 873 call popup_clear() 874 875 call assert_fails('call popup_create("text", #{line: "xxx"})', 'E475:') 876 call popup_clear() 877 call assert_fails('call popup_create("text", #{line: "cursor8"})', 'E15:') 878 call popup_clear() 879 call assert_fails('call popup_create("text", #{line: "cursor+x"})', 'E15:') 880 call popup_clear() 881 call assert_fails('call popup_create("text", #{line: "cursor+8x"})', 'E15:') 882 call popup_clear() 883 884 call assert_fails('call popup_create("text", #{pos: "there"})', 'E475:') 885 call popup_clear() 886 call assert_fails('call popup_create("text", #{padding: "none"})', 'E714:') 887 call popup_clear() 888 call assert_fails('call popup_create("text", #{border: "none"})', 'E714:') 889 call popup_clear() 890 call assert_fails('call popup_create("text", #{borderhighlight: "none"})', 'E714:') 891 call popup_clear() 892 call assert_fails('call popup_create("text", #{borderhighlight: test_null_list()})', 'E714:') 893 call popup_clear() 894 call assert_fails('call popup_create("text", #{borderchars: "none"})', 'E714:') 895 call popup_clear() 896 897 call assert_fails('call popup_create([#{text: "text"}, 666], {})', 'E715:') 898 call popup_clear() 899 call assert_fails('call popup_create([#{text: "text", props: "none"}], {})', 'E714:') 900 call popup_clear() 901 call assert_fails('call popup_create([#{text: "text", props: ["none"]}], {})', 'E715:') 902 call popup_clear() 903 call assert_fails('call popup_create([#{text: "text", props: range(3)}], {})', 'E715:') 904 call popup_clear() 905 call assert_fails('call popup_create("text", #{mask: ["asdf"]})', 'E475:') 906 call popup_clear() 907 call assert_fails('call popup_create("text", #{mask: range(5)})', 'E475:') 908 call popup_clear() 909 call popup_create("text", #{mask: [range(4)]}) 910 call popup_clear() 911 call assert_fails('call popup_create("text", #{mask: test_null_list()})', 'E475:') 912 call assert_fails('call popup_create("text", #{mapping: []})', 'E745:') 913 call popup_clear() 914 call assert_fails('call popup_create("text", #{tabpage : 4})', 'E997:') 915 call popup_clear() 916endfunc 917 918func Test_win_execute_closing_curwin() 919 split 920 let winid = popup_create('some text', {}) 921 call assert_fails('call win_execute(winid, winnr() .. "close")', 'E994') 922 call popup_clear() 923 924 let winid = popup_create('some text', {}) 925 call assert_fails('call win_execute(winid, printf("normal! :\<C-u>call popup_close(%d)\<CR>", winid))', 'E994') 926 call popup_clear() 927endfunc 928 929func Test_win_execute_not_allowed() 930 let winid = popup_create('some text', {}) 931 call assert_fails('call win_execute(winid, "split")', 'E994:') 932 call assert_fails('call win_execute(winid, "vsplit")', 'E994:') 933 call assert_fails('call win_execute(winid, "close")', 'E994:') 934 call assert_fails('call win_execute(winid, "bdelete")', 'E994:') 935 call assert_fails('call win_execute(winid, "bwipe!")', 'E994:') 936 call assert_fails('call win_execute(winid, "tabnew")', 'E994:') 937 call assert_fails('call win_execute(winid, "tabnext")', 'E994:') 938 call assert_fails('call win_execute(winid, "next")', 'E994:') 939 call assert_fails('call win_execute(winid, "rewind")', 'E994:') 940 call assert_fails('call win_execute(winid, "pedit filename")', 'E994:') 941 call assert_fails('call win_execute(winid, "buf")', 'E994:') 942 call assert_fails('call win_execute(winid, "bnext")', 'E994:') 943 call assert_fails('call win_execute(winid, "bprev")', 'E994:') 944 call assert_fails('call win_execute(winid, "bfirst")', 'E994:') 945 call assert_fails('call win_execute(winid, "blast")', 'E994:') 946 call assert_fails('call win_execute(winid, "edit")', 'E994:') 947 call assert_fails('call win_execute(winid, "enew")', 'E994:') 948 call assert_fails('call win_execute(winid, "wincmd x")', 'E994:') 949 call assert_fails('call win_execute(winid, "wincmd w")', 'E994:') 950 call assert_fails('call win_execute(winid, "wincmd t")', 'E994:') 951 call assert_fails('call win_execute(winid, "wincmd b")', 'E994:') 952 call popup_clear() 953endfunc 954 955func Test_popup_with_wrap() 956 CheckScreendump 957 958 let lines =<< trim END 959 call setline(1, range(1, 100)) 960 let winid = popup_create( 961 \ 'a long line that wont fit', 962 \ #{line: 3, col: 20, maxwidth: 10, wrap: 1}) 963 END 964 call writefile(lines, 'XtestPopup') 965 let buf = RunVimInTerminal('-S XtestPopup', #{rows: 10}) 966 call VerifyScreenDump(buf, 'Test_popupwin_wrap', {}) 967 968 " clean up 969 call StopVimInTerminal(buf) 970 call delete('XtestPopup') 971endfunc 972 973func Test_popup_without_wrap() 974 CheckScreendump 975 976 let lines =<< trim END 977 call setline(1, range(1, 100)) 978 let winid = popup_create( 979 \ 'a long line that wont fit', 980 \ #{line: 3, col: 20, maxwidth: 10, wrap: 0}) 981 END 982 call writefile(lines, 'XtestPopup') 983 let buf = RunVimInTerminal('-S XtestPopup', #{rows: 10}) 984 call VerifyScreenDump(buf, 'Test_popupwin_nowrap', {}) 985 986 " clean up 987 call StopVimInTerminal(buf) 988 call delete('XtestPopup') 989endfunc 990 991func Test_popup_with_showbreak() 992 CheckScreendump 993 994 let lines =<< trim END 995 set showbreak=>>\ 996 call setline(1, range(1, 20)) 997 let winid = popup_dialog( 998 \ 'a long line here that wraps', 999 \ #{filter: 'popup_filter_yesno', 1000 \ maxwidth: 12}) 1001 END 1002 call writefile(lines, 'XtestPopupShowbreak') 1003 let buf = RunVimInTerminal('-S XtestPopupShowbreak', #{rows: 10}) 1004 call VerifyScreenDump(buf, 'Test_popupwin_showbreak', {}) 1005 1006 " clean up 1007 call term_sendkeys(buf, "y") 1008 call StopVimInTerminal(buf) 1009 call delete('XtestPopupShowbreak') 1010endfunc 1011 1012func Test_popup_time() 1013 CheckFeature timers 1014 1015 topleft vnew 1016 call setline(1, 'hello') 1017 1018 let winid = popup_create('world', #{ 1019 \ line: 1, 1020 \ col: 1, 1021 \ minwidth: 20, 1022 \ time: 500, 1023 \}) 1024 redraw 1025 let line = join(map(range(1, 5), 'screenstring(1, v:val)'), '') 1026 call assert_equal('world', line) 1027 1028 call assert_equal(winid, popup_locate(1, 1)) 1029 call assert_equal(winid, popup_locate(1, 20)) 1030 call assert_equal(0, popup_locate(1, 21)) 1031 call assert_equal(0, popup_locate(2, 1)) 1032 1033 sleep 700m 1034 redraw 1035 let line = join(map(range(1, 5), '1->screenstring(v:val)'), '') 1036 call assert_equal('hello', line) 1037 1038 call popup_create('on the command line', #{ 1039 \ line: &lines, 1040 \ col: 10, 1041 \ minwidth: 20, 1042 \ time: 500, 1043 \}) 1044 redraw 1045 let line = join(map(range(1, 30), 'screenstring(&lines, v:val)'), '') 1046 call assert_match('.*on the command line.*', line) 1047 1048 sleep 700m 1049 redraw 1050 let line = join(map(range(1, 30), 'screenstring(&lines, v:val)'), '') 1051 call assert_notmatch('.*on the command line.*', line) 1052 1053 bwipe! 1054endfunc 1055 1056func Test_popup_hide() 1057 topleft vnew 1058 call setline(1, 'hello') 1059 1060 let winid = popup_create('world', #{ 1061 \ line: 1, 1062 \ col: 1, 1063 \ minwidth: 20, 1064 \}) 1065 redraw 1066 let line = join(map(range(1, 5), 'screenstring(1, v:val)'), '') 1067 call assert_equal('world', line) 1068 call assert_equal(1, popup_getpos(winid).visible) 1069 " buffer is still listed and active 1070 call assert_match(winbufnr(winid) .. 'u a.*\[Popup\]', execute('ls u')) 1071 1072 call popup_hide(winid) 1073 redraw 1074 let line = join(map(range(1, 5), 'screenstring(1, v:val)'), '') 1075 call assert_equal('hello', line) 1076 call assert_equal(0, popup_getpos(winid).visible) 1077 " buffer is still listed but hidden 1078 call assert_match(winbufnr(winid) .. 'u a.*\[Popup\]', execute('ls u')) 1079 1080 eval winid->popup_show() 1081 redraw 1082 let line = join(map(range(1, 5), 'screenstring(1, v:val)'), '') 1083 call assert_equal('world', line) 1084 call assert_equal(1, popup_getpos(winid).visible) 1085 1086 1087 call popup_close(winid) 1088 redraw 1089 let line = join(map(range(1, 5), 'screenstring(1, v:val)'), '') 1090 call assert_equal('hello', line) 1091 1092 " error is given for existing non-popup window 1093 call assert_fails('call popup_hide(win_getid())', 'E993:') 1094 1095 " no error non-existing window 1096 eval 1234234->popup_hide() 1097 call popup_show(41234234) 1098 1099 bwipe! 1100endfunc 1101 1102func Test_popup_move() 1103 topleft vnew 1104 call setline(1, 'hello') 1105 1106 let winid = popup_create('world', #{ 1107 \ line: 1, 1108 \ col: 1, 1109 \ minwidth: 20, 1110 \}) 1111 redraw 1112 let line = join(map(range(1, 6), 'screenstring(1, v:val)'), '') 1113 call assert_equal('world ', line) 1114 1115 call popup_move(winid, #{line: 2, col: 2}) 1116 redraw 1117 let line = join(map(range(1, 6), 'screenstring(1, v:val)'), '') 1118 call assert_equal('hello ', line) 1119 let line = join(map(range(1, 6), 'screenstring(2, v:val)'), '') 1120 call assert_equal('~world', line) 1121 1122 eval winid->popup_move(#{line: 1}) 1123 redraw 1124 let line = join(map(range(1, 6), 'screenstring(1, v:val)'), '') 1125 call assert_equal('hworld', line) 1126 1127 call assert_fails('call popup_move(winid, [])', 'E715:') 1128 call assert_fails('call popup_move(winid, test_null_dict())', 'E715:') 1129 1130 call popup_close(winid) 1131 1132 call assert_equal(0, popup_move(-1, {})) 1133 1134 bwipe! 1135endfunc 1136 1137func Test_popup_getpos() 1138 let winid = popup_create('hello', #{ 1139 \ line: 2, 1140 \ col: 3, 1141 \ minwidth: 10, 1142 \ minheight: 11, 1143 \}) 1144 redraw 1145 let res = popup_getpos(winid) 1146 call assert_equal(2, res.line) 1147 call assert_equal(3, res.col) 1148 call assert_equal(10, res.width) 1149 call assert_equal(11, res.height) 1150 call assert_equal(1, res.visible) 1151 1152 call popup_close(winid) 1153endfunc 1154 1155func Test_popup_width_longest() 1156 let tests = [ 1157 \ [['hello', 'this', 'window', 'displays', 'all of its text'], 15], 1158 \ [['hello', 'this', 'window', 'all of its text', 'displays'], 15], 1159 \ [['hello', 'this', 'all of its text', 'window', 'displays'], 15], 1160 \ [['hello', 'all of its text', 'this', 'window', 'displays'], 15], 1161 \ [['all of its text', 'hello', 'this', 'window', 'displays'], 15], 1162 \ ] 1163 1164 for test in tests 1165 let winid = popup_create(test[0], #{line: 2, col: 3}) 1166 redraw 1167 let position = popup_getpos(winid) 1168 call assert_equal(test[1], position.width) 1169 call popup_close(winid) 1170 endfor 1171endfunc 1172 1173func Test_popup_wraps() 1174 let tests = [ 1175 \ ['nowrap', 6, 1], 1176 \ ['a line that wraps once', 12, 2], 1177 \ ['a line that wraps two times', 12, 3], 1178 \ ] 1179 for test in tests 1180 let winid = popup_create(test[0], 1181 \ #{line: 2, col: 3, maxwidth: 12}) 1182 redraw 1183 let position = popup_getpos(winid) 1184 call assert_equal(test[1], position.width) 1185 call assert_equal(test[2], position.height) 1186 1187 call popup_close(winid) 1188 call assert_equal({}, popup_getpos(winid)) 1189 endfor 1190endfunc 1191 1192func Test_popup_getoptions() 1193 let winid = popup_create('hello', #{ 1194 \ line: 2, 1195 \ col: 3, 1196 \ minwidth: 10, 1197 \ minheight: 11, 1198 \ maxwidth: 20, 1199 \ maxheight: 21, 1200 \ zindex: 100, 1201 \ time: 5000, 1202 \ fixed: 1 1203 \}) 1204 redraw 1205 let res = popup_getoptions(winid) 1206 call assert_equal(2, res.line) 1207 call assert_equal(3, res.col) 1208 call assert_equal(10, res.minwidth) 1209 call assert_equal(11, res.minheight) 1210 call assert_equal(20, res.maxwidth) 1211 call assert_equal(21, res.maxheight) 1212 call assert_equal(100, res.zindex) 1213 call assert_equal(1, res.fixed) 1214 call assert_equal(1, res.mapping) 1215 if has('timers') 1216 call assert_equal(5000, res.time) 1217 endif 1218 call popup_close(winid) 1219 1220 let winid = popup_create('hello', {}) 1221 redraw 1222 let res = popup_getoptions(winid) 1223 call assert_equal(0, res.line) 1224 call assert_equal(0, res.col) 1225 call assert_equal(0, res.minwidth) 1226 call assert_equal(0, res.minheight) 1227 call assert_equal(0, res.maxwidth) 1228 call assert_equal(0, res.maxheight) 1229 call assert_equal(50, res.zindex) 1230 call assert_equal(0, res.fixed) 1231 if has('timers') 1232 call assert_equal(0, res.time) 1233 endif 1234 call popup_close(winid) 1235 call assert_equal({}, popup_getoptions(winid)) 1236endfunc 1237 1238func Test_popup_option_values() 1239 new 1240 " window-local 1241 setlocal number 1242 setlocal nowrap 1243 " buffer-local 1244 setlocal omnifunc=Something 1245 " global/buffer-local 1246 setlocal path=/there 1247 " global/window-local 1248 setlocal statusline=2 1249 1250 let winid = popup_create('hello', {}) 1251 call assert_equal(0, getwinvar(winid, '&number')) 1252 call assert_equal(1, getwinvar(winid, '&wrap')) 1253 call assert_equal('', getwinvar(winid, '&omnifunc')) 1254 call assert_equal(&g:path, getwinvar(winid, '&path')) 1255 call assert_equal(&g:statusline, getwinvar(winid, '&statusline')) 1256 1257 " 'scrolloff' is reset to zero 1258 call assert_equal(5, &scrolloff) 1259 call assert_equal(0, getwinvar(winid, '&scrolloff')) 1260 1261 call popup_close(winid) 1262 bwipe 1263endfunc 1264 1265func Test_popup_atcursor() 1266 topleft vnew 1267 call setline(1, [ 1268 \ 'xxxxxxxxxxxxxxxxx', 1269 \ 'xxxxxxxxxxxxxxxxx', 1270 \ 'xxxxxxxxxxxxxxxxx', 1271 \]) 1272 1273 call cursor(2, 2) 1274 redraw 1275 let winid = popup_atcursor('vim', {}) 1276 redraw 1277 let line = join(map(range(1, 17), 'screenstring(1, v:val)'), '') 1278 call assert_equal('xvimxxxxxxxxxxxxx', line) 1279 call popup_close(winid) 1280 1281 call cursor(3, 4) 1282 redraw 1283 let winid = 'vim'->popup_atcursor({}) 1284 redraw 1285 let line = join(map(range(1, 17), 'screenstring(2, v:val)'), '') 1286 call assert_equal('xxxvimxxxxxxxxxxx', line) 1287 call popup_close(winid) 1288 1289 call cursor(1, 1) 1290 redraw 1291 let winid = popup_create('vim', #{ 1292 \ line: 'cursor+2', 1293 \ col: 'cursor+1', 1294 \}) 1295 redraw 1296 let line = join(map(range(1, 17), 'screenstring(3, v:val)'), '') 1297 call assert_equal('xvimxxxxxxxxxxxxx', line) 1298 call popup_close(winid) 1299 1300 call cursor(3, 3) 1301 redraw 1302 let winid = popup_create('vim', #{ 1303 \ line: 'cursor-2', 1304 \ col: 'cursor-1', 1305 \}) 1306 redraw 1307 let line = join(map(range(1, 17), 'screenstring(1, v:val)'), '') 1308 call assert_equal('xvimxxxxxxxxxxxxx', line) 1309 call popup_close(winid) 1310 1311 " just enough room above 1312 call cursor(3, 3) 1313 redraw 1314 let winid = popup_atcursor(['vim', 'is great'], {}) 1315 redraw 1316 let pos = popup_getpos(winid) 1317 call assert_equal(1, pos.line) 1318 call popup_close(winid) 1319 1320 " not enough room above, popup goes below the cursor 1321 call cursor(3, 3) 1322 redraw 1323 let winid = popup_atcursor(['vim', 'is', 'great'], {}) 1324 redraw 1325 let pos = popup_getpos(winid) 1326 call assert_equal(4, pos.line) 1327 call popup_close(winid) 1328 1329 " cursor in first line, popup in line 2 1330 call cursor(1, 1) 1331 redraw 1332 let winid = popup_atcursor(['vim', 'is', 'great'], {}) 1333 redraw 1334 let pos = popup_getpos(winid) 1335 call assert_equal(2, pos.line) 1336 call popup_close(winid) 1337 1338 bwipe! 1339endfunc 1340 1341func Test_popup_atcursor_pos() 1342 CheckScreendump 1343 1344 let lines =<< trim END 1345 call setline(1, repeat([repeat('-', 60)], 15)) 1346 set so=0 1347 1348 normal 9G3|r# 1349 let winid1 = popup_atcursor(['first', 'second'], #{ 1350 \ moved: [0, 0, 0], 1351 \ }) 1352 normal 9G21|r& 1353 let winid1 = popup_atcursor(['FIrsT', 'SEcoND'], #{ 1354 \ pos: 'botright', 1355 \ moved: [0, 0, 0], 1356 \ }) 1357 normal 3G27|r% 1358 let winid1 = popup_atcursor(['fiRSt', 'seCOnd'], #{ 1359 \ pos: 'topleft', 1360 \ moved: [0, 0, 0], 1361 \ }) 1362 normal 3G45|r@ 1363 let winid1 = popup_atcursor(['First', 'SeconD'], #{ 1364 \ pos: 'topright', 1365 \ moved: range(3), 1366 \ mousemoved: range(3), 1367 \ }) 1368 END 1369 call writefile(lines, 'XtestPopupAtcursorPos') 1370 let buf = RunVimInTerminal('-S XtestPopupAtcursorPos', #{rows: 12}) 1371 call VerifyScreenDump(buf, 'Test_popupwin_atcursor_pos', {}) 1372 1373 " clean up 1374 call StopVimInTerminal(buf) 1375 call delete('XtestPopupAtcursorPos') 1376endfunc 1377 1378func Test_popup_beval() 1379 CheckScreendump 1380 CheckFeature balloon_eval_term 1381 1382 let lines =<< trim END 1383 call setline(1, range(1, 20)) 1384 call setline(5, 'here is some text to hover over') 1385 set balloonevalterm 1386 set balloonexpr=BalloonExpr() 1387 set balloondelay=100 1388 func BalloonExpr() 1389 let s:winid = [v:beval_text]->popup_beval({}) 1390 return '' 1391 endfunc 1392 func Hover() 1393 call test_setmouse(5, 15) 1394 call feedkeys("\<MouseMove>\<Ignore>", "xt") 1395 sleep 100m 1396 endfunc 1397 func MoveOntoPopup() 1398 call test_setmouse(4, 17) 1399 call feedkeys("\<F4>\<MouseMove>\<Ignore>", "xt") 1400 endfunc 1401 func MoveAway() 1402 call test_setmouse(5, 13) 1403 call feedkeys("\<F5>\<MouseMove>\<Ignore>", "xt") 1404 endfunc 1405 END 1406 call writefile(lines, 'XtestPopupBeval') 1407 let buf = RunVimInTerminal('-S XtestPopupBeval', #{rows: 10}) 1408 call TermWait(buf, 50) 1409 call term_sendkeys(buf, 'j') 1410 call term_sendkeys(buf, ":call Hover()\<CR>") 1411 call VerifyScreenDump(buf, 'Test_popupwin_beval_1', {}) 1412 1413 call term_sendkeys(buf, ":call MoveOntoPopup()\<CR>") 1414 call VerifyScreenDump(buf, 'Test_popupwin_beval_2', {}) 1415 1416 call term_sendkeys(buf, ":call MoveAway()\<CR>") 1417 call VerifyScreenDump(buf, 'Test_popupwin_beval_3', {}) 1418 1419 " clean up 1420 call StopVimInTerminal(buf) 1421 call delete('XtestPopupBeval') 1422endfunc 1423 1424func Test_popup_filter() 1425 new 1426 call setline(1, 'some text') 1427 1428 func MyPopupFilter(winid, c) 1429 if a:c == 'e' || a:c == "\<F9>" 1430 let g:eaten = a:c 1431 return 1 1432 endif 1433 if a:c == '0' 1434 let g:ignored = '0' 1435 return 0 1436 endif 1437 if a:c == 'x' 1438 call popup_close(a:winid) 1439 return 1 1440 endif 1441 return 0 1442 endfunc 1443 1444 let winid = 'something'->popup_create(#{filter: 'MyPopupFilter'}) 1445 redraw 1446 1447 " e is consumed by the filter 1448 call feedkeys('e', 'xt') 1449 call assert_equal('e', g:eaten) 1450 call feedkeys("\<F9>", 'xt') 1451 call assert_equal("\<F9>", g:eaten) 1452 1453 " 0 is ignored by the filter 1454 normal $ 1455 call assert_equal(9, getcurpos()[2]) 1456 call feedkeys('0', 'xt') 1457 call assert_equal('0', g:ignored) 1458 call assert_equal(1, getcurpos()[2]) 1459 1460 " x closes the popup 1461 call feedkeys('x', 'xt') 1462 call assert_equal("\<F9>", g:eaten) 1463 call assert_equal(-1, winbufnr(winid)) 1464 1465 delfunc MyPopupFilter 1466 call popup_clear() 1467endfunc 1468 1469func ShowDialog(key, result) 1470 let s:cb_res = 999 1471 let winid = popup_dialog('do you want to quit (Yes/no)?', #{ 1472 \ filter: 'popup_filter_yesno', 1473 \ callback: 'QuitCallback', 1474 \ }) 1475 redraw 1476 call feedkeys(a:key, "xt") 1477 call assert_equal(winid, s:cb_winid) 1478 call assert_equal(a:result, s:cb_res) 1479endfunc 1480 1481func Test_popup_dialog() 1482 func QuitCallback(id, res) 1483 let s:cb_winid = a:id 1484 let s:cb_res = a:res 1485 endfunc 1486 1487 let winid = ShowDialog("y", 1) 1488 let winid = ShowDialog("Y", 1) 1489 let winid = ShowDialog("n", 0) 1490 let winid = ShowDialog("N", 0) 1491 let winid = ShowDialog("x", 0) 1492 let winid = ShowDialog("X", 0) 1493 let winid = ShowDialog("\<Esc>", 0) 1494 let winid = ShowDialog("\<C-C>", -1) 1495 1496 delfunc QuitCallback 1497endfunc 1498 1499func ShowMenu(key, result) 1500 let s:cb_res = 999 1501 let winid = popup_menu(['one', 'two', 'something else'], #{ 1502 \ callback: 'QuitCallback', 1503 \ }) 1504 redraw 1505 call feedkeys(a:key, "xt") 1506 call assert_equal(winid, s:cb_winid) 1507 call assert_equal(a:result, s:cb_res) 1508endfunc 1509 1510func Test_popup_menu() 1511 func QuitCallback(id, res) 1512 let s:cb_winid = a:id 1513 let s:cb_res = a:res 1514 endfunc 1515 " mapping won't be used in popup 1516 map j k 1517 1518 let winid = ShowMenu(" ", 1) 1519 let winid = ShowMenu("j \<CR>", 2) 1520 let winid = ShowMenu("JjK \<CR>", 2) 1521 let winid = ShowMenu("jjjjjj ", 3) 1522 let winid = ShowMenu("kkk ", 1) 1523 let winid = ShowMenu("x", -1) 1524 let winid = ShowMenu("X", -1) 1525 let winid = ShowMenu("\<Esc>", -1) 1526 let winid = ShowMenu("\<C-C>", -1) 1527 1528 delfunc QuitCallback 1529 unmap j 1530endfunc 1531 1532func Test_popup_menu_screenshot() 1533 CheckScreendump 1534 1535 let lines =<< trim END 1536 call setline(1, range(1, 20)) 1537 hi PopupSelected ctermbg=lightblue 1538 call popup_menu(['one', 'two', 'another'], #{callback: 'MenuDone', title: ' make a choice from the list '}) 1539 func MenuDone(id, res) 1540 echomsg "selected " .. a:res 1541 endfunc 1542 END 1543 call writefile(lines, 'XtestPopupMenu') 1544 let buf = RunVimInTerminal('-S XtestPopupMenu', #{rows: 10}) 1545 call VerifyScreenDump(buf, 'Test_popupwin_menu_01', {}) 1546 1547 call term_sendkeys(buf, "jj") 1548 call VerifyScreenDump(buf, 'Test_popupwin_menu_02', {}) 1549 1550 call term_sendkeys(buf, " ") 1551 call VerifyScreenDump(buf, 'Test_popupwin_menu_03', {}) 1552 1553 " clean up 1554 call StopVimInTerminal(buf) 1555 call delete('XtestPopupMenu') 1556endfunc 1557 1558func Test_popup_menu_narrow() 1559 CheckScreendump 1560 1561 let lines =<< trim END 1562 call setline(1, range(1, 20)) 1563 hi PopupSelected ctermbg=green 1564 call popup_menu(['one', 'two', 'three'], #{callback: 'MenuDone'}) 1565 func MenuDone(id, res) 1566 echomsg "selected " .. a:res 1567 endfunc 1568 END 1569 call writefile(lines, 'XtestPopupNarrowMenu') 1570 let buf = RunVimInTerminal('-S XtestPopupNarrowMenu', #{rows: 10}) 1571 call VerifyScreenDump(buf, 'Test_popupwin_menu_04', {}) 1572 1573 " clean up 1574 call term_sendkeys(buf, "x") 1575 call StopVimInTerminal(buf) 1576 call delete('XtestPopupNarrowMenu') 1577endfunc 1578 1579func Test_popup_title() 1580 CheckScreendump 1581 1582 " Create a popup without title or border, a line of padding will be added to 1583 " put the title on. 1584 let lines =<< trim END 1585 call setline(1, range(1, 20)) 1586 let winid = popup_create(['one', 'two', 'another'], #{title: 'Title String'}) 1587 END 1588 call writefile(lines, 'XtestPopupTitle') 1589 let buf = RunVimInTerminal('-S XtestPopupTitle', #{rows: 10}) 1590 call VerifyScreenDump(buf, 'Test_popupwin_title', {}) 1591 1592 call term_sendkeys(buf, ":call popup_setoptions(winid, #{maxwidth: 20, title: 'a very long title that is not going to fit'})\<CR>") 1593 call term_sendkeys(buf, ":\<CR>") 1594 call VerifyScreenDump(buf, 'Test_popupwin_longtitle_1', {}) 1595 1596 call term_sendkeys(buf, ":call popup_setoptions(winid, #{border: []})\<CR>") 1597 call term_sendkeys(buf, ":\<CR>") 1598 call VerifyScreenDump(buf, 'Test_popupwin_longtitle_2', {}) 1599 1600 " clean up 1601 call StopVimInTerminal(buf) 1602 call delete('XtestPopupTitle') 1603 1604 let winid = popup_create('something', #{title: 'Some Title'}) 1605 call assert_equal('Some Title', popup_getoptions(winid).title) 1606 call popup_setoptions(winid, #{title: 'Another Title'}) 1607 call assert_equal('Another Title', popup_getoptions(winid).title) 1608 1609 call popup_clear() 1610endfunc 1611 1612func Test_popup_close_callback() 1613 func PopupDone(id, result) 1614 let g:result = a:result 1615 endfunc 1616 let winid = popup_create('something', #{callback: 'PopupDone'}) 1617 redraw 1618 call popup_close(winid, 'done') 1619 call assert_equal('done', g:result) 1620endfunc 1621 1622func Test_popup_empty() 1623 let winid = popup_create('', #{padding: [2,2,2,2]}) 1624 redraw 1625 let pos = popup_getpos(winid) 1626 call assert_equal(5, pos.width) 1627 call assert_equal(5, pos.height) 1628 call popup_close(winid) 1629 1630 let winid = popup_create([], #{border: []}) 1631 redraw 1632 let pos = popup_getpos(winid) 1633 call assert_equal(3, pos.width) 1634 call assert_equal(3, pos.height) 1635 call popup_close(winid) 1636endfunc 1637 1638func Test_popup_never_behind() 1639 CheckScreendump 1640 1641 " +-----------------------------+ 1642 " | | | 1643 " | | | 1644 " | | | 1645 " | line1 | 1646 " |------------line2------------| 1647 " | line3 | 1648 " | line4 | 1649 " | | 1650 " | | 1651 " +-----------------------------+ 1652 let lines =<< trim END 1653 split 1654 vsplit 1655 let info_window1 = getwininfo()[0] 1656 let line = info_window1['height'] 1657 let col = info_window1['width'] 1658 call popup_create(['line1', 'line2', 'line3', 'line4'], #{ 1659 \ line : line, 1660 \ col : col, 1661 \ }) 1662 END 1663 call writefile(lines, 'XtestPopupBehind') 1664 let buf = RunVimInTerminal('-S XtestPopupBehind', #{rows: 10}) 1665 call term_sendkeys(buf, "\<C-W>w") 1666 call VerifyScreenDump(buf, 'Test_popupwin_behind', {}) 1667 1668 " clean up 1669 call StopVimInTerminal(buf) 1670 call delete('XtestPopupBehind') 1671endfunc 1672 1673func s:VerifyPosition(p, msg, line, col, width, height) 1674 call assert_equal(a:line, popup_getpos(a:p).line, a:msg . ' (l)') 1675 call assert_equal(a:col, popup_getpos(a:p).col, a:msg . ' (c)') 1676 call assert_equal(a:width, popup_getpos(a:p).width, a:msg . ' (w)') 1677 call assert_equal(a:height, popup_getpos(a:p).height, a:msg . ' (h)') 1678endfunc 1679 1680func Test_popup_position_adjust() 1681 " Anything placed past the last cell on the right of the screen is moved to 1682 " the left. 1683 " 1684 " When wrapping is disabled, we also shift to the left to display on the 1685 " screen, unless fixed is set. 1686 1687 " Entries for cases which don't vary based on wrapping. 1688 " Format is per tests described below 1689 let both_wrap_tests = [ 1690 \ ['a', 5, &columns, 5, &columns, 1, 1], 1691 \ ['b', 5, &columns + 1, 5, &columns, 1, 1], 1692 \ ['c', 5, &columns - 1, 5, &columns - 1, 1, 1], 1693 \ ['d', 5, &columns - 2, 5, &columns - 2, 1, 1], 1694 \ ['e', 5, &columns - 3, 5, &columns - 3, 1, 1]] 1695 1696 " these test groups are dicts with: 1697 " - comment: something to identify the group of tests by 1698 " - options: dict of options to merge with the row/col in tests 1699 " - tests: list of cases. Each one is a list with elements: 1700 " - text 1701 " - row 1702 " - col 1703 " - expected row 1704 " - expected col 1705 " - expected width 1706 " - expected height 1707 let tests = [ 1708 \ #{ 1709 \ comment: 'left-aligned with wrapping', 1710 \ options: #{ 1711 \ wrap: 1, 1712 \ pos: 'botleft', 1713 \ }, 1714 \ tests: both_wrap_tests + [ 1715 \ ['aa', 5, &columns, 4, &columns, 1, 2], 1716 \ ['bb', 5, &columns + 1, 4, &columns, 1, 2], 1717 \ ['cc', 5, &columns - 1, 5, &columns - 1, 2, 1], 1718 \ ['dd', 5, &columns - 2, 5, &columns - 2, 2, 1], 1719 \ ['ee', 5, &columns - 3, 5, &columns - 3, 2, 1], 1720 \ 1721 \ ['aaa', 5, &columns, 3, &columns, 1, 3], 1722 \ ['bbb', 5, &columns + 1, 3, &columns, 1, 3], 1723 \ ['ccc', 5, &columns - 1, 4, &columns - 1, 2, 2], 1724 \ ['ddd', 5, &columns - 2, 5, &columns - 2, 3, 1], 1725 \ ['eee', 5, &columns - 3, 5, &columns - 3, 3, 1], 1726 \ 1727 \ ['aaaa', 5, &columns, 2, &columns, 1, 4], 1728 \ ['bbbb', 5, &columns + 1, 2, &columns, 1, 4], 1729 \ ['cccc', 5, &columns - 1, 4, &columns - 1, 2, 2], 1730 \ ['dddd', 5, &columns - 2, 4, &columns - 2, 3, 2], 1731 \ ['eeee', 5, &columns - 3, 5, &columns - 3, 4, 1], 1732 \ ['eeee', 5, &columns - 4, 5, &columns - 4, 4, 1], 1733 \ ], 1734 \ }, 1735 \ #{ 1736 \ comment: 'left aligned without wrapping', 1737 \ options: #{ 1738 \ wrap: 0, 1739 \ pos: 'botleft', 1740 \ }, 1741 \ tests: both_wrap_tests + [ 1742 \ ['aa', 5, &columns, 5, &columns - 1, 2, 1], 1743 \ ['bb', 5, &columns + 1, 5, &columns - 1, 2, 1], 1744 \ ['cc', 5, &columns - 1, 5, &columns - 1, 2, 1], 1745 \ ['dd', 5, &columns - 2, 5, &columns - 2, 2, 1], 1746 \ ['ee', 5, &columns - 3, 5, &columns - 3, 2, 1], 1747 \ 1748 \ ['aaa', 5, &columns, 5, &columns - 2, 3, 1], 1749 \ ['bbb', 5, &columns + 1, 5, &columns - 2, 3, 1], 1750 \ ['ccc', 5, &columns - 1, 5, &columns - 2, 3, 1], 1751 \ ['ddd', 5, &columns - 2, 5, &columns - 2, 3, 1], 1752 \ ['eee', 5, &columns - 3, 5, &columns - 3, 3, 1], 1753 \ 1754 \ ['aaaa', 5, &columns, 5, &columns - 3, 4, 1], 1755 \ ['bbbb', 5, &columns + 1, 5, &columns - 3, 4, 1], 1756 \ ['cccc', 5, &columns - 1, 5, &columns - 3, 4, 1], 1757 \ ['dddd', 5, &columns - 2, 5, &columns - 3, 4, 1], 1758 \ ['eeee', 5, &columns - 3, 5, &columns - 3, 4, 1], 1759 \ ], 1760 \ }, 1761 \ #{ 1762 \ comment: 'left aligned with fixed position', 1763 \ options: #{ 1764 \ wrap: 0, 1765 \ fixed: 1, 1766 \ pos: 'botleft', 1767 \ }, 1768 \ tests: both_wrap_tests + [ 1769 \ ['aa', 5, &columns, 5, &columns, 1, 1], 1770 \ ['bb', 5, &columns + 1, 5, &columns, 1, 1], 1771 \ ['cc', 5, &columns - 1, 5, &columns - 1, 2, 1], 1772 \ ['dd', 5, &columns - 2, 5, &columns - 2, 2, 1], 1773 \ ['ee', 5, &columns - 3, 5, &columns - 3, 2, 1], 1774 \ 1775 \ ['aaa', 5, &columns, 5, &columns, 1, 1], 1776 \ ['bbb', 5, &columns + 1, 5, &columns, 1, 1], 1777 \ ['ccc', 5, &columns - 1, 5, &columns - 1, 2, 1], 1778 \ ['ddd', 5, &columns - 2, 5, &columns - 2, 3, 1], 1779 \ ['eee', 5, &columns - 3, 5, &columns - 3, 3, 1], 1780 \ 1781 \ ['aaaa', 5, &columns, 5, &columns, 1, 1], 1782 \ ['bbbb', 5, &columns + 1, 5, &columns, 1, 1], 1783 \ ['cccc', 5, &columns - 1, 5, &columns - 1, 2, 1], 1784 \ ['dddd', 5, &columns - 2, 5, &columns - 2, 3, 1], 1785 \ ['eeee', 5, &columns - 3, 5, &columns - 3, 4, 1], 1786 \ ], 1787 \ }, 1788 \ ] 1789 1790 for test_group in tests 1791 for test in test_group.tests 1792 let [ text, line, col, e_line, e_col, e_width, e_height ] = test 1793 let options = #{ 1794 \ line: line, 1795 \ col: col, 1796 \ } 1797 call extend(options, test_group.options) 1798 1799 let p = popup_create(text, options) 1800 1801 let msg = string(extend(options, #{text: text})) 1802 call s:VerifyPosition(p, msg, e_line, e_col, e_width, e_height) 1803 call popup_close(p) 1804 endfor 1805 endfor 1806 1807 call popup_clear() 1808 %bwipe! 1809endfunc 1810 1811func Test_adjust_left_past_screen_width() 1812 " width of screen 1813 let X = join(map(range(&columns), {->'X'}), '') 1814 1815 let p = popup_create(X, #{line: 1, col: 1, wrap: 0}) 1816 call s:VerifyPosition(p, 'full width topleft', 1, 1, &columns, 1) 1817 1818 redraw 1819 let line = join(map(range(1, &columns + 1), 'screenstring(1, v:val)'), '') 1820 call assert_equal(X, line) 1821 1822 call popup_close(p) 1823 redraw 1824 1825 " Same if placed on the right hand side 1826 let p = popup_create(X, #{line: 1, col: &columns, wrap: 0}) 1827 call s:VerifyPosition(p, 'full width topright', 1, 1, &columns, 1) 1828 1829 redraw 1830 let line = join(map(range(1, &columns + 1), 'screenstring(1, v:val)'), '') 1831 call assert_equal(X, line) 1832 1833 call popup_close(p) 1834 redraw 1835 1836 " Extend so > window width 1837 let X .= 'x' 1838 1839 let p = popup_create(X, #{line: 1, col: 1, wrap: 0}) 1840 call s:VerifyPosition(p, 'full width + 1 topleft', 1, 1, &columns, 1) 1841 1842 redraw 1843 let line = join(map(range(1, &columns + 1), 'screenstring(1, v:val)'), '') 1844 call assert_equal(X[ : -2 ], line) 1845 1846 call popup_close(p) 1847 redraw 1848 1849 " Shifted then truncated (the x is not visible) 1850 let p = popup_create(X, #{line: 1, col: &columns - 3, wrap: 0}) 1851 call s:VerifyPosition(p, 'full width + 1 topright', 1, 1, &columns, 1) 1852 1853 redraw 1854 let line = join(map(range(1, &columns + 1), 'screenstring(1, v:val)'), '') 1855 call assert_equal(X[ : -2 ], line) 1856 1857 call popup_close(p) 1858 redraw 1859 1860 " Not shifted, just truncated 1861 let p = popup_create(X, 1862 \ #{line: 1, col: 2, wrap: 0, fixed: 1}) 1863 call s:VerifyPosition(p, 'full width + 1 fixed', 1, 2, &columns - 1, 1) 1864 1865 redraw 1866 let line = join(map(range(1, &columns + 1), 'screenstring(1, v:val)'), '') 1867 let e_line = ' ' . X[ 1 : -2 ] 1868 call assert_equal(e_line, line) 1869 1870 call popup_close(p) 1871 redraw 1872 1873 call popup_clear() 1874 %bwipe! 1875endfunc 1876 1877func Test_popup_moved() 1878 new 1879 call test_override('char_avail', 1) 1880 call setline(1, ['one word to move around', 'a WORD.and->some thing']) 1881 1882 exe "normal gg0/word\<CR>" 1883 let winid = popup_atcursor('text', #{moved: 'any'}) 1884 redraw 1885 call assert_equal(1, popup_getpos(winid).visible) 1886 call assert_equal([1, 4, 4], popup_getoptions(winid).moved) 1887 " trigger the check for last_cursormoved by going into insert mode 1888 call feedkeys("li\<Esc>", 'xt') 1889 call assert_equal({}, popup_getpos(winid)) 1890 call popup_clear() 1891 1892 exe "normal gg0/word\<CR>" 1893 let winid = popup_atcursor('text', #{moved: 'word'}) 1894 redraw 1895 call assert_equal(1, popup_getpos(winid).visible) 1896 call assert_equal([1, 4, 7], popup_getoptions(winid).moved) 1897 call feedkeys("hi\<Esc>", 'xt') 1898 call assert_equal({}, popup_getpos(winid)) 1899 call popup_clear() 1900 1901 exe "normal gg0/word\<CR>" 1902 let winid = popup_atcursor('text', #{moved: 'word'}) 1903 redraw 1904 call assert_equal(1, popup_getpos(winid).visible) 1905 call assert_equal([1, 4, 7], popup_getoptions(winid).moved) 1906 call feedkeys("li\<Esc>", 'xt') 1907 call assert_equal(1, popup_getpos(winid).visible) 1908 call feedkeys("ei\<Esc>", 'xt') 1909 call assert_equal(1, popup_getpos(winid).visible) 1910 call feedkeys("eli\<Esc>", 'xt') 1911 call assert_equal({}, popup_getpos(winid)) 1912 call popup_clear() 1913 1914 " WORD is the default 1915 exe "normal gg0/WORD\<CR>" 1916 let winid = popup_atcursor('text', {}) 1917 redraw 1918 call assert_equal(1, popup_getpos(winid).visible) 1919 call assert_equal([2, 2, 15], popup_getoptions(winid).moved) 1920 call feedkeys("eli\<Esc>", 'xt') 1921 call assert_equal(1, popup_getpos(winid).visible) 1922 call feedkeys("wi\<Esc>", 'xt') 1923 call assert_equal(1, popup_getpos(winid).visible) 1924 call feedkeys("Eli\<Esc>", 'xt') 1925 call assert_equal({}, popup_getpos(winid)) 1926 call popup_clear() 1927 1928 exe "normal gg0/word\<CR>" 1929 let winid = popup_atcursor('text', #{moved: [5, 10]}) 1930 redraw 1931 call assert_equal(1, popup_getpos(winid).visible) 1932 call feedkeys("eli\<Esc>", 'xt') 1933 call feedkeys("ei\<Esc>", 'xt') 1934 call assert_equal(1, popup_getpos(winid).visible) 1935 call feedkeys("eli\<Esc>", 'xt') 1936 call assert_equal({}, popup_getpos(winid)) 1937 call popup_clear() 1938 1939 bwipe! 1940 call test_override('ALL', 0) 1941endfunc 1942 1943func Test_notifications() 1944 CheckFeature timers 1945 CheckScreendump 1946 1947 let lines =<< trim END 1948 call setline(1, range(1, 20)) 1949 hi Notification ctermbg=lightblue 1950 call popup_notification('first notification', {}) 1951 END 1952 call writefile(lines, 'XtestNotifications') 1953 let buf = RunVimInTerminal('-S XtestNotifications', #{rows: 10}) 1954 call VerifyScreenDump(buf, 'Test_popupwin_notify_01', {}) 1955 1956 " second one goes below the first one 1957 call term_sendkeys(buf, ":hi link PopupNotification Notification\<CR>") 1958 call term_sendkeys(buf, ":call popup_notification('another important notification', {})\<CR>") 1959 call VerifyScreenDump(buf, 'Test_popupwin_notify_02', {}) 1960 1961 " clean up 1962 call StopVimInTerminal(buf) 1963 call delete('XtestNotifications') 1964endfunc 1965 1966func Test_popup_scrollbar() 1967 CheckScreendump 1968 1969 let lines =<< trim END 1970 call setline(1, range(1, 20)) 1971 hi ScrollThumb ctermbg=blue 1972 hi ScrollBar ctermbg=red 1973 let winid = popup_create(['one', 'two', 'three', 'four', 'five', 1974 \ 'six', 'seven', 'eight', 'nine'], #{ 1975 \ minwidth: 8, 1976 \ maxheight: 4, 1977 \ }) 1978 func ScrollUp() 1979 call feedkeys("\<F3>\<ScrollWheelUp>", "xt") 1980 endfunc 1981 func ScrollDown() 1982 call feedkeys("\<F3>\<ScrollWheelDown>", "xt") 1983 endfunc 1984 func ClickTop() 1985 call feedkeys("\<F4>\<LeftMouse>", "xt") 1986 endfunc 1987 func ClickBot() 1988 call popup_setoptions(g:winid, #{border: [], close: 'button'}) 1989 call feedkeys("\<F5>\<LeftMouse>", "xt") 1990 endfunc 1991 func Popup_filter(winid, key) 1992 if a:key == 'j' 1993 let line = popup_getoptions(a:winid).firstline 1994 let nlines = line('$', a:winid) 1995 let newline = line < nlines ? (line + 1) : nlines 1996 call popup_setoptions(a:winid, #{firstline: newline}) 1997 return v:true 1998 elseif a:key == 'x' 1999 call popup_close(a:winid) 2000 return v:true 2001 endif 2002 endfunc 2003 2004 func PopupScroll() 2005 call popup_clear() 2006 let text =<< trim END 2007 1 2008 2 2009 3 2010 4 2011 long line long line long line long line long line long line 2012 long line long line long line long line long line long line 2013 long line long line long line long line long line long line 2014 END 2015 call popup_create(text, #{ 2016 \ minwidth: 30, 2017 \ maxwidth: 30, 2018 \ minheight: 4, 2019 \ maxheight: 4, 2020 \ firstline: 1, 2021 \ lastline: 4, 2022 \ wrap: v:true, 2023 \ scrollbar: v:true, 2024 \ mapping: v:false, 2025 \ filter: funcref('Popup_filter') 2026 \ }) 2027 endfunc 2028 map <silent> <F3> :call test_setmouse(5, 36)<CR> 2029 map <silent> <F4> :call test_setmouse(4, 42)<CR> 2030 map <silent> <F5> :call test_setmouse(7, 42)<CR> 2031 END 2032 call writefile(lines, 'XtestPopupScroll') 2033 let buf = RunVimInTerminal('-S XtestPopupScroll', #{rows: 10}) 2034 call VerifyScreenDump(buf, 'Test_popupwin_scroll_1', {}) 2035 2036 call term_sendkeys(buf, ":call popup_setoptions(winid, #{firstline: 2})\<CR>") 2037 call term_sendkeys(buf, ":\<CR>") 2038 call VerifyScreenDump(buf, 'Test_popupwin_scroll_2', {}) 2039 2040 call term_sendkeys(buf, ":call popup_setoptions(winid, #{firstline: 6})\<CR>") 2041 call term_sendkeys(buf, ":\<CR>") 2042 call VerifyScreenDump(buf, 'Test_popupwin_scroll_3', {}) 2043 2044 call term_sendkeys(buf, ":call popup_setoptions(winid, #{firstline: 9})\<CR>") 2045 call term_sendkeys(buf, ":\<CR>") 2046 call VerifyScreenDump(buf, 'Test_popupwin_scroll_4', {}) 2047 2048 call term_sendkeys(buf, ":call popup_setoptions(winid, #{scrollbarhighlight: 'ScrollBar', thumbhighlight: 'ScrollThumb', firstline: 5})\<CR>") 2049 " this scrolls two lines (half the window height) 2050 call term_sendkeys(buf, ":call ScrollUp()\<CR>") 2051 call VerifyScreenDump(buf, 'Test_popupwin_scroll_5', {}) 2052 2053 call term_sendkeys(buf, ":call ScrollDown()\<CR>") 2054 call VerifyScreenDump(buf, 'Test_popupwin_scroll_6', {}) 2055 2056 call term_sendkeys(buf, ":call ScrollDown()\<CR>") 2057 " wait a bit, otherwise it fails sometimes (double click recognized?) 2058 sleep 100m 2059 call term_sendkeys(buf, ":call ScrollDown()\<CR>") 2060 call VerifyScreenDump(buf, 'Test_popupwin_scroll_7', {}) 2061 2062 call term_sendkeys(buf, ":call ClickTop()\<CR>") 2063 sleep 100m 2064 call term_sendkeys(buf, ":call ClickTop()\<CR>") 2065 call VerifyScreenDump(buf, 'Test_popupwin_scroll_8', {}) 2066 2067 call term_sendkeys(buf, ":call ClickBot()\<CR>") 2068 call VerifyScreenDump(buf, 'Test_popupwin_scroll_9', {}) 2069 2070 " remove the minwidth and maxheight 2071 call term_sendkeys(buf, ":call popup_setoptions(winid, #{maxheight: 0, minwidth: 0})\<CR>") 2072 call term_sendkeys(buf, ":\<CR>") 2073 call VerifyScreenDump(buf, 'Test_popupwin_scroll_10', {}) 2074 2075 " check size with non-wrapping lines 2076 call term_sendkeys(buf, ":call PopupScroll()\<CR>") 2077 call VerifyScreenDump(buf, 'Test_popupwin_scroll_11', {}) 2078 2079 " check size with wrapping lines 2080 call term_sendkeys(buf, "j") 2081 call VerifyScreenDump(buf, 'Test_popupwin_scroll_12', {}) 2082 call term_sendkeys(buf, "x") 2083 2084 " clean up 2085 call StopVimInTerminal(buf) 2086 call delete('XtestPopupScroll') 2087endfunc 2088 2089func Test_popup_fitting_scrollbar() 2090 " this was causing a crash, divide by zero 2091 let winid = popup_create([ 2092 \ 'one', 'two', 'longer line that wraps', 'four', 'five'], #{ 2093 \ scrollbar: 1, 2094 \ maxwidth: 10, 2095 \ maxheight: 5, 2096 \ firstline: 2}) 2097 redraw 2098 call popup_clear() 2099endfunc 2100 2101func Test_popup_settext() 2102 CheckScreendump 2103 2104 let lines =<< trim END 2105 let opts = #{wrap: 0} 2106 let p = popup_create('test', opts) 2107 eval p->popup_settext('this is a text') 2108 END 2109 2110 call writefile(lines, 'XtestPopupSetText') 2111 let buf = RunVimInTerminal('-S XtestPopupSetText', #{rows: 10}) 2112 call VerifyScreenDump(buf, 'Test_popup_settext_01', {}) 2113 2114 " Setting to empty string clears it 2115 call term_sendkeys(buf, ":call popup_settext(p, '')\<CR>") 2116 call VerifyScreenDump(buf, 'Test_popup_settext_02', {}) 2117 2118 " Setting a list 2119 call term_sendkeys(buf, ":call popup_settext(p, ['a','b','c'])\<CR>") 2120 call VerifyScreenDump(buf, 'Test_popup_settext_03', {}) 2121 2122 " Shrinking with a list 2123 call term_sendkeys(buf, ":call popup_settext(p, ['a'])\<CR>") 2124 call VerifyScreenDump(buf, 'Test_popup_settext_04', {}) 2125 2126 " Growing with a list 2127 call term_sendkeys(buf, ":call popup_settext(p, ['a','b','c'])\<CR>") 2128 call VerifyScreenDump(buf, 'Test_popup_settext_03', {}) 2129 2130 " Empty list clears 2131 call term_sendkeys(buf, ":call popup_settext(p, [])\<CR>") 2132 call VerifyScreenDump(buf, 'Test_popup_settext_05', {}) 2133 2134 " Dicts 2135 call term_sendkeys(buf, ":call popup_settext(p, [#{text: 'aaaa'}, #{text: 'bbbb'}, #{text: 'cccc'}])\<CR>") 2136 call VerifyScreenDump(buf, 'Test_popup_settext_06', {}) 2137 2138 " range() (doesn't work) 2139 call term_sendkeys(buf, ":call popup_settext(p, range(4, 8))\<CR>") 2140 call VerifyScreenDump(buf, 'Test_popup_settext_07', {}) 2141 2142 " clean up 2143 call StopVimInTerminal(buf) 2144 call delete('XtestPopupSetText') 2145endfunc 2146 2147func Test_popup_hidden() 2148 new 2149 2150 let winid = popup_atcursor('text', #{hidden: 1}) 2151 redraw 2152 call assert_equal(0, popup_getpos(winid).visible) 2153 call popup_close(winid) 2154 2155 let winid = popup_create('text', #{hidden: 1}) 2156 redraw 2157 call assert_equal(0, popup_getpos(winid).visible) 2158 call popup_close(winid) 2159 2160 func QuitCallback(id, res) 2161 let s:cb_winid = a:id 2162 let s:cb_res = a:res 2163 endfunc 2164 let winid = 'make a choice'->popup_dialog(#{hidden: 1, 2165 \ filter: 'popup_filter_yesno', 2166 \ callback: 'QuitCallback', 2167 \ }) 2168 redraw 2169 call assert_equal(0, popup_getpos(winid).visible) 2170 call assert_equal(function('popup_filter_yesno'), popup_getoptions(winid).filter) 2171 call assert_equal(function('QuitCallback'), popup_getoptions(winid).callback) 2172 exe "normal anot used by filter\<Esc>" 2173 call assert_equal('not used by filter', getline(1)) 2174 2175 call popup_show(winid) 2176 call feedkeys('y', "xt") 2177 call assert_equal(1, s:cb_res) 2178 2179 bwipe! 2180 delfunc QuitCallback 2181endfunc 2182 2183" Test options not checked elsewhere 2184func Test_set_get_options() 2185 let winid = popup_create('some text', #{highlight: 'Beautiful'}) 2186 let options = popup_getoptions(winid) 2187 call assert_equal(1, options.wrap) 2188 call assert_equal(0, options.drag) 2189 call assert_equal('Beautiful', options.highlight) 2190 2191 call popup_setoptions(winid, #{wrap: 0, drag: 1, highlight: 'Another'}) 2192 let options = popup_getoptions(winid) 2193 call assert_equal(0, options.wrap) 2194 call assert_equal(1, options.drag) 2195 call assert_equal('Another', options.highlight) 2196 2197 call assert_fails('call popup_setoptions(winid, [])', 'E715:') 2198 call assert_fails('call popup_setoptions(winid, test_null_dict())', 'E715:') 2199 2200 call popup_close(winid) 2201 call assert_equal(0, popup_setoptions(winid, options.wrap)) 2202endfunc 2203 2204func Test_popupwin_garbage_collect() 2205 func MyPopupFilter(x, winid, c) 2206 " NOP 2207 endfunc 2208 2209 let winid = popup_create('something', #{filter: function('MyPopupFilter', [{}])}) 2210 call test_garbagecollect_now() 2211 redraw 2212 " Must not crash caused by invalid memory access 2213 call feedkeys('j', 'xt') 2214 call assert_true(v:true) 2215 2216 call popup_close(winid) 2217 delfunc MyPopupFilter 2218endfunc 2219 2220func Test_popupwin_filter_mode() 2221 func MyPopupFilter(winid, c) 2222 let s:typed = a:c 2223 if a:c == ':' || a:c == "\r" || a:c == 'v' 2224 " can start cmdline mode, get out, and start/stop Visual mode 2225 return 0 2226 endif 2227 return 1 2228 endfunc 2229 2230 " Normal, Visual and Insert mode 2231 let winid = popup_create('something', #{filter: 'MyPopupFilter', filtermode: 'nvi'}) 2232 redraw 2233 call feedkeys('x', 'xt') 2234 call assert_equal('x', s:typed) 2235 2236 call feedkeys(":let g:foo = 'foo'\<CR>", 'xt') 2237 call assert_equal(':', s:typed) 2238 call assert_equal('foo', g:foo) 2239 2240 let @x = 'something' 2241 call feedkeys('v$"xy', 'xt') 2242 call assert_equal('y', s:typed) 2243 call assert_equal('something', @x) " yank command is filtered out 2244 call feedkeys('v', 'xt') " end Visual mode 2245 2246 call popup_close(winid) 2247 2248 " only Normal mode 2249 let winid = popup_create('something', #{filter: 'MyPopupFilter', filtermode: 'n'}) 2250 redraw 2251 call feedkeys('x', 'xt') 2252 call assert_equal('x', s:typed) 2253 2254 call feedkeys(":let g:foo = 'foo'\<CR>", 'xt') 2255 call assert_equal(':', s:typed) 2256 call assert_equal('foo', g:foo) 2257 2258 let @x = 'something' 2259 call feedkeys('v$"xy', 'xt') 2260 call assert_equal('v', s:typed) 2261 call assert_notequal('something', @x) 2262 2263 call popup_close(winid) 2264 2265 " default: all modes 2266 let winid = popup_create('something', #{filter: 'MyPopupFilter'}) 2267 redraw 2268 call feedkeys('x', 'xt') 2269 call assert_equal('x', s:typed) 2270 2271 let g:foo = 'bar' 2272 call feedkeys(":let g:foo = 'foo'\<CR>", 'xt') 2273 call assert_equal("\r", s:typed) 2274 call assert_equal('bar', g:foo) 2275 2276 let @x = 'something' 2277 call feedkeys('v$"xy', 'xt') 2278 call assert_equal('y', s:typed) 2279 call assert_equal('something', @x) " yank command is filtered out 2280 call feedkeys('v', 'xt') " end Visual mode 2281 2282 call popup_close(winid) 2283 delfunc MyPopupFilter 2284endfunc 2285 2286func Test_popupwin_filter_mouse() 2287 func MyPopupFilter(winid, c) 2288 let g:got_mousepos = getmousepos() 2289 return 0 2290 endfunc 2291 2292 call setline(1, ['.'->repeat(25)]->repeat(10)) 2293 let winid = popup_create(['short', 'long line that will wrap', 'other'], #{ 2294 \ line: 2, 2295 \ col: 4, 2296 \ maxwidth: 12, 2297 \ padding: [], 2298 \ border: [], 2299 \ filter: 'MyPopupFilter', 2300 \ }) 2301 redraw 2302 " 123456789012345678901 2303 " 1 ..................... 2304 " 2 ...+--------------+.. 2305 " 3 ...| |.. 2306 " 4 ...| short |.. 2307 " 5 ...| long line th |.. 2308 " 6 ...| at will wrap |.. 2309 " 7 ...| other |.. 2310 " 8 ...| |.. 2311 " 9 ...+--------------+.. 2312 " 10 ..................... 2313 let tests = [] 2314 2315 func AddItemOutsidePopup(tests, row, col) 2316 eval a:tests->add(#{clickrow: a:row, clickcol: a:col, result: #{ 2317 \ screenrow: a:row, screencol: a:col, 2318 \ winid: win_getid(), winrow: a:row, wincol: a:col, 2319 \ line: a:row, column: a:col, 2320 \ }}) 2321 endfunc 2322 func AddItemInPopupBorder(tests, winid, row, col) 2323 eval a:tests->add(#{clickrow: a:row, clickcol: a:col, result: #{ 2324 \ screenrow: a:row, screencol: a:col, 2325 \ winid: a:winid, winrow: a:row - 1, wincol: a:col - 3, 2326 \ line: 0, column: 0, 2327 \ }}) 2328 endfunc 2329 func AddItemInPopupText(tests, winid, row, col, textline, textcol) 2330 eval a:tests->add(#{clickrow: a:row, clickcol: a:col, result: #{ 2331 \ screenrow: a:row, screencol: a:col, 2332 \ winid: a:winid, winrow: a:row - 1, wincol: a:col - 3, 2333 \ line: a:textline, column: a:textcol, 2334 \ }}) 2335 endfunc 2336 2337 " above and below popup 2338 for c in range(1, 21) 2339 call AddItemOutsidePopup(tests, 1, c) 2340 call AddItemOutsidePopup(tests, 10, c) 2341 endfor 2342 " left and right of popup 2343 for r in range(1, 10) 2344 call AddItemOutsidePopup(tests, r, 3) 2345 call AddItemOutsidePopup(tests, r, 20) 2346 endfor 2347 " top and bottom in popup 2348 for c in range(4, 19) 2349 call AddItemInPopupBorder(tests, winid, 2, c) 2350 call AddItemInPopupBorder(tests, winid, 3, c) 2351 call AddItemInPopupBorder(tests, winid, 8, c) 2352 call AddItemInPopupBorder(tests, winid, 9, c) 2353 endfor 2354 " left and right margin in popup 2355 for r in range(2, 9) 2356 call AddItemInPopupBorder(tests, winid, r, 4) 2357 call AddItemInPopupBorder(tests, winid, r, 5) 2358 call AddItemInPopupBorder(tests, winid, r, 18) 2359 call AddItemInPopupBorder(tests, winid, r, 19) 2360 endfor 2361 " text "short" 2362 call AddItemInPopupText(tests, winid, 4, 6, 1, 1) 2363 call AddItemInPopupText(tests, winid, 4, 10, 1, 5) 2364 call AddItemInPopupText(tests, winid, 4, 11, 1, 6) 2365 call AddItemInPopupText(tests, winid, 4, 17, 1, 6) 2366 " text "long line th" 2367 call AddItemInPopupText(tests, winid, 5, 6, 2, 1) 2368 call AddItemInPopupText(tests, winid, 5, 10, 2, 5) 2369 call AddItemInPopupText(tests, winid, 5, 17, 2, 12) 2370 " text "at will wrap" 2371 call AddItemInPopupText(tests, winid, 6, 6, 2, 13) 2372 call AddItemInPopupText(tests, winid, 6, 10, 2, 17) 2373 call AddItemInPopupText(tests, winid, 6, 17, 2, 24) 2374 " text "other" 2375 call AddItemInPopupText(tests, winid, 7, 6, 3, 1) 2376 call AddItemInPopupText(tests, winid, 7, 10, 3, 5) 2377 call AddItemInPopupText(tests, winid, 7, 11, 3, 6) 2378 call AddItemInPopupText(tests, winid, 7, 17, 3, 6) 2379 2380 for item in tests 2381 call test_setmouse(item.clickrow, item.clickcol) 2382 call feedkeys("\<LeftMouse>", 'xt') 2383 call assert_equal(item.result, g:got_mousepos) 2384 endfor 2385 2386 call popup_close(winid) 2387 enew! 2388 delfunc MyPopupFilter 2389endfunc 2390 2391func Test_popupwin_with_buffer() 2392 call writefile(['some text', 'in a buffer'], 'XsomeFile') 2393 let buf = bufadd('XsomeFile') 2394 call assert_equal(0, bufloaded(buf)) 2395 2396 setlocal number 2397 call setbufvar(buf, "&wrapmargin", 13) 2398 2399 let winid = popup_create(buf, {}) 2400 call assert_notequal(0, winid) 2401 let pos = popup_getpos(winid) 2402 call assert_equal(2, pos.height) 2403 call assert_equal(1, bufloaded(buf)) 2404 2405 " window-local option is set to default, buffer-local is not 2406 call assert_equal(0, getwinvar(winid, '&number')) 2407 call assert_equal(13, getbufvar(buf, '&wrapmargin')) 2408 2409 call popup_close(winid) 2410 call assert_equal({}, popup_getpos(winid)) 2411 call assert_equal(1, bufloaded(buf)) 2412 exe 'bwipe! ' .. buf 2413 setlocal nonumber 2414 2415 edit test_popupwin.vim 2416 let winid = popup_create(bufnr(''), {}) 2417 redraw 2418 call popup_close(winid) 2419 call delete('XsomeFile') 2420endfunc 2421 2422func Test_popupwin_terminal_buffer() 2423 CheckFeature terminal 2424 CheckUnix 2425 " Starting a terminal to run a shell in is considered flaky. 2426 let g:test_is_flaky = 1 2427 2428 let origwin = win_getid() 2429 let ptybuf = term_start(&shell, #{hidden: 1}) 2430 let winid = popup_create(ptybuf, #{minwidth: 40, minheight: 10}) 2431 " Wait for shell to start 2432 call WaitForAssert({-> assert_equal("run", job_status(term_getjob(ptybuf)))}) 2433 sleep 100m 2434 " Check this doesn't crash 2435 call assert_equal(winnr(), winnr('j')) 2436 call assert_equal(winnr(), winnr('k')) 2437 call assert_equal(winnr(), winnr('h')) 2438 call assert_equal(winnr(), winnr('l')) 2439 2440 " Cannot quit while job is running 2441 call assert_fails('call feedkeys("\<C-W>:quit\<CR>", "xt")', 'E948:') 2442 2443 " Cannot enter Terminal-Normal mode. 2444 call feedkeys("xxx\<C-W>N", 'xt') 2445 call assert_fails('call feedkeys("gf", "xt")', 'E863:') 2446 call feedkeys("a\<C-U>", 'xt') 2447 2448 " Exiting shell closes popup window 2449 call feedkeys("exit\<CR>", 'xt') 2450 " Wait for shell to exit 2451 sleep 100m 2452 call feedkeys(":quit\<CR>", 'xt') 2453 call assert_equal(origwin, win_getid()) 2454endfunc 2455 2456func Test_popupwin_with_buffer_and_filter() 2457 new Xwithfilter 2458 call setline(1, range(100)) 2459 let bufnr = bufnr() 2460 hide 2461 2462 func BufferFilter(win, key) 2463 if a:key == 'G' 2464 " recursive use of "G" does not cause problems. 2465 call win_execute(a:win, 'normal! G') 2466 return 1 2467 endif 2468 return 0 2469 endfunc 2470 2471 let winid = popup_create(bufnr, #{maxheight: 5, filter: 'BufferFilter'}) 2472 call assert_equal(1, popup_getpos(winid).firstline) 2473 redraw 2474 call feedkeys("G", 'xt') 2475 call assert_equal(99, popup_getpos(winid).firstline) 2476 2477 call popup_close(winid) 2478 exe 'bwipe! ' .. bufnr 2479endfunc 2480 2481func Test_popupwin_width() 2482 let winid = popup_create(repeat(['short', 'long long long line', 'medium width'], 50), #{ 2483 \ maxwidth: 40, 2484 \ maxheight: 10, 2485 \ }) 2486 for top in range(1, 20) 2487 eval winid->popup_setoptions(#{firstline: top}) 2488 redraw 2489 call assert_equal(19, popup_getpos(winid).width) 2490 endfor 2491 call popup_clear() 2492endfunc 2493 2494func Test_popupwin_buf_close() 2495 let buf = bufadd('Xtestbuf') 2496 call bufload(buf) 2497 call setbufline(buf, 1, ['just', 'some', 'lines']) 2498 let winid = popup_create(buf, {}) 2499 redraw 2500 call assert_equal(3, popup_getpos(winid).height) 2501 let bufinfo = getbufinfo(buf)[0] 2502 call assert_equal(1, bufinfo.changed) 2503 call assert_equal(0, bufinfo.hidden) 2504 call assert_equal(0, bufinfo.listed) 2505 call assert_equal(1, bufinfo.loaded) 2506 call assert_equal([], bufinfo.windows) 2507 call assert_equal([winid], bufinfo.popups) 2508 2509 call popup_close(winid) 2510 call assert_equal({}, popup_getpos(winid)) 2511 let bufinfo = getbufinfo(buf)[0] 2512 call assert_equal(1, bufinfo.changed) 2513 call assert_equal(1, bufinfo.hidden) 2514 call assert_equal(0, bufinfo.listed) 2515 call assert_equal(1, bufinfo.loaded) 2516 call assert_equal([], bufinfo.windows) 2517 call assert_equal([], bufinfo.popups) 2518 exe 'bwipe! ' .. buf 2519endfunc 2520 2521func Test_popup_menu_with_maxwidth() 2522 CheckScreendump 2523 2524 let lines =<< trim END 2525 call setline(1, range(1, 10)) 2526 hi ScrollThumb ctermbg=blue 2527 hi ScrollBar ctermbg=red 2528 func PopupMenu(lines, line, col, scrollbar = 0) 2529 return popup_menu(a:lines, #{ 2530 \ maxwidth: 10, 2531 \ maxheight: 3, 2532 \ pos : 'topleft', 2533 \ col : a:col, 2534 \ line : a:line, 2535 \ scrollbar : a:scrollbar, 2536 \ }) 2537 endfunc 2538 call PopupMenu(['x'], 1, 1) 2539 call PopupMenu(['123456789|'], 1, 16) 2540 call PopupMenu(['123456789|' .. ' '], 7, 1) 2541 call PopupMenu([repeat('123456789|', 100)], 7, 16) 2542 call PopupMenu(repeat(['123456789|' .. ' '], 5), 1, 33, 1) 2543 END 2544 call writefile(lines, 'XtestPopupMenuMaxWidth') 2545 let buf = RunVimInTerminal('-S XtestPopupMenuMaxWidth', #{rows: 13}) 2546 call VerifyScreenDump(buf, 'Test_popupwin_menu_maxwidth_1', {}) 2547 2548 " close the menu popupwin. 2549 call term_sendkeys(buf, " ") 2550 call term_sendkeys(buf, " ") 2551 call term_sendkeys(buf, " ") 2552 call term_sendkeys(buf, " ") 2553 call term_sendkeys(buf, " ") 2554 2555 " clean up 2556 call StopVimInTerminal(buf) 2557 call delete('XtestPopupMenuMaxWidth') 2558endfunc 2559 2560func Test_popup_menu_with_scrollbar() 2561 CheckScreendump 2562 2563 let lines =<< trim END 2564 call setline(1, range(1, 20)) 2565 hi ScrollThumb ctermbg=blue 2566 hi ScrollBar ctermbg=red 2567 eval ['one', 'two', 'three', 'four', 'five', 2568 \ 'six', 'seven', 'eight', 'nine'] 2569 \ ->popup_menu(#{ 2570 \ minwidth: 8, 2571 \ maxheight: 3, 2572 \ }) 2573 END 2574 call writefile(lines, 'XtestPopupMenuScroll') 2575 let buf = RunVimInTerminal('-S XtestPopupMenuScroll', #{rows: 10}) 2576 2577 call term_sendkeys(buf, "j") 2578 call VerifyScreenDump(buf, 'Test_popupwin_menu_scroll_1', {}) 2579 2580 call term_sendkeys(buf, "jjj") 2581 call VerifyScreenDump(buf, 'Test_popupwin_menu_scroll_2', {}) 2582 2583 " if the cursor is the bottom line, it stays at the bottom line. 2584 call term_sendkeys(buf, repeat("j", 20)) 2585 call VerifyScreenDump(buf, 'Test_popupwin_menu_scroll_3', {}) 2586 2587 call term_sendkeys(buf, "kk") 2588 call VerifyScreenDump(buf, 'Test_popupwin_menu_scroll_4', {}) 2589 2590 call term_sendkeys(buf, "k") 2591 call VerifyScreenDump(buf, 'Test_popupwin_menu_scroll_5', {}) 2592 2593 " if the cursor is in the top line, it stays in the top line. 2594 call term_sendkeys(buf, repeat("k", 20)) 2595 call VerifyScreenDump(buf, 'Test_popupwin_menu_scroll_6', {}) 2596 2597 " close the menu popupwin. 2598 call term_sendkeys(buf, " ") 2599 2600 " clean up 2601 call StopVimInTerminal(buf) 2602 call delete('XtestPopupMenuScroll') 2603endfunc 2604 2605func Test_popup_menu_filter() 2606 CheckScreendump 2607 2608 let lines =<< trim END 2609 function! MyFilter(winid, key) abort 2610 if a:key == "0" 2611 call win_execute(a:winid, "call setpos('.', [0, 1, 1, 0])") 2612 return 1 2613 endif 2614 if a:key == "G" 2615 call win_execute(a:winid, "call setpos('.', [0, line('$'), 1, 0])") 2616 return 1 2617 endif 2618 if a:key == "j" 2619 call win_execute(a:winid, "call setpos('.', [0, line('.') + 1, 1, 0])") 2620 return 1 2621 endif 2622 if a:key == "k" 2623 call win_execute(a:winid, "call setpos('.', [0, line('.') - 1, 1, 0])") 2624 return 1 2625 endif 2626 if a:key == ':' 2627 call popup_close(a:winid) 2628 return 0 2629 endif 2630 return 0 2631 endfunction 2632 call popup_menu(['111', '222', '333', '444', '555', '666', '777', '888', '999'], #{ 2633 \ maxheight : 3, 2634 \ filter : 'MyFilter' 2635 \ }) 2636 END 2637 call writefile(lines, 'XtestPopupMenuFilter') 2638 let buf = RunVimInTerminal('-S XtestPopupMenuFilter', #{rows: 10}) 2639 2640 call term_sendkeys(buf, "j") 2641 call VerifyScreenDump(buf, 'Test_popupwin_menu_filter_1', {}) 2642 2643 call term_sendkeys(buf, "k") 2644 call VerifyScreenDump(buf, 'Test_popupwin_menu_filter_2', {}) 2645 2646 call term_sendkeys(buf, "G") 2647 call VerifyScreenDump(buf, 'Test_popupwin_menu_filter_3', {}) 2648 2649 call term_sendkeys(buf, "0") 2650 call VerifyScreenDump(buf, 'Test_popupwin_menu_filter_4', {}) 2651 2652 " check that when the popup is closed in the filter the screen is redrawn 2653 call term_sendkeys(buf, ":") 2654 call VerifyScreenDump(buf, 'Test_popupwin_menu_filter_5', {}) 2655 call term_sendkeys(buf, "\<CR>") 2656 2657 " clean up 2658 call StopVimInTerminal(buf) 2659 call delete('XtestPopupMenuFilter') 2660endfunc 2661 2662func Test_popup_cursorline() 2663 CheckScreendump 2664 2665 let winid = popup_create('some text', {}) 2666 call assert_equal(0, popup_getoptions(winid).cursorline) 2667 call popup_close(winid) 2668 2669 let winid = popup_create('some text', #{ cursorline: 1, }) 2670 call assert_equal(1, popup_getoptions(winid).cursorline) 2671 call popup_close(winid) 2672 2673 let winid = popup_create('some text', #{ cursorline: 0, }) 2674 call assert_equal(0, popup_getoptions(winid).cursorline) 2675 call popup_close(winid) 2676 2677 let winid = popup_menu('some text', {}) 2678 call assert_equal(1, popup_getoptions(winid).cursorline) 2679 call popup_close(winid) 2680 2681 let winid = popup_menu('some text', #{ cursorline: 1, }) 2682 call assert_equal(1, popup_getoptions(winid).cursorline) 2683 call popup_close(winid) 2684 2685 let winid = popup_menu('some text', #{ cursorline: 0, }) 2686 call assert_equal(0, popup_getoptions(winid).cursorline) 2687 call popup_close(winid) 2688 2689 " --------- 2690 " Pattern 1 2691 " --------- 2692 let lines =<< trim END 2693 call popup_create(['111', '222', '333'], #{ cursorline : 0 }) 2694 END 2695 call writefile(lines, 'XtestPopupCursorLine') 2696 let buf = RunVimInTerminal('-S XtestPopupCursorLine', #{rows: 10}) 2697 call VerifyScreenDump(buf, 'Test_popupwin_cursorline_1', {}) 2698 call term_sendkeys(buf, ":call popup_clear()\<cr>") 2699 call StopVimInTerminal(buf) 2700 2701 " --------- 2702 " Pattern 2 2703 " --------- 2704 let lines =<< trim END 2705 call popup_create(['111', '222', '333'], #{ cursorline : 1 }) 2706 END 2707 call writefile(lines, 'XtestPopupCursorLine') 2708 let buf = RunVimInTerminal('-S XtestPopupCursorLine', #{rows: 10}) 2709 call VerifyScreenDump(buf, 'Test_popupwin_cursorline_2', {}) 2710 call term_sendkeys(buf, ":call popup_clear()\<cr>") 2711 call StopVimInTerminal(buf) 2712 2713 " --------- 2714 " Pattern 3 2715 " --------- 2716 let lines =<< trim END 2717 function! MyFilter(winid, key) abort 2718 if a:key == "j" 2719 call win_execute(a:winid, "call setpos('.', [0, line('.') + 1, 1, 0]) | redraw") 2720 return 1 2721 endif 2722 if a:key == 'x' 2723 call popup_close(a:winid) 2724 return 1 2725 endif 2726 return 0 2727 endfunction 2728 call popup_menu(['111', '222', '333'], #{ 2729 \ cursorline : 0, 2730 \ maxheight : 2, 2731 \ filter : 'MyFilter', 2732 \ }) 2733 END 2734 call writefile(lines, 'XtestPopupCursorLine') 2735 let buf = RunVimInTerminal('-S XtestPopupCursorLine', #{rows: 10}) 2736 call VerifyScreenDump(buf, 'Test_popupwin_cursorline_3', {}) 2737 call term_sendkeys(buf, "j") 2738 call term_sendkeys(buf, "j") 2739 call VerifyScreenDump(buf, 'Test_popupwin_cursorline_4', {}) 2740 call term_sendkeys(buf, "x") 2741 call StopVimInTerminal(buf) 2742 2743 " --------- 2744 " Pattern 4 2745 " --------- 2746 let lines =<< trim END 2747 function! MyFilter(winid, key) abort 2748 if a:key == "j" 2749 call win_execute(a:winid, "call setpos('.', [0, line('.') + 1, 1, 0]) | redraw") 2750 return 1 2751 endif 2752 if a:key == 'x' 2753 call popup_close(a:winid) 2754 return 1 2755 endif 2756 return 0 2757 endfunction 2758 call popup_menu(['111', '222', '333'], #{ 2759 \ cursorline : 1, 2760 \ maxheight : 2, 2761 \ filter : 'MyFilter', 2762 \ }) 2763 END 2764 call writefile(lines, 'XtestPopupCursorLine') 2765 let buf = RunVimInTerminal('-S XtestPopupCursorLine', #{rows: 10}) 2766 call VerifyScreenDump(buf, 'Test_popupwin_cursorline_5', {}) 2767 call term_sendkeys(buf, "j") 2768 call term_sendkeys(buf, "j") 2769 call VerifyScreenDump(buf, 'Test_popupwin_cursorline_6', {}) 2770 call term_sendkeys(buf, "x") 2771 call StopVimInTerminal(buf) 2772 2773 " --------- 2774 " Cursor in second line when creating the popup 2775 " --------- 2776 let lines =<< trim END 2777 let winid = popup_create(['111', '222', '333'], #{ 2778 \ cursorline : 1, 2779 \ }) 2780 call win_execute(winid, "2") 2781 END 2782 call writefile(lines, 'XtestPopupCursorLine') 2783 let buf = RunVimInTerminal('-S XtestPopupCursorLine', #{rows: 10}) 2784 call VerifyScreenDump(buf, 'Test_popupwin_cursorline_7', {}) 2785 call StopVimInTerminal(buf) 2786 2787 call delete('XtestPopupCursorLine') 2788 2789 " --------- 2790 " Use current buffer for popupmenu 2791 " --------- 2792 let lines =<< trim END 2793 call setline(1, ['one', 'two', 'three']) 2794 let winid = popup_create(bufnr('%'), #{ 2795 \ cursorline : 1, 2796 \ }) 2797 call win_execute(winid, "2") 2798 END 2799 call writefile(lines, 'XtestPopupCursorLine') 2800 let buf = RunVimInTerminal('-S XtestPopupCursorLine', #{rows: 10}) 2801 call VerifyScreenDump(buf, 'Test_popupwin_cursorline_8', {}) 2802 call StopVimInTerminal(buf) 2803 2804 call delete('XtestPopupCursorLine') 2805endfunc 2806 2807func Test_previewpopup() 2808 CheckScreendump 2809 CheckFeature quickfix 2810 2811 call writefile([ 2812 \ "!_TAG_FILE_ENCODING\tutf-8\t//", 2813 \ "another\tXtagfile\t/^this is another", 2814 \ "theword\tXtagfile\t/^theword"], 2815 \ 'Xtags') 2816 call writefile(range(1,20) 2817 \ + ['theword is here'] 2818 \ + range(22, 27) 2819 \ + ['this is another place'] 2820 \ + range(29, 40), 2821 \ "Xtagfile") 2822 call writefile(range(1,10) 2823 \ + ['searched word is here'] 2824 \ + range(12, 20), 2825 \ "Xheader.h") 2826 let lines =<< trim END 2827 set tags=Xtags 2828 call setline(1, [ 2829 \ 'one', 2830 \ '#include "Xheader.h"', 2831 \ 'three', 2832 \ 'four', 2833 \ 'five', 2834 \ 'six', 2835 \ 'seven', 2836 \ 'find theword somewhere', 2837 \ 'nine', 2838 \ 'this is another word', 2839 \ 'very long line where the word is also another']) 2840 set previewpopup=height:4,width:40 2841 set path=. 2842 END 2843 call writefile(lines, 'XtestPreviewPopup') 2844 let buf = RunVimInTerminal('-S XtestPreviewPopup', #{rows: 14}) 2845 2846 call term_sendkeys(buf, "/theword\<CR>\<C-W>}") 2847 call term_sendkeys(buf, ":\<CR>") 2848 call VerifyScreenDump(buf, 'Test_popupwin_previewpopup_1', {}) 2849 2850 call term_sendkeys(buf, "/another\<CR>\<C-W>}") 2851 call VerifyScreenDump(buf, 'Test_popupwin_previewpopup_2', {}) 2852 2853 call term_sendkeys(buf, ":call popup_move(popup_findpreview(), #{col: 15})\<CR>") 2854 call term_sendkeys(buf, ":\<CR>") 2855 call VerifyScreenDump(buf, 'Test_popupwin_previewpopup_3', {}) 2856 2857 call term_sendkeys(buf, "/another\<CR>\<C-W>}") 2858 call VerifyScreenDump(buf, 'Test_popupwin_previewpopup_4', {}) 2859 2860 call term_sendkeys(buf, ":silent cd ..\<CR>:\<CR>") 2861 call VerifyScreenDump(buf, 'Test_popupwin_previewpopup_5', {}) 2862 call term_sendkeys(buf, ":silent cd testdir\<CR>") 2863 2864 call term_sendkeys(buf, ":pclose\<CR>") 2865 call term_sendkeys(buf, ":\<BS>") 2866 call VerifyScreenDump(buf, 'Test_popupwin_previewpopup_6', {}) 2867 2868 call term_sendkeys(buf, ":pedit +/theword Xtagfile\<CR>") 2869 call term_sendkeys(buf, ":\<CR>") 2870 call VerifyScreenDump(buf, 'Test_popupwin_previewpopup_7', {}) 2871 2872 call term_sendkeys(buf, ":pclose\<CR>") 2873 call term_sendkeys(buf, ":psearch searched\<CR>") 2874 call term_sendkeys(buf, ":\<CR>") 2875 call VerifyScreenDump(buf, 'Test_popupwin_previewpopup_8', {}) 2876 2877 call term_sendkeys(buf, "\<C-W>p") 2878 call VerifyScreenDump(buf, 'Test_popupwin_previewpopup_9', {}) 2879 2880 call term_sendkeys(buf, ":call win_execute(popup_findpreview(), 'call popup_clear()')\<CR>") 2881 call VerifyScreenDump(buf, 'Test_popupwin_previewpopup_10', {}) 2882 2883 call StopVimInTerminal(buf) 2884 call delete('Xtags') 2885 call delete('Xtagfile') 2886 call delete('XtestPreviewPopup') 2887 call delete('Xheader.h') 2888endfunc 2889 2890func Get_popupmenu_lines() 2891 let lines =<< trim END 2892 set completeopt+=preview,popup 2893 set completefunc=CompleteFuncDict 2894 hi InfoPopup ctermbg=yellow 2895 2896 func CompleteFuncDict(findstart, base) 2897 if a:findstart 2898 if col('.') > 10 2899 return col('.') - 10 2900 endif 2901 return 0 2902 endif 2903 2904 return { 2905 \ 'words': [ 2906 \ { 2907 \ 'word': 'aword', 2908 \ 'abbr': 'wrd', 2909 \ 'menu': 'extra text', 2910 \ 'info': 'words are cool', 2911 \ 'kind': 'W', 2912 \ 'user_data': 'test' 2913 \ }, 2914 \ { 2915 \ 'word': 'anotherword', 2916 \ 'abbr': 'anotwrd', 2917 \ 'menu': 'extra text', 2918 \ 'info': "other words are\ncooler than this and some more text\nto make wrap", 2919 \ 'kind': 'W', 2920 \ 'user_data': 'notest' 2921 \ }, 2922 \ { 2923 \ 'word': 'noinfo', 2924 \ 'abbr': 'noawrd', 2925 \ 'menu': 'extra text', 2926 \ 'info': "lets\nshow\na\nscrollbar\nhere", 2927 \ 'kind': 'W', 2928 \ 'user_data': 'notest' 2929 \ }, 2930 \ { 2931 \ 'word': 'thatword', 2932 \ 'abbr': 'thatwrd', 2933 \ 'menu': 'extra text', 2934 \ 'info': 'that word is cool', 2935 \ 'kind': 'W', 2936 \ 'user_data': 'notest' 2937 \ }, 2938 \ ] 2939 \ } 2940 endfunc 2941 call setline(1, 'text text text text text text text ') 2942 func ChangeColor() 2943 let id = popup_findinfo() 2944 eval id->popup_setoptions(#{highlight: 'InfoPopup'}) 2945 endfunc 2946 2947 func InfoHidden() 2948 set completepopup=height:4,border:off,align:menu 2949 set completeopt-=popup completeopt+=popuphidden 2950 au CompleteChanged * call HandleChange() 2951 endfunc 2952 2953 let s:counter = 0 2954 func HandleChange() 2955 let s:counter += 1 2956 let selected = complete_info(['selected']).selected 2957 if selected <= 0 2958 " First time: do nothing, info remains hidden 2959 return 2960 endif 2961 if selected == 1 2962 " Second time: show info right away 2963 let id = popup_findinfo() 2964 if id 2965 call popup_settext(id, 'immediate info ' .. s:counter) 2966 call popup_show(id) 2967 endif 2968 else 2969 " Third time: show info after a short delay 2970 call timer_start(100, 'ShowInfo') 2971 endif 2972 endfunc 2973 2974 func ShowInfo(...) 2975 let id = popup_findinfo() 2976 if id 2977 call popup_settext(id, 'async info ' .. s:counter) 2978 call popup_show(id) 2979 endif 2980 endfunc 2981 END 2982 return lines 2983endfunc 2984 2985func Test_popupmenu_info_border() 2986 CheckScreendump 2987 CheckFeature quickfix 2988 2989 let lines = Get_popupmenu_lines() 2990 call add(lines, 'set completepopup=height:4,highlight:InfoPopup') 2991 call writefile(lines, 'XtestInfoPopup') 2992 2993 let buf = RunVimInTerminal('-S XtestInfoPopup', #{rows: 14}) 2994 call TermWait(buf, 25) 2995 2996 call term_sendkeys(buf, "A\<C-X>\<C-U>") 2997 call VerifyScreenDump(buf, 'Test_popupwin_infopopup_1', {}) 2998 2999 call term_sendkeys(buf, "\<C-N>") 3000 call VerifyScreenDump(buf, 'Test_popupwin_infopopup_2', {}) 3001 3002 call term_sendkeys(buf, "\<C-N>") 3003 call VerifyScreenDump(buf, 'Test_popupwin_infopopup_3', {}) 3004 3005 call term_sendkeys(buf, "\<C-N>\<C-N>") 3006 call VerifyScreenDump(buf, 'Test_popupwin_infopopup_4', {}) 3007 3008 " info on the left with scrollbar 3009 call term_sendkeys(buf, "test text test text\<C-X>\<C-U>") 3010 call term_sendkeys(buf, "\<C-N>\<C-N>") 3011 call VerifyScreenDump(buf, 'Test_popupwin_infopopup_5', {}) 3012 3013 " Test that the popupmenu's scrollbar and infopopup do not overlap 3014 call term_sendkeys(buf, "\<Esc>") 3015 call term_sendkeys(buf, ":set pumheight=3\<CR>") 3016 call term_sendkeys(buf, "cc\<C-X>\<C-U>") 3017 call VerifyScreenDump(buf, 'Test_popupwin_infopopup_6', {}) 3018 3019 " Hide the info popup, cycle trough buffers, make sure it didn't get 3020 " deleted. 3021 call term_sendkeys(buf, "\<Esc>") 3022 call term_sendkeys(buf, ":set hidden\<CR>") 3023 call term_sendkeys(buf, ":bn\<CR>") 3024 call term_sendkeys(buf, ":bn\<CR>") 3025 call term_sendkeys(buf, "otest text test text\<C-X>\<C-U>") 3026 call VerifyScreenDump(buf, 'Test_popupwin_infopopup_7', {}) 3027 3028 call term_sendkeys(buf, "\<Esc>") 3029 call StopVimInTerminal(buf) 3030 call delete('XtestInfoPopup') 3031endfunc 3032 3033func Test_popupmenu_info_noborder() 3034 CheckScreendump 3035 CheckFeature quickfix 3036 3037 let lines = Get_popupmenu_lines() 3038 call add(lines, 'set completepopup=height:4,border:off') 3039 call writefile(lines, 'XtestInfoPopupNb') 3040 3041 let buf = RunVimInTerminal('-S XtestInfoPopupNb', #{rows: 14}) 3042 call TermWait(buf, 25) 3043 3044 call term_sendkeys(buf, "A\<C-X>\<C-U>") 3045 call VerifyScreenDump(buf, 'Test_popupwin_infopopup_nb_1', {}) 3046 3047 call StopVimInTerminal(buf) 3048 call delete('XtestInfoPopupNb') 3049endfunc 3050 3051func Test_popupmenu_info_align_menu() 3052 CheckScreendump 3053 CheckFeature quickfix 3054 3055 let lines = Get_popupmenu_lines() 3056 call add(lines, 'set completepopup=height:4,border:off,align:menu') 3057 call writefile(lines, 'XtestInfoPopupNb') 3058 3059 let buf = RunVimInTerminal('-S XtestInfoPopupNb', #{rows: 14}) 3060 call TermWait(buf, 25) 3061 3062 call term_sendkeys(buf, "A\<C-X>\<C-U>") 3063 call term_sendkeys(buf, "\<C-N>") 3064 call term_sendkeys(buf, "\<C-N>") 3065 call term_sendkeys(buf, "\<C-N>") 3066 call VerifyScreenDump(buf, 'Test_popupwin_infopopup_align_1', {}) 3067 3068 call term_sendkeys(buf, "test text test text test\<C-X>\<C-U>") 3069 call term_sendkeys(buf, "\<C-N>") 3070 call VerifyScreenDump(buf, 'Test_popupwin_infopopup_align_2', {}) 3071 3072 call term_sendkeys(buf, "\<Esc>") 3073 call term_sendkeys(buf, ":call ChangeColor()\<CR>") 3074 call term_sendkeys(buf, ":call setline(2, ['x']->repeat(10))\<CR>") 3075 call term_sendkeys(buf, "Gotest text test text\<C-X>\<C-U>") 3076 call VerifyScreenDump(buf, 'Test_popupwin_infopopup_align_3', {}) 3077 3078 call StopVimInTerminal(buf) 3079 call delete('XtestInfoPopupNb') 3080endfunc 3081 3082func Test_popupmenu_info_hidden() 3083 CheckScreendump 3084 CheckFeature quickfix 3085 3086 let lines = Get_popupmenu_lines() 3087 call add(lines, 'call InfoHidden()') 3088 call writefile(lines, 'XtestInfoPopupHidden') 3089 3090 let buf = RunVimInTerminal('-S XtestInfoPopupHidden', #{rows: 14}) 3091 call TermWait(buf, 25) 3092 3093 call term_sendkeys(buf, "A\<C-X>\<C-U>") 3094 call VerifyScreenDump(buf, 'Test_popupwin_infopopup_hidden_1', {}) 3095 3096 call term_sendkeys(buf, "\<C-N>") 3097 call VerifyScreenDump(buf, 'Test_popupwin_infopopup_hidden_2', {}) 3098 3099 call term_sendkeys(buf, "\<C-N>") 3100 call VerifyScreenDump(buf, 'Test_popupwin_infopopup_hidden_3', {}) 3101 3102 call term_sendkeys(buf, "\<Esc>") 3103 call StopVimInTerminal(buf) 3104 call delete('XtestInfoPopupHidden') 3105endfunc 3106 3107func Test_popupmenu_info_too_wide() 3108 CheckScreendump 3109 CheckFeature quickfix 3110 3111 let lines =<< trim END 3112 call setline(1, range(10)) 3113 3114 set completeopt+=preview,popup 3115 set completepopup=align:menu 3116 set omnifunc=OmniFunc 3117 hi InfoPopup ctermbg=lightgrey 3118 3119 func OmniFunc(findstart, base) 3120 if a:findstart 3121 return 0 3122 endif 3123 3124 let menuText = 'some long text to make sure the menu takes up all of the width of the window' 3125 return #{ 3126 \ words: [ 3127 \ #{ 3128 \ word: 'scrap', 3129 \ menu: menuText, 3130 \ info: "other words are\ncooler than this and some more text\nto make wrap", 3131 \ }, 3132 \ #{ 3133 \ word: 'scappier', 3134 \ menu: menuText, 3135 \ info: 'words are cool', 3136 \ }, 3137 \ #{ 3138 \ word: 'scrappier2', 3139 \ menu: menuText, 3140 \ info: 'words are cool', 3141 \ }, 3142 \ ] 3143 \ } 3144 endfunc 3145 END 3146 3147 call writefile(lines, 'XtestInfoPopupWide') 3148 let buf = RunVimInTerminal('-S XtestInfoPopupWide', #{rows: 8}) 3149 call TermWait(buf, 25) 3150 3151 call term_sendkeys(buf, "Ascr\<C-X>\<C-O>") 3152 call VerifyScreenDump(buf, 'Test_popupwin_infopopup_wide_1', {}) 3153 3154 call term_sendkeys(buf, "\<Esc>") 3155 call StopVimInTerminal(buf) 3156 call delete('XtestInfoPopupWide') 3157endfunc 3158 3159func Test_popupwin_recycle_bnr() 3160 let bufnr = popup_notification('nothing wrong', {})->winbufnr() 3161 call popup_clear() 3162 let winid = 'nothing wrong'->popup_notification({}) 3163 call assert_equal(bufnr, winbufnr(winid)) 3164 call popup_clear() 3165endfunc 3166 3167func Test_popupwin_getoptions_tablocal() 3168 topleft split 3169 let win1 = popup_create('nothing', #{maxheight: 8}) 3170 let win2 = popup_create('something', #{maxheight: 10}) 3171 let win3 = popup_create('something', #{maxheight: 15}) 3172 call assert_equal(8, popup_getoptions(win1).maxheight) 3173 call assert_equal(10, popup_getoptions(win2).maxheight) 3174 call assert_equal(15, popup_getoptions(win3).maxheight) 3175 call popup_clear() 3176 quit 3177endfunc 3178 3179func Test_popupwin_cancel() 3180 let win1 = popup_create('one', #{line: 5, filter: {... -> 0}}) 3181 let win2 = popup_create('two', #{line: 10, filter: {... -> 0}}) 3182 let win3 = popup_create('three', #{line: 15, filter: {... -> 0}}) 3183 call assert_equal(5, popup_getpos(win1).line) 3184 call assert_equal(10, popup_getpos(win2).line) 3185 call assert_equal(15, popup_getpos(win3).line) 3186 " TODO: this also works without patch 8.1.2110 3187 call feedkeys("\<C-C>", 'xt') 3188 call assert_equal(5, popup_getpos(win1).line) 3189 call assert_equal(10, popup_getpos(win2).line) 3190 call assert_equal({}, popup_getpos(win3)) 3191 call feedkeys("\<C-C>", 'xt') 3192 call assert_equal(5, popup_getpos(win1).line) 3193 call assert_equal({}, popup_getpos(win2)) 3194 call assert_equal({}, popup_getpos(win3)) 3195 call feedkeys("\<C-C>", 'xt') 3196 call assert_equal({}, popup_getpos(win1)) 3197 call assert_equal({}, popup_getpos(win2)) 3198 call assert_equal({}, popup_getpos(win3)) 3199endfunc 3200 3201func Test_popupwin_filter_redraw() 3202 " Create two popups with a filter that closes the popup when typing "0". 3203 " Both popups should close, even though the redraw also calls 3204 " popup_reset_handled() 3205 3206 func CloseFilter(winid, key) 3207 if a:key == '0' 3208 call popup_close(a:winid) 3209 redraw 3210 endif 3211 return 0 " pass the key 3212 endfunc 3213 3214 let id1 = popup_create('first one', #{ 3215 \ line: 1, 3216 \ col: 1, 3217 \ filter: 'CloseFilter', 3218 \ }) 3219 let id2 = popup_create('second one', #{ 3220 \ line: 9, 3221 \ col: 1, 3222 \ filter: 'CloseFilter', 3223 \ }) 3224 call assert_equal(1, popup_getpos(id1).line) 3225 call assert_equal(9, popup_getpos(id2).line) 3226 3227 call feedkeys('0', 'xt') 3228 call assert_equal({}, popup_getpos(id1)) 3229 call assert_equal({}, popup_getpos(id2)) 3230 3231 call popup_clear() 3232 delfunc CloseFilter 3233endfunc 3234 3235func Test_popupwin_double_width() 3236 CheckScreendump 3237 3238 let lines =<< trim END 3239 call setline(1, 'x你好世界你好世你好世界你好') 3240 call setline(2, '你好世界你好世你好世界你好') 3241 call setline(3, 'x你好世界你好世你好世界你好') 3242 call popup_create('你好,世界 - 你好,世界xxxxx', #{line: 1, col: 3, maxwidth: 14}) 3243 END 3244 call writefile(lines, 'XtestPopupWide') 3245 3246 let buf = RunVimInTerminal('-S XtestPopupWide', #{rows: 10}) 3247 call VerifyScreenDump(buf, 'Test_popupwin_doublewidth_1', {}) 3248 3249 call StopVimInTerminal(buf) 3250 call delete('XtestPopupWide') 3251endfunc 3252 3253func Test_popupwin_sign() 3254 CheckScreendump 3255 3256 let lines =<< trim END 3257 call setline(1, range(10)) 3258 call sign_define('Current', { 3259 \ 'text': '>>', 3260 \ 'texthl': 'WarningMsg', 3261 \ 'linehl': 'Error', 3262 \ }) 3263 call sign_define('Other', { 3264 \ 'text': '#!', 3265 \ 'texthl': 'Error', 3266 \ 'linehl': 'Search', 3267 \ }) 3268 let winid = popup_create(['hello', 'bright', 'world'], { 3269 \ 'minwidth': 20, 3270 \ }) 3271 call setwinvar(winid, "&signcolumn", "yes") 3272 let winbufnr = winbufnr(winid) 3273 3274 " add sign to current buffer, shows 3275 call sign_place(1, 'Selected', 'Current', bufnr('%'), {'lnum': 1}) 3276 " add sign to current buffer, does not show 3277 call sign_place(2, 'PopUpSelected', 'Other', bufnr('%'), {'lnum': 2}) 3278 3279 " add sign to popup buffer, shows 3280 call sign_place(3, 'PopUpSelected', 'Other', winbufnr, {'lnum': 1}) 3281 " add sign to popup buffer, does not show 3282 call sign_place(4, 'Selected', 'Current', winbufnr, {'lnum': 2}) 3283 END 3284 call writefile(lines, 'XtestPopupSign') 3285 3286 let buf = RunVimInTerminal('-S XtestPopupSign', #{rows: 10}) 3287 call VerifyScreenDump(buf, 'Test_popupwin_sign_1', {}) 3288 3289 call StopVimInTerminal(buf) 3290 call delete('XtestPopupSign') 3291endfunc 3292 3293func Test_popupwin_bufnr() 3294 let popwin = popup_create(['blah'], #{}) 3295 let popbuf = winbufnr(popwin) 3296 split asdfasdf 3297 let newbuf = bufnr() 3298 call assert_true(newbuf > popbuf, 'New buffer number is higher') 3299 call assert_equal(newbuf, bufnr('$')) 3300 call popup_clear() 3301 let popwin = popup_create(['blah'], #{}) 3302 " reuses previous buffer number 3303 call assert_equal(popbuf, winbufnr(popwin)) 3304 call assert_equal(newbuf, bufnr('$')) 3305 3306 call popup_clear() 3307 bwipe! 3308endfunc 3309 3310func Test_popupwin_filter_input_multibyte() 3311 func MyPopupFilter(winid, c) 3312 let g:bytes = range(a:c->strlen())->map({i -> char2nr(a:c[i])}) 3313 return 0 3314 endfunc 3315 let winid = popup_create('', #{mapping: 0, filter: 'MyPopupFilter'}) 3316 3317 " UTF-8: E3 80 80, including K_SPECIAL(0x80) 3318 call feedkeys("\u3000", 'xt') 3319 call assert_equal([0xe3, 0x80, 0x80], g:bytes) 3320 3321 " UTF-8: E3 80 9B, including CSI(0x9B) 3322 call feedkeys("\u301b", 'xt') 3323 call assert_equal([0xe3, 0x80, 0x9b], g:bytes) 3324 3325 call popup_clear() 3326 delfunc MyPopupFilter 3327 unlet g:bytes 3328endfunc 3329 3330func Test_popupwin_atcursor_far_right() 3331 new 3332 3333 " this was getting stuck 3334 set signcolumn=yes 3335 call setline(1, repeat('=', &columns)) 3336 normal! ggg$ 3337 let winid = popup_atcursor(repeat('x', 500), #{moved: 'any', border: []}) 3338 3339 call popup_close(winid) 3340 bwipe! 3341 set signcolumn& 3342endfunc 3343 3344func Test_popupwin_splitmove() 3345 vsplit 3346 let win2 = win_getid() 3347 let popup_winid = popup_dialog('hello', {}) 3348 call assert_fails('call win_splitmove(popup_winid, win2)', 'E957:') 3349 call assert_fails('call win_splitmove(win2, popup_winid)', 'E957:') 3350 3351 call popup_clear() 3352 bwipe 3353endfunc 3354 3355 3356" vim: shiftwidth=2 sts=2 3357