Repository: neovim/neovim
File: src/nvim/autocmd.c (C)

Code before:
  AutoPatCmd patcmd = {
    // aucmd_next will set lastpat back to NULL if there are no more autocommands left to run
    .lastpat = NULL,
    // current autocommand index
    .auidx = 0,
    // save vector size, to avoid an endless loop when more patterns
    // are added when executing autocommands
    .ausize = kv_size(autocmds[(int)event]),
    .afile_orig = afile_orig,
    .fname = fname,
    .sfname = sfname,
    .tail = tail,
    .group = group,
    .event = event,
    .arg_bufnr = autocmd_bufnr,
    .data = data,
  };
  aucmd_next(&patcmd);

  // Found first autocommand, start executing them
  if (patcmd.lastpat != NULL) {
    // add to active_apc_list
    patcmd.next = active_apc_list;
    active_apc_list = &patcmd;

    // set v:event with event data (if any)
    save_v_event_T save_v_event;
    dict_T *v_event = get_v_event(&save_v_event);
    if (data && data->type == kObjectTypeDict) {
      for (size_t i = 0; i < data->data.dict.size; i++) {
        KeyValuePair item = data->data.dict.items[i];
        typval_T tv;
        Error err = ERROR_INIT;
        object_to_vim(item.value, &tv, &err);
        if (ERROR_SET(&err)) {
          api_clear_error(&err);
          continue;
        }
        tv_dict_add_tv(v_event, item.key.data, item.key.size, &tv);
      }
    }
    tv_dict_set_keys_readonly(v_event);

    // set v:cmdarg (only when there is a matching pattern)
    varnumber_T save_cmdbang = get_vim_var_nr(VV_CMDBANG);
    if (eap != NULL) {
      save_cmdarg = set_cmdarg(eap, NULL);
      set_vim_var_nr(VV_CMDBANG, eap->forceit);
    } else {
      save_cmdarg = NULL;  // avoid gcc warning
    }

Review comment (suggestion):
Let me know if there's a better way to do this. This was required to get `v:event` working in the test.

Code after:
  // Don't redraw while doing autocommands.
  RedrawingDisabled++;

  // name and lnum are filled in later
  estack_push(ETYPE_AUCMD, NULL, 0);

  const sctx_T save_current_sctx = current_sctx;

  if (do_profiling == PROF_YES) {
    prof_child_enter(&wait_time);  // doesn't count for the caller itself
  }

  // Don't use local function variables, if called from a function.
  funccal_entry_T funccal_entry;
  save_funccal(&funccal_entry);

  // When starting to execute autocommands, save the search patterns.
  if (!autocmd_busy) {
    save_search_patterns();
    if (!ins_compl_active()) {
      saveRedobuff(&save_redo);
      did_save_redobuff = true;
    }
    curbuf->b_did_filetype = curbuf->b_keep_filetype;
  }

  // Note that we are applying autocmds.  Some commands need to know.
  autocmd_busy = true;
  filechangeshell_busy = (event == EVENT_FILECHANGEDSHELL);
  nesting++;  // see matching decrement below

  // Remember that FileType was triggered.  Used for did_filetype().
  if (event == EVENT_FILETYPE) {
    curbuf->b_did_filetype = true;
  }

  char *tail = path_tail(fname);

  // Find first autocommand that matches
  AutoPatCmd patcmd = {
    // aucmd_next will set lastpat back to NULL if there are no more autocommands left to run
    .lastpat = NULL,
    // current autocommand index
    .auidx = 0,
    // save vector size, to avoid an endless loop when more patterns
    // are added when executing autocommands
    .ausize = kv_size(autocmds[(int)event]),
    .afile_orig = afile_orig,
    .fname = fname,
    .sfname = sfname,
    .tail = tail,