mirror of
https://github.com/neovim/neovim.git
synced 2025-09-18 01:08:20 +00:00
startup: stdin as text instead of commands
Treat stdin as text by default (so the "-" file is not needed): echo foo | nvim It works with file args (implemented in next commit), too: echo foo | nvim file1.txt file2.txt Why? Because: - Execution of input is (1) almost always unintentional/confusing, and (2) potentially destructive. - Avoids the need for time-delayed warning. #7659 - The _common_ case is to open text in a buffer, not send commands. Note: - Not for Ex-mode (-es) because it is used by scripts. But maybe `-Es`? - Not for --headless, because stdio may be a protocol stream and may be used for any purpose by stdioopen(). To treat stdin as Normal-mode commands, use `-s -` instead: echo ifoo | nvim -s - Other alternatives: - Replay a register. E.g. the following mostly works, except @q aborts on any "beep" (e.g. if the cursor can't move). nvim -c '%d q|norm @q' - - Future: Let `:%source` work with unsaved buffer contents? closes #2087 closes #7659
This commit is contained in:
@@ -281,12 +281,6 @@ int main(int argc, char **argv)
|
|||||||
|
|
||||||
full_screen = true;
|
full_screen = true;
|
||||||
|
|
||||||
// When starting in Ex mode and commands come from a file, set Silent mode.
|
|
||||||
// is active input a terminal?
|
|
||||||
if (!headless_mode && exmode_active && !params.input_isatty) {
|
|
||||||
silent_mode = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Set the default values for the options that use Rows and Columns.
|
* Set the default values for the options that use Rows and Columns.
|
||||||
*/
|
*/
|
||||||
@@ -1097,7 +1091,7 @@ scripterror:
|
|||||||
mch_exit(2);
|
mch_exit(2);
|
||||||
}
|
}
|
||||||
int error;
|
int error;
|
||||||
if (STRCMP(argv[0], "-") == 0) {
|
if (strequal(argv[0], "-")) {
|
||||||
const int stdin_dup_fd = os_dup(STDIN_FILENO);
|
const int stdin_dup_fd = os_dup(STDIN_FILENO);
|
||||||
#ifdef WIN32
|
#ifdef WIN32
|
||||||
// On Windows, replace the original stdin with the
|
// On Windows, replace the original stdin with the
|
||||||
@@ -1212,6 +1206,21 @@ scripterror:
|
|||||||
set_vim_var_string(VV_SWAPCOMMAND, swcmd, -1);
|
set_vim_var_string(VV_SWAPCOMMAND, swcmd, -1);
|
||||||
xfree(swcmd);
|
xfree(swcmd);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Handle "foo | nvim". #6299
|
||||||
|
if (!headless_mode
|
||||||
|
&& !embedded_mode
|
||||||
|
&& !parmp->input_isatty
|
||||||
|
&& !exmode_active // `-es` was not given.
|
||||||
|
&& scriptin[0] == NULL // `-s -` was not given.
|
||||||
|
) {
|
||||||
|
if (parmp->edit_type == EDIT_NONE) {
|
||||||
|
parmp->edit_type = EDIT_STDIN;
|
||||||
|
} else if (parmp->edit_type != EDIT_STDIN) {
|
||||||
|
mainerr(err_too_many_args, "stdin");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
TIME_MSG("parsing arguments");
|
TIME_MSG("parsing arguments");
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1884,7 +1893,6 @@ static void usage(void)
|
|||||||
|
|
||||||
mch_msg(_("Usage:\n"));
|
mch_msg(_("Usage:\n"));
|
||||||
mch_msg(_(" nvim [options] [file ...] Edit file(s)\n"));
|
mch_msg(_(" nvim [options] [file ...] Edit file(s)\n"));
|
||||||
mch_msg(_(" nvim [options] - Read text from stdin\n"));
|
|
||||||
mch_msg(_(" nvim [options] -t <tag> Edit file where tag is defined\n"));
|
mch_msg(_(" nvim [options] -t <tag> Edit file where tag is defined\n"));
|
||||||
mch_msg(_(" nvim [options] -q [errorfile] Edit file with first error\n"));
|
mch_msg(_(" nvim [options] -q [errorfile] Edit file with first error\n"));
|
||||||
mch_msg(_("\nOptions:\n"));
|
mch_msg(_("\nOptions:\n"));
|
||||||
@@ -1918,7 +1926,7 @@ static void usage(void)
|
|||||||
mch_msg(_(" --api-info Write msgpack-encoded API metadata to stdout\n"));
|
mch_msg(_(" --api-info Write msgpack-encoded API metadata to stdout\n"));
|
||||||
mch_msg(_(" --embed Use stdin/stdout as a msgpack-rpc channel\n"));
|
mch_msg(_(" --embed Use stdin/stdout as a msgpack-rpc channel\n"));
|
||||||
mch_msg(_(" --headless Don't start a user interface\n"));
|
mch_msg(_(" --headless Don't start a user interface\n"));
|
||||||
mch_msg(_(" --listen <address> Start RPC server at this address\n"));
|
mch_msg(_(" --listen <address> Serve RPC API from this address\n"));
|
||||||
#if !defined(UNIX)
|
#if !defined(UNIX)
|
||||||
mch_msg(_(" --literal Don't expand wildcards\n"));
|
mch_msg(_(" --literal Don't expand wildcards\n"));
|
||||||
#endif
|
#endif
|
||||||
|
@@ -9,11 +9,13 @@ local nvim_prog = helpers.nvim_prog
|
|||||||
local nvim_set = helpers.nvim_set
|
local nvim_set = helpers.nvim_set
|
||||||
local read_file = helpers.read_file
|
local read_file = helpers.read_file
|
||||||
local retry = helpers.retry
|
local retry = helpers.retry
|
||||||
|
local sleep = helpers.sleep
|
||||||
local iswin = helpers.iswin
|
local iswin = helpers.iswin
|
||||||
|
|
||||||
describe('startup', function()
|
describe('startup', function()
|
||||||
before_each(function()
|
before_each(function()
|
||||||
clear()
|
clear()
|
||||||
|
os.remove('Xtest_startup_ttyout')
|
||||||
end)
|
end)
|
||||||
after_each(function()
|
after_each(function()
|
||||||
os.remove('Xtest_startup_ttyout')
|
os.remove('Xtest_startup_ttyout')
|
||||||
@@ -46,8 +48,8 @@ describe('startup', function()
|
|||||||
end
|
end
|
||||||
-- Running in :terminal
|
-- Running in :terminal
|
||||||
command([[exe printf("terminal %s -u NONE -i NONE --cmd \"]]
|
command([[exe printf("terminal %s -u NONE -i NONE --cmd \"]]
|
||||||
..nvim_set..[[\" ]]
|
..nvim_set..[[\"]]
|
||||||
..[[-c \"echo has('ttyin') has('ttyout')\""]]
|
..[[ -c \"echo has('ttyin') has('ttyout')\""]]
|
||||||
..[[, shellescape(v:progpath))]])
|
..[[, shellescape(v:progpath))]])
|
||||||
screen:expect([[
|
screen:expect([[
|
||||||
^ |
|
^ |
|
||||||
@@ -56,25 +58,40 @@ describe('startup', function()
|
|||||||
]])
|
]])
|
||||||
end)
|
end)
|
||||||
it('output to pipe: has("ttyin")==1 has("ttyout")==0', function()
|
it('output to pipe: has("ttyin")==1 has("ttyout")==0', function()
|
||||||
local screen = Screen.new(25, 5)
|
|
||||||
screen:attach()
|
|
||||||
if iswin() then
|
if iswin() then
|
||||||
command([[set shellcmdflag=/s\ /c shellxquote=\"]])
|
command([[set shellcmdflag=/s\ /c shellxquote=\"]])
|
||||||
end
|
end
|
||||||
-- Running in :terminal
|
-- Running in :terminal
|
||||||
command([[exe printf("terminal %s -u NONE -i NONE --cmd \"]]
|
command([[exe printf("terminal %s -u NONE -i NONE --cmd \"]]
|
||||||
..nvim_set..[[\" ]]
|
..nvim_set..[[\"]]
|
||||||
..[[-c \"call writefile([has('ttyin'), has('ttyout')], 'Xtest_startup_ttyout')\"]]
|
..[[ -c \"call writefile([has('ttyin'), has('ttyout')], 'Xtest_startup_ttyout')\"]]
|
||||||
..[[-c q | cat -v"]] -- Output to a pipe.
|
..[[ -c q | cat -v"]] -- Output to a pipe.
|
||||||
..[[, shellescape(v:progpath))]])
|
..[[, shellescape(v:progpath))]])
|
||||||
retry(nil, 3000, function()
|
retry(nil, 3000, function()
|
||||||
screen:sleep(1)
|
sleep(1)
|
||||||
eq('1\n0\n', -- stdin is a TTY, stdout is a pipe
|
eq('1\n0\n', -- stdin is a TTY, stdout is a pipe
|
||||||
read_file('Xtest_startup_ttyout'))
|
read_file('Xtest_startup_ttyout'))
|
||||||
end)
|
end)
|
||||||
end)
|
end)
|
||||||
it('input from pipe: has("ttyin")==0 has("ttyout")==1', function()
|
it('input from pipe: has("ttyin")==0 has("ttyout")==1', function()
|
||||||
local screen = Screen.new(25, 5)
|
if iswin() then
|
||||||
|
command([[set shellcmdflag=/s\ /c shellxquote=\"]])
|
||||||
|
end
|
||||||
|
-- Running in :terminal
|
||||||
|
command([[exe printf("terminal echo foo | ]] -- Input from a pipe.
|
||||||
|
..[[%s -u NONE -i NONE --cmd \"]]
|
||||||
|
..nvim_set..[[\"]]
|
||||||
|
..[[ -c \"call writefile([has('ttyin'), has('ttyout')], 'Xtest_startup_ttyout')\"]]
|
||||||
|
..[[ -c q -- -"]]
|
||||||
|
..[[, shellescape(v:progpath))]])
|
||||||
|
retry(nil, 3000, function()
|
||||||
|
sleep(1)
|
||||||
|
eq('0\n1\n', -- stdin is a pipe, stdout is a TTY
|
||||||
|
read_file('Xtest_startup_ttyout'))
|
||||||
|
end)
|
||||||
|
end)
|
||||||
|
it('input from pipe (implicit) #7679', function()
|
||||||
|
local screen = Screen.new(25, 3)
|
||||||
screen:attach()
|
screen:attach()
|
||||||
if iswin() then
|
if iswin() then
|
||||||
command([[set shellcmdflag=/s\ /c shellxquote=\"]])
|
command([[set shellcmdflag=/s\ /c shellxquote=\"]])
|
||||||
@@ -82,15 +99,34 @@ describe('startup', function()
|
|||||||
-- Running in :terminal
|
-- Running in :terminal
|
||||||
command([[exe printf("terminal echo foo | ]] -- Input from a pipe.
|
command([[exe printf("terminal echo foo | ]] -- Input from a pipe.
|
||||||
..[[%s -u NONE -i NONE --cmd \"]]
|
..[[%s -u NONE -i NONE --cmd \"]]
|
||||||
..nvim_set..[[\" ]]
|
..nvim_set..[[\"]]
|
||||||
..[[-c \"call writefile([has('ttyin'), has('ttyout')], 'Xtest_startup_ttyout')\"]]
|
..[[ -c \"echo has('ttyin') has('ttyout')\""]]
|
||||||
..[[-c q -- -"]]
|
|
||||||
..[[, shellescape(v:progpath))]])
|
..[[, shellescape(v:progpath))]])
|
||||||
retry(nil, 3000, function()
|
screen:expect([[
|
||||||
screen:sleep(1)
|
^foo |
|
||||||
eq('0\n1\n', -- stdin is a pipe, stdout is a TTY
|
0 1 |
|
||||||
read_file('Xtest_startup_ttyout'))
|
|
|
||||||
end)
|
]])
|
||||||
|
end)
|
||||||
|
it('input from pipe (implicit) + file args #7679', function()
|
||||||
|
local screen = Screen.new(25, 3)
|
||||||
|
screen:attach()
|
||||||
|
if iswin() then
|
||||||
|
command([[set shellcmdflag=/s\ /c shellxquote=\"]])
|
||||||
|
end
|
||||||
|
command([[exe "terminal echo ohyeah | "]] -- Input from a pipe.
|
||||||
|
..[[.shellescape(v:progpath)." -u NONE -i NONE --cmd \"]]
|
||||||
|
..nvim_set..[[\"]]
|
||||||
|
..[[ --cmd \"set shortmess+=I\"]]
|
||||||
|
..[[ -c \"echo has('ttyin') has('ttyout') 'bufs='.bufnr('$')\"]]
|
||||||
|
..[[ -- test/functional/fixtures/shell-test.c]]
|
||||||
|
..[[ test/functional/fixtures/tty-test.c]]
|
||||||
|
..[["]])
|
||||||
|
screen:expect([[
|
||||||
|
^ohyeah |
|
||||||
|
0 1 bufs=3 |
|
||||||
|
|
|
||||||
|
]])
|
||||||
end)
|
end)
|
||||||
end)
|
end)
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user