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:
parent
ed18f2c03a
commit
5e66b42aae
@ -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
|
||||
|
@ -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
|
||||
|
@ -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 \
|
||||
|
@ -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
|
||||
|
146
src/testdir/test_filechanged.vim
Normal file
146
src/testdir/test_filechanged.vim
Normal 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
|
@ -788,7 +788,9 @@ static char *(features[]) =
|
||||
static int included_patches[] =
|
||||
{ /* Add new patch number below this line */
|
||||
/**/
|
||||
84,
|
||||
815,
|
||||
/**/
|
||||
814,
|
||||
/**/
|
||||
813,
|
||||
/**/
|
||||
|
Loading…
x
Reference in New Issue
Block a user