mirror of
https://github.com/neovim/neovim.git
synced 2025-09-07 11:58:17 +00:00

When a terminal application running inside the terminal emulator sets the cursor shape or blink status of the cursor, update the cursor in the parent terminal to match. This removes the "virtual cursor" that has been in use by the terminal emulator since the beginning. The original rationale for using the virtual cursor was to avoid having to support additional UI methods to change the cursor color for other (non-TUI) UIs, instead relying on the TermCursor and TermCursorNC highlight groups. The TermCursor highlight group is now used in the default 'guicursor' value, which has a new entry for Terminal mode. However, the TermCursorNC highlight group is no longer supported: since terminal windows now use the real cursor, when the window is not focused there is no cursor displayed in the window at all, so there is nothing to highlight. Users can still use the StatusLineTermNC highlight group to differentiate non-focused terminal windows. BREAKING CHANGE: The TermCursorNC highlight group is no longer supported.
1049 lines
46 KiB
Lua
1049 lines
46 KiB
Lua
local t = require('test.testutil')
|
|
local n = require('test.functional.testnvim')()
|
|
local tt = require('test.functional.testterm')
|
|
|
|
local feed, clear = n.feed, n.clear
|
|
local testprg, command = n.testprg, n.command
|
|
local eq, eval = t.eq, n.eval
|
|
local matches = t.matches
|
|
local call = n.call
|
|
local hide_cursor = tt.hide_cursor
|
|
local show_cursor = tt.show_cursor
|
|
local is_os = t.is_os
|
|
local skip = t.skip
|
|
|
|
describe(':terminal cursor', function()
|
|
local screen
|
|
|
|
before_each(function()
|
|
clear()
|
|
screen = tt.setup_screen()
|
|
end)
|
|
|
|
it('moves the screen cursor when focused', function()
|
|
tt.feed_data('testing cursor')
|
|
screen:expect([[
|
|
tty ready |
|
|
testing cursor^ |
|
|
|*4
|
|
{3:-- 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([[
|
|
{7: 1 }tty ready |
|
|
{7: 2 }^rows: 6, cols: 46 |
|
|
{7: 3 } |
|
|
{7: 4 } |
|
|
{7: 5 } |
|
|
{7: 6 } |
|
|
:set number |
|
|
]])
|
|
end)
|
|
|
|
it('is positioned correctly when focused', function()
|
|
screen:expect([[
|
|
{7: 1 }tty ready |
|
|
{7: 2 }^rows: 6, cols: 46 |
|
|
{7: 3 } |
|
|
{7: 4 } |
|
|
{7: 5 } |
|
|
{7: 6 } |
|
|
:set number |
|
|
]])
|
|
feed('i')
|
|
n.poke_eventloop()
|
|
screen:expect([[
|
|
{7: 1 }tty ready |
|
|
{7: 2 }rows: 6, cols: 46 |
|
|
{7: 3 }^ |
|
|
{7: 4 } |
|
|
{7: 5 } |
|
|
{7: 6 } |
|
|
{3:-- TERMINAL --} |
|
|
]])
|
|
end)
|
|
end)
|
|
|
|
describe('when invisible', function()
|
|
it('is not highlighted', function()
|
|
skip(is_os('win'), '#31587')
|
|
hide_cursor()
|
|
screen:expect([[
|
|
tty ready |
|
|
|*5
|
|
{3:-- TERMINAL --} |
|
|
]])
|
|
show_cursor()
|
|
screen:expect([[
|
|
tty ready |
|
|
^ |
|
|
|*4
|
|
{3:-- TERMINAL --} |
|
|
]])
|
|
-- same for when the terminal is unfocused
|
|
feed('<c-\\><c-n>')
|
|
hide_cursor()
|
|
screen:expect({
|
|
grid = [[
|
|
tty ready |
|
|
^ |
|
|
|*5
|
|
]],
|
|
unchanged = true,
|
|
})
|
|
show_cursor()
|
|
screen:expect({
|
|
grid = [[
|
|
tty ready |
|
|
^ |
|
|
|*5
|
|
]],
|
|
unchanged = true,
|
|
})
|
|
end)
|
|
|
|
it('becomes visible when exiting Terminal mode', function()
|
|
skip(is_os('win'), '#31587')
|
|
hide_cursor()
|
|
screen:expect([[
|
|
tty ready |
|
|
|*5
|
|
{3:-- TERMINAL --} |
|
|
]])
|
|
feed('<c-\\><c-n>')
|
|
screen:expect([[
|
|
tty ready |
|
|
^ |
|
|
|*5
|
|
]])
|
|
feed('i')
|
|
screen:expect([[
|
|
tty ready |
|
|
|*5
|
|
{3:-- TERMINAL --} |
|
|
]])
|
|
end)
|
|
end)
|
|
|
|
it('can be modified by application #3681', function()
|
|
skip(is_os('win'), '#31587')
|
|
local idx ---@type number
|
|
for i, v in ipairs(screen._mode_info) do
|
|
if v.name == 'terminal' then
|
|
idx = i
|
|
end
|
|
end
|
|
assert(idx)
|
|
|
|
local states = {
|
|
[1] = { blink = true, shape = 'block' },
|
|
[2] = { blink = false, shape = 'block' },
|
|
[3] = { blink = true, shape = 'horizontal' },
|
|
[4] = { blink = false, shape = 'horizontal' },
|
|
[5] = { blink = true, shape = 'vertical' },
|
|
[6] = { blink = false, shape = 'vertical' },
|
|
}
|
|
|
|
for k, v in pairs(states) do
|
|
tt.feed_csi(('%d q'):format(k))
|
|
screen:expect({
|
|
grid = [[
|
|
tty ready |
|
|
^ |
|
|
|*4
|
|
{3:-- TERMINAL --} |
|
|
]],
|
|
condition = function()
|
|
if v.blink then
|
|
eq(500, screen._mode_info[idx].blinkon)
|
|
eq(500, screen._mode_info[idx].blinkoff)
|
|
else
|
|
eq(0, screen._mode_info[idx].blinkon)
|
|
eq(0, screen._mode_info[idx].blinkoff)
|
|
end
|
|
eq(v.shape, screen._mode_info[idx].cursor_shape)
|
|
end,
|
|
})
|
|
end
|
|
|
|
feed([[<C-\><C-N>]])
|
|
|
|
screen:expect([[
|
|
tty ready |
|
|
^ |
|
|
|*5
|
|
]])
|
|
|
|
-- Cursor returns to default on TermLeave
|
|
eq(500, screen._mode_info[idx].blinkon)
|
|
eq(500, screen._mode_info[idx].blinkoff)
|
|
eq('block', screen._mode_info[idx].cursor_shape)
|
|
end)
|
|
|
|
it('can be modified per terminal', function()
|
|
skip(is_os('win'), '#31587')
|
|
local idx ---@type number
|
|
for i, v in ipairs(screen._mode_info) do
|
|
if v.name == 'terminal' then
|
|
idx = i
|
|
end
|
|
end
|
|
assert(idx)
|
|
|
|
-- Set cursor to vertical bar with blink
|
|
tt.feed_csi('5 q')
|
|
screen:expect({
|
|
grid = [[
|
|
tty ready |
|
|
^ |
|
|
|*4
|
|
{3:-- TERMINAL --} |
|
|
]],
|
|
condition = function()
|
|
eq(500, screen._mode_info[idx].blinkon)
|
|
eq(500, screen._mode_info[idx].blinkoff)
|
|
eq('vertical', screen._mode_info[idx].cursor_shape)
|
|
end,
|
|
})
|
|
|
|
tt.hide_cursor()
|
|
screen:expect({
|
|
grid = [[
|
|
tty ready |
|
|
|
|
|
|*4
|
|
{3:-- TERMINAL --} |
|
|
]],
|
|
condition = function()
|
|
eq(500, screen._mode_info[idx].blinkon)
|
|
eq(500, screen._mode_info[idx].blinkoff)
|
|
eq('vertical', screen._mode_info[idx].cursor_shape)
|
|
end,
|
|
})
|
|
|
|
-- Exit terminal mode to reset terminal cursor settings to default and
|
|
-- create a new terminal window
|
|
feed([[<C-\><C-N>]])
|
|
command('set statusline=~~~')
|
|
command('new')
|
|
call('termopen', { testprg('tty-test') })
|
|
feed('i')
|
|
screen:expect({
|
|
grid = [[
|
|
tty ready |
|
|
^ |
|
|
{17:~~~ }|
|
|
rows: 2, cols: 50 |
|
|
|
|
|
{18:~~~ }|
|
|
{3:-- TERMINAL --} |
|
|
]],
|
|
condition = function()
|
|
-- New terminal, cursor resets to defaults
|
|
eq(500, screen._mode_info[idx].blinkon)
|
|
eq(500, screen._mode_info[idx].blinkoff)
|
|
eq('block', screen._mode_info[idx].cursor_shape)
|
|
end,
|
|
})
|
|
|
|
-- Set cursor to underline, no blink
|
|
tt.feed_csi('4 q')
|
|
screen:expect({
|
|
grid = [[
|
|
tty ready |
|
|
^ |
|
|
{17:~~~ }|
|
|
rows: 2, cols: 50 |
|
|
|
|
|
{18:~~~ }|
|
|
{3:-- TERMINAL --} |
|
|
]],
|
|
condition = function()
|
|
eq(0, screen._mode_info[idx].blinkon)
|
|
eq(0, screen._mode_info[idx].blinkoff)
|
|
eq('horizontal', screen._mode_info[idx].cursor_shape)
|
|
end,
|
|
})
|
|
|
|
-- Switch back to first terminal, cursor should still be hidden
|
|
command('wincmd p')
|
|
screen:expect({
|
|
grid = [[
|
|
tty ready |
|
|
|
|
|
{18:~~~ }|
|
|
rows: 2, cols: 50 |
|
|
|
|
|
{17:~~~ }|
|
|
{3:-- TERMINAL --} |
|
|
]],
|
|
condition = function()
|
|
eq(500, screen._mode_info[idx].blinkon)
|
|
eq(500, screen._mode_info[idx].blinkoff)
|
|
eq('vertical', screen._mode_info[idx].cursor_shape)
|
|
end,
|
|
})
|
|
end)
|
|
|
|
it('can be positioned arbitrarily', function()
|
|
clear()
|
|
screen = tt.setup_child_nvim({
|
|
'-u',
|
|
'NONE',
|
|
'-i',
|
|
'NONE',
|
|
'--cmd',
|
|
n.nvim_set .. ' noshowmode',
|
|
})
|
|
screen:expect([[
|
|
^ |
|
|
~ |*4
|
|
|
|
|
{3:-- TERMINAL --} |
|
|
]])
|
|
|
|
feed('i<Tab>')
|
|
screen:expect([[
|
|
^ |
|
|
~ |*4
|
|
|
|
|
{3:-- TERMINAL --} |
|
|
]])
|
|
end)
|
|
end)
|
|
|
|
describe('buffer cursor position is correct in terminal without number column', function()
|
|
local screen
|
|
|
|
local function setup_ex_register(str)
|
|
screen = tt.setup_child_nvim({
|
|
'-u',
|
|
'NONE',
|
|
'-i',
|
|
'NONE',
|
|
'-E',
|
|
'--cmd',
|
|
string.format('let @r = "%s"', str),
|
|
-- <Left> and <Right> don't always work
|
|
'--cmd',
|
|
'cnoremap <C-X> <Left>',
|
|
'--cmd',
|
|
'cnoremap <C-O> <Right>',
|
|
'--cmd',
|
|
'set notermguicolors',
|
|
}, {
|
|
cols = 70,
|
|
})
|
|
screen:set_default_attr_ids({
|
|
[1] = { foreground = 253, background = 11 },
|
|
[2] = { reverse = true },
|
|
[3] = { bold = true },
|
|
[4] = { background = 11 },
|
|
})
|
|
-- Also check for real cursor position, as it is used for stuff like input methods
|
|
screen._handle_busy_start = function() end
|
|
screen._handle_busy_stop = function() end
|
|
screen:expect([[
|
|
|*4
|
|
Entering Ex mode. Type "visual" to go to Normal mode. |
|
|
:^ |
|
|
{3:-- TERMINAL --} |
|
|
]])
|
|
end
|
|
|
|
before_each(clear)
|
|
|
|
describe('in a line with no multibyte chars or trailing spaces,', function()
|
|
before_each(function()
|
|
setup_ex_register('aaaaaaaa')
|
|
end)
|
|
|
|
it('at the end', function()
|
|
feed('<C-R>r')
|
|
screen:expect([[
|
|
|*4
|
|
Entering Ex mode. Type "visual" to go to Normal mode. |
|
|
:aaaaaaaa^ |
|
|
{3:-- TERMINAL --} |
|
|
]])
|
|
eq({ 6, 9 }, eval('nvim_win_get_cursor(0)'))
|
|
feed([[<C-\><C-N>]])
|
|
screen:expect([[
|
|
|*4
|
|
Entering Ex mode. Type "visual" to go to Normal mode. |
|
|
:aaaaaaa^a |
|
|
|
|
|
]])
|
|
eq({ 6, 8 }, eval('nvim_win_get_cursor(0)'))
|
|
end)
|
|
|
|
it('near the end', function()
|
|
feed('<C-R>r<C-X><C-X>')
|
|
screen:expect([[
|
|
|*4
|
|
Entering Ex mode. Type "visual" to go to Normal mode. |
|
|
:aaaaaa^aa |
|
|
{3:-- TERMINAL --} |
|
|
]])
|
|
eq({ 6, 7 }, eval('nvim_win_get_cursor(0)'))
|
|
feed([[<C-\><C-N>]])
|
|
screen:expect([[
|
|
|*4
|
|
Entering Ex mode. Type "visual" to go to Normal mode. |
|
|
:aaaaa^aaa |
|
|
|
|
|
]])
|
|
eq({ 6, 6 }, eval('nvim_win_get_cursor(0)'))
|
|
end)
|
|
|
|
it('near the start', function()
|
|
feed('<C-R>r<C-B><C-O>')
|
|
screen:expect([[
|
|
|*4
|
|
Entering Ex mode. Type "visual" to go to Normal mode. |
|
|
:a^aaaaaaa |
|
|
{3:-- TERMINAL --} |
|
|
]])
|
|
eq({ 6, 2 }, eval('nvim_win_get_cursor(0)'))
|
|
feed([[<C-\><C-N>]])
|
|
screen:expect([[
|
|
|*4
|
|
Entering Ex mode. Type "visual" to go to Normal mode. |
|
|
:^aaaaaaaa |
|
|
|
|
|
]])
|
|
eq({ 6, 1 }, eval('nvim_win_get_cursor(0)'))
|
|
end)
|
|
end)
|
|
|
|
describe('in a line with single-cell multibyte chars and no trailing spaces,', function()
|
|
before_each(function()
|
|
setup_ex_register('µµµµµµµµ')
|
|
end)
|
|
|
|
it('at the end', function()
|
|
feed('<C-R>r')
|
|
screen:expect([[
|
|
|*4
|
|
Entering Ex mode. Type "visual" to go to Normal mode. |
|
|
:µµµµµµµµ^ |
|
|
{3:-- TERMINAL --} |
|
|
]])
|
|
eq({ 6, 17 }, eval('nvim_win_get_cursor(0)'))
|
|
feed([[<C-\><C-N>]])
|
|
screen:expect([[
|
|
|*4
|
|
Entering Ex mode. Type "visual" to go to Normal mode. |
|
|
:µµµµµµµ^µ |
|
|
|
|
|
]])
|
|
eq({ 6, 15 }, eval('nvim_win_get_cursor(0)'))
|
|
end)
|
|
|
|
it('near the end', function()
|
|
feed('<C-R>r<C-X><C-X>')
|
|
screen:expect([[
|
|
|*4
|
|
Entering Ex mode. Type "visual" to go to Normal mode. |
|
|
:µµµµµµ^µµ |
|
|
{3:-- TERMINAL --} |
|
|
]])
|
|
eq({ 6, 13 }, eval('nvim_win_get_cursor(0)'))
|
|
feed([[<C-\><C-N>]])
|
|
screen:expect([[
|
|
|*4
|
|
Entering Ex mode. Type "visual" to go to Normal mode. |
|
|
:µµµµµ^µµµ |
|
|
|
|
|
]])
|
|
eq({ 6, 11 }, eval('nvim_win_get_cursor(0)'))
|
|
end)
|
|
|
|
it('near the start', function()
|
|
feed('<C-R>r<C-B><C-O>')
|
|
screen:expect([[
|
|
|*4
|
|
Entering Ex mode. Type "visual" to go to Normal mode. |
|
|
:µ^µµµµµµµ |
|
|
{3:-- TERMINAL --} |
|
|
]])
|
|
eq({ 6, 3 }, eval('nvim_win_get_cursor(0)'))
|
|
feed([[<C-\><C-N>]])
|
|
screen:expect([[
|
|
|*4
|
|
Entering Ex mode. Type "visual" to go to Normal mode. |
|
|
:^µµµµµµµµ |
|
|
|
|
|
]])
|
|
eq({ 6, 1 }, eval('nvim_win_get_cursor(0)'))
|
|
end)
|
|
end)
|
|
|
|
describe('in a line with single-cell composed multibyte chars and no trailing spaces,', function()
|
|
before_each(function()
|
|
setup_ex_register('µ̳µ̳µ̳µ̳µ̳µ̳µ̳µ̳')
|
|
end)
|
|
|
|
it('at the end', function()
|
|
feed('<C-R>r')
|
|
screen:expect([[
|
|
|*4
|
|
Entering Ex mode. Type "visual" to go to Normal mode. |
|
|
:µ̳µ̳µ̳µ̳µ̳µ̳µ̳µ̳^ |
|
|
{3:-- TERMINAL --} |
|
|
]])
|
|
eq({ 6, 33 }, eval('nvim_win_get_cursor(0)'))
|
|
feed([[<C-\><C-N>]])
|
|
screen:expect([[
|
|
|*4
|
|
Entering Ex mode. Type "visual" to go to Normal mode. |
|
|
:µ̳µ̳µ̳µ̳µ̳µ̳µ̳^µ̳ |
|
|
|
|
|
]])
|
|
eq({ 6, 29 }, eval('nvim_win_get_cursor(0)'))
|
|
end)
|
|
|
|
it('near the end', function()
|
|
skip(is_os('win'))
|
|
feed('<C-R>r<C-X><C-X>')
|
|
screen:expect([[
|
|
|*4
|
|
Entering Ex mode. Type "visual" to go to Normal mode. |
|
|
:µ̳µ̳µ̳µ̳µ̳µ̳^µ̳µ̳ |
|
|
{3:-- TERMINAL --} |
|
|
]])
|
|
eq({ 6, 25 }, eval('nvim_win_get_cursor(0)'))
|
|
feed([[<C-\><C-N>]])
|
|
screen:expect([[
|
|
|*4
|
|
Entering Ex mode. Type "visual" to go to Normal mode. |
|
|
:µ̳µ̳µ̳µ̳µ̳^µ̳µ̳µ̳ |
|
|
|
|
|
]])
|
|
eq({ 6, 21 }, eval('nvim_win_get_cursor(0)'))
|
|
end)
|
|
|
|
it('near the start', function()
|
|
skip(is_os('win'))
|
|
feed('<C-R>r<C-B><C-O>')
|
|
screen:expect([[
|
|
|*4
|
|
Entering Ex mode. Type "visual" to go to Normal mode. |
|
|
:µ̳^µ̳µ̳µ̳µ̳µ̳µ̳µ̳ |
|
|
{3:-- TERMINAL --} |
|
|
]])
|
|
eq({ 6, 5 }, eval('nvim_win_get_cursor(0)'))
|
|
feed([[<C-\><C-N>]])
|
|
screen:expect([[
|
|
|*4
|
|
Entering Ex mode. Type "visual" to go to Normal mode. |
|
|
:^µ̳µ̳µ̳µ̳µ̳µ̳µ̳µ̳ |
|
|
|
|
|
]])
|
|
eq({ 6, 1 }, eval('nvim_win_get_cursor(0)'))
|
|
end)
|
|
end)
|
|
|
|
describe('in a line with double-cell multibyte chars and no trailing spaces,', function()
|
|
before_each(function()
|
|
setup_ex_register('哦哦哦哦哦哦哦哦')
|
|
end)
|
|
|
|
it('at the end', function()
|
|
feed('<C-R>r')
|
|
screen:expect([[
|
|
|*4
|
|
Entering Ex mode. Type "visual" to go to Normal mode. |
|
|
:哦哦哦哦哦哦哦哦^ |
|
|
{3:-- TERMINAL --} |
|
|
]])
|
|
eq({ 6, 25 }, eval('nvim_win_get_cursor(0)'))
|
|
feed([[<C-\><C-N>]])
|
|
screen:expect([[
|
|
|*4
|
|
Entering Ex mode. Type "visual" to go to Normal mode. |
|
|
:哦哦哦哦哦哦哦^哦 |
|
|
|
|
|
]])
|
|
eq({ 6, 22 }, eval('nvim_win_get_cursor(0)'))
|
|
end)
|
|
|
|
it('near the end', function()
|
|
feed('<C-R>r<C-X><C-X>')
|
|
screen:expect([[
|
|
|*4
|
|
Entering Ex mode. Type "visual" to go to Normal mode. |
|
|
:哦哦哦哦哦哦^哦哦 |
|
|
{3:-- TERMINAL --} |
|
|
]])
|
|
eq({ 6, 19 }, eval('nvim_win_get_cursor(0)'))
|
|
feed([[<C-\><C-N>]])
|
|
screen:expect([[
|
|
|*4
|
|
Entering Ex mode. Type "visual" to go to Normal mode. |
|
|
:哦哦哦哦哦^哦哦哦 |
|
|
|
|
|
]])
|
|
eq({ 6, 16 }, eval('nvim_win_get_cursor(0)'))
|
|
end)
|
|
|
|
it('near the start', function()
|
|
feed('<C-R>r<C-B><C-O>')
|
|
screen:expect([[
|
|
|*4
|
|
Entering Ex mode. Type "visual" to go to Normal mode. |
|
|
:哦^哦哦哦哦哦哦哦 |
|
|
{3:-- TERMINAL --} |
|
|
]])
|
|
eq({ 6, 4 }, eval('nvim_win_get_cursor(0)'))
|
|
feed([[<C-\><C-N>]])
|
|
screen:expect([[
|
|
|*4
|
|
Entering Ex mode. Type "visual" to go to Normal mode. |
|
|
:^哦哦哦哦哦哦哦哦 |
|
|
|
|
|
]])
|
|
eq({ 6, 1 }, eval('nvim_win_get_cursor(0)'))
|
|
end)
|
|
end)
|
|
|
|
it('at the end of a line with trailing spaces #16234', function()
|
|
setup_ex_register('aaaaaaaa ')
|
|
feed('<C-R>r')
|
|
screen:expect([[
|
|
|*4
|
|
Entering Ex mode. Type "visual" to go to Normal mode. |
|
|
:aaaaaaaa ^ |
|
|
{3:-- TERMINAL --} |
|
|
]])
|
|
matches('^:aaaaaaaa [ ]*$', eval('nvim_get_current_line()'))
|
|
eq({ 6, 13 }, eval('nvim_win_get_cursor(0)'))
|
|
feed([[<C-\><C-N>]])
|
|
screen:expect([[
|
|
|*4
|
|
Entering Ex mode. Type "visual" to go to Normal mode. |
|
|
:aaaaaaaa ^ |
|
|
|
|
|
]])
|
|
eq({ 6, 12 }, eval('nvim_win_get_cursor(0)'))
|
|
end)
|
|
end)
|
|
|
|
describe('buffer cursor position is correct in terminal with number column', function()
|
|
local screen
|
|
|
|
local function setup_ex_register(str)
|
|
screen = tt.setup_child_nvim({
|
|
'-u',
|
|
'NONE',
|
|
'-i',
|
|
'NONE',
|
|
'-E',
|
|
'--cmd',
|
|
string.format('let @r = "%s"', str),
|
|
-- <Left> and <Right> don't always work
|
|
'--cmd',
|
|
'cnoremap <C-X> <Left>',
|
|
'--cmd',
|
|
'cnoremap <C-O> <Right>',
|
|
'--cmd',
|
|
'set notermguicolors',
|
|
}, {
|
|
cols = 70,
|
|
})
|
|
screen:set_default_attr_ids({
|
|
[1] = { foreground = 253, background = 11 },
|
|
[2] = { reverse = true },
|
|
[3] = { bold = true },
|
|
[4] = { background = 11 },
|
|
[7] = { foreground = 130 },
|
|
})
|
|
-- Also check for real cursor position, as it is used for stuff like input methods
|
|
screen._handle_busy_start = function() end
|
|
screen._handle_busy_stop = function() end
|
|
screen:expect([[
|
|
{7: 1 } |
|
|
{7: 2 } |
|
|
{7: 3 } |
|
|
{7: 4 } |
|
|
{7: 5 }Entering Ex mode. Type "visual" to go to Normal mode. |
|
|
{7: 6 }:^ |
|
|
{3:-- TERMINAL --} |
|
|
]])
|
|
end
|
|
|
|
before_each(function()
|
|
clear()
|
|
command('au TermOpen * set number')
|
|
end)
|
|
|
|
describe('in a line with no multibyte chars or trailing spaces,', function()
|
|
before_each(function()
|
|
setup_ex_register('aaaaaaaa')
|
|
end)
|
|
|
|
it('at the end', function()
|
|
feed('<C-R>r')
|
|
screen:expect([[
|
|
{7: 1 } |
|
|
{7: 2 } |
|
|
{7: 3 } |
|
|
{7: 4 } |
|
|
{7: 5 }Entering Ex mode. Type "visual" to go to Normal mode. |
|
|
{7: 6 }:aaaaaaaa^ |
|
|
{3:-- TERMINAL --} |
|
|
]])
|
|
eq({ 6, 9 }, eval('nvim_win_get_cursor(0)'))
|
|
feed([[<C-\><C-N>]])
|
|
screen:expect([[
|
|
{7: 1 } |
|
|
{7: 2 } |
|
|
{7: 3 } |
|
|
{7: 4 } |
|
|
{7: 5 }Entering Ex mode. Type "visual" to go to Normal mode. |
|
|
{7: 6 }:aaaaaaa^a |
|
|
|
|
|
]])
|
|
eq({ 6, 8 }, eval('nvim_win_get_cursor(0)'))
|
|
end)
|
|
|
|
it('near the end', function()
|
|
feed('<C-R>r<C-X><C-X>')
|
|
screen:expect([[
|
|
{7: 1 } |
|
|
{7: 2 } |
|
|
{7: 3 } |
|
|
{7: 4 } |
|
|
{7: 5 }Entering Ex mode. Type "visual" to go to Normal mode. |
|
|
{7: 6 }:aaaaaa^aa |
|
|
{3:-- TERMINAL --} |
|
|
]])
|
|
eq({ 6, 7 }, eval('nvim_win_get_cursor(0)'))
|
|
feed([[<C-\><C-N>]])
|
|
screen:expect([[
|
|
{7: 1 } |
|
|
{7: 2 } |
|
|
{7: 3 } |
|
|
{7: 4 } |
|
|
{7: 5 }Entering Ex mode. Type "visual" to go to Normal mode. |
|
|
{7: 6 }:aaaaa^aaa |
|
|
|
|
|
]])
|
|
eq({ 6, 6 }, eval('nvim_win_get_cursor(0)'))
|
|
end)
|
|
|
|
it('near the start', function()
|
|
feed('<C-R>r<C-B><C-O>')
|
|
screen:expect([[
|
|
{7: 1 } |
|
|
{7: 2 } |
|
|
{7: 3 } |
|
|
{7: 4 } |
|
|
{7: 5 }Entering Ex mode. Type "visual" to go to Normal mode. |
|
|
{7: 6 }:a^aaaaaaa |
|
|
{3:-- TERMINAL --} |
|
|
]])
|
|
eq({ 6, 2 }, eval('nvim_win_get_cursor(0)'))
|
|
feed([[<C-\><C-N>]])
|
|
screen:expect([[
|
|
{7: 1 } |
|
|
{7: 2 } |
|
|
{7: 3 } |
|
|
{7: 4 } |
|
|
{7: 5 }Entering Ex mode. Type "visual" to go to Normal mode. |
|
|
{7: 6 }:^aaaaaaaa |
|
|
|
|
|
]])
|
|
eq({ 6, 1 }, eval('nvim_win_get_cursor(0)'))
|
|
end)
|
|
end)
|
|
|
|
describe('in a line with single-cell multibyte chars and no trailing spaces,', function()
|
|
before_each(function()
|
|
setup_ex_register('µµµµµµµµ')
|
|
end)
|
|
|
|
it('at the end', function()
|
|
feed('<C-R>r')
|
|
screen:expect([[
|
|
{7: 1 } |
|
|
{7: 2 } |
|
|
{7: 3 } |
|
|
{7: 4 } |
|
|
{7: 5 }Entering Ex mode. Type "visual" to go to Normal mode. |
|
|
{7: 6 }:µµµµµµµµ^ |
|
|
{3:-- TERMINAL --} |
|
|
]])
|
|
eq({ 6, 17 }, eval('nvim_win_get_cursor(0)'))
|
|
feed([[<C-\><C-N>]])
|
|
screen:expect([[
|
|
{7: 1 } |
|
|
{7: 2 } |
|
|
{7: 3 } |
|
|
{7: 4 } |
|
|
{7: 5 }Entering Ex mode. Type "visual" to go to Normal mode. |
|
|
{7: 6 }:µµµµµµµ^µ |
|
|
|
|
|
]])
|
|
eq({ 6, 15 }, eval('nvim_win_get_cursor(0)'))
|
|
end)
|
|
|
|
it('near the end', function()
|
|
feed('<C-R>r<C-X><C-X>')
|
|
screen:expect([[
|
|
{7: 1 } |
|
|
{7: 2 } |
|
|
{7: 3 } |
|
|
{7: 4 } |
|
|
{7: 5 }Entering Ex mode. Type "visual" to go to Normal mode. |
|
|
{7: 6 }:µµµµµµ^µµ |
|
|
{3:-- TERMINAL --} |
|
|
]])
|
|
eq({ 6, 13 }, eval('nvim_win_get_cursor(0)'))
|
|
feed([[<C-\><C-N>]])
|
|
screen:expect([[
|
|
{7: 1 } |
|
|
{7: 2 } |
|
|
{7: 3 } |
|
|
{7: 4 } |
|
|
{7: 5 }Entering Ex mode. Type "visual" to go to Normal mode. |
|
|
{7: 6 }:µµµµµ^µµµ |
|
|
|
|
|
]])
|
|
eq({ 6, 11 }, eval('nvim_win_get_cursor(0)'))
|
|
end)
|
|
|
|
it('near the start', function()
|
|
feed('<C-R>r<C-B><C-O>')
|
|
screen:expect([[
|
|
{7: 1 } |
|
|
{7: 2 } |
|
|
{7: 3 } |
|
|
{7: 4 } |
|
|
{7: 5 }Entering Ex mode. Type "visual" to go to Normal mode. |
|
|
{7: 6 }:µ^µµµµµµµ |
|
|
{3:-- TERMINAL --} |
|
|
]])
|
|
eq({ 6, 3 }, eval('nvim_win_get_cursor(0)'))
|
|
feed([[<C-\><C-N>]])
|
|
screen:expect([[
|
|
{7: 1 } |
|
|
{7: 2 } |
|
|
{7: 3 } |
|
|
{7: 4 } |
|
|
{7: 5 }Entering Ex mode. Type "visual" to go to Normal mode. |
|
|
{7: 6 }:^µµµµµµµµ |
|
|
|
|
|
]])
|
|
eq({ 6, 1 }, eval('nvim_win_get_cursor(0)'))
|
|
end)
|
|
end)
|
|
|
|
describe('in a line with single-cell composed multibyte chars and no trailing spaces,', function()
|
|
before_each(function()
|
|
setup_ex_register('µ̳µ̳µ̳µ̳µ̳µ̳µ̳µ̳')
|
|
end)
|
|
|
|
it('at the end', function()
|
|
feed('<C-R>r')
|
|
screen:expect([[
|
|
{7: 1 } |
|
|
{7: 2 } |
|
|
{7: 3 } |
|
|
{7: 4 } |
|
|
{7: 5 }Entering Ex mode. Type "visual" to go to Normal mode. |
|
|
{7: 6 }:µ̳µ̳µ̳µ̳µ̳µ̳µ̳µ̳^ |
|
|
{3:-- TERMINAL --} |
|
|
]])
|
|
eq({ 6, 33 }, eval('nvim_win_get_cursor(0)'))
|
|
feed([[<C-\><C-N>]])
|
|
screen:expect([[
|
|
{7: 1 } |
|
|
{7: 2 } |
|
|
{7: 3 } |
|
|
{7: 4 } |
|
|
{7: 5 }Entering Ex mode. Type "visual" to go to Normal mode. |
|
|
{7: 6 }:µ̳µ̳µ̳µ̳µ̳µ̳µ̳^µ̳ |
|
|
|
|
|
]])
|
|
eq({ 6, 29 }, eval('nvim_win_get_cursor(0)'))
|
|
end)
|
|
|
|
it('near the end', function()
|
|
skip(is_os('win'))
|
|
feed('<C-R>r<C-X><C-X>')
|
|
screen:expect([[
|
|
{7: 1 } |
|
|
{7: 2 } |
|
|
{7: 3 } |
|
|
{7: 4 } |
|
|
{7: 5 }Entering Ex mode. Type "visual" to go to Normal mode. |
|
|
{7: 6 }:µ̳µ̳µ̳µ̳µ̳µ̳^µ̳µ̳ |
|
|
{3:-- TERMINAL --} |
|
|
]])
|
|
eq({ 6, 25 }, eval('nvim_win_get_cursor(0)'))
|
|
feed([[<C-\><C-N>]])
|
|
screen:expect([[
|
|
{7: 1 } |
|
|
{7: 2 } |
|
|
{7: 3 } |
|
|
{7: 4 } |
|
|
{7: 5 }Entering Ex mode. Type "visual" to go to Normal mode. |
|
|
{7: 6 }:µ̳µ̳µ̳µ̳µ̳^µ̳µ̳µ̳ |
|
|
|
|
|
]])
|
|
eq({ 6, 21 }, eval('nvim_win_get_cursor(0)'))
|
|
end)
|
|
|
|
it('near the start', function()
|
|
skip(is_os('win'))
|
|
feed('<C-R>r<C-B><C-O>')
|
|
screen:expect([[
|
|
{7: 1 } |
|
|
{7: 2 } |
|
|
{7: 3 } |
|
|
{7: 4 } |
|
|
{7: 5 }Entering Ex mode. Type "visual" to go to Normal mode. |
|
|
{7: 6 }:µ̳^µ̳µ̳µ̳µ̳µ̳µ̳µ̳ |
|
|
{3:-- TERMINAL --} |
|
|
]])
|
|
eq({ 6, 5 }, eval('nvim_win_get_cursor(0)'))
|
|
feed([[<C-\><C-N>]])
|
|
screen:expect([[
|
|
{7: 1 } |
|
|
{7: 2 } |
|
|
{7: 3 } |
|
|
{7: 4 } |
|
|
{7: 5 }Entering Ex mode. Type "visual" to go to Normal mode. |
|
|
{7: 6 }:^µ̳µ̳µ̳µ̳µ̳µ̳µ̳µ̳ |
|
|
|
|
|
]])
|
|
eq({ 6, 1 }, eval('nvim_win_get_cursor(0)'))
|
|
end)
|
|
end)
|
|
|
|
describe('in a line with double-cell multibyte chars and no trailing spaces,', function()
|
|
before_each(function()
|
|
setup_ex_register('哦哦哦哦哦哦哦哦')
|
|
end)
|
|
|
|
it('at the end', function()
|
|
feed('<C-R>r')
|
|
screen:expect([[
|
|
{7: 1 } |
|
|
{7: 2 } |
|
|
{7: 3 } |
|
|
{7: 4 } |
|
|
{7: 5 }Entering Ex mode. Type "visual" to go to Normal mode. |
|
|
{7: 6 }:哦哦哦哦哦哦哦哦^ |
|
|
{3:-- TERMINAL --} |
|
|
]])
|
|
eq({ 6, 25 }, eval('nvim_win_get_cursor(0)'))
|
|
feed([[<C-\><C-N>]])
|
|
screen:expect([[
|
|
{7: 1 } |
|
|
{7: 2 } |
|
|
{7: 3 } |
|
|
{7: 4 } |
|
|
{7: 5 }Entering Ex mode. Type "visual" to go to Normal mode. |
|
|
{7: 6 }:哦哦哦哦哦哦哦^哦 |
|
|
|
|
|
]])
|
|
eq({ 6, 22 }, eval('nvim_win_get_cursor(0)'))
|
|
end)
|
|
|
|
it('near the end', function()
|
|
feed('<C-R>r<C-X><C-X>')
|
|
screen:expect([[
|
|
{7: 1 } |
|
|
{7: 2 } |
|
|
{7: 3 } |
|
|
{7: 4 } |
|
|
{7: 5 }Entering Ex mode. Type "visual" to go to Normal mode. |
|
|
{7: 6 }:哦哦哦哦哦哦^哦哦 |
|
|
{3:-- TERMINAL --} |
|
|
]])
|
|
eq({ 6, 19 }, eval('nvim_win_get_cursor(0)'))
|
|
feed([[<C-\><C-N>]])
|
|
screen:expect([[
|
|
{7: 1 } |
|
|
{7: 2 } |
|
|
{7: 3 } |
|
|
{7: 4 } |
|
|
{7: 5 }Entering Ex mode. Type "visual" to go to Normal mode. |
|
|
{7: 6 }:哦哦哦哦哦^哦哦哦 |
|
|
|
|
|
]])
|
|
eq({ 6, 16 }, eval('nvim_win_get_cursor(0)'))
|
|
end)
|
|
|
|
it('near the start', function()
|
|
feed('<C-R>r<C-B><C-O>')
|
|
screen:expect([[
|
|
{7: 1 } |
|
|
{7: 2 } |
|
|
{7: 3 } |
|
|
{7: 4 } |
|
|
{7: 5 }Entering Ex mode. Type "visual" to go to Normal mode. |
|
|
{7: 6 }:哦^哦哦哦哦哦哦哦 |
|
|
{3:-- TERMINAL --} |
|
|
]])
|
|
eq({ 6, 4 }, eval('nvim_win_get_cursor(0)'))
|
|
feed([[<C-\><C-N>]])
|
|
screen:expect([[
|
|
{7: 1 } |
|
|
{7: 2 } |
|
|
{7: 3 } |
|
|
{7: 4 } |
|
|
{7: 5 }Entering Ex mode. Type "visual" to go to Normal mode. |
|
|
{7: 6 }:^哦哦哦哦哦哦哦哦 |
|
|
|
|
|
]])
|
|
eq({ 6, 1 }, eval('nvim_win_get_cursor(0)'))
|
|
end)
|
|
end)
|
|
|
|
it('at the end of a line with trailing spaces #16234', function()
|
|
setup_ex_register('aaaaaaaa ')
|
|
feed('<C-R>r')
|
|
screen:expect([[
|
|
{7: 1 } |
|
|
{7: 2 } |
|
|
{7: 3 } |
|
|
{7: 4 } |
|
|
{7: 5 }Entering Ex mode. Type "visual" to go to Normal mode. |
|
|
{7: 6 }:aaaaaaaa ^ |
|
|
{3:-- TERMINAL --} |
|
|
]])
|
|
matches('^:aaaaaaaa [ ]*$', eval('nvim_get_current_line()'))
|
|
eq({ 6, 13 }, eval('nvim_win_get_cursor(0)'))
|
|
feed([[<C-\><C-N>]])
|
|
screen:expect([[
|
|
{7: 1 } |
|
|
{7: 2 } |
|
|
{7: 3 } |
|
|
{7: 4 } |
|
|
{7: 5 }Entering Ex mode. Type "visual" to go to Normal mode. |
|
|
{7: 6 }:aaaaaaaa ^ |
|
|
|
|
|
]])
|
|
eq({ 6, 12 }, eval('nvim_win_get_cursor(0)'))
|
|
end)
|
|
end)
|