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