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.c78
1 files changed, 62 insertions, 16 deletions
diff --git a/src/nvim/os/shell.c b/src/nvim/os/shell.c
index f5a1637c94..64c673930a 100644
--- a/src/nvim/os/shell.c
+++ b/src/nvim/os/shell.c
@@ -14,6 +14,7 @@
#include "nvim/os/shell.h"
#include "nvim/os/signal.h"
#include "nvim/types.h"
+#include "nvim/main.h"
#include "nvim/vim.h"
#include "nvim/message.h"
#include "nvim/memory.h"
@@ -205,16 +206,16 @@ static int do_os_system(char **argv,
xstrlcpy(prog, argv[0], MAXPATHL);
Stream in, out, err;
- LibuvProcess uvproc = libuv_process_init(&loop, &buf);
+ LibuvProcess uvproc = libuv_process_init(&main_loop, &buf);
Process *proc = &uvproc.process;
- Queue *events = queue_new_child(loop.events);
+ Queue *events = queue_new_child(main_loop.events);
proc->events = events;
proc->argv = argv;
proc->in = input != NULL ? &in : NULL;
proc->out = &out;
proc->err = &err;
if (!process_spawn(proc)) {
- loop_poll_events(&loop, 0);
+ loop_poll_events(&main_loop, 0);
// Failed, probably due to `sh` not being executable
if (!silent) {
MSG_PUTS(_("\nCannot execute "));
@@ -309,25 +310,70 @@ static void system_data_cb(Stream *stream, RBuffer *buf, size_t count,
dbuf->len += nread;
}
+/// Continue to append data to last screen line.
+///
+/// @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 append_to_screen_end(char *output, size_t remaining, bool new_line)
+{
+ // Column of last row to start appending data to.
+ static colnr_T last_col = 0;
+
+ size_t off = 0;
+ int last_row = (int)Rows - 1;
+
+ while (off < remaining) {
+ // Found end of line?
+ if (output[off] == NL) {
+ // Can we start a new line or do we need to continue the last one?
+ if (last_col == 0) {
+ screen_del_lines(0, 0, 1, (int)Rows, NULL);
+ }
+ screen_puts_len((char_u *)output, (int)off, last_row, last_col, 0);
+ last_col = 0;
+
+ size_t skip = off + 1;
+ output += skip;
+ remaining -= skip;
+ off = 0;
+ continue;
+ }
+
+ // Translate NUL to SOH
+ if (output[off] == NUL) {
+ output[off] = 1;
+ }
+
+ off++;
+ }
+
+ if (remaining) {
+ if (last_col == 0) {
+ screen_del_lines(0, 0, 1, (int)Rows, NULL);
+ }
+ screen_puts_len((char_u *)output, (int)remaining, last_row, last_col, 0);
+ last_col += (colnr_T)remaining;
+ }
+
+ if (new_line) {
+ last_col = 0;
+ }
+
+ ui_flush();
+}
+
static void out_data_cb(Stream *stream, RBuffer *buf, size_t count, void *data,
bool eof)
{
+ // We always output the whole buffer, so the buffer can never
+ // wrap around.
size_t cnt;
char *ptr = rbuffer_read_ptr(buf, &cnt);
- if (!cnt) {
- return;
- }
-
- size_t written = write_output(ptr, cnt, false, eof);
- // No output written, force emptying the Rbuffer if it is full.
- if (!written && rbuffer_size(buf) == rbuffer_capacity(buf)) {
- screen_del_lines(0, 0, 1, (int)Rows, NULL);
- screen_puts_len((char_u *)ptr, (int)cnt, (int)Rows - 1, 0, 0);
- written = cnt;
- }
- if (written) {
- rbuffer_consumed(buf, written);
+ append_to_screen_end(ptr, cnt, eof);
+ if (cnt) {
+ rbuffer_consumed(buf, cnt);
}
}