]> granicus.if.org Git - vim/commitdiff
patch 8.1.2251: ":term command" may not work without a shell v8.1.2251
authorBram Moolenaar <Bram@vim.org>
Sun, 3 Nov 2019 22:37:12 +0000 (23:37 +0100)
committerBram Moolenaar <Bram@vim.org>
Sun, 3 Nov 2019 22:37:12 +0000 (23:37 +0100)
Problem:    ":term command" may not work without a shell.
Solution:   Add the ++shell option to :term. (closes #3340)

runtime/doc/terminal.txt
src/os_unix.c
src/proto/os_unix.pro
src/terminal.c
src/testdir/test_terminal.vim
src/version.c

index db126deb690337d1ef0975a14fd269b0869e10e4..7b40bf2322f1bb36ec797f2412b6def4f25955d5 100644 (file)
@@ -210,6 +210,10 @@ Command syntax ~
                                        no window will be used.
                        ++norestore     Do not include this terminal window
                                        in a session file.
+                       ++shell         Instead of executing {command}
+                                       directly, use a shell, like with
+                                       `:!command`             *E279*
+                                       {only works on Unix currently}
                        ++kill={how}    When trying to close the terminal
                                        window kill the job with {how}.  See
                                        |term_setkill()| for the values.
index e8fe90a1c087f019943cd1904193e0d4dff6d637..6fa0702747fd5cd7e622149cba2dd25cf38b0f73 100644 (file)
@@ -4299,10 +4299,10 @@ may_send_sigint(int c UNUSED, pid_t pid UNUSED, pid_t wpid UNUSED)
 # endif
 }
 
-#if !defined(USE_SYSTEM) || (defined(FEAT_GUI) && defined(FEAT_TERMINAL))
+#if !defined(USE_SYSTEM) || defined(FEAT_TERMINAL) || defined(PROTO)
 
-    static int
-build_argv(
+    int
+unix_build_argv(
        char_u *cmd,
        char ***argvp,
        char_u **sh_tofree,
@@ -4369,7 +4369,7 @@ mch_call_shell_terminal(
     aco_save_T aco;
     oparg_T    oa;             /* operator arguments */
 
-    if (build_argv(cmd, &argv, &tofree1, &tofree2) == FAIL)
+    if (unix_build_argv(cmd, &argv, &tofree1, &tofree2) == FAIL)
        goto theend;
 
     init_job_options(&opt);
@@ -4546,7 +4546,7 @@ mch_call_shell_fork(
     if (options & SHELL_COOKED)
        settmode(TMODE_COOK);           /* set to normal mode */
 
-    if (build_argv(cmd, &argv, &tofree1, &tofree2) == FAIL)
+    if (unix_build_argv(cmd, &argv, &tofree1, &tofree2) == FAIL)
        goto error;
 
     /*
index 86e12a0f69fbaefe445442284d0dd4fa040c9bde..14cde4a1356674c4a665050867f66602c4ff813f 100644 (file)
@@ -59,6 +59,7 @@ int mch_get_shellsize(void);
 int mch_report_winsize(int fd, int rows, int cols);
 void mch_set_shellsize(void);
 void mch_new_shellsize(void);
+int unix_build_argv(char_u *cmd, char ***argvp, char_u **sh_tofree, char_u **shcf_tofree);
 int mch_call_shell(char_u *cmd, int options);
 void mch_job_start(char **argv, job_T *job, jobopt_T *options, int is_terminal);
 char *mch_job_status(job_T *job);
index 10343fe20ec6f21f8ba177155ac7b04ab233635f..290d7c7bafa0109f6667c91d7b88d5269891726b 100644 (file)
@@ -703,6 +703,7 @@ ex_terminal(exarg_T *eap)
 {
     typval_T   argvar[2];
     jobopt_T   opt;
+    int                opt_shell = FALSE;
     char_u     *cmd;
     char_u     *tofree = NULL;
 
@@ -738,6 +739,8 @@ ex_terminal(exarg_T *eap)
            opt.jo_hidden = 1;
        else if (OPTARG_HAS("norestore"))
            opt.jo_term_norestore = 1;
+       else if (OPTARG_HAS("shell"))
+           opt_shell = TRUE;
        else if (OPTARG_HAS("kill") && ep != NULL)
        {
            opt.jo_set2 |= JO2_TERM_KILL;
@@ -831,10 +834,30 @@ ex_terminal(exarg_T *eap)
        opt.jo_in_bot = eap->line2;
     }
 
-    argvar[0].v_type = VAR_STRING;
-    argvar[0].vval.v_string = cmd;
-    argvar[1].v_type = VAR_UNKNOWN;
-    term_start(argvar, NULL, &opt, eap->forceit ? TERM_START_FORCEIT : 0);
+    if (opt_shell && tofree == NULL)
+    {
+#ifdef UNIX
+       char    **argv = NULL;
+       char_u  *tofree1 = NULL;
+       char_u  *tofree2 = NULL;
+
+       // :term ++shell command
+       if (unix_build_argv(cmd, &argv, &tofree1, &tofree2) == OK)
+           term_start(NULL, argv, &opt, eap->forceit ? TERM_START_FORCEIT : 0);
+       vim_free(tofree1);
+       vim_free(tofree2);
+#else
+       emsg(_("E279: Sorry, ++shell is not supported on this system"));
+#endif
+    }
+    else
+    {
+       argvar[0].v_type = VAR_STRING;
+       argvar[0].vval.v_string = cmd;
+       argvar[1].v_type = VAR_UNKNOWN;
+       term_start(argvar, NULL, &opt, eap->forceit ? TERM_START_FORCEIT : 0);
+    }
+
     vim_free(tofree);
 
 theend:
@@ -6474,7 +6497,7 @@ failed:
 term_and_job_init(
        term_T      *term,
        typval_T    *argvar,
-       char        **argv UNUSED,
+       char        **argv,
        jobopt_T    *opt,
        jobopt_T    *orig_opt)
 {
index 9aae680b4fc9e70e0bb9edfec4c158537f52642c..1a126b9e10c09877df91df6be25f03343a2df947 100644 (file)
@@ -2214,6 +2214,18 @@ func Test_terminal_altscreen()
   call delete('Xtext')
 endfunc
 
+func Test_terminal_shell_option()
+  CheckUnix
+  " exec is a shell builtin command, should fail without a shell.
+  term exec ls runtest.vim
+  call WaitForAssert({-> assert_match('job failed', term_getline(bufnr(), 1))})
+  bwipe!
+
+  term ++shell exec ls runtest.vim
+  call WaitForAssert({-> assert_match('runtest.vim', term_getline(bufnr(), 1))})
+  bwipe!
+endfunc
+
 func Test_terminal_setapi_and_call()
   if !CanRunVimInTerminal()
     return
index 5a4a1e48513cfdd66b6e3ebf913a0f84aa010a71..767cbec8bd86f56ec043d0c1b7d8a7ec8426e56f 100644 (file)
@@ -741,6 +741,8 @@ static char *(features[]) =
 
 static int included_patches[] =
 {   /* Add new patch number below this line */
+/**/
+    2251,
 /**/
     2250,
 /**/