# HG changeset patch # User Bram Moolenaar # Date 1564662607 -7200 # Node ID 97a750e8707f9b79968c0e196f4424bb3acc2b18 # Parent b2a246caeb257474280450845c56d12e4cebe0f8 patch 8.1.1785: map functionality mixed with character input commit https://github.com/vim/vim/commit/b66bab381c8ba71fd6e92327d1d34c6f8a65f2a7 Author: Bram Moolenaar Date: Thu Aug 1 14:28:24 2019 +0200 patch 8.1.1785: map functionality mixed with character input Problem: Map functionality mixed with character input. Solution: Move the map functionality to a separate file. (Yegappan Lakshmanan, closes #4740) Graduate the +localmap feature. diff --git a/Filelist b/Filelist --- a/Filelist +++ b/Filelist @@ -60,6 +60,7 @@ SRC_ALL = \ src/keymap.h \ src/macros.h \ src/main.c \ + src/map.c \ src/mark.c \ src/mbyte.c \ src/memfile.c \ @@ -199,6 +200,7 @@ SRC_ALL = \ src/proto/json.pro \ src/proto/list.pro \ src/proto/main.pro \ + src/proto/map.pro \ src/proto/mark.pro \ src/proto/mbyte.pro \ src/proto/memfile.pro \ diff --git a/src/Make_cyg_ming.mak b/src/Make_cyg_ming.mak --- a/src/Make_cyg_ming.mak +++ b/src/Make_cyg_ming.mak @@ -736,6 +736,7 @@ OBJ = \ $(OUTDIR)/json.o \ $(OUTDIR)/list.o \ $(OUTDIR)/main.o \ + $(OUTDIR)/map.o \ $(OUTDIR)/mark.o \ $(OUTDIR)/memfile.o \ $(OUTDIR)/memline.o \ diff --git a/src/Make_morph.mak b/src/Make_morph.mak --- a/src/Make_morph.mak +++ b/src/Make_morph.mak @@ -56,6 +56,7 @@ SRC = arabic.c \ json.c \ list.c \ main.c \ + map.c \ mark.c \ mbyte.c \ memfile.c \ diff --git a/src/Make_mvc.mak b/src/Make_mvc.mak --- a/src/Make_mvc.mak +++ b/src/Make_mvc.mak @@ -745,6 +745,7 @@ OBJ = \ $(OUTDIR)\json.obj \ $(OUTDIR)\list.obj \ $(OUTDIR)\main.obj \ + $(OUTDIR)\map.obj \ $(OUTDIR)\mark.obj \ $(OUTDIR)\mbyte.obj \ $(OUTDIR)\memfile.obj \ @@ -1556,6 +1557,8 @@ lib$(MZSCHEME_MAIN_LIB)$(MZSCHEME_VER).l $(OUTDIR)/main.obj: $(OUTDIR) main.c $(INCL) $(CUI_INCL) +$(OUTDIR)/map.obj: $(OUTDIR) map.c $(INCL) + $(OUTDIR)/mark.obj: $(OUTDIR) mark.c $(INCL) $(OUTDIR)/memfile.obj: $(OUTDIR) memfile.c $(INCL) @@ -1769,6 +1772,7 @@ proto.h: \ proto/json.pro \ proto/list.pro \ proto/main.pro \ + proto/map.pro \ proto/mark.pro \ proto/memfile.pro \ proto/memline.pro \ diff --git a/src/Make_vms.mms b/src/Make_vms.mms --- a/src/Make_vms.mms +++ b/src/Make_vms.mms @@ -312,8 +312,8 @@ SRC = arabic.c autocmd.c beval.c blob.c evalfunc.c ex_cmds.c ex_cmds2.c ex_docmd.c ex_eval.c ex_getln.c \ if_cscope.c if_xcmdsrv.c fileio.c findfile.c fold.c getchar.c \ hardcopy.c hashtab.c highlight.c indent.c insexpand.c json.c list.c \ - main.c mark.c menu.c mbyte.c memfile.c memline.c message.c misc1.c \ - misc2.c move.c normal.c ops.c option.c popupmnu.c popupwin.c \ + main.c map.c mark.c menu.c mbyte.c memfile.c memline.c message.c \ + misc1.c misc2.c move.c normal.c ops.c option.c popupmnu.c popupwin.c \ profiler.c quickfix.c regexp.c search.c session.c sha256.c sign.c \ spell.c spellfile.c syntax.c tag.c term.c termlib.c testing.c \ textprop.c ui.c undo.c usercmd.c userfunc.c version.c viminfo.c \ @@ -327,8 +327,8 @@ OBJ = arabic.obj autocmd.obj beval.obj ex_docmd.obj ex_eval.obj ex_getln.obj if_cscope.obj if_xcmdsrv.obj \ fileio.obj findfile.obj fold.obj getchar.obj hardcopy.obj hashtab.obj \ highlight.obj indent.obj insexpand.obj json.obj list.obj main.obj \ - mark.obj menu.obj memfile.obj memline.obj message.obj misc1.obj \ - misc2.obj move.obj mbyte.obj normal.obj ops.obj option.obj \ + map.obj mark.obj menu.obj memfile.obj memline.obj message.obj \ + misc1.obj misc2.obj move.obj mbyte.obj normal.obj ops.obj option.obj \ popupmnu.obj popupwin.obj profiler.obj quickfix.obj regexp.obj \ search.obj session.obj sha256.obj sign.obj spell.obj spellfile.obj \ syntax.obj tag.obj term.obj termlib.obj testing.obj textprop.obj \ @@ -630,6 +630,9 @@ main.obj : main.c vim.h [.auto]config.h ascii.h keymap.h term.h macros.h structs.h regexp.h gui.h beval.h \ [.proto]gui_beval.pro option.h ex_cmds.h proto.h globals.h \ arabic.c +map.obj : map.c vim.h [.auto]config.h feature.h os_unix.h \ + ascii.h keymap.h term.h macros.h structs.h regexp.h gui.h beval.h \ + [.proto]gui_beval.pro option.h ex_cmds.h proto.h globals.h \ mark.obj : mark.c vim.h [.auto]config.h feature.h os_unix.h \ ascii.h keymap.h term.h macros.h structs.h regexp.h gui.h beval.h \ [.proto]gui_beval.pro option.h ex_cmds.h proto.h globals.h \ diff --git a/src/Makefile b/src/Makefile --- a/src/Makefile +++ b/src/Makefile @@ -1612,6 +1612,7 @@ BASIC_SRC = \ json.c \ list.c \ main.c \ + map.c \ mark.c \ memfile.c \ memline.c \ @@ -1735,6 +1736,7 @@ OBJ_COMMON = \ objects/indent.o \ objects/insexpand.o \ objects/list.o \ + objects/map.o \ objects/mark.o \ objects/memline.o \ objects/menu.o \ @@ -1879,6 +1881,7 @@ PRO_AUTO = \ json.pro \ list.pro \ main.pro \ + map.pro \ mark.pro \ mbyte.pro \ memfile.pro \ @@ -3169,6 +3172,9 @@ objects/list.o: list.c objects/main.o: main.c $(CCC) -o $@ main.c +objects/map.o: map.c + $(CCC) -o $@ map.c + objects/mark.o: mark.c $(CCC) -o $@ mark.c @@ -3604,6 +3610,10 @@ objects/main.o: main.c vim.h protodef.h auto/osdef.h ascii.h keymap.h term.h macros.h option.h beval.h \ proto/gui_beval.pro structs.h regexp.h gui.h alloc.h ex_cmds.h spell.h \ proto.h globals.h +objects/map.o: map.c vim.h protodef.h auto/config.h feature.h os_unix.h \ + auto/osdef.h ascii.h keymap.h term.h macros.h option.h beval.h \ + proto/gui_beval.pro structs.h regexp.h gui.h alloc.h ex_cmds.h spell.h \ + proto.h globals.h objects/mark.o: mark.c vim.h protodef.h auto/config.h feature.h os_unix.h \ auto/osdef.h ascii.h keymap.h term.h macros.h option.h beval.h \ proto/gui_beval.pro structs.h regexp.h gui.h alloc.h ex_cmds.h spell.h \ diff --git a/src/README.md b/src/README.md --- a/src/README.md +++ b/src/README.md @@ -38,6 +38,7 @@ highlight.c | syntax highlighting indent.c | C and Lisp indentation insexpand.c | Insert mode completion mark.c | marks +map.c | mapping and abbreviations mbyte.c | multi-byte character handling memfile.c | storing lines for buffers in a swapfile memline.c | storing lines for buffers in memory diff --git a/src/buffer.c b/src/buffer.c --- a/src/buffer.c +++ b/src/buffer.c @@ -951,10 +951,8 @@ free_buffer_stuff( #ifdef FEAT_NETBEANS_INTG netbeans_file_killed(buf); #endif -#ifdef FEAT_LOCALMAP map_clear_int(buf, MAP_ALL_MODES, TRUE, FALSE); /* clear local mappings */ map_clear_int(buf, MAP_ALL_MODES, TRUE, TRUE); /* clear local abbrevs */ -#endif VIM_CLEAR(buf->b_start_fenc); } diff --git a/src/evalfunc.c b/src/evalfunc.c --- a/src/evalfunc.c +++ b/src/evalfunc.c @@ -6189,9 +6189,7 @@ f_has(typval_T *argvars, typval_T *rettv "lispindent", #endif "listcmds", -#ifdef FEAT_LOCALMAP "localmap", -#endif #ifdef FEAT_LUA # ifndef DYNAMIC_LUA "lua", @@ -7396,84 +7394,6 @@ f_localtime(typval_T *argvars UNUSED, ty rettv->vval.v_number = (varnumber_T)time(NULL); } - static void -get_maparg(typval_T *argvars, typval_T *rettv, int exact) -{ - char_u *keys; - char_u *which; - char_u buf[NUMBUFLEN]; - char_u *keys_buf = NULL; - char_u *rhs; - int mode; - int abbr = FALSE; - int get_dict = FALSE; - mapblock_T *mp; - int buffer_local; - - /* return empty string for failure */ - rettv->v_type = VAR_STRING; - rettv->vval.v_string = NULL; - - keys = tv_get_string(&argvars[0]); - if (*keys == NUL) - return; - - if (argvars[1].v_type != VAR_UNKNOWN) - { - which = tv_get_string_buf_chk(&argvars[1], buf); - if (argvars[2].v_type != VAR_UNKNOWN) - { - abbr = (int)tv_get_number(&argvars[2]); - if (argvars[3].v_type != VAR_UNKNOWN) - get_dict = (int)tv_get_number(&argvars[3]); - } - } - else - which = (char_u *)""; - if (which == NULL) - return; - - mode = get_map_mode(&which, 0); - - keys = replace_termcodes(keys, &keys_buf, TRUE, TRUE, FALSE); - rhs = check_map(keys, mode, exact, FALSE, abbr, &mp, &buffer_local); - vim_free(keys_buf); - - if (!get_dict) - { - /* Return a string. */ - if (rhs != NULL) - { - if (*rhs == NUL) - rettv->vval.v_string = vim_strsave((char_u *)""); - else - rettv->vval.v_string = str2special_save(rhs, FALSE); - } - - } - else if (rettv_dict_alloc(rettv) != FAIL && rhs != NULL) - { - /* Return a dictionary. */ - char_u *lhs = str2special_save(mp->m_keys, TRUE); - char_u *mapmode = map_mode_to_chars(mp->m_mode); - dict_T *dict = rettv->vval.v_dict; - - dict_add_string(dict, "lhs", lhs); - dict_add_string(dict, "rhs", mp->m_orig_str); - dict_add_number(dict, "noremap", mp->m_noremap ? 1L : 0L); - dict_add_number(dict, "expr", mp->m_expr ? 1L : 0L); - dict_add_number(dict, "silent", mp->m_silent ? 1L : 0L); - dict_add_number(dict, "sid", (long)mp->m_script_ctx.sc_sid); - dict_add_number(dict, "lnum", (long)mp->m_script_ctx.sc_lnum); - dict_add_number(dict, "buffer", (long)buffer_local); - dict_add_number(dict, "nowait", mp->m_nowait ? 1L : 0L); - dict_add_string(dict, "mode", mapmode); - - vim_free(lhs); - vim_free(mapmode); - } -} - #ifdef FEAT_FLOAT /* * "log()" function diff --git a/src/ex_docmd.c b/src/ex_docmd.c --- a/src/ex_docmd.c +++ b/src/ex_docmd.c @@ -29,11 +29,6 @@ static void free_cmdmod(void); static void append_command(char_u *cmd); static char_u *find_command(exarg_T *eap, int *full); -static void ex_abbreviate(exarg_T *eap); -static void ex_map(exarg_T *eap); -static void ex_unmap(exarg_T *eap); -static void ex_mapclear(exarg_T *eap); -static void ex_abclear(exarg_T *eap); #ifndef FEAT_MENU # define ex_emenu ex_ni # define ex_menu ex_ni @@ -231,7 +226,6 @@ static void ex_read(exarg_T *eap); static void ex_pwd(exarg_T *eap); static void ex_equal(exarg_T *eap); static void ex_sleep(exarg_T *eap); -static void do_exmap(exarg_T *eap, int isabbrev); static void ex_winsize(exarg_T *eap); static void ex_wincmd(exarg_T *eap); #if defined(FEAT_GUI) || defined(UNIX) || defined(VMS) || defined(MSWIN) @@ -5347,61 +5341,6 @@ getargopt(exarg_T *eap) return OK; } -/* - * ":abbreviate" and friends. - */ - static void -ex_abbreviate(exarg_T *eap) -{ - do_exmap(eap, TRUE); /* almost the same as mapping */ -} - -/* - * ":map" and friends. - */ - static void -ex_map(exarg_T *eap) -{ - /* - * If we are sourcing .exrc or .vimrc in current directory we - * print the mappings for security reasons. - */ - if (secure) - { - secure = 2; - msg_outtrans(eap->cmd); - msg_putchar('\n'); - } - do_exmap(eap, FALSE); -} - -/* - * ":unmap" and friends. - */ - static void -ex_unmap(exarg_T *eap) -{ - do_exmap(eap, FALSE); -} - -/* - * ":mapclear" and friends. - */ - static void -ex_mapclear(exarg_T *eap) -{ - map_clear(eap->cmd, eap->arg, eap->forceit, FALSE); -} - -/* - * ":abclear" and friends. - */ - static void -ex_abclear(exarg_T *eap) -{ - map_clear(eap->cmd, eap->arg, TRUE, TRUE); -} - static void ex_autocmd(exarg_T *eap) { @@ -7782,25 +7721,6 @@ do_sleep(long msec) (void)vpeekc(); } - static void -do_exmap(exarg_T *eap, int isabbrev) -{ - int mode; - char_u *cmdp; - - cmdp = eap->cmd; - mode = get_map_mode(&cmdp, eap->forceit || isabbrev); - - switch (do_map((*cmdp == 'n') ? 2 : (*cmdp == 'u'), - eap->arg, mode, isabbrev)) - { - case 1: emsg(_(e_invarg)); - break; - case 2: emsg((isabbrev ? _(e_noabbr) : _(e_nomap))); - break; - } -} - /* * ":winsize" command (obsolete). */ diff --git a/src/feature.h b/src/feature.h --- a/src/feature.h +++ b/src/feature.h @@ -166,10 +166,8 @@ /* * +localmap Mappings and abbreviations local to a buffer. + * Now always included. */ -#ifdef FEAT_NORMAL -# define FEAT_LOCALMAP -#endif /* * +insert_expand CTRL-N/CTRL-P/CTRL-X in insert mode. Takes about diff --git a/src/getchar.c b/src/getchar.c --- a/src/getchar.c +++ b/src/getchar.c @@ -52,26 +52,6 @@ static int typeahead_char = 0; /* typea */ static int block_redo = FALSE; -/* - * Make a hash value for a mapping. - * "mode" is the lower 4 bits of the State for the mapping. - * "c1" is the first character of the "lhs". - * Returns a value between 0 and 255, index in maphash. - * Put Normal/Visual mode mappings mostly separately from Insert/Cmdline mode. - */ -#define MAP_HASH(mode, c1) (((mode) & (NORMAL + VISUAL + SELECTMODE + OP_PENDING + TERMINAL)) ? (c1) : ((c1) ^ 0x80)) - -/* - * Each mapping is put in one of the 256 hash lists, to speed up finding it. - */ -static mapblock_T *(maphash[256]); -static int maphash_valid = FALSE; - -/* - * List used for abbreviations. - */ -static mapblock_T *first_abbr = NULL; /* first entry in abbrlist */ - static int KeyNoremap = 0; /* remapping flags */ /* @@ -113,13 +93,7 @@ static void init_typebuf(void); static void may_sync_undo(void); static void closescript(void); static int vgetorpeek(int); -static void map_free(mapblock_T **); -static void validate_maphash(void); -static void showmap(mapblock_T *mp, int local); static int inchar(char_u *buf, int maxlen, long wait_time); -#ifdef FEAT_EVAL -static char_u *eval_map_expr(char_u *str, int c); -#endif /* * Free and clear a buffer. @@ -911,6 +885,15 @@ init_typebuf(void) } /* + * Returns TRUE when keys cannot be remapped. + */ + int +noremap_keys(void) +{ + return KeyNoremap & (RM_NONE|RM_SCRIPT); +} + +/* * Insert a string in position 'offset' in the typeahead buffer (for "@r" * and ":normal" command, vgetorpeek() and check_termcode()). * @@ -1962,9 +1945,7 @@ vgetorpeek(int advance) int keylen; char_u *s; mapblock_T *mp; -#ifdef FEAT_LOCALMAP mapblock_T *mp2; -#endif mapblock_T *mp_match; int mp_match_len = 0; int timedout = FALSE; /* waited for more than 1 second @@ -2112,7 +2093,7 @@ vgetorpeek(int advance) mp = NULL; max_mlen = 0; c1 = typebuf.tb_buf[typebuf.tb_off]; - if (no_mapping == 0 && maphash_valid + if (no_mapping == 0 && is_maphash_valid() && (no_zero_mapping == 0 || c1 != '0') && (typebuf.tb_maplen == 0 || (p_remap @@ -2141,19 +2122,15 @@ vgetorpeek(int advance) nolmaplen = 0; } #endif -#ifdef FEAT_LOCALMAP - /* First try buffer-local mappings. */ - mp = curbuf->b_maphash[MAP_HASH(local_State, c1)]; - mp2 = maphash[MAP_HASH(local_State, c1)]; + // First try buffer-local mappings. + mp = get_buf_maphash_list(local_State, c1); + mp2 = get_maphash_list(local_State, c1); if (mp == NULL) { - /* There are no buffer-local mappings. */ + // There are no buffer-local mappings. mp = mp2; mp2 = NULL; } -#else - mp = maphash[MAP_HASH(local_State, c1)]; -#endif /* * Loop until a partly matching mapping is found or * all (local) mappings have been checked. @@ -2164,10 +2141,8 @@ vgetorpeek(int advance) mp_match = NULL; mp_match_len = 0; for ( ; mp != NULL; -#ifdef FEAT_LOCALMAP - mp->m_next == NULL ? (mp = mp2, mp2 = NULL) : -#endif - (mp = mp->m_next)) + mp->m_next == NULL ? (mp = mp2, mp2 = NULL) + : (mp = mp->m_next)) { /* * Only consider an entry if the first character @@ -3194,2196 +3169,3 @@ input_available(void) ); } #endif - -/* - * map[!] : show all key mappings - * map[!] {lhs} : show key mapping for {lhs} - * map[!] {lhs} {rhs} : set key mapping for {lhs} to {rhs} - * noremap[!] {lhs} {rhs} : same, but no remapping for {rhs} - * unmap[!] {lhs} : remove key mapping for {lhs} - * abbr : show all abbreviations - * abbr {lhs} : show abbreviations for {lhs} - * abbr {lhs} {rhs} : set abbreviation for {lhs} to {rhs} - * noreabbr {lhs} {rhs} : same, but no remapping for {rhs} - * unabbr {lhs} : remove abbreviation for {lhs} - * - * maptype: 0 for :map, 1 for :unmap, 2 for noremap. - * - * arg is pointer to any arguments. Note: arg cannot be a read-only string, - * it will be modified. - * - * for :map mode is NORMAL + VISUAL + SELECTMODE + OP_PENDING - * for :map! mode is INSERT + CMDLINE - * for :cmap mode is CMDLINE - * for :imap mode is INSERT - * for :lmap mode is LANGMAP - * for :nmap mode is NORMAL - * for :vmap mode is VISUAL + SELECTMODE - * for :xmap mode is VISUAL - * for :smap mode is SELECTMODE - * for :omap mode is OP_PENDING - * for :tmap mode is TERMINAL - * - * for :abbr mode is INSERT + CMDLINE - * for :iabbr mode is INSERT - * for :cabbr mode is CMDLINE - * - * Return 0 for success - * 1 for invalid arguments - * 2 for no match - * 4 for out of mem - * 5 for entry not unique - */ - int -do_map( - int maptype, - char_u *arg, - int mode, - int abbrev) /* not a mapping but an abbreviation */ -{ - char_u *keys; - mapblock_T *mp, **mpp; - char_u *rhs; - char_u *p; - int n; - int len = 0; /* init for GCC */ - char_u *newstr; - int hasarg; - int haskey; - int did_it = FALSE; -#ifdef FEAT_LOCALMAP - int did_local = FALSE; -#endif - int round; - char_u *keys_buf = NULL; - char_u *arg_buf = NULL; - int retval = 0; - int do_backslash; - int hash; - int new_hash; - mapblock_T **abbr_table; - mapblock_T **map_table; - int unique = FALSE; - int nowait = FALSE; - int silent = FALSE; - int special = FALSE; -#ifdef FEAT_EVAL - int expr = FALSE; -#endif - int noremap; - char_u *orig_rhs; - - keys = arg; - map_table = maphash; - abbr_table = &first_abbr; - - /* For ":noremap" don't remap, otherwise do remap. */ - if (maptype == 2) - noremap = REMAP_NONE; - else - noremap = REMAP_YES; - - /* Accept , , ,