aboutsummaryrefslogtreecommitdiff
path: root/src/nvim/os/shell.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/nvim/os/shell.c')
-rw-r--r--src/nvim/os/shell.c48
1 files changed, 41 insertions, 7 deletions
diff --git a/src/nvim/os/shell.c b/src/nvim/os/shell.c
index 04f59d7522..19d199f4d5 100644
--- a/src/nvim/os/shell.c
+++ b/src/nvim/os/shell.c
@@ -80,27 +80,61 @@ char **shell_build_argv(const char *cmd, const char *extra_args)
void shell_free_argv(char **argv)
{
char **p = argv;
-
if (p == NULL) {
// Nothing was allocated, return
return;
}
-
while (*p != NULL) {
// Free each argument
xfree(*p);
p++;
}
-
xfree(argv);
}
+/// Joins shell arguments from `argv` into a new string.
+/// If the result is too long it is truncated with ellipsis ("...").
+///
+/// @returns[allocated] `argv` joined to a string.
+char *shell_argv_to_str(char **const argv)
+ FUNC_ATTR_NONNULL_ALL
+{
+ size_t n = 0;
+ char **p = argv;
+ char *rv = xcalloc(256, sizeof(*rv));
+ const size_t maxsize = (256 * sizeof(*rv));
+ if (*p == NULL) {
+ return rv;
+ }
+ while (*p != NULL) {
+ xstrlcat(rv, "'", maxsize);
+ xstrlcat(rv, *p, maxsize);
+ n = xstrlcat(rv, "' ", maxsize);
+ if (n >= maxsize) {
+ break;
+ }
+ p++;
+ }
+ if (n < maxsize) {
+ rv[n - 1] = '\0';
+ } else {
+ // Command too long, show ellipsis: "/bin/bash 'foo' 'bar'..."
+ rv[maxsize - 4] = '.';
+ rv[maxsize - 3] = '.';
+ rv[maxsize - 2] = '.';
+ rv[maxsize - 1] = '\0';
+ }
+ return rv;
+}
+
/// Calls the user-configured 'shell' (p_sh) for running a command or wildcard
/// expansion.
///
/// @param cmd The command to execute, or NULL to run an interactive shell.
/// @param opts Options that control how the shell will work.
/// @param extra_args Extra arguments to the shell, or NULL.
+///
+/// @return shell command exit code
int os_call_shell(char_u *cmd, ShellOpts opts, char_u *extra_args)
{
DynamicBuffer input = DYNAMIC_BUFFER_INIT;
@@ -450,8 +484,8 @@ static void out_data_ring(char *output, size_t size)
/// @param output Data to append to screen lines.
/// @param remaining Size of data.
/// @param new_line If true, next data output will be on a new line.
-static void out_data_append_to_screen(char *output, size_t *count,
- bool eof)
+static void out_data_append_to_screen(char *output, size_t *count, bool eof)
+ FUNC_ATTR_NONNULL_ALL
{
char *p = output, *end = output + *count;
while (p < end) {
@@ -466,7 +500,7 @@ static void out_data_append_to_screen(char *output, size_t *count,
// incomplete UTF-8 sequence that could be composing with the last
// complete sequence.
// This will be corrected when we switch to vterm based implementation
- int i = *p ? mb_ptr2len_len((char_u *)p, (int)(end-p)) : 1;
+ int i = *p ? utfc_ptr2len_len((char_u *)p, (int)(end-p)) : 1;
if (!eof && i == 1 && utf8len_tab_zero[*(uint8_t *)p] > (end-p)) {
*count = (size_t)(p - output);
goto end;
@@ -491,7 +525,7 @@ static void out_data_cb(Stream *stream, RBuffer *buf, size_t count, void *data,
&& out_data_decide_throttle(cnt)) { // Skip output above a threshold.
// Save the skipped output. If it is the final chunk, we display it later.
out_data_ring(ptr, cnt);
- } else {
+ } else if (ptr != NULL) {
out_data_append_to_screen(ptr, &cnt, eof);
}