local t = require('test.testutil')
local n = require('test.functional.testnvim')()
local tt = require('test.functional.testterm')
local describe, it, before_each = t.describe, t.it, t.before_each
local feed, clear = n.feed, n.clear
local testprg, command = n.testprg, n.command
local eq, eval = t.eq, n.eval
local api = n.api
local exec_lua = n.exec_lua
local matches = t.matches
local call = n.call
local hide_cursor = tt.hide_cursor
local show_cursor = tt.show_cursor
local retry = t.retry
local is_os = t.is_os
local skip = t.skip
describe(':terminal cursor', function()
local screen
local terminal_mode_idx ---@type number
before_each(function()
clear()
screen = tt.setup_screen()
if terminal_mode_idx == nil then
for i, v in ipairs(screen._mode_info) do
if v.name == 'terminal' then
terminal_mode_idx = i
end
end
assert(terminal_mode_idx)
end
end)
it('moves the screen cursor when focused', function()
tt.feed_data('testing cursor')
screen:expect([[
tty ready |
testing cursor^ |
|*4
{5:-- TERMINAL --} |
]])
end)
it('is highlighted when not focused', function()
feed('<c-\\><c-n>')
screen:expect([[
tty ready |
^ |
|*5
]])
end)
describe('with number column', function()
before_each(function()
feed('<c-\\><c-n>:set number<cr>')
end)
it('is positioned correctly when unfocused', function()
screen:expect([[
{121: 1 }tty ready |
{121: 2 }^rows: 6, cols: 46 |
{121: 3 } |
{121: 4 } |
{121: 5 } |
{121: 6 } |
:set number |
]])
end)
it('is positioned correctly when focused', function()
screen:expect([[
{121: 1 }tty ready |
{121: 2 }^rows: 6, cols: 46 |
{121: 3 } |
{121: 4 } |
{121: 5 } |
{121: 6 } |
:set number |
]])
feed('i')
n.poke_eventloop()
screen:expect([[
{121: 1 }tty ready |
{121: 2 }rows: 6, cols: 46 |
{121: 3 }^ |
{121: 4 } |
{121: 5 } |
{121: 6 } |
{5:-- TERMINAL --} |
]])
end)
end)
describe('when invisible', function()
it('is not highlighted', function()
hide_cursor()
screen:expect([[
tty ready |
|*5
{5:-- TERMINAL --} |
]])
show_cursor()
screen:expect([[
tty ready |
^ |
|*4
{5:-- TERMINAL --} |
]])
-- same for when the terminal is unfocused
feed('<c-\\><c-n>')
hide_cursor()
screen:expect([[
tty ready |
^ |
|*5
]])
show_cursor()
screen:expect_unchanged()
end)
it('becomes visible when exiting Terminal mode', function()
hide_cursor()
screen:expect([[
tty ready |
|*5
{5:-- TERMINAL --} |
]])
feed('<c-\\><c-n>')
screen:expect([[
tty ready |
^ |
|*5
]])
feed('i')
screen:expect([[
tty ready |
|*5
{5:-- TERMINAL --} |
]])
-- Cursor is hidden; now request to show it while in a TermLeave autocmd.
-- Process events (via :sleep) to handle the escape sequence now.
n.exec([[
autocmd TermLeave * ++once call chansend(&channel, "\e[?25h") | sleep 1m
\ | let g:did_termleave = 1]])
feed([[<C-\><C-N>]]) -- Exit terminal mode; cursor should not remain hidden
screen:expect([[
tty ready |
^ |
|*5
]])
-- Wait for the TermLeave autocommand to finish. Sometimes :sleep can be slow.
retry(nil, 1000, function()
eq(1, api.nvim_get_var('did_termleave'))
end)
command('bwipeout! | let chan = nvim_open_term(0, {})')
feed('i')
-- Hide the cursor, switch to a non-terminal buffer, then show the cursor; it shouldn't remain
-- hidden after we're kicked out of terminal mode in the new buffer.
-- Must ensure these actions happen within the same terminal_execute call. The stream is
-- internal, so polling the event loop isn't necessary (terminal_receive is directly called).
command([[call chansend(chan, "\e[?25l") | new floob | call chansend(chan, "\e[?25h")]])
screen:expect([[
^ |
{100:~ }|
{3:floob }|
|*2
{119:[Scratch] [-] }|
|
]])
feed('<C-W>pi')
screen:expect([[
|
{100:~ }|
{2:floob }|
^ |
|
{120:[Scratch] [-] }|
{5:-- TERMINAL --} |
]])
end)
it('becomes visible on TermLeave if hidden immediately by events #32456', function()
|