mirror of
https://github.com/neovim/neovim.git
synced 2025-09-06 03:18:16 +00:00
vim-patch:8.1.0815: dialog for file changed outside of Vim not tested (#28184)
Problem: Dialog for file changed outside of Vim not tested.
Solution: Add a test. Move FileChangedShell test. Add 'L' flag to
feedkeys().
5e66b42aae
Co-authored-by: Bram Moolenaar <Bram@vim.org>
This commit is contained in:
1
runtime/doc/builtin.txt
generated
1
runtime/doc/builtin.txt
generated
@@ -1588,6 +1588,7 @@ feedkeys({string} [, {mode}]) *feedkeys()*
|
|||||||
't' Handle keys as if typed; otherwise they are handled as
|
't' Handle keys as if typed; otherwise they are handled as
|
||||||
if coming from a mapping. This matters for undo,
|
if coming from a mapping. This matters for undo,
|
||||||
opening folds, etc.
|
opening folds, etc.
|
||||||
|
'L' Lowlevel input. Other flags are not used.
|
||||||
'i' Insert the string instead of appending (see above).
|
'i' Insert the string instead of appending (see above).
|
||||||
'x' Execute commands until typeahead is empty. This is
|
'x' Execute commands until typeahead is empty. This is
|
||||||
similar to using ":normal!". You can call feedkeys()
|
similar to using ":normal!". You can call feedkeys()
|
||||||
|
1
runtime/lua/vim/_meta/vimfn.lua
generated
1
runtime/lua/vim/_meta/vimfn.lua
generated
@@ -1959,6 +1959,7 @@ function vim.fn.extendnew(expr1, expr2, expr3) end
|
|||||||
--- 't' Handle keys as if typed; otherwise they are handled as
|
--- 't' Handle keys as if typed; otherwise they are handled as
|
||||||
--- if coming from a mapping. This matters for undo,
|
--- if coming from a mapping. This matters for undo,
|
||||||
--- opening folds, etc.
|
--- opening folds, etc.
|
||||||
|
--- 'L' Lowlevel input. Other flags are not used.
|
||||||
--- 'i' Insert the string instead of appending (see above).
|
--- 'i' Insert the string instead of appending (see above).
|
||||||
--- 'x' Execute commands until typeahead is empty. This is
|
--- 'x' Execute commands until typeahead is empty. This is
|
||||||
--- similar to using ":normal!". You can call feedkeys()
|
--- similar to using ":normal!". You can call feedkeys()
|
||||||
|
@@ -277,6 +277,7 @@ void nvim_feedkeys(String keys, String mode, Boolean escape_ks)
|
|||||||
bool typed = false;
|
bool typed = false;
|
||||||
bool execute = false;
|
bool execute = false;
|
||||||
bool dangerous = false;
|
bool dangerous = false;
|
||||||
|
bool lowlevel = false;
|
||||||
|
|
||||||
for (size_t i = 0; i < mode.size; i++) {
|
for (size_t i = 0; i < mode.size; i++) {
|
||||||
switch (mode.data[i]) {
|
switch (mode.data[i]) {
|
||||||
@@ -292,6 +293,8 @@ void nvim_feedkeys(String keys, String mode, Boolean escape_ks)
|
|||||||
execute = true; break;
|
execute = true; break;
|
||||||
case '!':
|
case '!':
|
||||||
dangerous = true; break;
|
dangerous = true; break;
|
||||||
|
case 'L':
|
||||||
|
lowlevel = true; break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -307,10 +310,14 @@ void nvim_feedkeys(String keys, String mode, Boolean escape_ks)
|
|||||||
} else {
|
} else {
|
||||||
keys_esc = keys.data;
|
keys_esc = keys.data;
|
||||||
}
|
}
|
||||||
ins_typebuf(keys_esc, (remap ? REMAP_YES : REMAP_NONE),
|
if (lowlevel) {
|
||||||
insert ? 0 : typebuf.tb_len, !typed, false);
|
input_enqueue_raw(cstr_as_string(keys_esc));
|
||||||
if (vgetc_busy) {
|
} else {
|
||||||
typebuf_was_filled = true;
|
ins_typebuf(keys_esc, (remap ? REMAP_YES : REMAP_NONE),
|
||||||
|
insert ? 0 : typebuf.tb_len, !typed, false);
|
||||||
|
if (vgetc_busy) {
|
||||||
|
typebuf_was_filled = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (escape_ks) {
|
if (escape_ks) {
|
||||||
|
@@ -2481,6 +2481,7 @@ M.funcs = {
|
|||||||
't' Handle keys as if typed; otherwise they are handled as
|
't' Handle keys as if typed; otherwise they are handled as
|
||||||
if coming from a mapping. This matters for undo,
|
if coming from a mapping. This matters for undo,
|
||||||
opening folds, etc.
|
opening folds, etc.
|
||||||
|
'L' Lowlevel input. Other flags are not used.
|
||||||
'i' Insert the string instead of appending (see above).
|
'i' Insert the string instead of appending (see above).
|
||||||
'x' Execute commands until typeahead is empty. This is
|
'x' Execute commands until typeahead is empty. This is
|
||||||
similar to using ":normal!". You can call feedkeys()
|
similar to using ":normal!". You can call feedkeys()
|
||||||
|
@@ -3395,9 +3395,7 @@ int do_dialog(int type, const char *title, const char *message, const char *butt
|
|||||||
int retval = 0;
|
int retval = 0;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
if (silent_mode // No dialogs in silent mode ("ex -s")
|
if (silent_mode) { // No dialogs in silent mode ("ex -s")
|
||||||
|| !ui_active() // Without a UI Nvim waits for input forever.
|
|
||||||
) {
|
|
||||||
return dfltbutton; // return default option
|
return dfltbutton; // return default option
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -3414,6 +3412,12 @@ int do_dialog(int type, const char *title, const char *message, const char *butt
|
|||||||
char *hotkeys = msg_show_console_dialog(message, buttons, dfltbutton);
|
char *hotkeys = msg_show_console_dialog(message, buttons, dfltbutton);
|
||||||
|
|
||||||
while (true) {
|
while (true) {
|
||||||
|
// Without a UI Nvim waits for input forever.
|
||||||
|
if (!ui_active() && !input_available()) {
|
||||||
|
retval = dfltbutton;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
// Get a typed character directly from the user.
|
// Get a typed character directly from the user.
|
||||||
int c = get_keystroke(NULL);
|
int c = get_keystroke(NULL);
|
||||||
switch (c) {
|
switch (c) {
|
||||||
|
@@ -247,6 +247,13 @@ bool os_isatty(int fd)
|
|||||||
return uv_guess_handle(fd) == UV_TTY;
|
return uv_guess_handle(fd) == UV_TTY;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void input_enqueue_raw(String keys)
|
||||||
|
{
|
||||||
|
if (keys.size > 0) {
|
||||||
|
rbuffer_write(input_buffer, keys.data, keys.size);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
size_t input_enqueue(String keys)
|
size_t input_enqueue(String keys)
|
||||||
{
|
{
|
||||||
const char *ptr = keys.data;
|
const char *ptr = keys.data;
|
||||||
|
@@ -1,59 +0,0 @@
|
|||||||
local helpers = require('test.functional.helpers')(after_each)
|
|
||||||
local clear, source = helpers.clear, helpers.source
|
|
||||||
local call, eq, api = helpers.call, helpers.eq, helpers.api
|
|
||||||
|
|
||||||
local function expected_empty()
|
|
||||||
eq({}, api.nvim_get_vvar('errors'))
|
|
||||||
end
|
|
||||||
|
|
||||||
describe('buffer', function()
|
|
||||||
before_each(function()
|
|
||||||
clear()
|
|
||||||
api.nvim_ui_attach(80, 24, {})
|
|
||||||
api.nvim_set_option_value('hidden', false, {})
|
|
||||||
end)
|
|
||||||
|
|
||||||
it('deleting a modified buffer with :confirm', function()
|
|
||||||
source([[
|
|
||||||
func Test_bdel_with_confirm()
|
|
||||||
new
|
|
||||||
call setline(1, 'test')
|
|
||||||
call assert_fails('bdel', 'E89:')
|
|
||||||
call nvim_input('c')
|
|
||||||
confirm bdel
|
|
||||||
call assert_equal(2, winnr('$'))
|
|
||||||
call assert_equal(1, &modified)
|
|
||||||
call nvim_input('n')
|
|
||||||
confirm bdel
|
|
||||||
call assert_equal(1, winnr('$'))
|
|
||||||
endfunc
|
|
||||||
]])
|
|
||||||
call('Test_bdel_with_confirm')
|
|
||||||
expected_empty()
|
|
||||||
end)
|
|
||||||
|
|
||||||
it('editing another buffer from a modified buffer with :confirm', function()
|
|
||||||
source([[
|
|
||||||
func Test_goto_buf_with_confirm()
|
|
||||||
new Xfile
|
|
||||||
enew
|
|
||||||
call setline(1, 'test')
|
|
||||||
call assert_fails('b Xfile', 'E37:')
|
|
||||||
call nvim_input('c')
|
|
||||||
call assert_fails('confirm b Xfile', 'E37:')
|
|
||||||
call assert_equal(1, &modified)
|
|
||||||
call assert_equal('', @%)
|
|
||||||
call nvim_input('y')
|
|
||||||
call assert_fails('confirm b Xfile', 'E37:')
|
|
||||||
call assert_equal(1, &modified)
|
|
||||||
call assert_equal('', @%)
|
|
||||||
call nvim_input('n')
|
|
||||||
confirm b Xfile
|
|
||||||
call assert_equal('Xfile', @%)
|
|
||||||
close!
|
|
||||||
endfunc
|
|
||||||
]])
|
|
||||||
call('Test_goto_buf_with_confirm')
|
|
||||||
expected_empty()
|
|
||||||
end)
|
|
||||||
end)
|
|
@@ -1,142 +0,0 @@
|
|||||||
local helpers = require('test.functional.helpers')(after_each)
|
|
||||||
local clear, source = helpers.clear, helpers.source
|
|
||||||
local call, eq, api = helpers.call, helpers.eq, helpers.api
|
|
||||||
local is_os = helpers.is_os
|
|
||||||
local skip = helpers.skip
|
|
||||||
|
|
||||||
local function expected_empty()
|
|
||||||
eq({}, api.nvim_get_vvar('errors'))
|
|
||||||
end
|
|
||||||
|
|
||||||
describe('file changed dialog', function()
|
|
||||||
before_each(function()
|
|
||||||
clear()
|
|
||||||
api.nvim_ui_attach(80, 24, {})
|
|
||||||
api.nvim_set_option_value('autoread', false, {})
|
|
||||||
api.nvim_set_option_value('fsync', true, {})
|
|
||||||
end)
|
|
||||||
|
|
||||||
it('works', function()
|
|
||||||
skip(is_os('win'))
|
|
||||||
source([[
|
|
||||||
func Test_file_changed_dialog()
|
|
||||||
au! FileChangedShell
|
|
||||||
|
|
||||||
new Xchanged_d
|
|
||||||
call setline(1, 'reload this')
|
|
||||||
write
|
|
||||||
" Need to wait until the timestamp would change by at least a second.
|
|
||||||
sleep 2
|
|
||||||
silent !echo 'extra line' >>Xchanged_d
|
|
||||||
call nvim_input('L')
|
|
||||||
checktime
|
|
||||||
call assert_match('W11:', v:warningmsg)
|
|
||||||
call assert_equal(2, line('$'))
|
|
||||||
call assert_equal('reload this', getline(1))
|
|
||||||
call assert_equal('extra line', getline(2))
|
|
||||||
|
|
||||||
" delete buffer, only shows an error, no prompt
|
|
||||||
silent !rm Xchanged_d
|
|
||||||
checktime
|
|
||||||
call assert_match('E211:', v:warningmsg)
|
|
||||||
call assert_equal(2, line('$'))
|
|
||||||
call assert_equal('extra line', getline(2))
|
|
||||||
let v:warningmsg = 'empty'
|
|
||||||
|
|
||||||
" change buffer, recreate the file and reload
|
|
||||||
call setline(1, 'buffer is changed')
|
|
||||||
silent !echo 'new line' >Xchanged_d
|
|
||||||
call nvim_input('L')
|
|
||||||
checktime
|
|
||||||
call assert_match('W12:', v:warningmsg)
|
|
||||||
call assert_equal(1, line('$'))
|
|
||||||
call assert_equal('new line', getline(1))
|
|
||||||
|
|
||||||
" Only mode changed, reload
|
|
||||||
silent !chmod +x Xchanged_d
|
|
||||||
call nvim_input('L')
|
|
||||||
checktime
|
|
||||||
call assert_match('W16:', v:warningmsg)
|
|
||||||
call assert_equal(1, line('$'))
|
|
||||||
call assert_equal('new line', getline(1))
|
|
||||||
|
|
||||||
" Only time changed, no prompt
|
|
||||||
sleep 2
|
|
||||||
silent !touch Xchanged_d
|
|
||||||
let v:warningmsg = ''
|
|
||||||
checktime Xchanged_d
|
|
||||||
call assert_equal('', v:warningmsg)
|
|
||||||
call assert_equal(1, line('$'))
|
|
||||||
call assert_equal('new line', getline(1))
|
|
||||||
|
|
||||||
" File created after starting to edit it
|
|
||||||
call delete('Xchanged_d')
|
|
||||||
new Xchanged_d
|
|
||||||
call writefile(['one'], 'Xchanged_d')
|
|
||||||
call nvim_input('L')
|
|
||||||
checktime Xchanged_d
|
|
||||||
call assert_equal(['one'], getline(1, '$'))
|
|
||||||
close!
|
|
||||||
|
|
||||||
bwipe!
|
|
||||||
call delete('Xchanged_d')
|
|
||||||
endfunc
|
|
||||||
]])
|
|
||||||
call('Test_file_changed_dialog')
|
|
||||||
expected_empty()
|
|
||||||
end)
|
|
||||||
|
|
||||||
it('works with FileChangedShell', function()
|
|
||||||
source([[
|
|
||||||
func Test_FileChangedShell_edit_dialog()
|
|
||||||
new Xchanged_r
|
|
||||||
call setline(1, 'reload this')
|
|
||||||
set fileformat=unix
|
|
||||||
silent write " Use :silent to prevent a hit-enter prompt
|
|
||||||
|
|
||||||
" File format changed, reload (content only) via prompt
|
|
||||||
augroup testreload
|
|
||||||
au!
|
|
||||||
au FileChangedShell Xchanged_r let g:reason = v:fcs_reason | let v:fcs_choice = 'ask'
|
|
||||||
augroup END
|
|
||||||
call assert_equal(&fileformat, 'unix')
|
|
||||||
sleep 10m " make the test less flaky in Nvim
|
|
||||||
call writefile(["line1\r", "line2\r"], 'Xchanged_r')
|
|
||||||
let g:reason = ''
|
|
||||||
call nvim_input('L') " load file content only
|
|
||||||
checktime
|
|
||||||
call assert_equal('changed', g:reason)
|
|
||||||
call assert_equal(&fileformat, 'unix')
|
|
||||||
call assert_equal("line1\r", getline(1))
|
|
||||||
call assert_equal("line2\r", getline(2))
|
|
||||||
%s/\r
|
|
||||||
silent write " Use :silent to prevent a hit-enter prompt
|
|
||||||
|
|
||||||
" File format changed, reload (file and options) via prompt
|
|
||||||
augroup testreload
|
|
||||||
au!
|
|
||||||
au FileChangedShell Xchanged_r let g:reason = v:fcs_reason | let v:fcs_choice = 'ask'
|
|
||||||
augroup END
|
|
||||||
call assert_equal(&fileformat, 'unix')
|
|
||||||
sleep 10m " make the test less flaky in Nvim
|
|
||||||
call writefile(["line1\r", "line2\r"], 'Xchanged_r')
|
|
||||||
let g:reason = ''
|
|
||||||
call nvim_input('a') " load file content and options
|
|
||||||
checktime
|
|
||||||
call assert_equal('changed', g:reason)
|
|
||||||
call assert_equal(&fileformat, 'dos')
|
|
||||||
call assert_equal("line1", getline(1))
|
|
||||||
call assert_equal("line2", getline(2))
|
|
||||||
set fileformat=unix
|
|
||||||
silent write " Use :silent to prevent a hit-enter prompt
|
|
||||||
|
|
||||||
au! testreload
|
|
||||||
bwipe!
|
|
||||||
call delete(undofile('Xchanged_r'))
|
|
||||||
call delete('Xchanged_r')
|
|
||||||
endfunc
|
|
||||||
]])
|
|
||||||
call('Test_FileChangedShell_edit_dialog')
|
|
||||||
expected_empty()
|
|
||||||
end)
|
|
||||||
end)
|
|
@@ -8,7 +8,6 @@ local clear = helpers.clear
|
|||||||
local source = helpers.source
|
local source = helpers.source
|
||||||
local command = helpers.command
|
local command = helpers.command
|
||||||
local exc_exec = helpers.exc_exec
|
local exc_exec = helpers.exc_exec
|
||||||
local pcall_err = helpers.pcall_err
|
|
||||||
local async_meths = helpers.async_meths
|
local async_meths = helpers.async_meths
|
||||||
local NIL = vim.NIL
|
local NIL = vim.NIL
|
||||||
|
|
||||||
@@ -407,7 +406,6 @@ describe('inputdialog()', function()
|
|||||||
end)
|
end)
|
||||||
|
|
||||||
describe('confirm()', function()
|
describe('confirm()', function()
|
||||||
-- oldtest: Test_confirm()
|
|
||||||
it('works', function()
|
it('works', function()
|
||||||
api.nvim_set_option_value('more', false, {}) -- Avoid hit-enter prompt
|
api.nvim_set_option_value('more', false, {}) -- Avoid hit-enter prompt
|
||||||
api.nvim_set_option_value('laststatus', 2, {})
|
api.nvim_set_option_value('laststatus', 2, {})
|
||||||
@@ -470,20 +468,6 @@ describe('confirm()', function()
|
|||||||
screen:expect({ any = '%[No Name%]' })
|
screen:expect({ any = '%[No Name%]' })
|
||||||
eq(1, api.nvim_get_var('a'))
|
eq(1, api.nvim_get_var('a'))
|
||||||
end
|
end
|
||||||
|
|
||||||
eq('Vim(call):E730: Using a List as a String', pcall_err(command, 'call confirm([])'))
|
|
||||||
eq(
|
|
||||||
'Vim(call):E730: Using a List as a String',
|
|
||||||
pcall_err(command, 'call confirm("Are you sure?", [])')
|
|
||||||
)
|
|
||||||
eq(
|
|
||||||
'Vim(call):E745: Using a List as a Number',
|
|
||||||
pcall_err(command, 'call confirm("Are you sure?", "&Yes\n&No\n", [])')
|
|
||||||
)
|
|
||||||
eq(
|
|
||||||
'Vim(call):E730: Using a List as a String',
|
|
||||||
pcall_err(command, 'call confirm("Are you sure?", "&Yes\n&No\n", 0, [])')
|
|
||||||
)
|
|
||||||
end)
|
end)
|
||||||
|
|
||||||
it('shows dialog even if :silent #8788', function()
|
it('shows dialog even if :silent #8788', function()
|
||||||
|
@@ -232,8 +232,6 @@ endfunc
|
|||||||
|
|
||||||
" Test for deleting a modified buffer with :confirm
|
" Test for deleting a modified buffer with :confirm
|
||||||
func Test_bdel_with_confirm()
|
func Test_bdel_with_confirm()
|
||||||
" requires a UI to be active
|
|
||||||
throw 'Skipped: use test/functional/legacy/buffer_spec.lua'
|
|
||||||
CheckUnix
|
CheckUnix
|
||||||
CheckNotGui
|
CheckNotGui
|
||||||
CheckFeature dialog_con
|
CheckFeature dialog_con
|
||||||
@@ -251,8 +249,6 @@ endfunc
|
|||||||
|
|
||||||
" Test for editing another buffer from a modified buffer with :confirm
|
" Test for editing another buffer from a modified buffer with :confirm
|
||||||
func Test_goto_buf_with_confirm()
|
func Test_goto_buf_with_confirm()
|
||||||
" requires a UI to be active
|
|
||||||
throw 'Skipped: use test/functional/legacy/buffer_spec.lua'
|
|
||||||
CheckUnix
|
CheckUnix
|
||||||
CheckNotGui
|
CheckNotGui
|
||||||
CheckFeature dialog_con
|
CheckFeature dialog_con
|
||||||
|
@@ -140,8 +140,6 @@ func Test_FileChangedShell_edit()
|
|||||||
endfunc
|
endfunc
|
||||||
|
|
||||||
func Test_FileChangedShell_edit_dialog()
|
func Test_FileChangedShell_edit_dialog()
|
||||||
" requires a UI to be active
|
|
||||||
throw 'Skipped: use test/functional/legacy/filechanged_spec.lua'
|
|
||||||
CheckNotGui
|
CheckNotGui
|
||||||
CheckUnix " Using low level feedkeys() does not work on MS-Windows.
|
CheckUnix " Using low level feedkeys() does not work on MS-Windows.
|
||||||
|
|
||||||
@@ -156,6 +154,7 @@ func Test_FileChangedShell_edit_dialog()
|
|||||||
au FileChangedShell Xchanged_r let g:reason = v:fcs_reason | let v:fcs_choice = 'ask'
|
au FileChangedShell Xchanged_r let g:reason = v:fcs_reason | let v:fcs_choice = 'ask'
|
||||||
augroup END
|
augroup END
|
||||||
call assert_equal(&fileformat, 'unix')
|
call assert_equal(&fileformat, 'unix')
|
||||||
|
sleep 10m " make the test less flaky in Nvim
|
||||||
call writefile(["line1\r", "line2\r"], 'Xchanged_r')
|
call writefile(["line1\r", "line2\r"], 'Xchanged_r')
|
||||||
let g:reason = ''
|
let g:reason = ''
|
||||||
call feedkeys('L', 'L') " load file content only
|
call feedkeys('L', 'L') " load file content only
|
||||||
@@ -173,6 +172,7 @@ func Test_FileChangedShell_edit_dialog()
|
|||||||
au FileChangedShell Xchanged_r let g:reason = v:fcs_reason | let v:fcs_choice = 'ask'
|
au FileChangedShell Xchanged_r let g:reason = v:fcs_reason | let v:fcs_choice = 'ask'
|
||||||
augroup END
|
augroup END
|
||||||
call assert_equal(&fileformat, 'unix')
|
call assert_equal(&fileformat, 'unix')
|
||||||
|
sleep 10m " make the test less flaky in Nvim
|
||||||
call writefile(["line1\r", "line2\r"], 'Xchanged_r')
|
call writefile(["line1\r", "line2\r"], 'Xchanged_r')
|
||||||
let g:reason = ''
|
let g:reason = ''
|
||||||
call feedkeys('a', 'L') " load file content and options
|
call feedkeys('a', 'L') " load file content and options
|
||||||
@@ -191,8 +191,6 @@ func Test_FileChangedShell_edit_dialog()
|
|||||||
endfunc
|
endfunc
|
||||||
|
|
||||||
func Test_file_changed_dialog()
|
func Test_file_changed_dialog()
|
||||||
" requires a UI to be active
|
|
||||||
throw 'Skipped: use test/functional/legacy/filechanged_spec.lua'
|
|
||||||
CheckUnix
|
CheckUnix
|
||||||
CheckNotGui
|
CheckNotGui
|
||||||
au! FileChangedShell
|
au! FileChangedShell
|
||||||
|
@@ -2590,8 +2590,6 @@ endfunc
|
|||||||
|
|
||||||
" Test confirm({msg} [, {choices} [, {default} [, {type}]]])
|
" Test confirm({msg} [, {choices} [, {default} [, {type}]]])
|
||||||
func Test_confirm()
|
func Test_confirm()
|
||||||
" requires a UI to be active
|
|
||||||
throw 'Skipped: use test/functional/vimscript/input_spec.lua'
|
|
||||||
CheckUnix
|
CheckUnix
|
||||||
CheckNotGui
|
CheckNotGui
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user