mirror of
https://github.com/neovim/neovim.git
synced 2024-12-24 13:15:09 -07:00
test: Add terminal tests
- Modify tty-test to allow easier control over the terminal - Add a new directory with various terminal tests/specifications - Remove a pending job/pty test. - Flush stdout in Screen:snapshot_util() (avoid waiting for the test to finish) - Replace libuv sigwinch watcher by a sigaction handler. libuv randomly fails to deliver signals on OSX. Might be related to the problem fixed by @bbcddc55ee1e5605657592644be0102ed3a5f104 (under the hoods, libuv uses a pipe to deliver signals to the main thread, which might be blocking in some situations)
This commit is contained in:
parent
710002c820
commit
2aa2513b8e
@ -174,24 +174,14 @@ describe('jobs', function()
|
||||
|
||||
it('echoing input', function()
|
||||
send('test')
|
||||
-- the tty driver will echo input by default
|
||||
eq('test', next_chunk())
|
||||
end)
|
||||
|
||||
it('resizing window', function()
|
||||
nvim('command', 'call jobresize(j, 40, 10)')
|
||||
eq('screen resized. rows: 10, columns: 40', next_chunk())
|
||||
eq('rows: 10, cols: 40', next_chunk())
|
||||
nvim('command', 'call jobresize(j, 10, 40)')
|
||||
eq('screen resized. rows: 40, columns: 10', next_chunk())
|
||||
end)
|
||||
|
||||
-- FIXME This test is flawed because there is no telling when the OS will send chunks of data.
|
||||
pending('preprocessing ctrl+c with terminal driver', function()
|
||||
send('\\<c-c>')
|
||||
eq('^Cinterrupt received, press again to exit', next_chunk())
|
||||
send('\\<c-c>')
|
||||
eq('^Ctty done', next_chunk())
|
||||
eq({'notification', 'exit', {0}}, next_message())
|
||||
eq('rows: 40, cols: 10', next_chunk())
|
||||
end)
|
||||
end)
|
||||
end)
|
||||
|
@ -3,6 +3,8 @@
|
||||
#include <stdlib.h>
|
||||
#include <uv.h>
|
||||
|
||||
uv_tty_t tty;
|
||||
|
||||
#ifdef _WIN32
|
||||
#include <windows.h>
|
||||
bool owns_tty(void)
|
||||
@ -13,10 +15,10 @@ bool owns_tty(void)
|
||||
return GetCurrentProcessId() == dwProcessId;
|
||||
}
|
||||
#else
|
||||
#include <unistd.h>
|
||||
bool owns_tty(void)
|
||||
{
|
||||
// TODO: Check if the process is the session leader
|
||||
return true;
|
||||
return getsid(0) == getpid();
|
||||
}
|
||||
#endif
|
||||
|
||||
@ -29,26 +31,20 @@ static void walk_cb(uv_handle_t *handle, void *arg) {
|
||||
}
|
||||
}
|
||||
|
||||
static void sigwinch_cb(uv_signal_t *handle, int signum)
|
||||
static void sigwinch_handler(int signum)
|
||||
{
|
||||
int width, height;
|
||||
uv_tty_t *tty = handle->data;
|
||||
uv_tty_get_winsize(tty, &width, &height);
|
||||
fprintf(stderr, "screen resized. rows: %d, columns: %d\n", height, width);
|
||||
uv_tty_get_winsize(&tty, &width, &height);
|
||||
fprintf(stderr, "rows: %d, cols: %d\n", height, width);
|
||||
}
|
||||
|
||||
static void sigint_cb(uv_signal_t *handle, int signum)
|
||||
{
|
||||
bool *interrupted = handle->data;
|
||||
|
||||
if (*interrupted) {
|
||||
uv_walk(uv_default_loop(), walk_cb, NULL);
|
||||
return;
|
||||
}
|
||||
|
||||
*interrupted = true;
|
||||
fprintf(stderr, "interrupt received, press again to exit\n");
|
||||
}
|
||||
// static void sigwinch_cb(uv_signal_t *handle, int signum)
|
||||
// {
|
||||
// int width, height;
|
||||
// uv_tty_t *tty = handle->data;
|
||||
// uv_tty_get_winsize(tty, &width, &height);
|
||||
// fprintf(stderr, "rows: %d, cols: %d\n", height, width);
|
||||
// }
|
||||
|
||||
static void alloc_cb(uv_handle_t *handle, size_t suggested, uv_buf_t *buf)
|
||||
{
|
||||
@ -63,13 +59,20 @@ static void read_cb(uv_stream_t *stream, ssize_t cnt, const uv_buf_t *buf)
|
||||
return;
|
||||
}
|
||||
|
||||
fprintf(stderr, "received data: ");
|
||||
int *interrupted = stream->data;
|
||||
|
||||
for (int i = 0; i < cnt; i++) {
|
||||
if (buf->base[i] == 3) {
|
||||
(*interrupted)++;
|
||||
}
|
||||
}
|
||||
|
||||
uv_loop_t write_loop;
|
||||
uv_loop_init(&write_loop);
|
||||
uv_tty_t out;
|
||||
uv_tty_init(&write_loop, &out, 1, 0);
|
||||
uv_write_t req;
|
||||
uv_buf_t b = {.base = buf->base, .len = buf->len};
|
||||
uv_buf_t b = {.base = buf->base, .len = (size_t)cnt};
|
||||
uv_write(&req, (uv_stream_t *)&out, &b, 1, NULL);
|
||||
uv_run(&write_loop, UV_RUN_DEFAULT);
|
||||
uv_close((uv_handle_t *)&out, NULL);
|
||||
@ -78,6 +81,12 @@ static void read_cb(uv_stream_t *stream, ssize_t cnt, const uv_buf_t *buf)
|
||||
abort();
|
||||
}
|
||||
free(buf->base);
|
||||
|
||||
if (*interrupted >= 2) {
|
||||
uv_walk(uv_default_loop(), walk_cb, NULL);
|
||||
} else if (*interrupted == 1) {
|
||||
fprintf(stderr, "interrupt received, press again to exit\n");
|
||||
}
|
||||
}
|
||||
|
||||
static void prepare_cb(uv_prepare_t *handle)
|
||||
@ -88,6 +97,11 @@ static void prepare_cb(uv_prepare_t *handle)
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
if (!owns_tty()) {
|
||||
fprintf(stderr, "process does not own the terminal\n");
|
||||
exit(2);
|
||||
}
|
||||
|
||||
if (!is_terminal(stdin)) {
|
||||
fprintf(stderr, "stdin is not a terminal\n");
|
||||
exit(2);
|
||||
@ -103,20 +117,34 @@ int main(int argc, char **argv)
|
||||
exit(2);
|
||||
}
|
||||
|
||||
bool interrupted = false;
|
||||
if (argc > 1) {
|
||||
int count = atoi(argv[1]);
|
||||
for (int i = 0; i < count; ++i) {
|
||||
printf("line%d\n", i);
|
||||
}
|
||||
fflush(stdout);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int interrupted = 0;
|
||||
uv_prepare_t prepare;
|
||||
uv_prepare_init(uv_default_loop(), &prepare);
|
||||
uv_prepare_start(&prepare, prepare_cb);
|
||||
uv_tty_t tty;
|
||||
// uv_tty_t tty;
|
||||
uv_tty_init(uv_default_loop(), &tty, fileno(stderr), 1);
|
||||
uv_tty_set_mode(&tty, UV_TTY_MODE_RAW);
|
||||
tty.data = &interrupted;
|
||||
uv_read_start((uv_stream_t *)&tty, alloc_cb, read_cb);
|
||||
uv_signal_t sigwinch_watcher, sigint_watcher;
|
||||
uv_signal_init(uv_default_loop(), &sigwinch_watcher);
|
||||
sigwinch_watcher.data = &tty;
|
||||
uv_signal_start(&sigwinch_watcher, sigwinch_cb, SIGWINCH);
|
||||
uv_signal_init(uv_default_loop(), &sigint_watcher);
|
||||
sigint_watcher.data = &interrupted;
|
||||
uv_signal_start(&sigint_watcher, sigint_cb, SIGINT);
|
||||
struct sigaction sa;
|
||||
sigemptyset(&sa.sa_mask);
|
||||
sa.sa_flags = 0;
|
||||
sa.sa_handler = sigwinch_handler;
|
||||
sigaction(SIGWINCH, &sa, NULL);
|
||||
// uv_signal_t sigwinch_watcher;
|
||||
// uv_signal_init(uv_default_loop(), &sigwinch_watcher);
|
||||
// sigwinch_watcher.data = &tty;
|
||||
// uv_signal_start(&sigwinch_watcher, sigwinch_cb, SIGWINCH);
|
||||
uv_run(uv_default_loop(), UV_RUN_DEFAULT);
|
||||
fprintf(stderr, "tty done\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
158
test/functional/terminal/altscreen_spec.lua
Normal file
158
test/functional/terminal/altscreen_spec.lua
Normal file
@ -0,0 +1,158 @@
|
||||
local helpers = require('test.functional.helpers')
|
||||
local thelpers = require('test.functional.terminal.helpers')
|
||||
local Screen = require('test.functional.ui.screen')
|
||||
local clear, eq, curbuf = helpers.clear, helpers.eq, helpers.curbuf
|
||||
local feed = helpers.feed
|
||||
local feed_data = thelpers.feed_data
|
||||
local enter_altscreen = thelpers.enter_altscreen
|
||||
local exit_altscreen = thelpers.exit_altscreen
|
||||
|
||||
describe('terminal altscreen', function()
|
||||
local screen
|
||||
|
||||
before_each(function()
|
||||
clear()
|
||||
screen = thelpers.screen_setup()
|
||||
feed_data({'line1', 'line2', 'line3', 'line4', 'line5', 'line6',
|
||||
'line7', 'line8', ''})
|
||||
screen:expect([[
|
||||
line4 |
|
||||
line5 |
|
||||
line6 |
|
||||
line7 |
|
||||
line8 |
|
||||
{1: } |
|
||||
-- TERMINAL -- |
|
||||
]])
|
||||
enter_altscreen()
|
||||
screen:expect([[
|
||||
|
|
||||
|
|
||||
|
|
||||
|
|
||||
|
|
||||
{1: } |
|
||||
-- TERMINAL -- |
|
||||
]])
|
||||
eq(10, curbuf('line_count'))
|
||||
end)
|
||||
|
||||
it('wont clear lines already in the scrollback', function()
|
||||
feed('<c-\\><c-n>gg')
|
||||
screen:expect([[
|
||||
^tty ready |
|
||||
line1 |
|
||||
line2 |
|
||||
line3 |
|
||||
|
|
||||
|
|
||||
|
|
||||
]])
|
||||
end)
|
||||
|
||||
describe('on exit', function()
|
||||
before_each(exit_altscreen)
|
||||
|
||||
it('restores buffer state', function()
|
||||
screen:expect([[
|
||||
line4 |
|
||||
line5 |
|
||||
line6 |
|
||||
line7 |
|
||||
line8 |
|
||||
{1: } |
|
||||
-- TERMINAL -- |
|
||||
]])
|
||||
feed('<c-\\><c-n>gg')
|
||||
screen:expect([[
|
||||
^tty ready |
|
||||
line1 |
|
||||
line2 |
|
||||
line3 |
|
||||
line4 |
|
||||
line5 |
|
||||
|
|
||||
]])
|
||||
end)
|
||||
end)
|
||||
|
||||
describe('with lines printed after the screen height limit', function()
|
||||
before_each(function()
|
||||
feed_data({'line9', 'line10', 'line11', 'line12', 'line13',
|
||||
'line14', 'line15', 'line16', ''})
|
||||
screen:expect([[
|
||||
line12 |
|
||||
line13 |
|
||||
line14 |
|
||||
line15 |
|
||||
line16 |
|
||||
{1: } |
|
||||
-- TERMINAL -- |
|
||||
]])
|
||||
end)
|
||||
|
||||
it('wont modify line count', function()
|
||||
eq(10, curbuf('line_count'))
|
||||
end)
|
||||
|
||||
it('wont modify lines in the scrollback', function()
|
||||
feed('<c-\\><c-n>gg')
|
||||
screen:expect([[
|
||||
^tty ready |
|
||||
line1 |
|
||||
line2 |
|
||||
line3 |
|
||||
line12 |
|
||||
line13 |
|
||||
|
|
||||
]])
|
||||
end)
|
||||
end)
|
||||
|
||||
describe('after height is decreased by 2', function()
|
||||
local function wait_removal()
|
||||
screen:try_resize(screen._width, screen._height - 2)
|
||||
screen:expect([[
|
||||
|
|
||||
|
|
||||
rows: 4, cols: 50 |
|
||||
{1: } |
|
||||
-- TERMINAL -- |
|
||||
]])
|
||||
end
|
||||
|
||||
it('removes 2 lines from the bottom of the visible buffer', function()
|
||||
wait_removal()
|
||||
feed('<c-\\><c-n>4k')
|
||||
screen:expect([[
|
||||
^line3 |
|
||||
|
|
||||
|
|
||||
rows: 4, cols: 50 |
|
||||
|
|
||||
]])
|
||||
eq(8, curbuf('line_count'))
|
||||
end)
|
||||
|
||||
describe('and after exit', function()
|
||||
before_each(function()
|
||||
wait_removal()
|
||||
exit_altscreen()
|
||||
end)
|
||||
|
||||
it('restore buffer state', function()
|
||||
-- FIXME(tarruda): Note that the last line was lost after restoring the
|
||||
-- screen. This is a libvterm bug: When the main screen is restored it
|
||||
-- seems to "cut" lines that would have been left below the new visible
|
||||
-- screen.
|
||||
screen:expect([[
|
||||
line4 |
|
||||
line5 |
|
||||
line6 |
|
||||
line7 |
|
||||
-- TERMINAL -- |
|
||||
]])
|
||||
end)
|
||||
end)
|
||||
end)
|
||||
end)
|
159
test/functional/terminal/buffer_spec.lua
Normal file
159
test/functional/terminal/buffer_spec.lua
Normal file
@ -0,0 +1,159 @@
|
||||
local helpers = require('test.functional.helpers')
|
||||
local Screen = require('test.functional.ui.screen')
|
||||
local thelpers = require('test.functional.terminal.helpers')
|
||||
local feed, clear, nvim = helpers.feed, helpers.clear, helpers.nvim
|
||||
local wait, execute, eq = helpers.wait, helpers.execute, helpers.eq
|
||||
|
||||
|
||||
describe('terminal buffer', function()
|
||||
local screen
|
||||
|
||||
before_each(function()
|
||||
clear()
|
||||
execute('set modifiable swapfile undolevels=20')
|
||||
wait()
|
||||
screen = thelpers.screen_setup()
|
||||
end)
|
||||
|
||||
describe('when a new file is edited', function()
|
||||
before_each(function()
|
||||
feed('<c-\\><c-n>:set bufhidden=wipe<cr>:enew<cr>')
|
||||
screen:expect([[
|
||||
^ |
|
||||
~ |
|
||||
~ |
|
||||
~ |
|
||||
~ |
|
||||
~ |
|
||||
:enew |
|
||||
]])
|
||||
end)
|
||||
|
||||
it('will hide the buffer, ignoring the bufhidden option', function()
|
||||
feed(':bnext:l<esc>')
|
||||
screen:expect([[
|
||||
^ |
|
||||
~ |
|
||||
~ |
|
||||
~ |
|
||||
~ |
|
||||
~ |
|
||||
|
|
||||
]])
|
||||
end)
|
||||
end)
|
||||
|
||||
describe('swap and undo', function()
|
||||
before_each(function()
|
||||
feed('<c-\\><c-n>')
|
||||
screen:expect([[
|
||||
tty ready |
|
||||
{2: } |
|
||||
|
|
||||
|
|
||||
|
|
||||
^ |
|
||||
|
|
||||
]])
|
||||
end)
|
||||
|
||||
it('does not create swap files', function()
|
||||
local swapfile = nvim('command_output', 'swapname'):gsub('\n', '')
|
||||
eq(nil, io.open(swapfile))
|
||||
end)
|
||||
|
||||
it('does not create undofiles files', function()
|
||||
local undofile = nvim('eval', 'undofile(bufname("%"))')
|
||||
eq(nil, io.open(undofile))
|
||||
end)
|
||||
end)
|
||||
|
||||
it('cannot be modified directly', function()
|
||||
feed('<c-\\><c-n>dd')
|
||||
screen:expect([[
|
||||
tty ready |
|
||||
{2: } |
|
||||
|
|
||||
|
|
||||
|
|
||||
^ |
|
||||
E21: Cannot make changes, 'modifiable' is off |
|
||||
]])
|
||||
end)
|
||||
|
||||
it('sends data to the terminal when the "put" operator is used', function()
|
||||
feed('<c-\\><c-n>gg"ayj')
|
||||
execute('let @a = "appended " . @a')
|
||||
feed('"ap"ap')
|
||||
screen:expect([[
|
||||
^tty ready |
|
||||
appended tty ready |
|
||||
appended tty ready |
|
||||
{2: } |
|
||||
|
|
||||
|
|
||||
:let @a = "appended " . @a |
|
||||
]])
|
||||
-- operator count is also taken into consideration
|
||||
feed('3"ap')
|
||||
screen:expect([[
|
||||
^tty ready |
|
||||
appended tty ready |
|
||||
appended tty ready |
|
||||
appended tty ready |
|
||||
appended tty ready |
|
||||
appended tty ready |
|
||||
:let @a = "appended " . @a |
|
||||
]])
|
||||
end)
|
||||
|
||||
it('sends data to the terminal when the ":put" command is used', function()
|
||||
feed('<c-\\><c-n>gg"ayj')
|
||||
execute('let @a = "appended " . @a')
|
||||
execute('put a')
|
||||
screen:expect([[
|
||||
^tty ready |
|
||||
appended tty ready |
|
||||
{2: } |
|
||||
|
|
||||
|
|
||||
|
|
||||
:put a |
|
||||
]])
|
||||
-- line argument is only used to move the cursor
|
||||
execute('6put a')
|
||||
screen:expect([[
|
||||
tty ready |
|
||||
appended tty ready |
|
||||
appended tty ready |
|
||||
{2: } |
|
||||
|
|
||||
^ |
|
||||
:6put a |
|
||||
]])
|
||||
end)
|
||||
|
||||
it('can be deleted', function()
|
||||
feed('<c-\\><c-n>:bd!<cr>')
|
||||
screen:expect([[
|
||||
^ |
|
||||
~ |
|
||||
~ |
|
||||
~ |
|
||||
~ |
|
||||
~ |
|
||||
:bd! |
|
||||
]])
|
||||
execute('bnext')
|
||||
screen:expect([[
|
||||
^ |
|
||||
~ |
|
||||
~ |
|
||||
~ |
|
||||
~ |
|
||||
~ |
|
||||
:bnext |
|
||||
]])
|
||||
end)
|
||||
end)
|
||||
|
174
test/functional/terminal/cursor_spec.lua
Normal file
174
test/functional/terminal/cursor_spec.lua
Normal file
@ -0,0 +1,174 @@
|
||||
local helpers = require('test.functional.helpers')
|
||||
local Screen = require('test.functional.ui.screen')
|
||||
local thelpers = require('test.functional.terminal.helpers')
|
||||
local feed, clear, nvim = helpers.feed, helpers.clear, helpers.nvim
|
||||
local nvim_dir, execute, eq = helpers.nvim_dir, helpers.execute, helpers.eq
|
||||
local hide_cursor = thelpers.hide_cursor
|
||||
local show_cursor = thelpers.show_cursor
|
||||
|
||||
|
||||
describe('terminal cursor', function()
|
||||
local screen
|
||||
|
||||
before_each(function()
|
||||
clear()
|
||||
screen = thelpers.screen_setup()
|
||||
end)
|
||||
|
||||
|
||||
it('moves the screen cursor when focused', function()
|
||||
thelpers.feed_data('testing cursor')
|
||||
screen:expect([[
|
||||
tty ready |
|
||||
testing cursor{1: } |
|
||||
|
|
||||
|
|
||||
|
|
||||
|
|
||||
-- TERMINAL -- |
|
||||
]])
|
||||
eq(2, screen._cursor.row)
|
||||
eq(15, screen._cursor.col)
|
||||
end)
|
||||
|
||||
it('is highlighted when not focused', function()
|
||||
feed('<c-\\><c-n>')
|
||||
screen:expect([[
|
||||
tty ready |
|
||||
{2: } |
|
||||
|
|
||||
|
|
||||
|
|
||||
^ |
|
||||
|
|
||||
]])
|
||||
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([[
|
||||
1 tty ready |
|
||||
2 {2: } |
|
||||
3 |
|
||||
4 |
|
||||
5 |
|
||||
6 ^ |
|
||||
:set number |
|
||||
]])
|
||||
end)
|
||||
|
||||
it('is positioned correctly when focused', function()
|
||||
feed('i')
|
||||
screen:expect([[
|
||||
1 tty ready |
|
||||
2 {1: } |
|
||||
3 |
|
||||
4 |
|
||||
5 |
|
||||
6 |
|
||||
-- TERMINAL -- |
|
||||
]])
|
||||
end)
|
||||
end)
|
||||
|
||||
describe('when invisible', function()
|
||||
it('is not highlighted and is detached from screen cursor', function()
|
||||
hide_cursor()
|
||||
screen:expect([[
|
||||
tty ready |
|
||||
|
|
||||
|
|
||||
|
|
||||
|
|
||||
|
|
||||
-- TERMINAL -- |
|
||||
]])
|
||||
show_cursor()
|
||||
screen:expect([[
|
||||
tty ready |
|
||||
{1: } |
|
||||
|
|
||||
|
|
||||
|
|
||||
|
|
||||
-- TERMINAL -- |
|
||||
]])
|
||||
-- same for when the terminal is unfocused
|
||||
feed('<c-\\><c-n>')
|
||||
hide_cursor()
|
||||
screen:expect([[
|
||||
tty ready |
|
||||
|
|
||||
|
|
||||
|
|
||||
|
|
||||
^ |
|
||||
|
|
||||
]])
|
||||
show_cursor()
|
||||
screen:expect([[
|
||||
tty ready |
|
||||
{2: } |
|
||||
|
|
||||
|
|
||||
|
|
||||
^ |
|
||||
|
|
||||
]])
|
||||
end)
|
||||
end)
|
||||
end)
|
||||
|
||||
|
||||
describe('cursor with customized highlighting', function()
|
||||
local screen
|
||||
|
||||
before_each(function()
|
||||
clear()
|
||||
nvim('set_var', 'terminal_focused_cursor_highlight', 'CursorFocused')
|
||||
nvim('set_var', 'terminal_unfocused_cursor_highlight', 'CursorUnfocused')
|
||||
nvim('command', 'highlight CursorFocused ctermfg=45 ctermbg=46')
|
||||
nvim('command', 'highlight CursorUnfocused ctermfg=55 ctermbg=56')
|
||||
screen = Screen.new(50, 7)
|
||||
screen:set_default_attr_ids({
|
||||
[1] = {foreground = 45, background = 46},
|
||||
[2] = {foreground = 55, background = 56}
|
||||
})
|
||||
screen:set_default_attr_ignore({
|
||||
[1] = {bold = true},
|
||||
[2] = {foreground = 12},
|
||||
[3] = {bold = true, reverse = true},
|
||||
[5] = {background = 11},
|
||||
[6] = {foreground = 130},
|
||||
})
|
||||
screen:attach(false)
|
||||
execute('term "' ..nvim_dir.. '/tty-test"')
|
||||
end)
|
||||
|
||||
it('overrides the default highlighting', function()
|
||||
screen:expect([[
|
||||
tty ready |
|
||||
{1: } |
|
||||
|
|
||||
|
|
||||
|
|
||||
|
|
||||
-- TERMINAL -- |
|
||||
]])
|
||||
feed('<c-\\><c-n>')
|
||||
screen:expect([[
|
||||
tty ready |
|
||||
{2: } |
|
||||
|
|
||||
|
|
||||
|
|
||||
^ |
|
||||
|
|
||||
]])
|
||||
end)
|
||||
end)
|
||||
|
95
test/functional/terminal/helpers.lua
Normal file
95
test/functional/terminal/helpers.lua
Normal file
@ -0,0 +1,95 @@
|
||||
local helpers = require('test.functional.helpers')
|
||||
local Screen = require('test.functional.ui.screen')
|
||||
local nvim_dir = helpers.nvim_dir
|
||||
local execute, nvim = helpers.execute, helpers.nvim
|
||||
|
||||
local function feed_data(data)
|
||||
nvim('set_var', 'term_data', data)
|
||||
nvim('command', 'call jobsend(b:terminal_job_id, term_data)')
|
||||
end
|
||||
|
||||
local function feed_termcode(data)
|
||||
-- feed with the job API
|
||||
nvim('command', 'call jobsend(b:terminal_job_id, "\\x1b'..data..'")')
|
||||
end
|
||||
-- some helpers for controlling the terminal. the codes were taken from
|
||||
-- infocmp xterm-256color which is less what libvterm understands
|
||||
-- civis/cnorm
|
||||
local function hide_cursor() feed_termcode('[?25l') end
|
||||
local function show_cursor() feed_termcode('[?25h') end
|
||||
-- smcup/rmcup
|
||||
local function enter_altscreen() feed_termcode('[?1049h') end
|
||||
local function exit_altscreen() feed_termcode('[?1049l') end
|
||||
-- character attributes
|
||||
local function set_fg(num) feed_termcode('[38;5;'..num..'m') end
|
||||
local function set_bg(num) feed_termcode('[48;5;'..num..'m') end
|
||||
local function set_bold() feed_termcode('[1m') end
|
||||
local function set_italic() feed_termcode('[3m') end
|
||||
local function set_underline() feed_termcode('[4m') end
|
||||
local function clear_attrs() feed_termcode('[0;10m') end
|
||||
-- mouse
|
||||
local function enable_mouse() feed_termcode('[?1002h') end
|
||||
local function disable_mouse() feed_termcode('[?1002l') end
|
||||
|
||||
|
||||
|
||||
local function screen_setup(extra_height)
|
||||
nvim('set_var', 'terminal_scrollback_buffer_size', 10)
|
||||
if not extra_height then extra_height = 0 end
|
||||
local screen = Screen.new(50, 7 + extra_height)
|
||||
screen:set_default_attr_ids({
|
||||
[1] = {reverse = true}, -- focused cursor
|
||||
[2] = {background = 11}, -- unfocused cursor
|
||||
})
|
||||
screen:set_default_attr_ignore({
|
||||
[1] = {bold = true},
|
||||
[2] = {foreground = 12},
|
||||
[3] = {bold = true, reverse = true},
|
||||
[5] = {background = 11},
|
||||
[6] = {foreground = 130},
|
||||
[7] = {foreground = 15, background = 1}, -- error message
|
||||
})
|
||||
|
||||
screen:attach(false)
|
||||
-- tty-test puts the terminal into raw mode and echoes all input. tests are
|
||||
-- done by feeding it with terminfo codes to control the display and
|
||||
-- verifying output with screen:expect.
|
||||
execute('term ' ..nvim_dir.. '/tty-test')
|
||||
-- wait for "tty ready" to be printed before each test or the terminal may
|
||||
-- still be in canonical mode(will echo characters for example)
|
||||
--
|
||||
local empty_line = ' '
|
||||
local expected = {
|
||||
'tty ready ',
|
||||
'{1: } ',
|
||||
empty_line,
|
||||
empty_line,
|
||||
empty_line,
|
||||
empty_line,
|
||||
}
|
||||
for i = 1, extra_height do
|
||||
table.insert(expected, empty_line)
|
||||
end
|
||||
|
||||
table.insert(expected, '-- TERMINAL -- ')
|
||||
screen:expect(table.concat(expected, '\n'))
|
||||
return screen
|
||||
end
|
||||
|
||||
return {
|
||||
feed_data = feed_data,
|
||||
feed_termcode = feed_termcode,
|
||||
hide_cursor = hide_cursor,
|
||||
show_cursor = show_cursor,
|
||||
enter_altscreen = enter_altscreen,
|
||||
exit_altscreen = exit_altscreen,
|
||||
set_fg = set_fg,
|
||||
set_bg = set_bg,
|
||||
set_bold = set_bold,
|
||||
set_italic = set_italic,
|
||||
set_underline = set_underline,
|
||||
clear_attrs = clear_attrs,
|
||||
enable_mouse = enable_mouse,
|
||||
disable_mouse = disable_mouse,
|
||||
screen_setup = screen_setup
|
||||
}
|
163
test/functional/terminal/highlight_spec.lua
Normal file
163
test/functional/terminal/highlight_spec.lua
Normal file
@ -0,0 +1,163 @@
|
||||
local helpers = require('test.functional.helpers')
|
||||
local Screen = require('test.functional.ui.screen')
|
||||
local thelpers = require('test.functional.terminal.helpers')
|
||||
local feed, clear, nvim = helpers.feed, helpers.clear, helpers.nvim
|
||||
local nvim_dir, execute = helpers.nvim_dir, helpers.execute
|
||||
|
||||
|
||||
describe('terminal window highlighting', function()
|
||||
local screen
|
||||
|
||||
before_each(function()
|
||||
clear()
|
||||
screen = Screen.new(50, 7)
|
||||
screen:set_default_attr_ids({
|
||||
[1] = {foreground = 45},
|
||||
[2] = {background = 46},
|
||||
[3] = {foreground = 45, background = 46},
|
||||
[4] = {bold = true, italic = true, underline = true}
|
||||
})
|
||||
screen:set_default_attr_ignore({
|
||||
[1] = {bold = true},
|
||||
[2] = {foreground = 12},
|
||||
[3] = {bold = true, reverse = true},
|
||||
[5] = {background = 11},
|
||||
[6] = {foreground = 130},
|
||||
[7] = {reverse = true},
|
||||
[8] = {background = 11}
|
||||
})
|
||||
screen:attach(false)
|
||||
execute('term "' ..nvim_dir.. '/tty-test"')
|
||||
screen:expect([[
|
||||
tty ready |
|
||||
|
|
||||
|
|
||||
|
|
||||
|
|
||||
|
|
||||
-- TERMINAL -- |
|
||||
]])
|
||||
end)
|
||||
|
||||
function descr(title, attr_num, set_attrs_fn)
|
||||
local function sub(s)
|
||||
return s:gsub('NUM', attr_num)
|
||||
end
|
||||
|
||||
describe(title, function()
|
||||
before_each(function()
|
||||
set_attrs_fn()
|
||||
thelpers.feed_data('text')
|
||||
thelpers.clear_attrs()
|
||||
thelpers.feed_data('text')
|
||||
end)
|
||||
|
||||
local function pass_attrs()
|
||||
local s = sub([[
|
||||
tty ready |
|
||||
{NUM:text}text |
|
||||
|
|
||||
|
|
||||
|
|
||||
|
|
||||
-- TERMINAL -- |
|
||||
]])
|
||||
screen:expect(s)
|
||||
end
|
||||
|
||||
it('will pass the corresponding attributes', pass_attrs)
|
||||
|
||||
it('will pass the corresponding attributes on scrollback', function()
|
||||
pass_attrs()
|
||||
local lines = {}
|
||||
for i = 1, 8 do
|
||||
table.insert(lines, 'line'..tostring(i))
|
||||
end
|
||||
table.insert(lines, '')
|
||||
thelpers.feed_data(lines)
|
||||
screen:expect([[
|
||||
line4 |
|
||||
line5 |
|
||||
line6 |
|
||||
line7 |
|
||||
line8 |
|
||||
|
|
||||
-- TERMINAL -- |
|
||||
]])
|
||||
feed('<c-\\><c-n>gg')
|
||||
local s = sub([[
|
||||
^tty ready |
|
||||
{NUM:text}textline1 |
|
||||
line2 |
|
||||
line3 |
|
||||
line4 |
|
||||
line5 |
|
||||
|
|
||||
]])
|
||||
screen:expect(s)
|
||||
end)
|
||||
end)
|
||||
end
|
||||
|
||||
descr('foreground', 1, function() thelpers.set_fg(45) end)
|
||||
descr('background', 2, function() thelpers.set_bg(46) end)
|
||||
descr('foreground and background', 3, function()
|
||||
thelpers.set_fg(45)
|
||||
thelpers.set_bg(46)
|
||||
end)
|
||||
descr('bold, italics and underline', 4, function()
|
||||
thelpers.set_bold()
|
||||
thelpers.set_italic()
|
||||
thelpers.set_underline()
|
||||
end)
|
||||
end)
|
||||
|
||||
|
||||
describe('terminal window highlighting with custom palette', function()
|
||||
local screen
|
||||
|
||||
before_each(function()
|
||||
clear()
|
||||
screen = Screen.new(50, 7)
|
||||
screen:set_default_attr_ids({
|
||||
[1] = {foreground = 1193046}
|
||||
})
|
||||
screen:set_default_attr_ignore({
|
||||
[1] = {bold = true},
|
||||
[2] = {foreground = 12},
|
||||
[3] = {bold = true, reverse = true},
|
||||
[5] = {background = 11},
|
||||
[6] = {foreground = 130},
|
||||
[7] = {reverse = true},
|
||||
[8] = {background = 11}
|
||||
})
|
||||
screen:attach(true)
|
||||
nvim('set_var', 'terminal_color_3', '#123456')
|
||||
execute('term "' ..nvim_dir.. '/tty-test"')
|
||||
screen:expect([[
|
||||
tty ready |
|
||||
|
|
||||
|
|
||||
|
|
||||
|
|
||||
|
|
||||
-- TERMINAL -- |
|
||||
]])
|
||||
end)
|
||||
|
||||
it('will use the custom color', function()
|
||||
thelpers.set_fg(3)
|
||||
thelpers.feed_data('text')
|
||||
thelpers.clear_attrs()
|
||||
thelpers.feed_data('text')
|
||||
screen:expect([[
|
||||
tty ready |
|
||||
{1:text}text |
|
||||
|
|
||||
|
|
||||
|
|
||||
|
|
||||
-- TERMINAL -- |
|
||||
]])
|
||||
end)
|
||||
end)
|
188
test/functional/terminal/mouse_spec.lua
Normal file
188
test/functional/terminal/mouse_spec.lua
Normal file
@ -0,0 +1,188 @@
|
||||
local Screen = require('test.functional.ui.screen')
|
||||
local helpers = require('test.functional.helpers')
|
||||
local thelpers = require('test.functional.terminal.helpers')
|
||||
local clear, eq, curbuf = helpers.clear, helpers.eq, helpers.curbuf
|
||||
local feed, execute, nvim = helpers.feed, helpers.execute, helpers.nvim
|
||||
local feed_data = thelpers.feed_data
|
||||
|
||||
describe('terminal mouse', function()
|
||||
local screen
|
||||
|
||||
before_each(function()
|
||||
clear()
|
||||
nvim('set_option', 'statusline', '==========')
|
||||
nvim('command', 'highlight StatusLine cterm=NONE')
|
||||
nvim('command', 'highlight StatusLineNC cterm=NONE')
|
||||
nvim('command', 'highlight VertSplit cterm=NONE')
|
||||
screen = thelpers.screen_setup()
|
||||
local lines = {}
|
||||
for i = 1, 30 do
|
||||
table.insert(lines, 'line'..tostring(i))
|
||||
end
|
||||
table.insert(lines, '')
|
||||
feed_data(lines)
|
||||
screen:expect([[
|
||||
line26 |
|
||||
line27 |
|
||||
line28 |
|
||||
line29 |
|
||||
line30 |
|
||||
{1: } |
|
||||
-- TERMINAL -- |
|
||||
]])
|
||||
end)
|
||||
|
||||
after_each(function()
|
||||
screen:detach()
|
||||
end)
|
||||
|
||||
describe('when the terminal has focus', function()
|
||||
it('will exit focus when scrolled', function()
|
||||
feed('<MouseDown><0,0>')
|
||||
screen:expect([[
|
||||
line23 |
|
||||
line24 |
|
||||
line25 |
|
||||
line26 |
|
||||
line27 |
|
||||
^line28 |
|
||||
|
|
||||
]])
|
||||
end)
|
||||
|
||||
describe('with mouse events enabled by the program', function()
|
||||
before_each(function()
|
||||
thelpers.enable_mouse()
|
||||
thelpers.feed_data('mouse enabled\n')
|
||||
screen:expect([[
|
||||
line27 |
|
||||
line28 |
|
||||
line29 |
|
||||
line30 |
|
||||
mouse enabled |
|
||||
{1: } |
|
||||
-- TERMINAL -- |
|
||||
]])
|
||||
end)
|
||||
|
||||
it('will forward mouse clicks to the program', function()
|
||||
feed('<LeftMouse><1,2>')
|
||||
screen:expect([[
|
||||
line27 |
|
||||
line28 |
|
||||
line29 |
|
||||
line30 |
|
||||
mouse enabled |
|
||||
"#{1: } |
|
||||
-- TERMINAL -- |
|
||||
]])
|
||||
end)
|
||||
|
||||
it('will forward mouse scroll to the program', function()
|
||||
feed('<MouseDown><0,0>')
|
||||
screen:expect([[
|
||||
line27 |
|
||||
line28 |
|
||||
line29 |
|
||||
line30 |
|
||||
mouse enabled |
|
||||
`!!{1: } |
|
||||
-- TERMINAL -- |
|
||||
]])
|
||||
end)
|
||||
end)
|
||||
|
||||
describe('with a split window and other buffer', function()
|
||||
before_each(function()
|
||||
feed('<c-\\><c-n>:vsp<cr>')
|
||||
screen:expect([[
|
||||
line21 |line21 |
|
||||
line22 |line22 |
|
||||
line23 |line23 |
|
||||
line24 |line24 |
|
||||
^rows: 5, cols: 24 |rows: 5, cols: 24 |
|
||||
========== ========== |
|
||||
|
|
||||
]])
|
||||
feed(':enew | set number<cr>')
|
||||
screen:expect([[
|
||||
1 ^ |line21 |
|
||||
~ |line22 |
|
||||
~ |line23 |
|
||||
~ |line24 |
|
||||
~ |rows: 5, cols: 24 |
|
||||
========== ========== |
|
||||
:enew | set number |
|
||||
]])
|
||||
feed('30iline\n<esc>')
|
||||
screen:expect([[
|
||||
27 line |line21 |
|
||||
28 line |line22 |
|
||||
29 line |line23 |
|
||||
30 line |line24 |
|
||||
31 ^ |rows: 5, cols: 24 |
|
||||
========== ========== |
|
||||
|
|
||||
]])
|
||||
feed('<c-w>li')
|
||||
screen:expect([[
|
||||
27 line |line22 |
|
||||
28 line |line23 |
|
||||
29 line |line24 |
|
||||
30 line |rows: 5, cols: 24 |
|
||||
31 |{1: } |
|
||||
========== ========== |
|
||||
-- TERMINAL -- |
|
||||
]])
|
||||
-- enabling mouse won't affect interaction with other windows
|
||||
thelpers.enable_mouse()
|
||||
thelpers.feed_data('mouse enabled\n')
|
||||
screen:expect([[
|
||||
27 line |line23 |
|
||||
28 line |line24 |
|
||||
29 line |rows: 5, cols: 24 |
|
||||
30 line |mouse enabled |
|
||||
31 |{1: } |
|
||||
========== ========== |
|
||||
-- TERMINAL -- |
|
||||
]])
|
||||
end)
|
||||
|
||||
it('wont lose focus if another window is scrolled', function()
|
||||
feed('<MouseDown><0,0><MouseDown><0,0>')
|
||||
screen:expect([[
|
||||
21 line |line23 |
|
||||
22 line |line24 |
|
||||
23 line |rows: 5, cols: 24 |
|
||||
24 line |mouse enabled |
|
||||
25 line |{1: } |
|
||||
========== ========== |
|
||||
-- TERMINAL -- |
|
||||
]])
|
||||
feed('<S-MouseUp><0,0>')
|
||||
screen:expect([[
|
||||
26 line |line23 |
|
||||
27 line |line24 |
|
||||
28 line |rows: 5, cols: 24 |
|
||||
29 line |mouse enabled |
|
||||
30 line |{1: } |
|
||||
========== ========== |
|
||||
-- TERMINAL -- |
|
||||
]])
|
||||
end)
|
||||
|
||||
it('will lose focus if another window is clicked', function()
|
||||
feed('<LeftMouse><5,1>')
|
||||
screen:expect([[
|
||||
27 line |line23 |
|
||||
28 l^ine |line24 |
|
||||
29 line |rows: 5, cols: 24 |
|
||||
30 line |mouse enabled |
|
||||
31 |{2: } |
|
||||
========== ========== |
|
||||
|
|
||||
]])
|
||||
end)
|
||||
end)
|
||||
end)
|
||||
end)
|
348
test/functional/terminal/scrollback_spec.lua
Normal file
348
test/functional/terminal/scrollback_spec.lua
Normal file
@ -0,0 +1,348 @@
|
||||
local Screen = require('test.functional.ui.screen')
|
||||
local helpers = require('test.functional.helpers')
|
||||
local thelpers = require('test.functional.terminal.helpers')
|
||||
local clear, eq, curbuf = helpers.clear, helpers.eq, helpers.curbuf
|
||||
local feed, nvim_dir, execute = helpers.feed, helpers.nvim_dir, helpers.execute
|
||||
local wait = helpers.wait
|
||||
local feed_data = thelpers.feed_data
|
||||
|
||||
describe('terminal scrollback', function()
|
||||
local screen
|
||||
|
||||
before_each(function()
|
||||
clear()
|
||||
screen = thelpers.screen_setup()
|
||||
end)
|
||||
|
||||
after_each(function()
|
||||
screen:detach()
|
||||
end)
|
||||
|
||||
describe('when the limit is crossed', function()
|
||||
before_each(function()
|
||||
local lines = {}
|
||||
for i = 1, 30 do
|
||||
table.insert(lines, 'line'..tostring(i))
|
||||
end
|
||||
table.insert(lines, '')
|
||||
feed_data(lines)
|
||||
screen:expect([[
|
||||
line26 |
|
||||
line27 |
|
||||
line28 |
|
||||
line29 |
|
||||
line30 |
|
||||
{1: } |
|
||||
-- TERMINAL -- |
|
||||
]])
|
||||
end)
|
||||
|
||||
it('will delete extra lines at the top', function()
|
||||
feed('<c-\\><c-n>gg')
|
||||
screen:expect([[
|
||||
^line16 |
|
||||
line17 |
|
||||
line18 |
|
||||
line19 |
|
||||
line20 |
|
||||
line21 |
|
||||
|
|
||||
]])
|
||||
end)
|
||||
end)
|
||||
|
||||
describe('with the cursor at the last row', function()
|
||||
before_each(function()
|
||||
feed_data({'line1', 'line2', 'line3', 'line4', ''})
|
||||
screen:expect([[
|
||||
tty ready |
|
||||
line1 |
|
||||
line2 |
|
||||
line3 |
|
||||
line4 |
|
||||
{1: } |
|
||||
-- TERMINAL -- |
|
||||
]])
|
||||
end)
|
||||
|
||||
describe('and 1 line is printed', function()
|
||||
before_each(function() feed_data({'line5', ''}) end)
|
||||
|
||||
it('will hide the top line', function()
|
||||
screen:expect([[
|
||||
line1 |
|
||||
line2 |
|
||||
line3 |
|
||||
line4 |
|
||||
line5 |
|
||||
{1: } |
|
||||
-- TERMINAL -- |
|
||||
]])
|
||||
eq(7, curbuf('line_count'))
|
||||
end)
|
||||
|
||||
describe('and then 3 more lines are printed', function()
|
||||
before_each(function() feed_data({'line6', 'line7', 'line8'}) end)
|
||||
|
||||
it('will hide the top 4 lines', function()
|
||||
screen:expect([[
|
||||
line3 |
|
||||
line4 |
|
||||
line5 |
|
||||
line6 |
|
||||
line7 |
|
||||
line8{1: } |
|
||||
-- TERMINAL -- |
|
||||
]])
|
||||
|
||||
feed('<c-\\><c-n>6k')
|
||||
screen:expect([[
|
||||
^line2 |
|
||||
line3 |
|
||||
line4 |
|
||||
line5 |
|
||||
line6 |
|
||||
line7 |
|
||||
|
|
||||
]])
|
||||
|
||||
feed('gg')
|
||||
screen:expect([[
|
||||
^tty ready |
|
||||
line1 |
|
||||
line2 |
|
||||
line3 |
|
||||
line4 |
|
||||
line5 |
|
||||
|
|
||||
]])
|
||||
|
||||
feed('G')
|
||||
screen:expect([[
|
||||
line3 |
|
||||
line4 |
|
||||
line5 |
|
||||
line6 |
|
||||
line7 |
|
||||
^line8{2: } |
|
||||
|
|
||||
]])
|
||||
end)
|
||||
end)
|
||||
end)
|
||||
|
||||
|
||||
describe('and the height is decreased by 1', function()
|
||||
local function will_hide_top_line()
|
||||
screen:try_resize(screen._width, screen._height - 1)
|
||||
screen:expect([[
|
||||
line2 |
|
||||
line3 |
|
||||
line4 |
|
||||
rows: 5, cols: 50 |
|
||||
{1: } |
|
||||
-- TERMINAL -- |
|
||||
]])
|
||||
end
|
||||
|
||||
it('will hide top line', will_hide_top_line)
|
||||
|
||||
describe('and then decreased by 2', function()
|
||||
before_each(function()
|
||||
will_hide_top_line()
|
||||
screen:try_resize(screen._width, screen._height - 2)
|
||||
end)
|
||||
|
||||
it('will hide the top 3 lines', function()
|
||||
screen:expect([[
|
||||
rows: 5, cols: 50 |
|
||||
rows: 3, cols: 50 |
|
||||
{1: } |
|
||||
-- TERMINAL -- |
|
||||
]])
|
||||
eq(8, curbuf('line_count'))
|
||||
feed('<c-\\><c-n>3k')
|
||||
screen:expect([[
|
||||
^line4 |
|
||||
rows: 5, cols: 50 |
|
||||
rows: 3, cols: 50 |
|
||||
|
|
||||
]])
|
||||
end)
|
||||
end)
|
||||
end)
|
||||
end)
|
||||
|
||||
describe('with empty lines after the cursor', function()
|
||||
describe('and the height is decreased by 2', function()
|
||||
before_each(function()
|
||||
screen:try_resize(screen._width, screen._height - 2)
|
||||
end)
|
||||
|
||||
local function will_delete_last_two_lines()
|
||||
screen:expect([[
|
||||
tty ready |
|
||||
rows: 4, cols: 50 |
|
||||
{1: } |
|
||||
|
|
||||
-- TERMINAL -- |
|
||||
]])
|
||||
eq(4, curbuf('line_count'))
|
||||
end
|
||||
|
||||
it('will delete the last two empty lines', will_delete_last_two_lines)
|
||||
|
||||
describe('and then decreased by 1', function()
|
||||
before_each(function()
|
||||
will_delete_last_two_lines()
|
||||
screen:try_resize(screen._width, screen._height - 1)
|
||||
end)
|
||||
|
||||
it('will delete the last line and hide the first', function()
|
||||
screen:expect([[
|
||||
rows: 4, cols: 50 |
|
||||
rows: 3, cols: 50 |
|
||||
{1: } |
|
||||
-- TERMINAL -- |
|
||||
]])
|
||||
eq(4, curbuf('line_count'))
|
||||
feed('<c-\\><c-n>gg')
|
||||
screen:expect([[
|
||||
^tty ready |
|
||||
rows: 4, cols: 50 |
|
||||
rows: 3, cols: 50 |
|
||||
|
|
||||
]])
|
||||
feed('a')
|
||||
screen:expect([[
|
||||
rows: 4, cols: 50 |
|
||||
rows: 3, cols: 50 |
|
||||
{1: } |
|
||||
-- TERMINAL -- |
|
||||
]])
|
||||
end)
|
||||
end)
|
||||
end)
|
||||
end)
|
||||
|
||||
describe('with 4 lines hidden in the scrollback', function()
|
||||
before_each(function()
|
||||
feed_data({'line1', 'line2', 'line3', 'line4', ''})
|
||||
screen:expect([[
|
||||
tty ready |
|
||||
line1 |
|
||||
line2 |
|
||||
line3 |
|
||||
line4 |
|
||||
{1: } |
|
||||
-- TERMINAL -- |
|
||||
]])
|
||||
screen:try_resize(screen._width, screen._height - 3)
|
||||
screen:expect([[
|
||||
line4 |
|
||||
rows: 3, cols: 50 |
|
||||
{1: } |
|
||||
-- TERMINAL -- |
|
||||
]])
|
||||
eq(7, curbuf('line_count'))
|
||||
end)
|
||||
|
||||
describe('and the height is increased by 1', function()
|
||||
local function pop_then_push()
|
||||
screen:try_resize(screen._width, screen._height + 1)
|
||||
screen:expect([[
|
||||
line4 |
|
||||
rows: 3, cols: 50 |
|
||||
rows: 4, cols: 50 |
|
||||
{1: } |
|
||||
-- TERMINAL -- |
|
||||
]])
|
||||
end
|
||||
|
||||
it('will pop 1 line and then push it back', pop_then_push)
|
||||
|
||||
describe('and then by 3', function()
|
||||
before_each(function()
|
||||
pop_then_push()
|
||||
eq(8, curbuf('line_count'))
|
||||
screen:try_resize(screen._width, screen._height + 3)
|
||||
end)
|
||||
|
||||
local function pop3_then_push1()
|
||||
screen:expect([[
|
||||
line2 |
|
||||
line3 |
|
||||
line4 |
|
||||
rows: 3, cols: 50 |
|
||||
rows: 4, cols: 50 |
|
||||
rows: 7, cols: 50 |
|
||||
{1: } |
|
||||
-- TERMINAL -- |
|
||||
]])
|
||||
eq(9, curbuf('line_count'))
|
||||
feed('<c-\\><c-n>gg')
|
||||
screen:expect([[
|
||||
^tty ready |
|
||||
line1 |
|
||||
line2 |
|
||||
line3 |
|
||||
line4 |
|
||||
rows: 3, cols: 50 |
|
||||
rows: 4, cols: 50 |
|
||||
|
|
||||
]])
|
||||
end
|
||||
|
||||
it('will pop 3 lines and then push one back', pop3_then_push1)
|
||||
|
||||
describe('and then by 4', function()
|
||||
before_each(function()
|
||||
pop3_then_push1()
|
||||
feed('Gi')
|
||||
screen:try_resize(screen._width, screen._height + 4)
|
||||
end)
|
||||
|
||||
it('will show all lines and leave a blank one at the end', function()
|
||||
screen:expect([[
|
||||
tty ready |
|
||||
line1 |
|
||||
line2 |
|
||||
line3 |
|
||||
line4 |
|
||||
rows: 3, cols: 50 |
|
||||
rows: 4, cols: 50 |
|
||||
rows: 7, cols: 50 |
|
||||
rows: 11, cols: 50 |
|
||||
{1: } |
|
||||
|
|
||||
-- TERMINAL -- |
|
||||
]])
|
||||
-- since there's an empty line after the cursor, the buffer line
|
||||
-- count equals the terminal screen height
|
||||
eq(11, curbuf('line_count'))
|
||||
end)
|
||||
end)
|
||||
end)
|
||||
end)
|
||||
end)
|
||||
end)
|
||||
|
||||
describe('terminal prints more lines than the screen height and exits', function()
|
||||
it('will push extra lines to scrollback', function()
|
||||
clear()
|
||||
local screen = Screen.new(50, 7)
|
||||
screen:attach(false)
|
||||
execute('term ' ..nvim_dir.. '/tty-test 10')
|
||||
wait()
|
||||
screen:expect([[
|
||||
line6 |
|
||||
line7 |
|
||||
line8 |
|
||||
line9 |
|
||||
|
|
||||
[Program exited, press any key to close] |
|
||||
-- TERMINAL -- |
|
||||
]])
|
||||
end)
|
||||
end)
|
||||
|
64
test/functional/terminal/window_spec.lua
Normal file
64
test/functional/terminal/window_spec.lua
Normal file
@ -0,0 +1,64 @@
|
||||
local helpers = require('test.functional.helpers')
|
||||
local thelpers = require('test.functional.terminal.helpers')
|
||||
local feed, clear, nvim = helpers.feed, helpers.clear, helpers.nvim
|
||||
local wait, eq = helpers.wait, helpers.eq
|
||||
|
||||
|
||||
describe('terminal window', function()
|
||||
local screen
|
||||
|
||||
before_each(function()
|
||||
clear()
|
||||
screen = thelpers.screen_setup()
|
||||
end)
|
||||
|
||||
describe('with colorcolumn set', function()
|
||||
before_each(function()
|
||||
feed('<c-\\><c-n>:set colorcolumn=20<cr>i')
|
||||
wait()
|
||||
end)
|
||||
|
||||
it('wont show the color column', function()
|
||||
screen:expect([[
|
||||
tty ready |
|
||||
{1: } |
|
||||
|
|
||||
|
|
||||
|
|
||||
|
|
||||
-- TERMINAL -- |
|
||||
]])
|
||||
end)
|
||||
end)
|
||||
|
||||
describe('with fold set', function()
|
||||
before_each(function()
|
||||
feed('<c-\\><c-n>:set foldenable foldmethod=manual<cr>i')
|
||||
thelpers.feed_data({'line1', 'line2', 'line3', 'line4', ''})
|
||||
screen:expect([[
|
||||
tty ready |
|
||||
line1 |
|
||||
line2 |
|
||||
line3 |
|
||||
line4 |
|
||||
{1: } |
|
||||
-- TERMINAL -- |
|
||||
]])
|
||||
end)
|
||||
|
||||
it('wont show any folds', function()
|
||||
feed('<c-\\><c-n>ggvGzf')
|
||||
wait()
|
||||
screen:expect([[
|
||||
^tty ready |
|
||||
line1 |
|
||||
line2 |
|
||||
line3 |
|
||||
line4 |
|
||||
{2: } |
|
||||
|
|
||||
]])
|
||||
end)
|
||||
end)
|
||||
end)
|
||||
|
138
test/functional/terminal/window_split_tab_spec.lua
Normal file
138
test/functional/terminal/window_split_tab_spec.lua
Normal file
@ -0,0 +1,138 @@
|
||||
local helpers = require('test.functional.helpers')
|
||||
local thelpers = require('test.functional.terminal.helpers')
|
||||
local clear, eq, curbuf = helpers.clear, helpers.eq, helpers.curbuf
|
||||
local feed, nvim = helpers.feed, helpers.nvim
|
||||
local feed_data = thelpers.feed_data
|
||||
|
||||
describe('terminal', function()
|
||||
local screen
|
||||
|
||||
before_each(function()
|
||||
clear()
|
||||
-- set the statusline to a constant value because of variables like pid
|
||||
-- and current directory and to improve visibility of splits
|
||||
nvim('set_option', 'statusline', '==========')
|
||||
nvim('command', 'highlight StatusLine cterm=NONE')
|
||||
nvim('command', 'highlight StatusLineNC cterm=NONE')
|
||||
nvim('command', 'highlight VertSplit cterm=NONE')
|
||||
screen = thelpers.screen_setup(3)
|
||||
end)
|
||||
|
||||
after_each(function()
|
||||
screen:detach()
|
||||
end)
|
||||
|
||||
describe('when the screen is resized', function()
|
||||
it('will forward a resize request to the program', function()
|
||||
screen:try_resize(screen._width + 3, screen._height + 5)
|
||||
screen:expect([[
|
||||
tty ready |
|
||||
rows: 14, cols: 53 |
|
||||
{1: } |
|
||||
|
|
||||
|
|
||||
|
|
||||
|
|
||||
|
|
||||
|
|
||||
|
|
||||
|
|
||||
|
|
||||
|
|
||||
|
|
||||
-- TERMINAL -- |
|
||||
]])
|
||||
screen:try_resize(screen._width - 6, screen._height - 10)
|
||||
screen:expect([[
|
||||
tty ready |
|
||||
rows: 14, cols: 53 |
|
||||
rows: 4, cols: 47 |
|
||||
{1: } |
|
||||
-- TERMINAL -- |
|
||||
]])
|
||||
end)
|
||||
end)
|
||||
|
||||
describe('split horizontally', function()
|
||||
before_each(function()
|
||||
nvim('command', 'sp')
|
||||
end)
|
||||
|
||||
local function reduce_height()
|
||||
screen:expect([[
|
||||
tty ready |
|
||||
rows: 3, cols: 50 |
|
||||
{1: } |
|
||||
~ |
|
||||
========== |
|
||||
tty ready |
|
||||
rows: 3, cols: 50 |
|
||||
{2: } |
|
||||
========== |
|
||||
-- TERMINAL -- |
|
||||
]])
|
||||
end
|
||||
|
||||
it('uses the minimum height of all window displaying it', reduce_height)
|
||||
|
||||
describe('and then vertically', function()
|
||||
before_each(function()
|
||||
reduce_height()
|
||||
nvim('command', 'vsp')
|
||||
end)
|
||||
|
||||
local function reduce_width()
|
||||
screen:expect([[
|
||||
rows: 3, cols: 50 |rows: 3, cols: 50 |
|
||||
rows: 3, cols: 24 |rows: 3, cols: 24 |
|
||||
{1: } |{2: } |
|
||||
~ |~ |
|
||||
========== ========== |
|
||||
rows: 3, cols: 50 |
|
||||
rows: 3, cols: 24 |
|
||||
{2: } |
|
||||
========== |
|
||||
-- TERMINAL -- |
|
||||
]])
|
||||
feed('<c-\\><c-n>gg')
|
||||
screen:expect([[
|
||||
^tty ready |rows: 3, cols: 50 |
|
||||
rows: 3, cols: 50 |rows: 3, cols: 24 |
|
||||
rows: 3, cols: 24 |{2: } |
|
||||
{2: } |~ |
|
||||
========== ========== |
|
||||
rows: 3, cols: 50 |
|
||||
rows: 3, cols: 24 |
|
||||
{2: } |
|
||||
========== |
|
||||
|
|
||||
]])
|
||||
end
|
||||
|
||||
it('uses the minimum width of all window displaying it', reduce_width)
|
||||
|
||||
describe('and then closes one of the vertical splits with q:', function()
|
||||
before_each(function()
|
||||
reduce_width()
|
||||
nvim('command', 'q')
|
||||
feed('<c-w>ja')
|
||||
end)
|
||||
|
||||
it('will restore the width', function()
|
||||
screen:expect([[
|
||||
rows: 3, cols: 24 |
|
||||
rows: 3, cols: 50 |
|
||||
{2: } |
|
||||
~ |
|
||||
========== |
|
||||
rows: 3, cols: 24 |
|
||||
rows: 3, cols: 50 |
|
||||
{1: } |
|
||||
========== |
|
||||
-- TERMINAL -- |
|
||||
]])
|
||||
end)
|
||||
end)
|
||||
end)
|
||||
end)
|
||||
end)
|
@ -190,8 +190,11 @@ function Screen:set_default_attr_ignore(attr_ignore)
|
||||
self._default_attr_ignore = attr_ignore
|
||||
end
|
||||
|
||||
function Screen:attach()
|
||||
request('ui_attach', self._width, self._height, true)
|
||||
function Screen:attach(rgb)
|
||||
if rgb == nil then
|
||||
rgb = true
|
||||
end
|
||||
request('ui_attach', self._width, self._height, rgb)
|
||||
end
|
||||
|
||||
function Screen:detach()
|
||||
@ -500,6 +503,7 @@ function Screen:snapshot_util(attrs, ignore)
|
||||
else
|
||||
print( "]], "..attrstr..")\n")
|
||||
end
|
||||
io.stdout:flush()
|
||||
end
|
||||
|
||||
function pprint_attrs(attrs)
|
||||
|
Loading…
Reference in New Issue
Block a user