neovim/test/functional/ui/winbar_spec.lua
bfredl e61228a214 fix(tests): needing two calls to setup a screen is cringe
Before calling "attach" a screen object is just a dummy container for
(row, col) values whose purpose is to be sent as part of the "attach"
function call anyway.

Just create the screen in an attached state directly. Keep the complete
(row, col, options) config together. It is still completely valid to
later detach and re-attach as needed, including to another session.
2024-11-14 12:40:57 +01:00

635 lines
29 KiB
Lua

local t = require('test.testutil')
local n = require('test.functional.testnvim')()
local Screen = require('test.functional.ui.screen')
local clear = n.clear
local command = n.command
local insert = n.insert
local api = n.api
local eq = t.eq
local poke_eventloop = n.poke_eventloop
local feed = n.feed
local fn = n.fn
local pcall_err = t.pcall_err
describe('winbar', function()
local screen
before_each(function()
clear()
screen = Screen.new(60, 13)
screen:set_default_attr_ids({
[1] = { bold = true },
[2] = { reverse = true },
[3] = { bold = true, foreground = Screen.colors.Blue },
[4] = { bold = true, reverse = true },
[5] = { bold = true, foreground = Screen.colors.Red },
[6] = { foreground = Screen.colors.Blue },
[7] = { foreground = Screen.colors.Black, background = Screen.colors.LightGrey },
[8] = { background = Screen.colors.LightMagenta },
[9] = {
bold = true,
foreground = Screen.colors.Blue,
background = Screen.colors.LightMagenta,
},
[10] = { background = Screen.colors.LightGrey, underline = true },
[11] = {
background = Screen.colors.LightGrey,
underline = true,
bold = true,
foreground = Screen.colors.Magenta,
},
[12] = {
underline = true,
background = Screen.colors.Red,
},
[13] = {
underline = true,
bold = true,
foreground = Screen.colors.Blue,
background = Screen.colors.Red,
},
})
api.nvim_set_option_value('winbar', 'Set Up The Bars', {})
end)
it('works', function()
screen:expect([[
{1:Set Up The Bars }|
^ |
{3:~ }|*10
|
]])
-- winbar is excluded from the heights returned by winheight() and getwininfo()
eq(11, fn.winheight(0))
local win_info = fn.getwininfo(api.nvim_get_current_win())[1]
eq(11, win_info.height)
eq(1, win_info.winbar)
end)
it("works with custom 'fillchars' value", function()
command('set fillchars=wbr:+')
screen:expect([[
{1:Set Up The Bars+++++++++++++++++++++++++++++++++++++++++++++}|
^ |
{3:~ }|*10
|
]])
end)
it('works with custom highlight', function()
command('hi WinBar guifg=red')
screen:expect([[
{5:Set Up The Bars }|
^ |
{3:~ }|*10
|
]])
end)
it('works with splits', function()
command('hi WinBar guifg=red')
command('hi WinBarNC guifg=blue')
command('belowright vsplit | split | split')
screen:expect([[
{6:Set Up The Bars }│{5:Set Up The Bars }|
│^ |
{3:~ }│{3:~ }|
{3:~ }│{4:[No Name] }|
{3:~ }│{6:Set Up The Bars }|
{3:~ }│ |
{3:~ }│{3:~ }|
{3:~ }│{2:[No Name] }|
{3:~ }│{6:Set Up The Bars }|
{3:~ }│ |
{3:~ }│{3:~ }|
{2:[No Name] [No Name] }|
|
]])
-- 'showcmdloc' "statusline" should not interfere with winbar redrawing #23030
command('set showcmd showcmdloc=statusline')
feed('<C-W>w')
feed('<C-W>')
screen:expect([[
{6:Set Up The Bars }│{6:Set Up The Bars }|
│ |
{3:~ }│{3:~ }|
{3:~ }│{2:[No Name] }|
{3:~ }│{5:Set Up The Bars }|
{3:~ }│^ |
{3:~ }│{3:~ }|
{3:~ }│{4:[No Name] ^W }|
{3:~ }│{6:Set Up The Bars }|
{3:~ }│ |
{3:~ }│{3:~ }|
{2:[No Name] [No Name] }|
|
]])
feed('w<C-W>W')
screen:expect([[
{6:Set Up The Bars }│{6:Set Up The Bars }|
│ |
{3:~ }│{3:~ }|
{3:~ }│{2:[No Name] }|
{3:~ }│{5:Set Up The Bars }|
{3:~ }│^ |
{3:~ }│{3:~ }|
{3:~ }│{4:[No Name] }|
{3:~ }│{6:Set Up The Bars }|
{3:~ }│ |
{3:~ }│{3:~ }|
{2:[No Name] [No Name] }|
|
]])
end)
it("works when switching value of 'winbar'", function()
command('belowright vsplit | split | split | set winbar=')
screen:expect([[
│^ |
{3:~ }│{3:~ }|*2
{3:~ }│{4:[No Name] }|
{3:~ }│ |
{3:~ }│{3:~ }|*2
{3:~ }│{2:[No Name] }|
{3:~ }│ |
{3:~ }│{3:~ }|*2
{2:[No Name] [No Name] }|
|
]])
command('set winbar=All\\ Your\\ Bar\\ Are\\ Belong\\ To\\ Us')
screen:expect([[
{1:All Your Bar Are Belong To Us}│{1:All Your Bar Are Belong To Us }|
│^ |
{3:~ }│{3:~ }|
{3:~ }│{4:[No Name] }|
{3:~ }│{1:All Your Bar Are Belong To Us }|
{3:~ }│ |
{3:~ }│{3:~ }|
{3:~ }│{2:[No Name] }|
{3:~ }│{1:All Your Bar Are Belong To Us }|
{3:~ }│ |
{3:~ }│{3:~ }|
{2:[No Name] [No Name] }|
|
]])
command('set winbar=Changed\\ winbar')
screen:expect([[
{1:Changed winbar }│{1:Changed winbar }|
│^ |
{3:~ }│{3:~ }|
{3:~ }│{4:[No Name] }|
{3:~ }│{1:Changed winbar }|
{3:~ }│ |
{3:~ }│{3:~ }|
{3:~ }│{2:[No Name] }|
{3:~ }│{1:Changed winbar }|
{3:~ }│ |
{3:~ }│{3:~ }|
{2:[No Name] [No Name] }|
|
]])
end)
it('works with combined highlight attributes', function()
command('hi Winbar guibg=red gui=underline')
command('hi Identifier guifg=blue gui=bold')
command('set winbar=Lookatmy%#Identifier#highlights')
screen:expect([[
{12:Lookatmy}{13:highlights }|
^ |
{3:~ }|*10
|
]])
end)
it('can be ruler', function()
insert [[
just some
random text]]
api.nvim_set_option_value('winbar', 'Hello, I am a ruler: %l,%c', {})
screen:expect {
grid = [[
{1:Hello, I am a ruler: 2,11 }|
just some |
random tex^t |
{3:~ }|*9
|
]],
}
feed 'b'
screen:expect {
grid = [[
{1:Hello, I am a ruler: 2,8 }|
just some |
random ^text |
{3:~ }|*9
|
]],
}
feed 'k'
screen:expect {
grid = [[
{1:Hello, I am a ruler: 1,8 }|
just so^me |
random text |
{3:~ }|*9
|
]],
}
end)
it('works with laststatus=3', function()
command('set laststatus=3')
screen:expect([[
{1:Set Up The Bars }|
^ |
{3:~ }|*9
{4:[No Name] }|
|
]])
command('belowright vsplit | split | split')
screen:expect([[
{1:Set Up The Bars }│{1:Set Up The Bars }|
│^ |
{3:~ }│{3:~ }|
{3:~ }├──────────────────────────────|
{3:~ }│{1:Set Up The Bars }|
{3:~ }│ |
{3:~ }│{3:~ }|
{3:~ }├──────────────────────────────|
{3:~ }│{1:Set Up The Bars }|
{3:~ }│ |
{3:~ }│{3:~ }|
{4:[No Name] }|
|
]])
-- Test for issue #18791
command('tabnew')
screen:expect([[
{10: }{11:4}{10: [No Name] }{1: [No Name] }{2: }{10:X}|
{1:Set Up The Bars }|
^ |
{3:~ }|*8
{4:[No Name] }|
|
]])
end)
it('mouse click and drag work correctly in buffer', function()
insert([[
line 1
line 2
line 3
line 4
line -42
line i
line sin(theta)
line 8]])
api.nvim_input_mouse('left', 'press', '', 0, 5, 1)
screen:expect([[
{1:Set Up The Bars }|
line 1 |
line 2 |
line 3 |
line 4 |
l^ine -42 |
line i |
line sin(theta) |
line 8 |
{3:~ }|*3
|
]])
eq({ 5, 1 }, api.nvim_win_get_cursor(0))
api.nvim_input_mouse('left', 'drag', '', 0, 6, 2)
screen:expect([[
{1:Set Up The Bars }|
line 1 |
line 2 |
line 3 |
line 4 |
l{7:ine -42} |
{7:li}^ne i |
line sin(theta) |
line 8 |
{3:~ }|*3
{1:-- VISUAL --} |
]])
eq({ 6, 2 }, api.nvim_win_get_cursor(0))
api.nvim_input_mouse('left', 'drag', '', 0, 1, 2)
screen:expect([[
{1:Set Up The Bars }|
li^n{7:e 1} |
{7:line 2} |
{7:line 3} |
{7:line 4} |
{7:li}ne -42 |
line i |
line sin(theta) |
line 8 |
{3:~ }|*3
{1:-- VISUAL --} |
]])
eq({ 1, 2 }, api.nvim_win_get_cursor(0))
api.nvim_input_mouse('left', 'drag', '', 0, 0, 2)
screen:expect_unchanged()
eq({ 1, 2 }, api.nvim_win_get_cursor(0))
end)
it('dragging statusline with mouse works correctly', function()
command('split')
screen:expect([[
{1:Set Up The Bars }|
^ |
{3:~ }|*3
{4:[No Name] }|
{1:Set Up The Bars }|
|
{3:~ }|*3
{2:[No Name] }|
|
]])
api.nvim_input_mouse('left', 'press', '', 1, 5, 10)
poke_eventloop()
api.nvim_input_mouse('left', 'drag', '', 1, 6, 10)
screen:expect([[
{1:Set Up The Bars }|
^ |
{3:~ }|*4
{4:[No Name] }|
{1:Set Up The Bars }|
|
{3:~ }|*2
{2:[No Name] }|
|
]])
api.nvim_input_mouse('left', 'drag', '', 1, 4, 10)
screen:expect([[
{1:Set Up The Bars }|
^ |
{3:~ }|*2
{4:[No Name] }|
{1:Set Up The Bars }|
|
{3:~ }|*4
{2:[No Name] }|
|
]])
api.nvim_input_mouse('left', 'press', '', 1, 11, 10)
poke_eventloop()
api.nvim_input_mouse('left', 'drag', '', 1, 9, 10)
screen:expect([[
{1:Set Up The Bars }|
^ |
{3:~ }|*2
{4:[No Name] }|
{1:Set Up The Bars }|
|
{3:~ }|*2
{2:[No Name] }|
|*3
]])
eq(3, api.nvim_get_option_value('cmdheight', {}))
api.nvim_input_mouse('left', 'drag', '', 1, 11, 10)
screen:expect([[
{1:Set Up The Bars }|
^ |
{3:~ }|*2
{4:[No Name] }|
{1:Set Up The Bars }|
|
{3:~ }|*4
{2:[No Name] }|
|
]])
eq(1, api.nvim_get_option_value('cmdheight', {}))
end)
it('properly equalizes window height for window-local value', function()
command('set equalalways | set winbar= | setlocal winbar=a | split')
command('setlocal winbar= | split')
command('setlocal winbar=b | split')
screen:expect([[
{1:b }|
^ |
{4:[No Name] }|
{1:b }|
|
{2:[No Name] }|
|
{3:~ }|
{2:[No Name] }|
{1:a }|
|
{2:[No Name] }|
|
]])
end)
it('requires window-local value for floating windows', function()
local win = api.nvim_open_win(
0,
false,
{ relative = 'editor', row = 2, col = 10, height = 7, width = 30 }
)
api.nvim_set_option_value('winbar', 'bar', {})
screen:expect {
grid = [[
{1:bar }|
^ |
{3:~ }{8: }{3: }|
{3:~ }{9:~ }{3: }|*6
{3:~ }|*3
|
]],
}
api.nvim_set_option_value('winbar', 'floaty bar', { scope = 'local', win = win })
screen:expect {
grid = [[
{1:bar }|
^ |
{3:~ }{1:floaty bar }{3: }|
{3:~ }{8: }{3: }|
{3:~ }{9:~ }{3: }|*5
{3:~ }|*3
|
]],
}
end)
it('works correctly when moving a split', function()
screen:try_resize(45, 6)
command('set winbar=')
command('vsplit')
command('setlocal winbar=foo')
screen:expect([[
{1:foo }│ |
^ │{3:~ }|
{3:~ }│{3:~ }|*2
{4:[No Name] }{2:[No Name] }|
|
]])
command('wincmd L')
screen:expect([[
│{1:foo }|
{3:~ }│^ |
{3:~ }│{3:~ }|*2
{2:[No Name] }{4:[No Name] }|
|
]])
command('wincmd w')
command('wincmd L')
screen:expect([[
{1:foo }│^ |
│{3:~ }|
{3:~ }│{3:~ }|*2
{2:[No Name] }{4:[No Name] }|
|
]])
end)
it('properly resizes window when there is no space in it', function()
command('set winbar= | 1split')
screen:expect([[
^ |
{4:[No Name] }|
|
{3:~ }|*8
{2:[No Name] }|
|
]])
command('set winbar=a')
screen:expect([[
{1:a }|
^ |
{4:[No Name] }|
{1:a }|
|
{3:~ }|*6
{2:[No Name] }|
|
]])
end)
it('cannot be added unless there is room', function()
command('set winbar= | split | split | split | split | split')
screen:expect([[
^ |
{4:[No Name] }|
|
{2:[No Name] }|
|
{2:[No Name] }|
|
{2:[No Name] }|
|
{2:[No Name] }|
|
{2:[No Name] }|
|
]])
eq('Vim(set):E36: Not enough room', pcall_err(command, 'set winbar=test'))
end)
end)
describe('local winbar with tabs', function()
local screen
before_each(function()
clear()
screen = Screen.new(60, 10)
api.nvim_set_option_value('winbar', 'foo', { scope = 'local', win = 0 })
end)
it('works', function()
command('tabnew')
screen:expect([[
{24: [No Name] }{5: [No Name] }{2: }{24:X}|
^ |
{1:~ }|*7
|
]])
command('tabnext')
screen:expect {
grid = [[
{5: [No Name] }{24: [No Name] }{2: }{24:X}|
{5:foo }|
^ |
{1:~ }|*6
|
]],
}
end)
it('can edit new empty buffer #19458', function()
insert [[
some
goofy
text]]
screen:expect {
grid = [[
{5:foo }|
some |
goofy |
tex^t |
{1:~ }|*5
|
]],
}
-- this used to throw an E315 ml_get error
command 'tabedit'
screen:expect {
grid = [[
{24: + [No Name] }{5: [No Name] }{2: }{24:X}|
^ |
{1:~ }|*7
|
]],
}
command 'tabprev'
screen:expect {
grid = [[
{5: + [No Name] }{24: [No Name] }{2: }{24:X}|
{5:foo }|
some |
goofy |
tex^t |
{1:~ }|*4
|
]],
}
end)
end)
it('winbar works properly when redrawing is postponed #23534', function()
clear({
args = {
'-c',
'set laststatus=2 lazyredraw',
'-c',
'setlocal statusline=(statusline) winbar=(winbar)',
'-c',
'call nvim_input(":<Esc>")',
},
})
local screen = Screen.new(60, 6)
screen:expect([[
{5:(winbar) }|
^ |
{1:~ }|*2
{3:(statusline) }|
|
]])
end)