terminal: Support extra arguments in 'shell'. #4504

Tokenize p_sh if used as default in ex_terminal(). Previously p_sh was
used as the first arg in a list when calling termopen(), this would try
to call an untokenized version of shell, meaning if you had an argument
in 'shell':
    set shell=/bin/bash\ --login
the command would fail.

Helped-by: oni-link <knil.ino@gmail.com>

Closes #3999
This commit is contained in:
Jack Bracewell
2016-03-29 13:47:30 +01:00
committed by Justin M. Keyes
parent 0c1f783164
commit 2ea7bfc627
4 changed files with 84 additions and 21 deletions

View File

@@ -9627,26 +9627,38 @@ static void ex_folddo(exarg_T *eap)
static void ex_terminal(exarg_T *eap)
{
char *name = (char *)p_sh; // Default to 'shell' if {cmd} is not given.
bool mustfree = false;
char *lquote = "['";
char *rquote = "']";
char ex_cmd[1024];
if (*eap->arg != NUL) {
name = (char *)vim_strsave_escaped(eap->arg, (char_u *)"\"\\");
mustfree = true;
lquote = rquote = "\"";
}
char ex_cmd[512];
snprintf(ex_cmd, sizeof(ex_cmd),
":enew%s | call termopen(%s%s%s) | startinsert",
eap->forceit==TRUE ? "!" : "", lquote, name, rquote);
do_cmdline_cmd(ex_cmd);
if (mustfree) {
if (*eap->arg != NUL) { // Run {cmd} in 'shell'.
char *name = (char *)vim_strsave_escaped(eap->arg, (char_u *)"\"\\");
snprintf(ex_cmd, sizeof(ex_cmd),
":enew%s | call termopen(\"%s\") | startinsert",
eap->forceit ? "!" : "", name);
xfree(name);
} else { // No {cmd}: run the job with tokenized 'shell'.
if (*p_sh == NUL) {
EMSG(_(e_shellempty));
return;
}
char **argv = shell_build_argv(NULL, NULL);
char **p = argv;
char tempstring[512];
char shell_argv[512] = { 0 };
while (*p != NULL) {
snprintf(tempstring, sizeof(tempstring), ",\"%s\"", *p);
xstrlcat(shell_argv, tempstring, sizeof(shell_argv));
p++;
}
shell_free_argv(argv);
snprintf(ex_cmd, sizeof(ex_cmd),
":enew%s | call termopen([%s]) | startinsert",
eap->forceit ? "!" : "", shell_argv + 1);
}
do_cmdline_cmd(ex_cmd);
}
/// Checks if `cmd` is "previewable" (i.e. supported by 'inccommand').

View File

@@ -39,12 +39,13 @@ typedef struct {
#endif
/// Builds the argument vector for running the user-configured 'shell' (p_sh)
/// with an optional command prefixed by 'shellcmdflag' (p_shcf).
/// with an optional command prefixed by 'shellcmdflag' (p_shcf). E.g.:
///
/// ["shell", "-extra_args", "-shellcmdflag", "command with spaces"]
///
/// @param cmd Command string, or NULL to run an interactive shell.
/// @param extra_args Extra arguments to the shell, or NULL.
/// @return A newly allocated argument vector. It must be freed with
/// `shell_free_argv` when no longer needed.
/// @return Newly allocated argument vector. Must be freed with shell_free_argv.
char **shell_build_argv(const char *cmd, const char *extra_args)
FUNC_ATTR_NONNULL_RET FUNC_ATTR_MALLOC
{