Esempio n. 1
0
File: vim.c Progetto: Inzulus/neovim
/// Pass input keys to Neovim
///
/// @param keys to be typed
/// @param mode specifies the mapping options
/// @see feedkeys()
void vim_feedkeys(String keys, String mode)
{
  bool remap = true;
  bool typed = false;

  if (keys.size == 0) {
    return;
  }

  for (size_t i = 0; i < mode.size; ++i) {
    switch (mode.data[i]) {
    case 'n': remap = false; break;
    case 'm': remap = true; break;
    case 't': typed = true; break;
    }
  }

  /* Need to escape K_SPECIAL and CSI before putting the string in the
   * typeahead buffer. */
  char *keys_esc = (char *)vim_strsave_escape_csi((char_u *)keys.data);
  ins_typebuf((char_u *)keys_esc, (remap ? REMAP_YES : REMAP_NONE),
      typebuf.tb_len, !typed, false);
  free(keys_esc);

  if (vgetc_busy)
    typebuf_was_filled = true;
}
Esempio n. 2
0
/// Passes input keys to Nvim.
/// On VimL error: Does not fail, but updates v:errmsg.
///
/// @param keys         to be typed
/// @param mode         mapping options
/// @param escape_csi   If true, escape K_SPECIAL/CSI bytes in `keys`
/// @see feedkeys()
/// @see vim_strsave_escape_csi
void nvim_feedkeys(String keys, String mode, Boolean escape_csi)
{
  bool remap = true;
  bool insert = false;
  bool typed = false;
  bool execute = false;
  bool dangerous = false;

  for (size_t i = 0; i < mode.size; ++i) {
    switch (mode.data[i]) {
    case 'n': remap = false; break;
    case 'm': remap = true; break;
    case 't': typed = true; break;
    case 'i': insert = true; break;
    case 'x': execute = true; break;
    case '!': dangerous = true; break;
    }
  }

  if (keys.size == 0 && !execute) {
    return;
  }

  char *keys_esc;
  if (escape_csi) {
      // Need to escape K_SPECIAL and CSI before putting the string in the
      // typeahead buffer.
      keys_esc = (char *)vim_strsave_escape_csi((char_u *)keys.data);
  } else {
      keys_esc = keys.data;
  }
  ins_typebuf((char_u *)keys_esc, (remap ? REMAP_YES : REMAP_NONE),
      insert ? 0 : typebuf.tb_len, !typed, false);

  if (escape_csi) {
      xfree(keys_esc);
  }

  if (vgetc_busy) {
    typebuf_was_filled = true;
  }
  if (execute) {
    int save_msg_scroll = msg_scroll;

    /* Avoid a 1 second delay when the keys start Insert mode. */
    msg_scroll = false;
    if (!dangerous) {
      ex_normal_busy++;
    }
    exec_normal(true);
    if (!dangerous) {
      ex_normal_busy--;
    }
    msg_scroll |= save_msg_scroll;
  }
}
Esempio n. 3
0
/// Pass input keys to Neovim
///
/// @param keys to be typed
/// @param replace_tcodes If true replace special keys such as <CR> or <Leader>
///           for compatibility with Vim --remote-send expressions
/// @param remap If True remap keys
/// @param typed Handle keys as if typed; otherwise they are handled as
///           if coming from a mapping.  This matters for undo,
///           opening folds, etc.
void vim_feedkeys(String keys, Boolean replace_tcodes, Boolean remap,
                Boolean typed, Error *err)
{
  char *ptr = NULL;
  char *cpo_save = (char *)p_cpo;

  if (replace_tcodes) {
    // Set 'cpoptions' the way we want it.
    //    B set - backslashes are *not* treated specially
    //    k set - keycodes are *not* reverse-engineered
    //    < unset - <Key> sequences *are* interpreted
    //  The last but one parameter of replace_termcodes() is TRUE so that the
    //  <lt> sequence is recognised - needed for a real backslash.
    p_cpo = (char_u *)"Bk";
    replace_termcodes((char_u *)keys.data, (char_u **)&ptr, false, true, true);
    p_cpo = (char_u *)cpo_save;
  } else {
    ptr = keys.data;
  }

  if (ptr == NULL) {
    set_api_error("Failed to eval expression", err);
  } else {
    // Add the string to the input stream.
    // Can't use add_to_input_buf() here, we now have K_SPECIAL bytes.
    //
    // First clear typed characters from the typeahead buffer, there could
    // be half a mapping there.  Then append to the existing string, so
    // that multiple commands from a client are concatenated.
    if (typebuf.tb_maplen < typebuf.tb_len) {
        del_typebuf(typebuf.tb_len - typebuf.tb_maplen, typebuf.tb_maplen);
    }
    (void)ins_typebuf((char_u *)ptr, (remap ? REMAP_YES : REMAP_NONE),
                    typebuf.tb_len, !typed, false);

    // Let input_available() know we inserted text in the typeahead
    // buffer. */
    typebuf_was_filled = true;

    if (replace_tcodes) {
      free(ptr);
    }
  }
}
Esempio n. 4
0
File: vim.c Progetto: DINKIN/neovim
/// Passes input keys to Neovim
///
/// @param keys to be typed
/// @param mode specifies the mapping options
/// @param escape_csi the string needs escaping for K_SPECIAL/CSI bytes
/// @see feedkeys()
/// @see vim_strsave_escape_csi
void vim_feedkeys(String keys, String mode, Boolean escape_csi)
{
  bool remap = true;
  bool insert = false;
  bool typed = false;
  bool execute = false;

  if (keys.size == 0) {
    return;
  }

  for (size_t i = 0; i < mode.size; ++i) {
    switch (mode.data[i]) {
    case 'n': remap = false; break;
    case 'm': remap = true; break;
    case 't': typed = true; break;
    case 'i': insert = true; break;
    case 'x': execute = true; break;
    }
  }

  char *keys_esc;
  if (escape_csi) {
      // Need to escape K_SPECIAL and CSI before putting the string in the
      // typeahead buffer.
      keys_esc = (char *)vim_strsave_escape_csi((char_u *)keys.data);
  } else {
      keys_esc = keys.data;
  }
  ins_typebuf((char_u *)keys_esc, (remap ? REMAP_YES : REMAP_NONE),
      insert ? 0 : typebuf.tb_len, !typed, false);

  if (escape_csi) {
      xfree(keys_esc);
  }

  if (vgetc_busy) {
    typebuf_was_filled = true;
  }
  if (execute) {
    exec_normal(true);
  }
}
Esempio n. 5
0
/*
 * Given a menu descriptor, e.g. "File.New", find it in the menu hierarchy and
 * execute it.
 */
