diff options
author | Scott Prager <splinterofchaos@gmail.com> | 2014-10-25 20:10:29 -0400 |
---|---|---|
committer | Thiago de Arruda <tpadilha84@gmail.com> | 2014-11-07 13:34:56 -0300 |
commit | 37cbafa5bbf01c2619f009bdf876dd4453e9a28a (patch) | |
tree | 7a0460f4db2b78d5290715d681b1bcf8bfb3c837 | |
parent | 50f1c5db258f95f4770537497f7acd1968f3485c (diff) | |
download | rneovim-37cbafa5bbf01c2619f009bdf876dd4453e9a28a.tar.gz rneovim-37cbafa5bbf01c2619f009bdf876dd4453e9a28a.tar.bz2 rneovim-37cbafa5bbf01c2619f009bdf876dd4453e9a28a.zip |
job: Read job data line-wise.
Only read up to the last newline in push_job_event().
-rw-r--r-- | src/nvim/eval.c | 43 |
1 files changed, 32 insertions, 11 deletions
diff --git a/src/nvim/eval.c b/src/nvim/eval.c index d75807800c..a58745f22a 100644 --- a/src/nvim/eval.c +++ b/src/nvim/eval.c @@ -453,6 +453,7 @@ static dictitem_T vimvars_var; /* variable used for v: */ typedef struct { int id; char *name, *type, *received; + size_t received_len; } JobEvent; #define JobEventFreer(x) KMEMPOOL_INIT(JobEventPool, JobEvent, JobEventFreer) @@ -19528,15 +19529,33 @@ char_u *do_string_sub(char_u *str, char_u *pat, char_u *sub, char_u *flags) // JobActivity autocommands will execute vimscript code, so it must be executed // on Nvim main loop -#define push_job_event(j, r, t) \ +#define push_job_event(j, r, t, eof) \ do { \ JobEvent *event_data = kmp_alloc(JobEventPool, job_event_pool); \ event_data->received = NULL; \ + size_t read_count = 0; \ if (r) { \ - size_t read_count = rstream_pending(r); \ - event_data->received = xmalloc(read_count + 1); \ + if (eof) { \ + read_count = rstream_pending(r); \ + } else { \ + char *read = rstream_read_ptr(r); \ + char *lastnl = xmemrchr(read, NL, rstream_pending(r)); \ + if (lastnl) { \ + read_count = (size_t) (lastnl - read) + 1; \ + } else if (rstream_available(r) == 0) { \ + /* No newline or room to grow; flush everything. */ \ + read_count = rstream_pending(r); \ + } \ + } \ + if (read_count == 0) { \ + /* Either we're at EOF or we need to wait until next time */ \ + /* to receive a '\n. */ \ + kmp_free(JobEventPool, job_event_pool, event_data); \ + return; \ + } \ + event_data->received_len = read_count; \ + event_data->received = xmallocz(read_count); \ rstream_read(r, event_data->received, read_count); \ - event_data->received[read_count] = NUL; \ } \ event_data->id = job_id(j); \ event_data->name = job_data(j); \ @@ -19549,31 +19568,33 @@ char_u *do_string_sub(char_u *str, char_u *pat, char_u *sub, char_u *flags) static void on_job_stdout(RStream *rstream, void *data, bool eof) { - if (!eof) { - push_job_event(data, rstream, "stdout"); + if (rstream_pending(rstream)) { + push_job_event(data, rstream, "stdout", eof); } } static void on_job_stderr(RStream *rstream, void *data, bool eof) { - if (!eof) { - push_job_event(data, rstream, "stderr"); + if (rstream_pending(rstream)) { + push_job_event(data, rstream, "stderr", eof); } } static void on_job_exit(Job *job, void *data) { - push_job_event(job, NULL, "exit"); + push_job_event(job, NULL, "exit", true); } static void on_job_event(Event event) { JobEvent *data = event.data; - apply_job_autocmds(data->id, data->name, data->type, data->received); + apply_job_autocmds(data->id, data->name, data->type, + data->received, data->received_len); kmp_free(JobEventPool, job_event_pool, data); } -static void apply_job_autocmds(int id, char *name, char *type, char *received) +static void apply_job_autocmds(int id, char *name, char *type, + char *received, size_t received_len) { // Create the list which will be set to v:job_data list_T *list = list_alloc(); |