diff options
Diffstat (limited to 'test/functional/ui/statuscolumn_spec.lua')
-rw-r--r-- | test/functional/ui/statuscolumn_spec.lua | 517 |
1 files changed, 454 insertions, 63 deletions
diff --git a/test/functional/ui/statuscolumn_spec.lua b/test/functional/ui/statuscolumn_spec.lua index 3233e6cd19..6eaf15cfad 100644 --- a/test/functional/ui/statuscolumn_spec.lua +++ b/test/functional/ui/statuscolumn_spec.lua @@ -3,11 +3,15 @@ local Screen = require('test.functional.ui.screen') local clear = helpers.clear local command = helpers.command local eq = helpers.eq +local exec = helpers.exec local eval = helpers.eval local exec_lua = helpers.exec_lua local feed = helpers.feed local meths = helpers.meths local pcall_err = helpers.pcall_err +local assert_alive = helpers.assert_alive + +local mousemodels = { "extend", "popup", "popup_setpos" } describe('statuscolumn', function() local screen @@ -15,6 +19,7 @@ describe('statuscolumn', function() clear('--cmd', 'set number nuw=1 | call setline(1, repeat(["aaaaa"], 16)) | norm GM') screen = Screen.new() screen:attach() + exec_lua('ns = vim.api.nvim_create_namespace("")') end) it("fails with invalid 'statuscolumn'", function() @@ -41,22 +46,17 @@ describe('statuscolumn', function() end) it("widens with irregular 'statuscolumn' width", function() - command([[set stc=%{v:relnum?v:relnum:(v:lnum==5?'bbbbb':v:lnum)}]]) - command('norm 5G | redraw!') + screen:try_resize(screen._width, 4) + command([=[ + set stc=%{v:relnum?v:relnum:(v:lnum==5?'bbbbb':v:lnum)} + let ns = nvim_create_namespace('') + call nvim_buf_set_extmark(0, ns, 3, 0, {'virt_text':[['virt_text']]}) + norm 5G | redraw! + ]=]) screen:expect([[ - 1 aaaaa | + 1 aaaaa virt_text | bbbbba^eaaa | 1 aaaaa | - 2 aaaaa | - 3 aaaaa | - 4 aaaaa | - 5 aaaaa | - 6 aaaaa | - 7 aaaaa | - 8 aaaaa | - 9 aaaaa | - 10 aaaaa | - 11 aaaaa | | ]]) end) @@ -193,8 +193,10 @@ describe('statuscolumn', function() [2] = {foreground = Screen.colors.DarkBlue, background = Screen.colors.WebGrey}, [3] = {foreground = Screen.colors.DarkBlue, background = Screen.colors.LightGrey}, [4] = {bold = true, foreground = Screen.colors.Brown}, - [5] = {background = Screen.colors.Grey90}, + [5] = {foreground = Screen.colors.Red}, + [6] = {foreground = Screen.colors.Red, background = Screen.colors.LightGrey}, }) + command('hi! CursorLine guifg=Red guibg=NONE') screen:expect([[ {1: 4│ }aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa| {1: │ }a | @@ -211,7 +213,7 @@ describe('statuscolumn', function() {1:10│ }aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa{0:@@@}| | ]]) - command("set stc=%C%s%=%l│\\ ") + command([[set stc=%C%s%=%l│\ ]]) screen:expect_unchanged() command('set signcolumn=auto:2 foldcolumn=auto') command('sign define piet1 text=>> texthl=LineNr') @@ -265,7 +267,7 @@ describe('statuscolumn', function() {2: }{1: │}{2: }{1: }aaaaaa | {2: }{1: 7│}{2: }{1: }aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa| {2: }{1: │}{2: }{1: }aaaaaa | - {2:+}{4: 8│}{2: }{4: }{5:^+-- 1 line: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa}| + {2:+}{4: 8│}{2: }{4: }{6:^+-- 1 line: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa}| {2: }{1: 9│}{2: }{1: }aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa| {2: }{1: │}{2: }{1: }aaaaaa | {2: }{1:10│}{2: }{1: }aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa| @@ -283,7 +285,7 @@ describe('statuscolumn', function() {2: }{1: 6│}{2: }{1: }aaaaaa | {2: }{1: 7│}{2: }{1: }aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa| {2: }{1: 7│}{2: }{1: }aaaaaa | - {2:+}{4: 8│}{2: }{4: }{5:^+-- 1 line: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa}| + {2:+}{4: 8│}{2: }{4: }{6:^+-- 1 line: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa}| {2: }{1: 9│}{2: }{1: }aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa| {2: }{1: 9│}{2: }{1: }aaaaaa | {2: }{1:10│}{2: }{1: }aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa| @@ -301,7 +303,7 @@ describe('statuscolumn', function() {2: }{1: 2│}{2: }{1: }aaaaaa | {2: }{1: 1│}{2: }{1: }aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa| {2: }{1: 1│}{2: }{1: }aaaaaa | - {2:+}{4: 0│}{2: }{4: }{5:^+-- 1 line: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa}| + {2:+}{4: 0│}{2: }{4: }{6:^+-- 1 line: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa}| {2: }{1: 1│}{2: }{1: }aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa| {2: }{1: 1│}{2: }{1: }aaaaaa | {2: }{1: 2│}{2: }{1: }aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa| @@ -318,7 +320,7 @@ describe('statuscolumn', function() {2: }{1: │}{2: }{1: }aaaaaa | {2: }{1: 1│}{2: }{1: }aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa| {2: }{1: │}{2: }{1: }aaaaaa | - {2:+}{4: 0│}{2: }{4: }{5:^+-- 1 line: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa}| + {2:+}{4: 0│}{2: }{4: }{6:^+-- 1 line: aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa}| {2: }{1: 1│}{2: }{1: }aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa| {2: }{1: │}{2: }{1: }aaaaaa | {2: }{1: 2│}{2: }{1: }aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa| @@ -343,16 +345,74 @@ describe('statuscolumn', function() {2: }{1: │}{2: }{1: }aaaaaaaaaaaaaaaaaaaa | {2: }{1: 1│}{2: }{1: }aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa| {2: }{1: │}{2: }{1: }aaaaaaaaaaaaaaaaaaaa | - {2:+}{4: 0│}{2: }{4: }{5:^+-- 1 line: aaaaaaaaaaaaaaaaa}| + {2:+}{4: 0│}{2: }{4: }{6:^+-- 1 line: aaaaaaaaaaaaaaaaa}| {2: }{1: 1│}{2: }{1: }aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa| {2: }{1: │}{2: }{1: }aaaaaaaaaaaaaaaaaaaa | {2: }{1: 2│}{2: }{1: }aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa| {2: }{1: │}{2: }{1: }aaaaaaaaaaaaaaaaaaaa | | ]]) + -- Also test fold and sign column when 'cpoptions' includes "n" + command('set cpoptions+=n') + feed('Hgjg0') + screen:expect([[ + {2: }{4: 0│}{1:>>}{2: }{4: }{5:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa}| + {2: }{5:^aaaaaaaaaaaaaaaaaaaa }| + {2: }{1: 3│}{0:>!}{2: }{1: }aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa| + {2: }aaaaaaaaaaaaaaaaaaaa | + {2: }{1: 2│>>}{0:>!}{1:>>}{0:>!}{1:>>}{0:>!}{1:>>}{0:>!}{1:>> }aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa| + {2: }aaaaaaaaaaaaaaaaaaaa | + {2: }{1: 1│}{2: }{1: }aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa| + {2: }aaaaaaaaaaaaaaaaaaaa | + {2:+}{1: 4│}{2: }{1: }{3:+-- 1 line: aaaaaaaaaaaaaaaaa}| + {2: }{1: 1│}{2: }{1: }aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa| + {2: }aaaaaaaaaaaaaaaaaaaa | + {2: }{1: 2│}{2: }{1: }aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa| + {2: }aaaaaaaaaaaaaaaaaaaa | + | + ]]) + command('set breakindent') + command('sign unplace 2') + feed('J2gjg0') + screen:expect([[ + {2: }{4: 0│}{1:>>}{2: }{4: }{5:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa}| + {2: } {5:aaaaaaaaaaaaaaaaaaaa aaaaaaaaa}| + {2: } {5:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa}| + {2: } {5:^aaaaaaaaaaa }| + {2: }{1: 1│>>}{0:>!}{1:>>}{0:>!}{1:>>}{0:>!}{1:>>}{0:>!}{1:>> }aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa| + {2: } aaaaaaaaaaaaaaaaaaaa | + {2: }{1: 2│}{2: }{1: }aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa| + {2: } aaaaaaaaaaaaaaaaaaaa | + {2:+}{1: 3│}{2: }{1: }{3:+-- 1 line: aaaaaaaaaaaaaaaaa}| + {2: }{1: 4│}{2: }{1: }aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa| + {2: } aaaaaaaaaaaaaaaaaaaa | + {2: }{1: 5│}{2: }{1: }aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa| + {2: } aaaaaaaaaaaaaaaaaaaa | + | + ]]) + command('set nobreakindent') + feed('$g0') + screen:expect([[ + {2: }{4: 0│}{1:>>}{2: }{4: }{5:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa}| + {2: }{5:aaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaa}| + {2: }{5:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa}| + {2: }{5:^aaa }| + {2: }{1: 1│>>}{0:>!}{1:>>}{0:>!}{1:>>}{0:>!}{1:>>}{0:>!}{1:>> }aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa| + {2: }aaaaaaaaaaaaaaaaaaaa | + {2: }{1: 2│}{2: }{1: }aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa| + {2: }aaaaaaaaaaaaaaaaaaaa | + {2:+}{1: 3│}{2: }{1: }{3:+-- 1 line: aaaaaaaaaaaaaaaaa}| + {2: }{1: 4│}{2: }{1: }aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa| + {2: }aaaaaaaaaaaaaaaaaaaa | + {2: }{1: 5│}{2: }{1: }aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa| + {2: }aaaaaaaaaaaaaaaaaaaa | + | + ]]) + command('silent undo') + feed('8gg') + command('set cpoptions-=n') -- Status column is re-evaluated for virt_lines, buffer line, and wrapped line exec_lua([[ - local ns = vim.api.nvim_create_namespace("ns") vim.api.nvim_buf_set_extmark(0, ns, 5, 0, { virt_lines_above = true, virt_lines = {{{"virt_line above", ""}}} }) vim.api.nvim_buf_set_extmark(0, ns, 4, 0, { virt_lines = {{{"virt_line", ""}}} }) @@ -365,57 +425,216 @@ describe('statuscolumn', function() {1:buffer 0 5}aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa| {1:wrapped 1 5}aaaaaaaa | {1:virtual-2 5}virt_line | - {1:virtual-2 5}virt_line above | + {1:virtual-1 5}virt_line above | {1:buffer 0 6}aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa| {1:wrapped 1 6}aaaaaaaa | {1:buffer 0 7}aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa| {1:wrapped 1 7}aaaaaaaa | - {4:buffer 0 8}{5:^+-- 1 line: aaaaaaaaaaaaaaaaaaaaaaaaaaaaa}| + {4:buffer 0 8}{6:^+-- 1 line: aaaaaaaaaaaaaaaaaaaaaaaaaaaaa}| {1:buffer 0 9}aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa| {1:wrapped 1 9}aaaaaaaa | | ]]) + -- Also test virt_lines at the end of buffer + exec_lua([[ + vim.api.nvim_buf_set_extmark(0, ns, 15, 0, { virt_lines = {{{"END", ""}}} }) + ]]) + feed('GkJzz') + screen:expect([[ + {1:buffer 0 12}aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa| + {1:wrapped 1 12}aaaaaaaaa | + {1:buffer 0 13}aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa| + {1:wrapped 1 13}aaaaaaaaa | + {1:buffer 0 14}aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa| + {1:wrapped 1 14}aaaaaaaaa | + {4:buffer 0 15}{5:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa}| + {4:wrapped 1 15}{5:aaaaaaaaa^ aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa}| + {4:wrapped 2 15}{5:aaaaaaaaaaaaaaaaaaa }| + {1:virtual-1 15}END | + {0:~ }| + {0:~ }| + {0:~ }| + | + ]]) + -- Also test virt_lines when 'cpoptions' includes "n" + exec_lua([[ + vim.opt.cpoptions:append("n") + vim.api.nvim_buf_set_extmark(0, ns, 14, 0, { virt_lines = {{{"virt_line1", ""}}} }) + vim.api.nvim_buf_set_extmark(0, ns, 14, 0, { virt_lines = {{{"virt_line2", ""}}} }) + ]]) + screen:expect([[ + {1:buffer 0 12}aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa| + aaaaaaaaa | + {1:buffer 0 13}aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa| + aaaaaaaaa | + {1:buffer 0 14}aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa| + aaaaaaaaa | + {4:buffer 0 15}{5:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa}| + {5:aaaaaaaaa^ aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa}| + {5:aaaaaaa }| + {1:virtual-3 15}virt_line1 | + {1:virtual-2 15}virt_line2 | + {1:virtual-1 15}END | + {0:~ }| + | + ]]) end) - it("works with 'statuscolumn' clicks", function() - command('set mousemodel=extend') - command([[ - function! MyClickFunc(minwid, clicks, button, mods) - let g:testvar = printf("%d %d %s %d", a:minwid, a:clicks, a:button, getmousepos().line) - if a:mods !=# ' ' - let g:testvar ..= '(' .. a:mods .. ')' - endif - endfunction - set stc=%0@MyClickFunc@%=%l%T - ]]) - meths.input_mouse('left', 'press', '', 0, 0, 0) - eq('0 1 l 4', eval("g:testvar")) - meths.input_mouse('left', 'press', '', 0, 0, 0) - eq('0 2 l 4', eval("g:testvar")) - meths.input_mouse('left', 'press', '', 0, 0, 0) - eq('0 3 l 4', eval("g:testvar")) - meths.input_mouse('left', 'press', '', 0, 0, 0) - eq('0 4 l 4', eval("g:testvar")) - meths.input_mouse('right', 'press', '', 0, 3, 0) - eq('0 1 r 7', eval("g:testvar")) - meths.input_mouse('right', 'press', '', 0, 3, 0) - eq('0 2 r 7', eval("g:testvar")) - meths.input_mouse('right', 'press', '', 0, 3, 0) - eq('0 3 r 7', eval("g:testvar")) - meths.input_mouse('right', 'press', '', 0, 3, 0) - eq('0 4 r 7', eval("g:testvar")) - command('set laststatus=2 winbar=%f') - command('let g:testvar=""') - -- Check that winbar click doesn't register as statuscolumn click - meths.input_mouse('right', 'press', '', 0, 0, 0) - eq('', eval("g:testvar")) - -- Check that statusline click doesn't register as statuscolumn click - meths.input_mouse('right', 'press', '', 0, 12, 0) - eq('', eval("g:testvar")) + it('does not corrupt the screen with minwid sign item', function() + screen:try_resize(screen._width, 3) + screen:set_default_attr_ids({ + [0] = {foreground = Screen.colors.Brown}, + [1] = {foreground = Screen.colors.Blue4, background = Screen.colors.Gray}, + }) + command([[set stc=%6s\ %l]]) + exec_lua('vim.api.nvim_buf_set_extmark(0, ns, 7, 0, {sign_text = "𒀀"})') + screen:expect([[ + {0: 𒀀 8}^aaaaa | + {0: }{1: }{0: 9}aaaaa | + | + ]]) end) - it('click labels do not leak memory', function() - command([[ + for _, model in ipairs(mousemodels) do + describe('with mousemodel=' .. model, function() + before_each(function() + command('set mousemodel=' .. model) + exec([[ + function! MyClickFunc(minwid, clicks, button, mods) + let g:testvar = printf("%d %d %s %d", a:minwid, a:clicks, a:button, getmousepos().line) + if a:mods !=# ' ' + let g:testvar ..= '(' .. a:mods .. ')' + endif + endfunction + let g:testvar = '' + ]]) + end) + + it('clicks work with mousemodel=' .. model, function() + meths.set_option_value('statuscolumn', '%0@MyClickFunc@%=%l%T', {}) + meths.input_mouse('left', 'press', '', 0, 0, 0) + eq('0 1 l 4', eval("g:testvar")) + meths.input_mouse('left', 'press', '', 0, 0, 0) + eq('0 2 l 4', eval("g:testvar")) + meths.input_mouse('left', 'press', '', 0, 0, 0) + eq('0 3 l 4', eval("g:testvar")) + meths.input_mouse('left', 'press', '', 0, 0, 0) + eq('0 4 l 4', eval("g:testvar")) + meths.input_mouse('right', 'press', '', 0, 3, 0) + eq('0 1 r 7', eval("g:testvar")) + meths.input_mouse('right', 'press', '', 0, 3, 0) + eq('0 2 r 7', eval("g:testvar")) + meths.input_mouse('right', 'press', '', 0, 3, 0) + eq('0 3 r 7', eval("g:testvar")) + meths.input_mouse('right', 'press', '', 0, 3, 0) + eq('0 4 r 7', eval("g:testvar")) + + command('rightbelow vsplit') + meths.input_mouse('left', 'press', '', 0, 0, 27) + eq('0 1 l 4', eval("g:testvar")) + meths.input_mouse('right', 'press', '', 0, 3, 27) + eq('0 1 r 7', eval("g:testvar")) + command('setlocal rightleft') + meths.input_mouse('left', 'press', '', 0, 0, 52) + eq('0 1 l 4', eval("g:testvar")) + meths.input_mouse('right', 'press', '', 0, 3, 52) + eq('0 1 r 7', eval("g:testvar")) + command('wincmd H') + meths.input_mouse('left', 'press', '', 0, 0, 25) + eq('0 1 l 4', eval("g:testvar")) + meths.input_mouse('right', 'press', '', 0, 3, 25) + eq('0 1 r 7', eval("g:testvar")) + command('close') + + command('set laststatus=2 winbar=%f') + command('let g:testvar = ""') + -- Check that winbar click doesn't register as statuscolumn click + meths.input_mouse('right', 'press', '', 0, 0, 0) + eq('', eval("g:testvar")) + -- Check that statusline click doesn't register as statuscolumn click + meths.input_mouse('right', 'press', '', 0, 12, 0) + eq('', eval("g:testvar")) + -- Check that cmdline click doesn't register as statuscolumn click + meths.input_mouse('right', 'press', '', 0, 13, 0) + eq('', eval("g:testvar")) + end) + + it('clicks and highlights work with control characters', function() + meths.set_option_value('statuscolumn', '\t%#NonText#\1%0@MyClickFunc@\t\1%T\t%##\1', {}) + screen:expect{grid=[[ + {1:^I}{0:^A^I^A^I}{1:^A}aaaaa | + {1:^I}{0:^A^I^A^I}{1:^A}aaaaa | + {1:^I}{0:^A^I^A^I}{1:^A}aaaaa | + {1:^I}{0:^A^I^A^I}{1:^A}aaaaa | + {1:^I}{0:^A^I^A^I}{1:^A}^aaaaa | + {1:^I}{0:^A^I^A^I}{1:^A}aaaaa | + {1:^I}{0:^A^I^A^I}{1:^A}aaaaa | + {1:^I}{0:^A^I^A^I}{1:^A}aaaaa | + {1:^I}{0:^A^I^A^I}{1:^A}aaaaa | + {1:^I}{0:^A^I^A^I}{1:^A}aaaaa | + {1:^I}{0:^A^I^A^I}{1:^A}aaaaa | + {1:^I}{0:^A^I^A^I}{1:^A}aaaaa | + {1:^I}{0:^A^I^A^I}{1:^A}aaaaa | + | + ]], attr_ids={ + [0] = {foreground = Screen.colors.Blue, bold = true}; -- NonText + [1] = {foreground = Screen.colors.Brown}; -- LineNr + }} + meths.input_mouse('right', 'press', '', 0, 4, 3) + eq('', eval("g:testvar")) + meths.input_mouse('left', 'press', '', 0, 5, 8) + eq('', eval("g:testvar")) + meths.input_mouse('right', 'press', '', 0, 6, 4) + eq('0 1 r 10', eval("g:testvar")) + meths.input_mouse('left', 'press', '', 0, 7, 7) + eq('0 1 l 11', eval("g:testvar")) + end) + + it('popupmenu callback does not drag mouse on close', function() + screen:try_resize(screen._width, 2) + screen:set_default_attr_ids({ + [0] = {foreground = Screen.colors.Brown}, + [1] = {background = Screen.colors.Plum1}, + }) + meths.set_option_value('statuscolumn', '%0@MyClickFunc@%l%T', {}) + exec([[ + function! MyClickFunc(minwid, clicks, button, mods) + let g:testvar = printf("%d %d %s %d", a:minwid, a:clicks, a:button, getmousepos().line) + menu PopupStc.Echo <cmd>echo g:testvar<CR> + popup PopupStc + endfunction + ]]) + -- clicking an item does not drag mouse + meths.input_mouse('left', 'press', '', 0, 0, 0) + screen:expect([[ + {0:8 }^aaaaa | + {1: Echo } | + ]]) + meths.input_mouse('left', 'press', '', 0, 1, 5) + meths.input_mouse('left', 'release', '', 0, 1, 5) + screen:expect([[ + {0:8 }^aaaaa | + 0 1 l 8 | + ]]) + command('echo') + -- clicking outside to close the menu does not drag mouse + meths.input_mouse('left', 'press', '', 0, 0, 0) + screen:expect([[ + {0:8 }^aaaaa | + {1: Echo } | + ]]) + meths.input_mouse('left', 'press', '', 0, 0, 10) + meths.input_mouse('left', 'release', '', 0, 0, 10) + screen:expect([[ + {0:8 }^aaaaa | + | + ]]) + end) + end) + end + + it('click labels do not leak memory #21878', function() + exec([[ set laststatus=2 setlocal statuscolumn=%0@MyClickFunc@abcd%T 4vsplit @@ -427,19 +646,29 @@ describe('statuscolumn', function() ]]) end) + it('click labels do not crash when initial width is 0 #24428', function() + exec([[ + set nonumber + bwipe! + setlocal statuscolumn=abcd + redraw + setlocal statuscolumn=%0@MyClickFunc@abcd%T + redraw + ]]) + assert_alive() + end) + it('works with foldcolumn', function() -- Fits maximum multibyte foldcolumn #21759 command([[set stc=%C%=%l\ fdc=9 fillchars=foldsep:𒀀]]) for _ = 0,8 do command('norm zfjzo') end -- 'statuscolumn' is not drawn for `virt_lines_leftcol` lines exec_lua([[ - local ns = vim.api.nvim_create_namespace("ns") vim.api.nvim_buf_set_extmark(0, ns, 6, 0, { virt_lines_leftcol = true, virt_lines = {{{"virt", ""}}} }) vim.api.nvim_buf_set_extmark(0, ns, 7, 0, { virt_lines_leftcol = true, virt_lines = {{{"virt", ""}}} }) ]]) - feed('lh') -- force update cursor row screen:expect([[ 4 aaaaa | 5 aaaaa | @@ -456,7 +685,7 @@ describe('statuscolumn', function() 14 aaaaa | | ]]) - command('set stc=') -- also for the default sign column + command('set stc=') -- also for the default fold column screen:expect_unchanged() -- 'statuscolumn' is not too wide with custom (bogus) fold column command([[set stc=%{foldlevel(v:lnum)>0?repeat('-',foldlevel(v:lnum)):''}%=%l\ ]]) @@ -478,4 +707,166 @@ describe('statuscolumn', function() | ]]) end) + + it('works with cmdwin', function() + feed(':set stc=%l<CR>q:k$') + screen:expect([[ + 7 aaaaa | + 8 aaaaa | + 9 aaaaa | + 10aaaaa | + [No Name] [+] | + :1set stc=%^l | + :2 | + ~ | + ~ | + ~ | + ~ | + ~ | + [Command Line] | + : | + ]]) + end) + + it("has correct width when toggling '(relative)number'", function() + screen:try_resize(screen._width, 6) + command('call setline(1, repeat(["aaaaa"], 100))') + command('set relativenumber') + command([[set stc=%{!&nu&&!&rnu?'':&rnu?v:relnum?v:relnum:&nu?v:lnum:'0':v:lnum}]]) + screen:expect([[ + 1 aaaaa | + 8 ^aaaaa | + 1 aaaaa | + 2 aaaaa | + 3 aaaaa | + | + ]]) + -- width correctly estimated with "w_nrwidth_line_count" when setting 'stc' + command([[set stc=%{!&nu&&!&rnu?'':&rnu?v:relnum?v:relnum:&nu?v:lnum:'0':v:lnum}]]) + screen:expect_unchanged() + -- zero width when disabling 'number' + command('set norelativenumber nonumber') + screen:expect([[ + aaaaa | + ^aaaaa | + aaaaa | + aaaaa | + aaaaa | + | + ]]) + -- width correctly estimated with "w_nrwidth_line_count" when setting 'nu' + command('set number') + screen:expect([[ + 7 aaaaa | + 8 ^aaaaa | + 9 aaaaa | + 10 aaaaa | + 11 aaaaa | + | + ]]) + end) + + it("has correct width with custom sign column when (un)placing signs", function() + screen:try_resize(screen._width, 3) + exec_lua([[ + vim.cmd.norm('gg') + vim.o.signcolumn = 'no' + vim.fn.sign_define('sign', { text = 'ss' }) + _G.StatusCol = function() + local s = vim.fn.sign_getplaced(1)[1].signs + local es = vim.api.nvim_buf_get_extmarks(0, ns, 0, -1, {type = "sign"}) + local sign = '' + local signs = #s + #es + if signs > 0 then + sign = (vim.v.lnum == 2 and 'ss' or ' '):rep(signs) + end + return vim.v.lnum .. '%=' .. sign + end + vim.o.number = true + vim.o.numberwidth = 2 + vim.o.statuscolumn = "%!v:lua.StatusCol()" + ]]) + command('sign place 1 line=2 name=sign') + screen:expect([[ + 1 ^aaaaa | + 2 ssaaaaa | + | + ]]) + command('sign place 2 line=2 name=sign') + screen:expect([[ + 1 ^aaaaa | + 2 ssssaaaaa | + | + ]]) + command('sign unplace 2') + screen:expect([[ + 1 ^aaaaa | + 2 ssaaaaa | + | + ]]) + command('sign unplace 1') + screen:expect([[ + 1 ^aaaaa | + 2 aaaaa | + | + ]]) + -- Also for extmark signs + exec_lua('id1 = vim.api.nvim_buf_set_extmark(0, ns, 1, 0, {sign_text = "ss"})') + screen:expect([[ + 1 ^aaaaa | + 2 ssaaaaa | + | + ]]) + exec_lua('id2 = vim.api.nvim_buf_set_extmark(0, ns, 1, 0, {sign_text = "ss"})') + screen:expect([[ + 1 ^aaaaa | + 2 ssssaaaaa | + | + ]]) + exec_lua("vim.api.nvim_buf_del_extmark(0, ns, id1)") + screen:expect([[ + 1 ^aaaaa | + 2 ssaaaaa | + | + ]]) + exec_lua("vim.api.nvim_buf_del_extmark(0, ns, id2)") + screen:expect([[ + 1 ^aaaaa | + 2 aaaaa | + | + ]]) + -- In all windows + command('wincmd v | set ls=0') + command('sign place 1 line=2 name=sign') + screen:expect([[ + 1 ^aaaaa │1 aaaaa | + 2 ssaaaaa │2 ssaaaaa | + | + ]]) + end) + + it("is only evaluated twice, once to estimate and once to draw", function() + command([[ + let g:stcnr = 0 + func! Stc() + let g:stcnr += 1 + return '12345' + endfunc + set stc=%!Stc() + norm ggdG + ]]) + eq(2, eval('g:stcnr')) + end) + + it('does not wrap multibyte characters at the end of a line', function() + screen:try_resize(33, 4) + command([[set spell stc=%l\ ]]) + command('call setline(8, "This is a line that contains ᶏ multibyte character.")') + screen:expect([[ + 8 ^This is a line that contains ᶏ| + multibyte character. | + 9 aaaaa | + | + ]]) + end) end) |