void ex_emenu(exarg_T *eap)
{
  vimmenu_T   *menu;
  char_u      *name;
  char_u      *saved_name;
  char_u      *p;
  int idx;
  char_u      *mode;

  saved_name = vim_strsave(eap->arg);

  menu = root_menu;
  name = saved_name;
  while (*name) {
    /* Find in the menu hierarchy */
    p = menu_name_skip(name);

    while (menu != NULL) {
      if (menu_name_equal(name, menu)) {
        if (*p == NUL && menu->children != NULL) {
          EMSG(_("E333: Menu path must lead to a menu item"));
          menu = NULL;
        } else if (*p != NUL && menu->children == NULL) {
          EMSG(_(e_notsubmenu));
          menu = NULL;
        }
        break;
      }
      menu = menu->next;
    }
    if (menu == NULL || *p == NUL)
      break;
    menu = menu->children;
    name = p;
  }
  free(saved_name);
  if (menu == NULL) {
    EMSG2(_("E334: Menu not found: %s"), eap->arg);
    return;
  }

  /* Found the menu, so execute.
   * Use the Insert mode entry when returning to Insert mode. */
  if (restart_edit
      && !current_SID
      ) {
    mode = (char_u *)"Insert";
    idx = MENU_INDEX_INSERT;
  } else if (eap->addr_count) {
    pos_T tpos;

    mode = (char_u *)"Visual";
    idx = MENU_INDEX_VISUAL;

    /* GEDDES: This is not perfect - but it is a
     * quick way of detecting whether we are doing this from a
     * selection - see if the range matches up with the visual
     * select start and end.  */
    if ((curbuf->b_visual.vi_start.lnum == eap->line1)
        && (curbuf->b_visual.vi_end.lnum) == eap->line2) {
      /* Set it up for visual mode - equivalent to gv.  */
      VIsual_mode = curbuf->b_visual.vi_mode;
      tpos = curbuf->b_visual.vi_end;
      curwin->w_cursor = curbuf->b_visual.vi_start;
      curwin->w_curswant = curbuf->b_visual.vi_curswant;
    } else {
      /* Set it up for line-wise visual mode */
      VIsual_mode = 'V';
      curwin->w_cursor.lnum = eap->line1;
      curwin->w_cursor.col = 1;
      tpos.lnum = eap->line2;
      tpos.col = MAXCOL;
      tpos.coladd = 0;
    }

    /* Activate visual mode */
    VIsual_active = TRUE;
    VIsual_reselect = TRUE;
    check_cursor();
    VIsual = curwin->w_cursor;
    curwin->w_cursor = tpos;

    check_cursor();

    /* Adjust the cursor to make sure it is in the correct pos
     * for exclusive mode */
    if (*p_sel == 'e' && gchar_cursor() != NUL)
      ++curwin->w_cursor.col;
  } else {
    mode = (char_u *)"Normal";
    idx = MENU_INDEX_NORMAL;
  }

  if (idx != MENU_INDEX_INVALID && menu->strings[idx] != NULL) {
    /* When executing a script or function execute the commands right now.
     * Otherwise put them in the typeahead buffer. */
    if (current_SID != 0)
      exec_normal_cmd(menu->strings[idx], menu->noremap[idx],
          menu->silent[idx]);
    else
      ins_typebuf(menu->strings[idx], menu->noremap[idx], 0,
          TRUE, menu->silent[idx]);
  } else
    EMSG2(_("E335: Menu not defined for %s mode"), mode);
}