diff --git a/src/nvim/eval.c b/src/nvim/eval.c index 80ae356ef7..8af7965dfc 100644 --- a/src/nvim/eval.c +++ b/src/nvim/eval.c @@ -6543,6 +6543,7 @@ static struct fst { {"synconcealed", 2, 2, f_synconcealed}, {"synstack", 2, 2, f_synstack}, {"system", 1, 2, f_system}, + {"systemlist", 1, 2, f_systemlist}, {"tabpagebuflist", 0, 1, f_tabpagebuflist}, {"tabpagenr", 0, 1, f_tabpagenr}, {"tabpagewinnr", 1, 2, f_tabpagewinnr}, @@ -9873,7 +9874,7 @@ static void f_has(typval_T *argvars, typval_T *rettv) "spell", "syntax", #if !defined(UNIX) - "system", + "system", // TODO(SplinterOfChaos): This IS defined for UNIX! #endif "tag_binary", "tag_old_static", @@ -14415,8 +14416,8 @@ static void f_synstack(typval_T *argvars, typval_T *rettv) } } -/// f_system - the VimL system() function -static void f_system(typval_T *argvars, typval_T *rettv) +static void get_system_output_as_rettv(typval_T *argvars, typval_T *rettv, + bool retlist) { rettv->v_type = VAR_STRING; rettv->vval.v_string = NULL; @@ -14453,9 +14454,41 @@ static void f_system(typval_T *argvars, typval_T *rettv) set_vim_var_nr(VV_SHELL_ERROR, (long) status); + if (res == NULL) { + rettv->v_type = VAR_STRING; + rettv->vval.v_string = NULL; + return; + } + + if (retlist) { + list_T *list = list_alloc(); + + // Copy each line to a list element using NL as the delimiter. + for (size_t i = 0; i < nread; i++) { + char_u *start = (char_u *) res + i; + size_t len = (char_u *) xmemscan(start, NL, nread - i) - start; + i += len; + + char_u *s = vim_strnsave(start, len); + for (size_t j = 0; j < len; j++) { + if (s[j] == NUL) { + s[j] = NL; + } + } + + listitem_T *li = listitem_alloc(); + li->li_tv.v_type = VAR_STRING; + li->li_tv.vval.v_string = s; + list_append(list, li); + } + + free(res); + + rettv->v_type = VAR_LIST; + rettv->vval.v_list = list; + } else { #ifdef USE_CRNL - // translate into - if (res != NULL) { + // translate into char *d = res; for (char *s = res; *s; ++s) { if (s[0] == CAR && s[1] == NL) { @@ -14466,12 +14499,23 @@ static void f_system(typval_T *argvars, typval_T *rettv) } *d = NUL; - } #endif - - rettv->vval.v_string = (char_u *) res; + rettv->vval.v_string = (char_u *) res; + } } +/// f_system - the VimL system() function +static void f_system(typval_T *argvars, typval_T *rettv) +{ + get_system_output_as_rettv(argvars, rettv, false); +} + +static void f_systemlist(typval_T *argvars, typval_T *rettv) +{ + get_system_output_as_rettv(argvars, rettv, true); +} + + /* * "tabpagebuflist()" function */ diff --git a/src/nvim/ex_cmds2.c b/src/nvim/ex_cmds2.c index 0703c76b8a..056a101d47 100644 --- a/src/nvim/ex_cmds2.c +++ b/src/nvim/ex_cmds2.c @@ -3181,8 +3181,8 @@ static char_u **find_locales(void) /* Find all available locales by running command "locale -a". If this * doesn't work we won't have completion. */ - char_u *locale_a = get_cmd_output((char_u *)"locale -a", - NULL, kShellOptSilent); + char_u *locale_a = get_cmd_output((char_u *)"locale -a", NULL, + kShellOptSilent, NULL); if (locale_a == NULL) return NULL; ga_init(&locales_ga, sizeof(char_u *), 20); diff --git a/src/nvim/misc1.c b/src/nvim/misc1.c index 52780b9a57..f832fa25f2 100644 --- a/src/nvim/misc1.c +++ b/src/nvim/misc1.c @@ -3401,13 +3401,16 @@ void fast_breakcheck(void) /* * Get the stdout of an external command. + * If "ret_len" is NULL replace NUL characters with NL. When "ret_len" is not + * NULL store the length there. * Returns an allocated string, or NULL for error. */ char_u * get_cmd_output ( char_u *cmd, char_u *infile, /* optional input file name */ - int flags /* can be SHELL_SILENT */ + int flags, // can be kShellOptSilent + size_t *ret_len ) { char_u *tempname; @@ -3463,13 +3466,15 @@ get_cmd_output ( EMSG2(_(e_notread), tempname); free(buffer); buffer = NULL; - } else { + } else if (ret_len == NULL) { /* Change NUL into SOH, otherwise the string is truncated. */ for (i = 0; i < len; ++i) if (buffer[i] == NUL) buffer[i] = 1; buffer[len] = NUL; /* make sure the buffer is terminated */ + } else { + *ret_len = len; } done: diff --git a/src/nvim/path.c b/src/nvim/path.c index 6990a1817c..ff97b7774a 100644 --- a/src/nvim/path.c +++ b/src/nvim/path.c @@ -1172,7 +1172,7 @@ expand_backtick ( buffer = eval_to_string(cmd + 1, &p, TRUE); else buffer = get_cmd_output(cmd, NULL, - (flags & EW_SILENT) ? kShellOptSilent : 0); + (flags & EW_SILENT) ? kShellOptSilent : 0, NULL); free(cmd); if (buffer == NULL) return 0; diff --git a/src/nvim/version.c b/src/nvim/version.c index ab609bf492..a453c0ee10 100644 --- a/src/nvim/version.c +++ b/src/nvim/version.c @@ -393,7 +393,7 @@ static int included_patches[] = { 251, //250 NA //249, - //248, + 248, 247, //246, 245,