screen_basic_spec.lua (34655B)
1 local t = require('test.testutil') 2 local n = require('test.functional.testnvim')() 3 local Screen = require('test.functional.ui.screen') 4 5 local set_session, clear, assert_alive = n.set_session, n.clear, n.assert_alive 6 local feed, command = n.feed, n.command 7 local exec = n.exec 8 local insert = n.insert 9 local eq = t.eq 10 local fn, api = n.fn, n.api 11 12 describe('screen', function() 13 local screen 14 local nvim_argv = { 15 n.nvim_prog, 16 '-u', 17 'NONE', 18 '-i', 19 'NONE', 20 '-n', 21 '--cmd', 22 'set shortmess+=I background=light noswapfile belloff= noshowcmd noruler', 23 '--cmd', 24 'colorscheme vim', 25 '--embed', 26 } 27 28 before_each(function() 29 local screen_nvim = n.new_session(false, { args = nvim_argv, merge = false }) 30 set_session(screen_nvim) 31 screen = Screen.new() 32 end) 33 34 it('default initial screen', function() 35 screen:expect([[ 36 ^ | 37 {1:~ }|*11 38 {3:[No Name] }| 39 | 40 ]]) 41 end) 42 end) 43 44 local function screen_tests(linegrid) 45 local screen 46 47 before_each(function() 48 clear() 49 screen = Screen.new(53, 14, { rgb = true, ext_linegrid = linegrid }) 50 screen:set_default_attr_ids({ 51 [0] = { bold = true, foreground = 255 }, 52 [1] = { bold = true, reverse = true }, 53 [2] = { bold = true }, 54 [3] = { reverse = true }, 55 [4] = { background = Screen.colors.LightGrey, underline = true }, 56 [5] = { 57 background = Screen.colors.LightGrey, 58 underline = true, 59 bold = true, 60 foreground = Screen.colors.Fuchsia, 61 }, 62 [6] = { bold = true, foreground = Screen.colors.Fuchsia }, 63 [7] = { bold = true, foreground = Screen.colors.SeaGreen }, 64 [8] = { foreground = Screen.colors.White, background = Screen.colors.Red }, 65 }) 66 end) 67 68 describe('bell/visual bell', function() 69 it('is forwarded to the UI', function() 70 feed('<left>') 71 screen:expect(function() 72 eq(true, screen.bell) 73 eq(false, screen.visual_bell) 74 end) 75 screen.bell = false 76 command('set visualbell') 77 feed('<left>') 78 screen:expect(function() 79 eq(true, screen.visual_bell) 80 eq(false, screen.bell) 81 end) 82 end) 83 end) 84 85 describe(':set title', function() 86 it('is forwarded to the UI', function() 87 local expected = 'test-title' 88 command('set titlestring=' .. expected) 89 command('set title') 90 screen:expect(function() 91 eq(expected, screen.title) 92 end) 93 screen:detach() 94 screen.title = nil 95 screen:attach() 96 screen:expect(function() 97 eq(expected, screen.title) 98 end) 99 end) 100 end) 101 102 describe(':set icon', function() 103 it('is forwarded to the UI', function() 104 local expected = 'test-icon' 105 command('set iconstring=' .. expected) 106 command('set icon') 107 screen:expect(function() 108 eq(expected, screen.icon) 109 end) 110 screen:detach() 111 screen.icon = nil 112 screen:attach() 113 screen:expect(function() 114 eq(expected, screen.icon) 115 end) 116 end) 117 end) 118 119 describe('statusline', function() 120 it('is redrawn after <c-l>', function() 121 command('set laststatus=2') 122 screen:expect([[ 123 ^ | 124 {0:~ }|*11 125 {1:[No Name] }| 126 | 127 ]]) 128 129 feed('<c-l>') 130 screen:expect { 131 grid = [[ 132 ^ | 133 {0:~ }|*11 134 {1:[No Name] }| 135 | 136 ]], 137 reset = true, 138 } 139 140 command('split') 141 screen:expect([[ 142 ^ | 143 {0:~ }|*5 144 {1:[No Name] }| 145 | 146 {0:~ }|*4 147 {3:[No Name] }| 148 | 149 ]]) 150 151 feed('<c-l>') 152 screen:expect { 153 grid = [[ 154 ^ | 155 {0:~ }|*5 156 {1:[No Name] }| 157 | 158 {0:~ }|*4 159 {3:[No Name] }| 160 | 161 ]], 162 reset = true, 163 } 164 end) 165 end) 166 167 describe('window', function() 168 describe('split', function() 169 it('horizontal', function() 170 command('sp') 171 screen:expect([[ 172 ^ | 173 {0:~ }|*5 174 {1:[No Name] }| 175 | 176 {0:~ }|*4 177 {3:[No Name] }| 178 | 179 ]]) 180 end) 181 182 it('horizontal and resize', function() 183 command('sp') 184 command('resize 8') 185 screen:expect([[ 186 ^ | 187 {0:~ }|*7 188 {1:[No Name] }| 189 | 190 {0:~ }|*2 191 {3:[No Name] }| 192 | 193 ]]) 194 end) 195 196 it('horizontal and vertical', function() 197 command('sp') 198 command('vsp') 199 command('vsp') 200 screen:expect([[ 201 ^ │ │ | 202 {0:~ }│{0:~ }│{0:~ }|*5 203 {1:[No Name] }{3:[No Name] [No Name] }| 204 | 205 {0:~ }|*4 206 {3:[No Name] }| 207 | 208 ]]) 209 insert('hello') 210 screen:expect([[ 211 hell^o │hello │hello | 212 {0:~ }│{0:~ }│{0:~ }|*5 213 {1:[No Name] [+] }{3:[No Name] [+] [No Name] [+] }| 214 hello | 215 {0:~ }|*4 216 {3:[No Name] [+] }| 217 | 218 ]]) 219 end) 220 end) 221 end) 222 223 describe('tabs', function() 224 it('tabnew creates a new buffer', function() 225 command('sp') 226 command('vsp') 227 command('vsp') 228 insert('hello') 229 screen:expect([[ 230 hell^o │hello │hello | 231 {0:~ }│{0:~ }│{0:~ }|*5 232 {1:[No Name] [+] }{3:[No Name] [+] [No Name] [+] }| 233 hello | 234 {0:~ }|*4 235 {3:[No Name] [+] }| 236 | 237 ]]) 238 command('tabnew') 239 insert('hello2') 240 feed('h') 241 screen:expect([[ 242 {4: }{5:4}{4:+ [No Name] }{2: + [No Name] }{3: }{4:X}| 243 hell^o2 | 244 {0:~ }|*11 245 | 246 ]]) 247 command('tabprevious') 248 screen:expect([[ 249 {2: }{6:4}{2:+ [No Name] }{4: + [No Name] }{3: }{4:X}| 250 hell^o │hello │hello | 251 {0:~ }│{0:~ }│{0:~ }|*5 252 {1:[No Name] [+] }{3:[No Name] [+] [No Name] [+] }| 253 hello | 254 {0:~ }|*3 255 {3:[No Name] [+] }| 256 | 257 ]]) 258 end) 259 260 it('tabline is redrawn after messages', function() 261 command('tabnew') 262 screen:expect([[ 263 {4: [No Name] }{2: [No Name] }{3: }{4:X}| 264 ^ | 265 {0:~ }|*11 266 | 267 ]]) 268 269 feed(':echo "' .. string.rep('x\\n', 11) .. '"<cr>') 270 screen:expect([[ 271 {1: }| 272 x |*11 273 | 274 {7:Press ENTER or type command to continue}^ | 275 ]]) 276 277 feed('<cr>') 278 screen:expect([[ 279 {4: [No Name] }{2: [No Name] }{3: }{4:X}| 280 ^ | 281 {0:~ }|*11 282 | 283 ]]) 284 285 feed(':echo "' .. string.rep('x\\n', 12) .. '"<cr>') 286 screen:expect([[ 287 x |*12 288 | 289 {7:Press ENTER or type command to continue}^ | 290 ]]) 291 292 feed('<cr>') 293 screen:expect([[ 294 {4: [No Name] }{2: [No Name] }{3: }{4:X}| 295 ^ | 296 {0:~ }|*11 297 | 298 ]]) 299 end) 300 301 it('redraws properly with :tab split right after scroll', function() 302 feed('15Ofoo<esc>15Obar<esc>gg') 303 304 command('vsplit') 305 screen:expect([[ 306 ^foo │foo | 307 foo │foo |*11 308 {1:[No Name] [+] }{3:[No Name] [+] }| 309 | 310 ]]) 311 312 feed('<PageDown>') 313 screen:expect([[ 314 ^foo │foo | 315 foo │foo |*3 316 bar │foo |*8 317 {1:[No Name] [+] }{3:[No Name] [+] }| 318 | 319 ]]) 320 command('tab split') 321 screen:expect([[ 322 {4: }{5:2}{4:+ [No Name] }{2: + [No Name] }{3: }{4:X}| 323 ^foo | 324 foo |*3 325 bar |*8 326 | 327 ]]) 328 end) 329 330 it('redraws unvisited tab #9152', function() 331 insert('hello') 332 -- create a tab without visiting it 333 command('tabnew|tabnext') 334 screen:expect([[ 335 {2: + [No Name] }{4: [No Name] }{3: }{4:X}| 336 hell^o | 337 {0:~ }|*11 338 | 339 ]]) 340 341 feed('gT') 342 screen:expect([[ 343 {4: + [No Name] }{2: [No Name] }{3: }{4:X}| 344 ^ | 345 {0:~ }|*11 346 | 347 ]]) 348 end) 349 end) 350 351 describe('insert mode', function() 352 it('move to next line with <cr>', function() 353 feed('iline 1<cr>line 2<cr>') 354 screen:expect([[ 355 line 1 | 356 line 2 | 357 ^ | 358 {0:~ }|*10 359 {2:-- INSERT --} | 360 ]]) 361 end) 362 end) 363 364 describe('normal mode', function() 365 -- https://code.google.com/p/vim/issues/detail?id=339 366 it("setting 'ruler' doesn't reset the preferred column", function() 367 command('set virtualedit=') 368 feed('i0123456<cr>789<esc>kllj') 369 command('set ruler') 370 feed('k') 371 screen:expect([[ 372 0123^456 | 373 789 | 374 {0:~ }|*11 375 1,5 All | 376 ]]) 377 end) 378 end) 379 380 describe('command mode', function() 381 it('typing commands', function() 382 feed(':ls') 383 screen:expect([[ 384 | 385 {0:~ }|*12 386 :ls^ | 387 ]]) 388 end) 389 390 it('execute command with multi-line output', function() 391 feed(':ls<cr>') 392 screen:expect([[ 393 | 394 {0:~ }|*9 395 {1: }| 396 :ls | 397 1 %a "[No Name]" line 1 | 398 {7:Press ENTER or type command to continue}^ | 399 ]]) 400 feed('<cr>') -- skip the "Press ENTER..." state or tests will hang 401 end) 402 end) 403 404 describe('scrolling and clearing', function() 405 before_each(function() 406 insert([[ 407 Inserting 408 text 409 with 410 many 411 lines 412 to 413 test 414 scrolling 415 and 416 clearing 417 in 418 split 419 windows 420 ]]) 421 command('sp') 422 command('vsp') 423 command('vsp') 424 screen:expect([[ 425 and │and │and | 426 clearing │clearing │clearing | 427 in │in │in | 428 split │split │split | 429 windows │windows │windows | 430 ^ │ │ | 431 {1:[No Name] [+] }{3:[No Name] [+] [No Name] [+] }| 432 clearing | 433 in | 434 split | 435 windows | 436 | 437 {3:[No Name] [+] }| 438 | 439 ]]) 440 end) 441 442 it('only affects the current scroll region', function() 443 feed('6k') 444 screen:expect([[ 445 ^scrolling │and │and | 446 and │clearing │clearing | 447 clearing │in │in | 448 in │split │split | 449 split │windows │windows | 450 windows │ │ | 451 {1:[No Name] [+] }{3:[No Name] [+] [No Name] [+] }| 452 clearing | 453 in | 454 split | 455 windows | 456 | 457 {3:[No Name] [+] }| 458 | 459 ]]) 460 feed('<c-w>l') 461 screen:expect([[ 462 scrolling │and │and | 463 and │clearing │clearing | 464 clearing │in │in | 465 in │split │split | 466 split │windows │windows | 467 windows │^ │ | 468 {3:[No Name] [+] }{1:[No Name] [+] }{3:<Name] [+] }| 469 clearing | 470 in | 471 split | 472 windows | 473 | 474 {3:[No Name] [+] }| 475 | 476 ]]) 477 feed('gg') 478 screen:expect([[ 479 scrolling │^Inserting │and | 480 and │text │clearing | 481 clearing │with │in | 482 in │many │split | 483 split │lines │windows | 484 windows │to │ | 485 {3:[No Name] [+] }{1:[No Name] [+] }{3:<Name] [+] }| 486 clearing | 487 in | 488 split | 489 windows | 490 | 491 {3:[No Name] [+] }| 492 | 493 ]]) 494 feed('7j') 495 screen:expect([[ 496 scrolling │with │and | 497 and │many │clearing | 498 clearing │lines │in | 499 in │to │split | 500 split │test │windows | 501 windows │^scrolling │ | 502 {3:[No Name] [+] }{1:[No Name] [+] }{3:<Name] [+] }| 503 clearing | 504 in | 505 split | 506 windows | 507 | 508 {3:[No Name] [+] }| 509 | 510 ]]) 511 feed('2j') 512 screen:expect([[ 513 scrolling │lines │and | 514 and │to │clearing | 515 clearing │test │in | 516 in │scrolling │split | 517 split │and │windows | 518 windows │^clearing │ | 519 {3:[No Name] [+] }{1:[No Name] [+] }{3:<Name] [+] }| 520 clearing | 521 in | 522 split | 523 windows | 524 | 525 {3:[No Name] [+] }| 526 | 527 ]]) 528 feed('5k') 529 screen:expect([[ 530 scrolling │^lines │and | 531 and │to │clearing | 532 clearing │test │in | 533 in │scrolling │split | 534 split │and │windows | 535 windows │clearing │ | 536 {3:[No Name] [+] }{1:[No Name] [+] }{3:<Name] [+] }| 537 clearing | 538 in | 539 split | 540 windows | 541 | 542 {3:[No Name] [+] }| 543 | 544 ]]) 545 feed('k') 546 screen:expect([[ 547 scrolling │^many │and | 548 and │lines │clearing | 549 clearing │to │in | 550 in │test │split | 551 split │scrolling │windows | 552 windows │and │ | 553 {3:[No Name] [+] }{1:[No Name] [+] }{3:<Name] [+] }| 554 clearing | 555 in | 556 split | 557 windows | 558 | 559 {3:[No Name] [+] }| 560 | 561 ]]) 562 end) 563 end) 564 565 describe('resize', function() 566 it('rebuilds the whole screen', function() 567 screen:try_resize(25, 5) 568 feed('iresize') 569 screen:expect([[ 570 resize^ | 571 {0:~ }|*3 572 {2:-- INSERT --} | 573 ]]) 574 end) 575 576 it('has minimum width/height values', function() 577 feed('iresize') 578 screen:try_resize(1, 1) 579 screen:expect([[ 580 resize^ | 581 {2:-- INSERT --}| 582 ]]) 583 584 feed('<esc>:ls') 585 screen:expect([[ 586 resize | 587 :ls^ | 588 ]]) 589 end) 590 591 it('VimResized autocommand does not cause invalid UI events #20692 #20759', function() 592 screen:try_resize(25, 5) 593 feed('iresize<Esc>') 594 command([[autocmd VimResized * redrawtabline]]) 595 command([[autocmd VimResized * lua vim.api.nvim_echo({ { 'Hello' } }, false, {})]]) 596 command([[autocmd VimResized * let g:echospace = v:echospace]]) 597 api.nvim_set_option_value('showtabline', 2, {}) 598 screen:expect([[ 599 {2: + [No Name] }{3: }| 600 resiz^e | 601 {0:~ }|*2 602 | 603 ]]) 604 screen:try_resize(30, 6) 605 screen:expect([[ 606 {2: + [No Name] }{3: }| 607 resiz^e | 608 {0:~ }|*3 609 | 610 ]]) 611 eq(29, api.nvim_get_var('echospace')) 612 end) 613 614 it('messages from the same Ex command as resize are visible #22225', function() 615 feed(':set columns=20 | call<CR>') 616 screen:expect([[ 617 |*9 618 {1: }| 619 {8:E471: Argument requi}| 620 {8:red} | 621 {7:Press ENTER or type }| 622 {7:command to continue}^ | 623 ]]) 624 feed('<CR>') 625 screen:expect([[ 626 ^ | 627 {0:~ }|*12 628 | 629 ]]) 630 feed(':set columns=0<CR>') 631 screen:expect([[ 632 | 633 {0:~ }|*7 634 {1: }| 635 {8:E594: Need at least }| 636 {8:12 columns: columns=}| 637 {8:0} | 638 {7:Press ENTER or type }| 639 {7:command to continue}^ | 640 ]]) 641 feed('<CR>') 642 screen:expect([[ 643 ^ | 644 {0:~ }|*12 645 | 646 ]]) 647 end) 648 649 it('does not crash when windows fill the screen #33883', function() 650 screen:try_resize(80, 20) 651 while true do 652 local ok = pcall(command, 'wincmd v') 653 if not ok then 654 break 655 end 656 end 657 658 screen:try_resize(60, 20) 659 660 assert_alive() 661 end) 662 663 it('clamps &cmdheight for current tabpage', function() 664 command('set cmdheight=10 laststatus=2') 665 screen:expect([[ 666 ^ | 667 {0:~ }|*2 668 {1:[No Name] }| 669 |*10 670 ]]) 671 screen:try_resize(53, 8) 672 screen:expect([[ 673 ^ | 674 {1:[No Name] }| 675 |*6 676 ]]) 677 eq(6, api.nvim_get_option_value('cmdheight', {})) 678 end) 679 680 it('clamps &cmdheight for another tabpage #31380', function() 681 command('tabnew') 682 command('set cmdheight=9 laststatus=2') 683 screen:expect([[ 684 {4: [No Name] }{2: [No Name] }{3: }{4:X}| 685 ^ | 686 {0:~ }|*2 687 {1:[No Name] }| 688 |*9 689 ]]) 690 command('tabprev') 691 screen:expect([[ 692 {2: [No Name] }{4: [No Name] }{3: }{4:X}| 693 ^ | 694 {0:~ }|*10 695 {1:[No Name] }| 696 | 697 ]]) 698 screen:try_resize(53, 8) 699 screen:expect([[ 700 {2: [No Name] }{4: [No Name] }{3: }{4:X}| 701 ^ | 702 {0:~ }|*4 703 {1:[No Name] }| 704 | 705 ]]) 706 command('tabnext') 707 screen:expect([[ 708 {4: [No Name] }{2: [No Name] }{3: }{4:X}| 709 ^ | 710 {1:[No Name] }| 711 |*5 712 ]]) 713 eq(5, api.nvim_get_option_value('cmdheight', {})) 714 end) 715 end) 716 717 describe('press enter', function() 718 it('does not crash on <F1> at “Press ENTER”', function() 719 command('nnoremap <F1> :echo "TEST"<CR>') 720 feed(':ls<CR>') 721 screen:expect([[ 722 | 723 {0:~ }|*9 724 {1: }| 725 :ls | 726 1 %a "[No Name]" line 1 | 727 {7:Press ENTER or type command to continue}^ | 728 ]]) 729 feed('<F1>') 730 screen:expect([[ 731 ^ | 732 {0:~ }|*12 733 TEST | 734 ]]) 735 end) 736 end) 737 738 -- Regression test for #8357 739 it('does not have artifacts after temporary chars in insert mode', function() 740 command('set timeoutlen=10000') 741 command('inoremap jk <esc>') 742 feed('ifooj') 743 screen:expect([[ 744 foo^j | 745 {0:~ }|*12 746 {2:-- INSERT --} | 747 ]]) 748 feed('k') 749 screen:expect([[ 750 fo^o | 751 {0:~ }|*12 752 | 753 ]]) 754 end) 755 end 756 757 describe('Screen (char-based)', function() 758 screen_tests(false) 759 end) 760 761 describe('Screen (line-based)', function() 762 screen_tests(true) 763 end) 764 765 describe('Screen default colors', function() 766 local screen 767 local function startup(light, termcolors) 768 local extra = (light and ' background=light') or '' 769 770 local nvim_argv = { 771 n.nvim_prog, 772 '-u', 773 'NONE', 774 '-i', 775 'NONE', 776 '-N', 777 '--cmd', 778 'set shortmess+=I noswapfile belloff= noshowcmd noruler' .. extra, 779 '--cmd', 780 'colorscheme vim', 781 '--embed', 782 } 783 local screen_nvim = n.new_session(false, { args = nvim_argv, merge = false }) 784 set_session(screen_nvim) 785 screen = Screen.new(53, 14, { rgb = true, ext_termcolors = termcolors or nil }) 786 end 787 788 it('are dark per default', function() 789 startup(false, false) 790 screen:expect { 791 condition = function() 792 eq({ 793 rgb_bg = 0, 794 rgb_fg = Screen.colors.White, 795 rgb_sp = Screen.colors.Red, 796 cterm_bg = 0, 797 cterm_fg = 0, 798 }, screen.default_colors) 799 end, 800 } 801 end) 802 803 it('can be set to light', function() 804 startup(true, false) 805 screen:expect { 806 condition = function() 807 eq({ 808 rgb_bg = Screen.colors.White, 809 rgb_fg = 0, 810 rgb_sp = Screen.colors.Red, 811 cterm_bg = 0, 812 cterm_fg = 0, 813 }, screen.default_colors) 814 end, 815 } 816 end) 817 818 it('can be handled by external terminal', function() 819 startup(false, true) 820 screen:expect { 821 condition = function() 822 eq( 823 { rgb_bg = -1, rgb_fg = -1, rgb_sp = -1, cterm_bg = 0, cterm_fg = 0 }, 824 screen.default_colors 825 ) 826 end, 827 } 828 829 startup(true, true) 830 screen:expect { 831 condition = function() 832 eq( 833 { rgb_bg = -1, rgb_fg = -1, rgb_sp = -1, cterm_bg = 0, cterm_fg = 0 }, 834 screen.default_colors 835 ) 836 end, 837 } 838 end) 839 end) 840 841 it('CTRL-F or CTRL-B scrolls a page after UI attach/resize #20605', function() 842 clear() 843 local screen = Screen.new(100, 100) 844 eq(100, api.nvim_get_option_value('lines', {})) 845 eq(99, api.nvim_get_option_value('window', {})) 846 eq(99, api.nvim_win_get_height(0)) 847 feed('1000o<Esc>') 848 eq(903, fn.line('w0')) 849 feed('<C-B>') 850 eq(806, fn.line('w0')) 851 feed('<C-B>') 852 eq(709, fn.line('w0')) 853 feed('<C-F>') 854 eq(806, fn.line('w0')) 855 feed('<C-F>') 856 eq(903, fn.line('w0')) 857 feed('G') 858 screen:try_resize(50, 50) 859 eq(50, api.nvim_get_option_value('lines', {})) 860 eq(49, api.nvim_get_option_value('window', {})) 861 eq(49, api.nvim_win_get_height(0)) 862 eq(953, fn.line('w0')) 863 feed('<C-B>') 864 eq(906, fn.line('w0')) 865 feed('<C-B>') 866 eq(859, fn.line('w0')) 867 feed('<C-F>') 868 eq(906, fn.line('w0')) 869 feed('<C-F>') 870 eq(953, fn.line('w0')) 871 end) 872 873 it("showcmd doesn't cause empty grid_line with redrawdebug=compositor #22593", function() 874 clear() 875 local screen = Screen.new(30, 2) 876 command('set showcmd redrawdebug=compositor') 877 feed('d') 878 screen:expect { 879 grid = [[ 880 ^ | 881 d | 882 ]], 883 } 884 end) 885 886 it("scrolling in narrow window doesn't draw over separator #29033", function() 887 clear() 888 local screen = Screen.new(60, 8) 889 feed('100Oa<Esc>gg') 890 exec([[ 891 set number nowrap 892 vsplit 893 set scrollbind 894 wincmd l 895 set scrollbind 896 wincmd | 897 ]]) 898 screen:expect([[ 899 {8: }│{8: 1 }^a | 900 {8: }│{8: 2 }a | 901 {8: }│{8: 3 }a | 902 {8: }│{8: 4 }a | 903 {8: }│{8: 5 }a | 904 {8: }│{8: 6 }a | 905 {2:< }{3:[No Name] [+] }| 906 | 907 ]]) 908 feed('<C-F>') 909 screen:expect([[ 910 {8: }│{8: 5 }^a | 911 {8: }│{8: 6 }a | 912 {8: }│{8: 7 }a | 913 {8: }│{8: 8 }a | 914 {8: }│{8: 9 }a | 915 {8: }│{8: 10 }a | 916 {2:< }{3:[No Name] [+] }| 917 | 918 ]]) 919 end)