diff options
Diffstat (limited to 'src/nvim/eval.c')
| -rw-r--r-- | src/nvim/eval.c | 71 | 
1 files changed, 53 insertions, 18 deletions
| diff --git a/src/nvim/eval.c b/src/nvim/eval.c index bfb332a149..d0af4b8249 100644 --- a/src/nvim/eval.c +++ b/src/nvim/eval.c @@ -18,6 +18,8 @@  #include <stdbool.h>  #include <math.h> +#include "nvim/lib/klist.h" +  #include "nvim/assert.h"  #include "nvim/vim.h"  #include "nvim/ascii.h" @@ -81,11 +83,12 @@  #include "nvim/os/rstream.h"  #include "nvim/os/rstream_defs.h"  #include "nvim/os/time.h" -#include "nvim/os/channel.h" +#include "nvim/msgpack_rpc/channel.h"  #include "nvim/api/private/helpers.h"  #include "nvim/api/vim.h"  #include "nvim/os/dl.h"  #include "nvim/os/provider.h" +#include "nvim/os/event.h"  #define DICT_MAXNEST 100        /* maximum nesting of lists and dicts */ @@ -421,7 +424,8 @@ static struct vimvar {    {VV_NAME("oldfiles",         VAR_LIST), 0},    {VV_NAME("windowid",         VAR_NUMBER), VV_RO},    {VV_NAME("progpath",         VAR_STRING), VV_RO}, -  {VV_NAME("job_data",         VAR_LIST), 0} +  {VV_NAME("job_data",         VAR_LIST), 0}, +  {VV_NAME("command_output",   VAR_STRING), 0}  };  /* shorthand */ @@ -443,6 +447,15 @@ static dictitem_T vimvars_var;                  /* variable used for v: */  #define FNE_CHECK_START 2       /* find_name_end(): check name starts with                                     valid character */ +// Memory pool for reusing JobEvent structures +typedef struct { +  int id; +  char *name, *type, *received; +} JobEvent; +#define JobEventFreer(x) +KMEMPOOL_INIT(JobEventPool, JobEvent, JobEventFreer) +kmempool_t(JobEventPool) *job_event_pool = NULL; +  /*   * Initialize the global and v: variables.   */ @@ -478,6 +491,7 @@ void eval_init(void)    set_vim_var_nr(VV_HLSEARCH, 1L);    set_reg_var(0);    /* default for v:register is not 0 but '"' */ +  job_event_pool = kmp_init(JobEventPool);  }  #if defined(EXITFREE) || defined(PROTO) @@ -19508,49 +19522,65 @@ char_u *do_string_sub(char_u *str, char_u *pat, char_u *sub, char_u *flags)    return ret;  } +// JobActivity autocommands will execute vimscript code, so it must be executed +// on Nvim main loop +#define push_job_event(j, r, t)                                      \ +  do {                                                               \ +    JobEvent *event_data = kmp_alloc(JobEventPool, job_event_pool);  \ +    event_data->received = NULL;                                     \ +    if (r) {                                                         \ +      size_t read_count = rstream_pending(r);                        \ +      event_data->received = xmalloc(read_count + 1);                \ +      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);                                  \ +    event_data->type = t;                                            \ +    event_push((Event) {                                             \ +      .handler = on_job_event,                                       \ +      .data = event_data                                             \ +    });                                                              \ +  } while(0) +  static void on_job_stdout(RStream *rstream, void *data, bool eof)  {    if (!eof) { -    on_job_data(rstream, data, eof, "stdout"); +    push_job_event(data, rstream, "stdout");    }  }  static void on_job_stderr(RStream *rstream, void *data, bool eof)  {    if (!eof) { -    on_job_data(rstream, data, eof, "stderr"); +    push_job_event(data, rstream, "stderr");    }  }  static void on_job_exit(Job *job, void *data)  { -  apply_job_autocmds(job, data, "exit", NULL); -  free(data); +  push_job_event(job, NULL, "exit");  } -static void on_job_data(RStream *rstream, void *data, bool eof, char *type) +static void on_job_event(Event event)  { -  Job *job = data; -  uint32_t read_count = rstream_pending(rstream); -  char *str = xmalloc(read_count + 1); - -  rstream_read(rstream, str, read_count); -  str[read_count] = NUL; -  apply_job_autocmds(job, job_data(job), type, str); +  JobEvent *data = event.data; +  apply_job_autocmds(data->id, data->name, data->type, data->received); +  kmp_free(JobEventPool, job_event_pool, data);  } -static void apply_job_autocmds(Job *job, char *name, char *type, char *str) +static void apply_job_autocmds(int id, char *name, char *type, char *received)  {    // Create the list which will be set to v:job_data    list_T *list = list_alloc(); -  list_append_number(list, job_id(job)); +  list_append_number(list, id);    list_append_string(list, (uint8_t *)type, -1); -  if (str) { +  if (received) {      listitem_T *str_slot = listitem_alloc();      str_slot->li_tv.v_type = VAR_STRING;      str_slot->li_tv.v_lock = 0; -    str_slot->li_tv.vval.v_string = (uint8_t *)str; +    str_slot->li_tv.vval.v_string = (uint8_t *)received;      list_append(list, str_slot);    } @@ -19558,6 +19588,11 @@ static void apply_job_autocmds(Job *job, char *name, char *type, char *str)    set_vim_var_list(VV_JOB_DATA, list);    // Call JobActivity autocommands    apply_autocmds(EVENT_JOBACTIVITY, (uint8_t *)name, NULL, TRUE, NULL); + +  if (!received) { +    // This must be the exit event. Free the name. +    free(name); +  }  }  static void script_host_eval(char *method, typval_T *argvars, typval_T *rettv) | 
