changeset 14139:4d3f6bf86bec v8.1.0087

patch 8.1.0087: v:shell_error is always zero when using terminal for "!cmd" commit https://github.com/vim/vim/commit/f9c3883b11b33f0c548df5e949ba59fde74d3e7b Author: Bram Moolenaar <Bram@vim.org> Date: Tue Jun 19 19:59:20 2018 +0200 patch 8.1.0087: v:shell_error is always zero when using terminal for "!cmd" Problem: v:shell_error is always zero when using terminal for "!cmd". Solution: Use "exitval" of terminal-job. (Ozaki Kiichi, closes https://github.com/vim/vim/issues/2994)
author Christian Brabandt <cb@256bit.org>
date Tue, 19 Jun 2018 20:00:08 +0200
parents aa8127dba7d0
children 752fc522d342
files src/os_unix.c src/os_win32.c src/proto/terminal.pro src/terminal.c src/testdir/test_terminal.vim src/version.c
diffstat 6 files changed, 80 insertions(+), 25 deletions(-) [+]
line wrap: on
line diff
--- a/src/os_unix.c
+++ b/src/os_unix.c
@@ -4365,6 +4365,7 @@ mch_call_shell_terminal(
     char_u	*tofree2 = NULL;
     int		retval = -1;
     buf_T	*buf;
+    job_T	*job;
     aco_save_T	aco;
     oparg_T	oa;		/* operator arguments */
 
@@ -4374,6 +4375,11 @@ mch_call_shell_terminal(
     init_job_options(&opt);
     ch_log(NULL, "starting terminal for system command '%s'", cmd);
     buf = term_start(NULL, argv, &opt, TERM_START_SYSTEM);
+    if (buf == NULL)
+	goto theend;
+
+    job = term_getjob(buf->b_term);
+    ++job->jv_refcount;
 
     /* Find a window to make "buf" curbuf. */
     aucmd_prepbuf(&aco, buf);
@@ -4391,9 +4397,11 @@ mch_call_shell_terminal(
 	else
 	    normal_cmd(&oa, TRUE);
     }
-    retval = 0;
+    retval = job->jv_exitval;
     ch_log(NULL, "system command finished");
 
+    job_unref(job);
+
     /* restore curwin/curbuf and a few other things */
     aucmd_restbuf(&aco);
 
--- a/src/os_win32.c
+++ b/src/os_win32.c
@@ -4796,6 +4796,7 @@ mch_call_shell_terminal(
     long_u	cmdlen;
     int		retval = -1;
     buf_T	*buf;
+    job_T	*job;
     aco_save_T	aco;
     oparg_T	oa;		/* operator arguments */
 
@@ -4826,6 +4827,9 @@ mch_call_shell_terminal(
     if (buf == NULL)
 	return 255;
 
+    job = term_getjob(buf->b_term);
+    ++job->jv_refcount;
+
     /* Find a window to make "buf" curbuf. */
     aucmd_prepbuf(&aco, buf);
 
@@ -4842,9 +4846,11 @@ mch_call_shell_terminal(
 	else
 	    normal_cmd(&oa, TRUE);
     }
-    retval = 0;
+    retval = job->jv_exitval;
     ch_log(NULL, "system command finished");
 
+    job_unref(job);
+
     /* restore curwin/curbuf and a few other things */
     aucmd_restbuf(&aco);
 
--- a/src/proto/terminal.pro
+++ b/src/proto/terminal.pro
@@ -55,5 +55,6 @@ void f_term_setkill(typval_T *argvars, t
 void f_term_start(typval_T *argvars, typval_T *rettv);
 void f_term_wait(typval_T *argvars, typval_T *rettv);
 void term_send_eof(channel_T *ch);
+job_T *term_getjob(term_T *term);
 int terminal_enabled(void);
 /* vim: set ft=c : */
--- a/src/terminal.c
+++ b/src/terminal.c
@@ -5336,6 +5336,12 @@ term_send_eof(channel_T *ch)
 	}
 }
 
+    job_T *
+term_getjob(term_T *term)
+{
+    return term != NULL ? term->tl_job : NULL;
+}
+
 # if defined(WIN3264) || defined(PROTO)
 
 /**************************************
--- a/src/testdir/test_terminal.vim
+++ b/src/testdir/test_terminal.vim
@@ -522,29 +522,6 @@ func Test_terminal_env()
   exe buf . 'bwipe'
 endfunc
 
-" must be last, we can't go back from GUI to terminal
-func Test_zz_terminal_in_gui()
-  if !CanRunGui()
-    return
-  endif
-
-  " Ignore the "failed to create input context" error.
-  call test_ignore_error('E285:')
-
-  gui -f
-
-  call assert_equal(1, winnr('$'))
-  let buf = Run_shell_in_terminal({'term_finish': 'close'})
-  call Stop_shell_in_terminal(buf)
-  call term_wait(buf)
-
-  " closing window wipes out the terminal buffer a with finished job
-  call WaitForAssert({-> assert_equal(1, winnr('$'))})
-  call assert_equal("", bufname(buf))
-
-  unlet g:job
-endfunc
-
 func Test_terminal_list_args()
   let buf = term_start([&shell, &shellcmdflag, 'echo "123"'])
   call assert_fails(buf . 'bwipe', 'E517')
@@ -1546,3 +1523,58 @@ func Test_terminwinscroll()
 
   exe buf . 'bwipe!'
 endfunc
+
+" must be nearly the last, we can't go back from GUI to terminal
+func Test_zz1_terminal_in_gui()
+  if !CanRunGui()
+    return
+  endif
+
+  " Ignore the "failed to create input context" error.
+  call test_ignore_error('E285:')
+
+  gui -f
+
+  call assert_equal(1, winnr('$'))
+  let buf = Run_shell_in_terminal({'term_finish': 'close'})
+  call Stop_shell_in_terminal(buf)
+  call term_wait(buf)
+
+  " closing window wipes out the terminal buffer a with finished job
+  call WaitForAssert({-> assert_equal(1, winnr('$'))})
+  call assert_equal("", bufname(buf))
+
+  unlet g:job
+endfunc
+
+func Test_zz2_terminal_guioptions_bang()
+  if !has('gui_running')
+    return
+  endif
+  set guioptions+=!
+
+  let filename = 'Xtestscript'
+  if has('win32')
+    let filename .= '.bat'
+    let prefix = ''
+    let contents = ['@echo off', 'exit %1']
+  else
+    let filename .= '.sh'
+    let prefix = './'
+    let contents = ['#!/bin/sh', 'exit $1']
+  endif
+  call writefile(contents, filename)
+  call setfperm(filename, 'rwxrwx---')
+
+  " Check if v:shell_error is equal to the exit status.
+  let exitval = 0
+  execute printf(':!%s%s %d', prefix, filename, exitval)
+  call assert_equal(exitval, v:shell_error)
+
+  let exitval = 9
+  execute printf(':!%s%s %d', prefix, filename, exitval)
+  call assert_equal(exitval, v:shell_error)
+
+  set guioptions&
+  call delete(filename)
+endfunc
--- a/src/version.c
+++ b/src/version.c
@@ -762,6 +762,8 @@ static char *(features[]) =
 static int included_patches[] =
 {   /* Add new patch number below this line */
 /**/
+    87,
+/**/
     86,
 /**/
     85,