0
0
mirror of https://github.com/vim/vim.git synced 2025-07-26 11:04:33 -04:00

patch 8.1.0815: dialog for file changed outside of Vim not tested

Problem:    Dialog for file changed outside of Vim not tested.
Solution:   Add a test.  Move FileChangedShell test.  Add 'L' flag to
            feedkeys().
This commit is contained in:
Bram Moolenaar 2019-01-24 21:58:10 +01:00
parent ed18f2c03a
commit 5e66b42aae
6 changed files with 217 additions and 120 deletions

View File

@ -1,4 +1,4 @@
*eval.txt* For Vim version 8.1. Last change: 2019 Jan 21
*eval.txt* For Vim version 8.1. Last change: 2019 Jan 24
VIM REFERENCE MANUAL by Bram Moolenaar
@ -662,6 +662,16 @@ is not available it returns -1 or the default value you specify: >
:echo get(myblob, idx, 999)
Blob iteration ~
The |:for| loop executes commands for each byte of a Blob. The loop variable is
set to each byte in the Blob. Example: >
:for byte in 0z112233
: call Doit(byte)
:endfor
This calls Doit() with 0x11, 0x22 and 0x33.
Blob concatenation ~
Two blobs can be concatenated with the "+" operator: >
@ -793,8 +803,9 @@ Expression syntax summary, from least to most significant:
etc. As above, append ? for ignoring case, # for
matching case
expr5 is expr5 same |List| instance
expr5 isnot expr5 different |List| instance
expr5 is expr5 same |List|, |Dictionary| or |Blob| instance
expr5 isnot expr5 different |List|, |Dictionary| or |Blob|
instance
|expr5| expr6
expr6 + expr6 .. number addition, list or blob concatenation
@ -962,12 +973,12 @@ Dictionary and arguments, use |get()| to get the function name: >
if get(Part1, 'name') == get(Part2, 'name')
" Part1 and Part2 refer to the same function
When using "is" or "isnot" with a |List| or a |Dictionary| this checks if the
expressions are referring to the same |List| or |Dictionary| instance. A copy
of a |List| is different from the original |List|. When using "is" without
a |List| or a |Dictionary| it is equivalent to using "equal", using "isnot"
equivalent to using "not equal". Except that a different type means the
values are different: >
Using "is" or "isnot" with a |List|, |Dictionary| or |Blob| checks whether
the expressions are referring to the same |List|, |Dictionary| or |Blob|
instance. A copy of a |List| is different from the original |List|. When
using "is" without a |List|, |Dictionary| or |Blob|, it is equivalent to
using "equal", using "isnot" equivalent to using "not equal". Except that
a different type means the values are different: >
echo 4 == '4'
1
echo 4 is '4'
@ -1012,16 +1023,16 @@ can be matched like an ordinary character. Examples:
expr5 and expr6 *expr5* *expr6*
---------------
expr6 + expr6 .. Number addition or |List| concatenation *expr-+*
expr6 - expr6 .. Number subtraction *expr--*
expr6 . expr6 .. String concatenation *expr-.*
expr6 + expr6 Number addition, |List| or |Blob| concatenation *expr-+*
expr6 - expr6 Number subtraction *expr--*
expr6 . expr6 String concatenation *expr-.*
For |Lists| only "+" is possible and then both expr6 must be a list. The
result is a new list with the two lists Concatenated.
expr7 * expr7 .. Number multiplication *expr-star*
expr7 / expr7 .. Number division *expr-/*
expr7 % expr7 .. Number modulo *expr-%*
expr7 * expr7 Number multiplication *expr-star*
expr7 / expr7 Number division *expr-/*
expr7 % expr7 Number modulo *expr-%*
For all, except ".", Strings are converted to Numbers.
For bitwise operators see |and()|, |or()| and |xor()|.
@ -4121,6 +4132,9 @@ feedkeys({string} [, {mode}]) *feedkeys()*
't' Handle keys as if typed; otherwise they are handled as
if coming from a mapping. This matters for undo,
opening folds, etc.
'L' Lowlevel input. Only works for Unix or when using the
GUI. Keys are used as if they were coming from the
terminal. Other flags are not used. *E980*
'i' Insert the string instead of appending (see above).
'x' Execute commands until typeahead is empty. This is
similar to using ":normal!". You can call feedkeys()
@ -5740,6 +5754,10 @@ job_start({command} [, {options}]) *job_start()*
|:!cmd| this does not wait for the job to finish.
To start a job in a terminal window see |term_start()|.
If the job fails to start then |job_status()| on the returned
Job object results in "fail" and none of the callbacks will be
invoked.
{command} can be a String. This works best on MS-Windows. On
Unix it is split up in white-separated parts to be passed to
execvp(). Arguments in double quotes can contain white space.
@ -11044,28 +11062,34 @@ This does NOT work: >
NOTE: The ":append" and ":insert" commands don't work
properly inside a ":while" and ":for" loop.
:for {var} in {list} *:for* *E690* *E732*
:for {var} in {object} *:for* *E690* *E732*
:endfo[r] *:endfo* *:endfor*
Repeat the commands between ":for" and ":endfor" for
each item in {list}. Variable {var} is set to the
value of each item.
When an error is detected for a command inside the
loop, execution continues after the "endfor".
Changing {list} inside the loop affects what items are
used. Make a copy if this is unwanted: >
each item in {object}. {object} can be a |List| or
a |Blob|. Variable {var} is set to the value of each
item. When an error is detected for a command inside
the loop, execution continues after the "endfor".
Changing {object} inside the loop affects what items
are used. Make a copy if this is unwanted: >
:for item in copy(mylist)
< When not making a copy, Vim stores a reference to the
next item in the list, before executing the commands
with the current item. Thus the current item can be
removed without effect. Removing any later item means
it will not be found. Thus the following example
works (an inefficient way to make a list empty): >
<
When {object} is a |List| and not making a copy, Vim
stores a reference to the next item in the |List|
before executing the commands with the current item.
Thus the current item can be removed without effect.
Removing any later item means it will not be found.
Thus the following example works (an inefficient way
to make a |List| empty): >
for item in mylist
call remove(mylist, 0)
endfor
< Note that reordering the list (e.g., with sort() or
< Note that reordering the |List| (e.g., with sort() or
reverse()) may have unexpected effects.
When {object} is a |Blob|, Vim always makes a copy to
iterate over. Unlike with |List|, modifying the
|Blob| does not affect the iteration.
:for [{var1}, {var2}, ...] in {listlist}
:endfo[r]
Like ":for" above, but each item in {listlist} must be

View File

@ -3674,6 +3674,7 @@ f_feedkeys(typval_T *argvars, typval_T *rettv UNUSED)
int typed = FALSE;
int execute = FALSE;
int dangerous = FALSE;
int lowlevel = FALSE;
char_u *keys_esc;
/* This is not allowed in the sandbox. If the commands would still be
@ -3697,6 +3698,7 @@ f_feedkeys(typval_T *argvars, typval_T *rettv UNUSED)
case 'i': insert = TRUE; break;
case 'x': execute = TRUE; break;
case '!': dangerous = TRUE; break;
case 'L': lowlevel = TRUE; break;
}
}
}
@ -3708,7 +3710,16 @@ f_feedkeys(typval_T *argvars, typval_T *rettv UNUSED)
keys_esc = vim_strsave_escape_csi(keys);
if (keys_esc != NULL)
{
ins_typebuf(keys_esc, (remap ? REMAP_YES : REMAP_NONE),
if (lowlevel)
{
#ifdef USE_INPUT_BUF
add_to_input_buf(keys, (int)STRLEN(keys));
#else
emsg(_("E980: lowlevel input not supported"));
#endif
}
else
ins_typebuf(keys_esc, (remap ? REMAP_YES : REMAP_NONE),
insert ? 0 : typebuf.tb_len, !typed, FALSE);
vim_free(keys_esc);
if (vgetc_busy

View File

@ -121,6 +121,7 @@ NEW_TESTS = \
test_feedkeys \
test_file_perm \
test_file_size \
test_filechanged \
test_fileformat \
test_filetype \
test_filter_cmd \
@ -316,6 +317,7 @@ NEW_TESTS_RES = \
test_exit.res \
test_farsi.res \
test_file_size.res \
test_filechanged.res \
test_find_complete.res \
test_fixeol.res \
test_fnameescape.res \

View File

@ -1386,92 +1386,4 @@ func Test_Changed_FirstTime()
bwipe!
endfunc
func Test_FileChangedShell_reload()
if !has('unix')
return
endif
augroup testreload
au FileChangedShell Xchanged let g:reason = v:fcs_reason | let v:fcs_choice = 'reload'
augroup END
new Xchanged
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
checktime
call assert_equal('changed', g:reason)
call assert_equal(2, line('$'))
call assert_equal('extra line', getline(2))
" Only triggers once
let g:reason = ''
checktime
call assert_equal('', g:reason)
" When deleted buffer is not reloaded
silent !rm Xchanged
let g:reason = ''
checktime
call assert_equal('deleted', g:reason)
call assert_equal(2, line('$'))
call assert_equal('extra line', getline(2))
" When recreated buffer is reloaded
call setline(1, 'buffer is changed')
silent !echo 'new line' >>Xchanged
let g:reason = ''
checktime
call assert_equal('conflict', g:reason)
call assert_equal(1, line('$'))
call assert_equal('new line', getline(1))
" Only mode changed
silent !chmod +x Xchanged
let g:reason = ''
checktime
call assert_equal('mode', g:reason)
call assert_equal(1, line('$'))
call assert_equal('new line', getline(1))
" Only time changed
sleep 2
silent !touch Xchanged
let g:reason = ''
checktime
call assert_equal('time', g:reason)
call assert_equal(1, line('$'))
call assert_equal('new line', getline(1))
if has('persistent_undo')
" With an undo file the reload can be undone and a change before the
" reload.
set undofile
call setline(2, 'before write')
write
call setline(2, 'after write')
sleep 2
silent !echo 'different line' >>Xchanged
let g:reason = ''
checktime
call assert_equal('conflict', g:reason)
call assert_equal(3, line('$'))
call assert_equal('before write', getline(2))
call assert_equal('different line', getline(3))
" undo the reload
undo
call assert_equal(2, line('$'))
call assert_equal('after write', getline(2))
" undo the change before reload
undo
call assert_equal(2, line('$'))
call assert_equal('before write', getline(2))
set noundofile
endif
au! testreload
bwipe!
call delete('Xchanged')
endfunc
" FileChangedShell tested in test_filechanged.vim

View File

@ -0,0 +1,146 @@
" Tests for when a file was changed outside of Vim.
func Test_FileChangedShell_reload()
if !has('unix')
return
endif
augroup testreload
au FileChangedShell Xchanged_r let g:reason = v:fcs_reason | let v:fcs_choice = 'reload'
augroup END
new Xchanged_r
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_r
checktime
call assert_equal('changed', g:reason)
call assert_equal(2, line('$'))
call assert_equal('extra line', getline(2))
" Only triggers once
let g:reason = ''
checktime
call assert_equal('', g:reason)
" When deleted buffer is not reloaded
silent !rm Xchanged_r
let g:reason = ''
checktime
call assert_equal('deleted', g:reason)
call assert_equal(2, line('$'))
call assert_equal('extra line', getline(2))
" When recreated buffer is reloaded
call setline(1, 'buffer is changed')
silent !echo 'new line' >>Xchanged_r
let g:reason = ''
checktime
call assert_equal('conflict', g:reason)
call assert_equal(1, line('$'))
call assert_equal('new line', getline(1))
" Only mode changed
silent !chmod +x Xchanged_r
let g:reason = ''
checktime
call assert_equal('mode', g:reason)
call assert_equal(1, line('$'))
call assert_equal('new line', getline(1))
" Only time changed
sleep 2
silent !touch Xchanged_r
let g:reason = ''
checktime
call assert_equal('time', g:reason)
call assert_equal(1, line('$'))
call assert_equal('new line', getline(1))
if has('persistent_undo')
" With an undo file the reload can be undone and a change before the
" reload.
set undofile
call setline(2, 'before write')
write
call setline(2, 'after write')
sleep 2
silent !echo 'different line' >>Xchanged_r
let g:reason = ''
checktime
call assert_equal('conflict', g:reason)
call assert_equal(3, line('$'))
call assert_equal('before write', getline(2))
call assert_equal('different line', getline(3))
" undo the reload
undo
call assert_equal(2, line('$'))
call assert_equal('after write', getline(2))
" undo the change before reload
undo
call assert_equal(2, line('$'))
call assert_equal('before write', getline(2))
set noundofile
endif
au! testreload
bwipe!
call delete('Xchanged_r')
endfunc
func Test_file_changed_dialog()
if !has('unix')
return
endif
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 feedkeys('L', '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))
" Recreate buffer and reload
call setline(1, 'buffer is changed')
silent !echo 'new line' >Xchanged_d
call feedkeys('L', '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 feedkeys('L', '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
call assert_equal('', v:warningmsg)
call assert_equal(1, line('$'))
call assert_equal('new line', getline(1))
bwipe!
call delete('Xchanged_d')
endfunc

View File

@ -788,7 +788,9 @@ static char *(features[]) =
static int included_patches[] =
{ /* Add new patch number below this line */
/**/
84,
815,
/**/
814,
/**/
813,
/**/