changeset 15615:536fca2cee19 v8.1.0815

patch 8.1.0815: dialog for file changed outside of Vim not tested commit https://github.com/vim/vim/commit/5e66b42aae7c67a3ef67617d4bd43052ac2b73ce Author: Bram Moolenaar <Bram@vim.org> Date: Thu Jan 24 21:58:10 2019 +0100 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().
author Bram Moolenaar <Bram@vim.org>
date Thu, 24 Jan 2019 22:00:05 +0100
parents 19317f8fdd2c
children a58f219678ca
files runtime/doc/eval.txt src/evalfunc.c src/testdir/Make_all.mak src/testdir/test_autocmd.vim src/testdir/test_filechanged.vim src/version.c
diffstat 6 files changed, 217 insertions(+), 120 deletions(-) [+]
line wrap: on
line diff
--- a/runtime/doc/eval.txt
+++ b/runtime/doc/eval.txt
@@ -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 de
 	: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
 	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
 	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 characte
 
 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}])				*feedke
 		'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}])			*jo
 		|:!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 @@ 7. Commands						*expression-commands*
 			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
--- a/src/evalfunc.c
+++ b/src/evalfunc.c
@@ -3674,6 +3674,7 @@ f_feedkeys(typval_T *argvars, typval_T *
     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 *
 		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 *
 	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
--- a/src/testdir/Make_all.mak
+++ b/src/testdir/Make_all.mak
@@ -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 \
--- a/src/testdir/test_autocmd.vim
+++ b/src/testdir/test_autocmd.vim
@@ -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
new file mode 100644
--- /dev/null
+++ b/src/testdir/test_filechanged.vim
@@ -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
--- a/src/version.c
+++ b/src/version.c
@@ -788,7 +788,9 @@ static char *(features[]) =
 static int included_patches[] =
 {   /* Add new patch number below this line */
 /**/
-    84,
+    815,
+/**/
+    814,
 /**/
     813,
 /**/