void set_map(char *from, char *to) { log_msg("INPUT", "<<-- from: %s to: %s", from, to); fn_map *mp = malloc(sizeof(fn_map)); replace_termcodes(&mp->lhs, from); mp->len = replace_termcodes(&mp->rhs, to); key_maps[0][(int)mp->lhs[0]] = mp; }
/// Replace any terminal codes with the internal representation /// /// @see replace_termcodes /// @see cpoptions String vim_replace_termcodes(String str, Boolean from_part, Boolean do_lt, Boolean special) { if (str.size == 0) { // Empty string return str; } char *ptr = NULL; replace_termcodes((char_u *)str.data, (char_u **)&ptr, from_part, do_lt, special); return cstr_as_string(ptr); }
/// 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); } } }
/// Replaces any terminal codes with the internal representation /// /// @see replace_termcodes /// @see cpoptions String vim_replace_termcodes(String str, Boolean from_part, Boolean do_lt, Boolean special) { if (str.size == 0) { // Empty string return str; } char *ptr = NULL; // Set 'cpoptions' the way we want it. // FLAG_CPO_BSLASH set - backslashes are *not* treated specially // FLAG_CPO_KEYCODE set - keycodes are *not* reverse-engineered // FLAG_CPO_SPECI unset - <Key> sequences *are* interpreted // The third from end parameter of replace_termcodes() is true so that the // <lt> sequence is recognised - needed for a real backslash. replace_termcodes((char_u *)str.data, str.size, (char_u **)&ptr, from_part, do_lt, special, CPO_TO_CPO_FLAGS); return cstr_as_string(ptr); }
/* * Do the :menu command and relatives. */ void ex_menu ( exarg_T *eap /* Ex command arguments */ ) { char_u *menu_path; int modes; char_u *map_to; int noremap; int silent = FALSE; int special = FALSE; int unmenu; char_u *map_buf; char_u *arg; char_u *p; int i; int pri_tab[MENUDEPTH + 1]; int enable = MAYBE; /* TRUE for "menu enable", FALSE for "menu * disable */ vimmenu_T menuarg; modes = get_menu_cmd_modes(eap->cmd, eap->forceit, &noremap, &unmenu); arg = eap->arg; for (;; ) { if (STRNCMP(arg, "<script>", 8) == 0) { noremap = REMAP_SCRIPT; arg = skipwhite(arg + 8); continue; } if (STRNCMP(arg, "<silent>", 8) == 0) { silent = TRUE; arg = skipwhite(arg + 8); continue; } if (STRNCMP(arg, "<special>", 9) == 0) { special = TRUE; arg = skipwhite(arg + 9); continue; } break; } /* Locate an optional "icon=filename" argument. */ if (STRNCMP(arg, "icon=", 5) == 0) { arg += 5; while (*arg != NUL && *arg != ' ') { if (*arg == '\\') STRMOVE(arg, arg + 1); mb_ptr_adv(arg); } if (*arg != NUL) { *arg++ = NUL; arg = skipwhite(arg); } } /* * Fill in the priority table. */ for (p = arg; *p; ++p) if (!VIM_ISDIGIT(*p) && *p != '.') break; if (vim_iswhite(*p)) { for (i = 0; i < MENUDEPTH && !vim_iswhite(*arg); ++i) { pri_tab[i] = getdigits_int(&arg); if (pri_tab[i] == 0) pri_tab[i] = 500; if (*arg == '.') ++arg; } arg = skipwhite(arg); } else if (eap->addr_count && eap->line2 != 0) { pri_tab[0] = eap->line2; i = 1; } else i = 0; while (i < MENUDEPTH) pri_tab[i++] = 500; pri_tab[MENUDEPTH] = -1; /* mark end of the table */ /* * Check for "disable" or "enable" argument. */ if (STRNCMP(arg, "enable", 6) == 0 && vim_iswhite(arg[6])) { enable = TRUE; arg = skipwhite(arg + 6); } else if (STRNCMP(arg, "disable", 7) == 0 && vim_iswhite(arg[7])) { enable = FALSE; arg = skipwhite(arg + 7); } /* * If there is no argument, display all menus. */ if (*arg == NUL) { show_menus(arg, modes); return; } menu_path = arg; if (*menu_path == '.') { EMSG2(_(e_invarg2), menu_path); goto theend; } map_to = menu_translate_tab_and_shift(arg); /* * If there is only a menu name, display menus with that name. */ if (*map_to == NUL && !unmenu && enable == MAYBE) { show_menus(menu_path, modes); goto theend; } else if (*map_to != NUL && (unmenu || enable != MAYBE)) { EMSG(_(e_trailing)); goto theend; } if (enable != MAYBE) { /* * Change sensitivity of the menu. * For the PopUp menu, remove a menu for each mode separately. * Careful: menu_nable_recurse() changes menu_path. */ if (STRCMP(menu_path, "*") == 0) /* meaning: do all menus */ menu_path = (char_u *)""; if (menu_is_popup(menu_path)) { for (i = 0; i < MENU_INDEX_TIP; ++i) if (modes & (1 << i)) { p = popup_mode_name(menu_path, i); menu_nable_recurse(root_menu, p, MENU_ALL_MODES, enable); free(p); } } menu_nable_recurse(root_menu, menu_path, modes, enable); } else if (unmenu) { /* * Delete menu(s). */ if (STRCMP(menu_path, "*") == 0) /* meaning: remove all menus */ menu_path = (char_u *)""; /* * For the PopUp menu, remove a menu for each mode separately. */ if (menu_is_popup(menu_path)) { for (i = 0; i < MENU_INDEX_TIP; ++i) if (modes & (1 << i)) { p = popup_mode_name(menu_path, i); remove_menu(&root_menu, p, MENU_ALL_MODES, TRUE); free(p); } } /* Careful: remove_menu() changes menu_path */ remove_menu(&root_menu, menu_path, modes, FALSE); } else { /* * Add menu(s). * Replace special key codes. */ if (STRICMP(map_to, "<nop>") == 0) { /* "<Nop>" means nothing */ map_to = (char_u *)""; map_buf = NULL; } else if (modes & MENU_TIP_MODE) map_buf = NULL; /* Menu tips are plain text. */ else map_to = replace_termcodes(map_to, &map_buf, FALSE, TRUE, special); menuarg.modes = modes; menuarg.noremap[0] = noremap; menuarg.silent[0] = silent; add_menu_path(menu_path, &menuarg, pri_tab, map_to ); /* * For the PopUp menu, add a menu for each mode separately. */ if (menu_is_popup(menu_path)) { for (i = 0; i < MENU_INDEX_TIP; ++i) if (modes & (1 << i)) { p = popup_mode_name(menu_path, i); // Include all modes, to make ":amenu" work menuarg.modes = modes; add_menu_path(p, &menuarg, pri_tab, map_to); free(p); } } free(map_buf); } theend: ; }