4 From: Bram Moolenaar <Bram@moolenaar.net>
6 Content-Type: text/plain; charset=UTF-8
7 Content-Transfer-Encoding: 8bit
11 Problem: maparg() doesn't return the flags, such as <buffer>, <script>,
12 <silent>. These are needed to save and restore a mapping.
13 Solution: Improve maparg(). (also by Christian Brabandt)
14 Files: runtime/doc/eval.txt, src/eval.c, src/getchar.c, src/gui_w48.c, src/message.c, src/proto/getchar.pro, src/proto/message.pro, src/structs.h src/testdir/test75.in, src/testdir/test75.ok
17 *** ../vim-7.3.031/runtime/doc/eval.txt 2010-10-20 19:17:43.000000000 +0200
18 --- runtime/doc/eval.txt 2010-10-20 19:44:41.000000000 +0200
21 log( {expr}) Float natural logarithm (base e) of {expr}
22 log10( {expr}) Float logarithm of Float {expr} to base 10
23 map( {expr}, {string}) List/Dict change each item in {expr} to {expr}
24 ! maparg( {name}[, {mode} [, {abbr}]])
25 String rhs of mapping {name} in mode {mode}
26 mapcheck( {name}[, {mode} [, {abbr}]])
27 String check for mappings matching {name}
29 log( {expr}) Float natural logarithm (base e) of {expr}
30 log10( {expr}) Float logarithm of Float {expr} to base 10
31 map( {expr}, {string}) List/Dict change each item in {expr} to {expr}
32 ! maparg( {name}[, {mode} [, {abbr} [, {dict}]]])
33 String rhs of mapping {name} in mode {mode}
34 mapcheck( {name}[, {mode} [, {abbr}]])
35 String check for mappings matching {name}
38 further items in {expr} are processed.
41 ! maparg({name}[, {mode} [, {abbr}]]) *maparg()*
42 ! Return the rhs of mapping {name} in mode {mode}. When there
43 ! is no mapping for {name}, an empty String is returned.
44 {mode} can be one of these strings:
50 "l" langmap |language-mapping|
51 "" Normal, Visual and Operator-pending
52 When {mode} is omitted, the modes for "" are used.
53 When {abbr} is there and it is non-zero use abbreviations
55 ! The {name} can have special key names, like in the ":map"
56 ! command. The returned String has special characters
57 ! translated like in the output of the ":map" command listing.
58 The mappings local to the current buffer are checked first,
59 then the global mappings.
60 This function can be used to map a key even when it's already
62 further items in {expr} are processed.
65 ! maparg({name}[, {mode} [, {abbr} [, {dict}]]]) *maparg()*
66 ! When {dict} is omitted or zero: Return the rhs of mapping
67 ! {name} in mode {mode}. The returned String has special
68 ! characters translated like in the output of the ":map" command
71 ! When there is no mapping for {name}, an empty String is
74 ! The {name} can have special key names, like in the ":map"
77 {mode} can be one of these strings:
79 ! "v" Visual (including Select)
85 "l" langmap |language-mapping|
86 "" Normal, Visual and Operator-pending
87 When {mode} is omitted, the modes for "" are used.
89 When {abbr} is there and it is non-zero use abbreviations
92 ! When {dict} is there and it is non-zero return a dictionary
93 ! containing all the information of the mapping with the
95 ! "lhs" The {lhs} of the mapping.
96 ! "rhs" The {rhs} of the mapping as typed.
97 ! "silent" 1 for a |:map-silent| mapping, else 0.
98 ! "noremap" 1 if the {rhs} of the mapping is remappable.
99 ! "expr" 1 for an expression mapping (|:map-<expr>|).
100 ! "buffer" 1 for a buffer local mapping (|:map-local|).
101 ! "mode" Modes for which the mapping is defined. In
102 ! addition to the modes mentioned above, these
103 ! characters will be used:
104 ! " " Normal, Visual and Operator-pending
105 ! "!" Insert and Commandline mode
107 ! "sid" the Script local ID, used for <sid> mappings
110 The mappings local to the current buffer are checked first,
111 then the global mappings.
112 This function can be used to map a key even when it's already
113 *** ../vim-7.3.031/src/eval.c 2010-10-20 19:17:43.000000000 +0200
114 --- src/eval.c 2010-10-20 21:15:55.000000000 +0200
117 {"log10", 1, 1, f_log10},
119 {"map", 2, 2, f_map},
120 ! {"maparg", 1, 3, f_maparg},
121 {"mapcheck", 1, 3, f_mapcheck},
122 {"match", 2, 4, f_match},
123 {"matchadd", 2, 4, f_matchadd},
125 {"log10", 1, 1, f_log10},
127 {"map", 2, 2, f_map},
128 ! {"maparg", 1, 4, f_maparg},
129 {"mapcheck", 1, 3, f_mapcheck},
130 {"match", 2, 4, f_match},
131 {"matchadd", 2, 4, f_matchadd},
134 char_u *keys_buf = NULL;
140 /* return empty string for failure */
141 rettv->v_type = VAR_STRING;
143 char_u *keys_buf = NULL;
147 + int get_dict = FALSE;
151 /* return empty string for failure */
152 rettv->v_type = VAR_STRING;
157 which = get_tv_string_buf_chk(&argvars[1], buf);
158 if (argvars[2].v_type != VAR_UNKNOWN)
160 abbr = get_tv_number(&argvars[2]);
161 + if (argvars[3].v_type != VAR_UNKNOWN)
162 + get_dict = get_tv_number(&argvars[3]);
166 which = (char_u *)"";
169 mode = get_map_mode(&which, 0);
171 keys = replace_termcodes(keys, &keys_buf, TRUE, TRUE, FALSE);
172 ! rhs = check_map(keys, mode, exact, FALSE, abbr);
177 - ga.ga_itemsize = 1;
178 - ga.ga_growsize = 40;
180 ! while (*rhs != NUL)
181 ! ga_concat(&ga, str2special(&rhs, FALSE));
183 ! ga_append(&ga, NUL);
184 ! rettv->vval.v_string = (char_u *)ga.ga_data;
189 mode = get_map_mode(&which, 0);
191 keys = replace_termcodes(keys, &keys_buf, TRUE, TRUE, FALSE);
192 ! rhs = check_map(keys, mode, exact, FALSE, abbr, &mp, &buffer_local);
197 ! /* Return a string. */
199 ! rettv->vval.v_string = str2special_save(rhs, FALSE);
202 ! else if (rettv_dict_alloc(rettv) != FAIL && rhs != NULL)
204 ! /* Return a dictionary. */
205 ! char_u *lhs = str2special_save(mp->m_keys, TRUE);
206 ! char_u *mapmode = map_mode_to_chars(mp->m_mode);
207 ! dict_T *dict = rettv->vval.v_dict;
209 ! dict_add_nr_str(dict, "lhs", 0L, lhs);
210 ! dict_add_nr_str(dict, "rhs", 0L, mp->m_orig_str);
211 ! dict_add_nr_str(dict, "noremap", mp->m_noremap ? 1L : 0L , NULL);
212 ! dict_add_nr_str(dict, "expr", mp->m_expr ? 1L : 0L, NULL);
213 ! dict_add_nr_str(dict, "silent", mp->m_silent ? 1L : 0L, NULL);
214 ! dict_add_nr_str(dict, "sid", (long)mp->m_script_ID, NULL);
215 ! dict_add_nr_str(dict, "buffer", (long)buffer_local, NULL);
216 ! dict_add_nr_str(dict, "mode", 0L, mapmode);
223 *** ../vim-7.3.031/src/getchar.c 2010-08-15 21:57:25.000000000 +0200
224 --- src/getchar.c 2010-10-20 21:16:24.000000000 +0200
244 hasarg = (*rhs != NUL);
248 keys = replace_termcodes(keys, &keys_buf, TRUE, TRUE, special);
252 if (STRICMP(rhs, "<nop>") == 0) /* "<Nop>" means nothing */
260 ! * when in right-to-left mode and alternate keymap option set,
261 * reverse the character flow in the rhs in Farsi.
263 if (p_altkeymap && curwin->w_p_rl)
268 ! * When in right-to-left mode and alternate keymap option set,
269 * reverse the character flow in the rhs in Farsi.
271 if (p_altkeymap && curwin->w_p_rl)
278 + vim_free(mp->m_orig_str);
279 + mp->m_orig_str = vim_strsave(orig_rhs);
280 mp->m_noremap = noremap;
281 mp->m_silent = silent;
287 mp->m_keys = vim_strsave(keys);
288 mp->m_str = vim_strsave(rhs);
289 + mp->m_orig_str = vim_strsave(orig_rhs);
290 if (mp->m_keys == NULL || mp->m_str == NULL)
292 vim_free(mp->m_keys);
294 + vim_free(mp->m_orig_str);
296 retval = 4; /* no mem */
302 vim_free(mp->m_keys);
304 + vim_free(mp->m_orig_str);
316 int local; /* TRUE for buffer-local map */
320 if (msg_didout || msg_silent != 0)
327 + * Return characters to represent the map mode in an allocated string.
328 + * Returns NULL when out of memory.
331 + map_mode_to_chars(mode)
336 + ga_init2(&mapmode, 1, 7);
338 + if ((mode & (INSERT + CMDLINE)) == INSERT + CMDLINE)
339 + ga_append(&mapmode, '!'); /* :map! */
340 + else if (mode & INSERT)
341 + ga_append(&mapmode, 'i'); /* :imap */
342 + else if (mode & LANGMAP)
343 + ga_append(&mapmode, 'l'); /* :lmap */
344 + else if (mode & CMDLINE)
345 + ga_append(&mapmode, 'c'); /* :cmap */
346 + else if ((mode & (NORMAL + VISUAL + SELECTMODE + OP_PENDING))
347 + == NORMAL + VISUAL + SELECTMODE + OP_PENDING)
348 + ga_append(&mapmode, ' '); /* :map */
352 + ga_append(&mapmode, 'n'); /* :nmap */
353 + if (mode & OP_PENDING)
354 + ga_append(&mapmode, 'o'); /* :omap */
355 + if ((mode & (VISUAL + SELECTMODE)) == VISUAL + SELECTMODE)
356 + ga_append(&mapmode, 'v'); /* :vmap */
360 + ga_append(&mapmode, 'x'); /* :xmap */
361 + if (mode & SELECTMODE)
362 + ga_append(&mapmode, 's'); /* :smap */
366 + ga_append(&mapmode, NUL);
367 + return (char_u *)mapmode.ga_data;
373 int local; /* TRUE for buffer-local map */
378 if (msg_didout || msg_silent != 0)
382 if (got_int) /* 'q' typed at MORE prompt */
385 ! if ((mp->m_mode & (INSERT + CMDLINE)) == INSERT + CMDLINE)
386 ! msg_putchar('!'); /* :map! */
387 ! else if (mp->m_mode & INSERT)
388 ! msg_putchar('i'); /* :imap */
389 ! else if (mp->m_mode & LANGMAP)
390 ! msg_putchar('l'); /* :lmap */
391 ! else if (mp->m_mode & CMDLINE)
392 ! msg_putchar('c'); /* :cmap */
393 ! else if ((mp->m_mode & (NORMAL + VISUAL + SELECTMODE + OP_PENDING))
394 ! == NORMAL + VISUAL + SELECTMODE + OP_PENDING)
395 ! msg_putchar(' '); /* :map */
399 ! if (mp->m_mode & NORMAL)
401 ! msg_putchar('n'); /* :nmap */
404 ! if (mp->m_mode & OP_PENDING)
406 ! msg_putchar('o'); /* :omap */
409 ! if ((mp->m_mode & (VISUAL + SELECTMODE)) == VISUAL + SELECTMODE)
411 ! msg_putchar('v'); /* :vmap */
416 ! if (mp->m_mode & VISUAL)
418 ! msg_putchar('x'); /* :xmap */
421 ! if (mp->m_mode & SELECTMODE)
423 ! msg_putchar('s'); /* :smap */
432 if (got_int) /* 'q' typed at MORE prompt */
436 ! mapchars = map_mode_to_chars(mp->m_mode);
437 ! if (mapchars != NULL)
439 ! msg_puts(mapchars);
440 ! len = STRLEN(mapchars);
441 ! vim_free(mapchars);
451 /* Use FALSE below if we only want things like <Up> to show up as such on
452 ! * the rhs, and not M-x etc, TRUE gets both -- webb
454 if (*mp->m_str == NUL)
455 msg_puts_attr((char_u *)"<Nop>", hl_attr(HLF_8));
460 /* Use FALSE below if we only want things like <Up> to show up as such on
461 ! * the rhs, and not M-x etc, TRUE gets both -- webb */
462 if (*mp->m_str == NUL)
463 msg_puts_attr((char_u *)"<Nop>", hl_attr(HLF_8));
467 sourcing_name = save_name;
472 ! * Check the string "keys" against the lhs of all mappings
473 ! * Return pointer to rhs of mapping (mapblock->m_str)
477 ! check_map(keys, mode, exact, ign_mod, abbr)
480 int exact; /* require exact match */
481 int ign_mod; /* ignore preceding modifier */
482 int abbr; /* do abbreviations */
487 sourcing_name = save_name;
490 ! #if defined(FEAT_EVAL) || defined(PROTO)
492 ! * Check the string "keys" against the lhs of all mappings.
493 ! * Return pointer to rhs of mapping (mapblock->m_str).
494 ! * NULL when no mapping found.
497 ! check_map(keys, mode, exact, ign_mod, abbr, mp_ptr, local_ptr)
500 int exact; /* require exact match */
501 int ign_mod; /* ignore preceding modifier */
502 int abbr; /* do abbreviations */
503 + mapblock_T **mp_ptr; /* return: pointer to mapblock or NULL */
504 + int *local_ptr; /* return: buffer-local mapping or NULL */
511 minlen = mp->m_keylen - 3;
513 if (STRNCMP(s, keys, minlen) == 0)
515 + if (mp_ptr != NULL)
517 + if (local_ptr != NULL)
518 + *local_ptr = local;
524 *** ../vim-7.3.031/src/gui_w48.c 2010-08-15 21:57:29.000000000 +0200
525 --- src/gui_w48.c 2010-10-20 20:29:20.000000000 +0200
528 * mapped we want to use the mapping instead. */
530 && gui.menu_is_active
531 ! && check_map(k10, State, FALSE, TRUE, FALSE) == NULL)
534 if (GetKeyState(VK_SHIFT) & 0x8000)
536 * mapped we want to use the mapping instead. */
538 && gui.menu_is_active
539 ! && check_map(k10, State, FALSE, TRUE, FALSE,
540 ! NULL, NULL) == NULL)
543 if (GetKeyState(VK_SHIFT) & 0x8000)
546 /* Check for <F10>: Default effect is to select the menu. When <F10> is
547 * mapped we need to stop it here to avoid strange effects (e.g., for the
549 ! if (vk != VK_F10 || check_map(k10, State, FALSE, TRUE, FALSE) == NULL)
551 DispatchMessage(&msg);
554 /* Check for <F10>: Default effect is to select the menu. When <F10> is
555 * mapped we need to stop it here to avoid strange effects (e.g., for the
557 ! if (vk != VK_F10 || check_map(k10, State, FALSE, TRUE, FALSE,
558 ! NULL, NULL) == NULL)
560 DispatchMessage(&msg);
562 *** ../vim-7.3.031/src/message.c 2010-08-15 21:57:29.000000000 +0200
563 --- src/message.c 2010-10-20 20:31:33.000000000 +0200
570 + #if defined(FEAT_EVAL) || defined(PROTO)
572 + * Return the lhs or rhs of a mapping, with the key codes turned into printable
573 + * strings, in an allocated string.
576 + str2special_save(str, is_lhs)
578 + int is_lhs; /* TRUE for lhs, FALSE for rhs */
583 + ga_init2(&ga, 1, 40);
585 + ga_concat(&ga, str2special(&p, is_lhs));
586 + ga_append(&ga, NUL);
587 + return (char_u *)ga.ga_data;
592 * Return the printable string for the key codes at "*sp".
593 * Used for translating the lhs or rhs of a mapping to printable chars.
594 *** ../vim-7.3.031/src/proto/getchar.pro 2010-08-15 21:57:28.000000000 +0200
595 --- src/proto/getchar.pro 2010-10-20 21:06:01.000000000 +0200
599 int get_map_mode __ARGS((char_u **cmdp, int forceit));
600 void map_clear __ARGS((char_u *cmdp, char_u *arg, int forceit, int abbr));
601 void map_clear_int __ARGS((buf_T *buf, int mode, int local, int abbr));
602 + char_u *map_mode_to_chars __ARGS((int mode));
603 int map_to_exists __ARGS((char_u *str, char_u *modechars, int abbr));
604 int map_to_exists_mode __ARGS((char_u *rhs, int mode, int abbr));
605 char_u *set_context_in_map_cmd __ARGS((expand_T *xp, char_u *cmd, char_u *arg, int forceit, int isabbrev, int isunmap, cmdidx_T cmdidx));
608 int makemap __ARGS((FILE *fd, buf_T *buf));
609 int put_escstr __ARGS((FILE *fd, char_u *strstart, int what));
610 void check_map_keycodes __ARGS((void));
611 ! char_u *check_map __ARGS((char_u *keys, int mode, int exact, int ign_mod, int abbr));
612 void init_mappings __ARGS((void));
613 void add_map __ARGS((char_u *map, int mode));
614 /* vim: set ft=c : */
616 int makemap __ARGS((FILE *fd, buf_T *buf));
617 int put_escstr __ARGS((FILE *fd, char_u *strstart, int what));
618 void check_map_keycodes __ARGS((void));
619 ! char_u *check_map __ARGS((char_u *keys, int mode, int exact, int ign_mod, int abbr, mapblock_T **mp_ptr, int *local_ptr));
620 void init_mappings __ARGS((void));
621 void add_map __ARGS((char_u *map, int mode));
622 /* vim: set ft=c : */
623 *** ../vim-7.3.031/src/proto/message.pro 2010-08-15 21:57:28.000000000 +0200
624 --- src/proto/message.pro 2010-10-20 20:31:25.000000000 +0200
628 int msg_outtrans_len_attr __ARGS((char_u *msgstr, int len, int attr));
629 void msg_make __ARGS((char_u *arg));
630 int msg_outtrans_special __ARGS((char_u *strstart, int from));
631 + char_u *str2special_save __ARGS((char_u *str, int is_lhs));
632 char_u *str2special __ARGS((char_u **sp, int from));
633 void str2specialbuf __ARGS((char_u *sp, char_u *buf, int len));
634 void msg_prt_line __ARGS((char_u *s, int list));
635 *** ../vim-7.3.031/src/structs.h 2010-08-15 21:57:28.000000000 +0200
636 --- src/structs.h 2010-10-20 20:23:38.000000000 +0200
641 mapblock_T *m_next; /* next mapblock in list */
642 ! char_u *m_keys; /* mapped from */
643 int m_keylen; /* strlen(m_keys) */
644 ! char_u *m_str; /* mapped to */
645 int m_mode; /* valid mode */
646 int m_noremap; /* if non-zero no re-mapping for m_str */
647 char m_silent; /* <silent> used, don't echo commands */
651 mapblock_T *m_next; /* next mapblock in list */
652 ! char_u *m_keys; /* mapped from, lhs */
653 int m_keylen; /* strlen(m_keys) */
654 ! char_u *m_str; /* mapped to, rhs */
655 ! char_u *m_orig_str; /* rhs as entered by the user */
656 int m_mode; /* valid mode */
657 int m_noremap; /* if non-zero no re-mapping for m_str */
658 char m_silent; /* <silent> used, don't echo commands */
659 *** ../vim-7.3.031/src/testdir/test75.in 2010-10-20 21:13:30.000000000 +0200
660 --- src/testdir/test75.in 2010-10-20 20:54:04.000000000 +0200
664 + " Tests for functions.
668 + :" Test maparg() with a string result
669 + :map foo<C-V> is<F4>foo
670 + :vnoremap <script> <buffer> <expr> <silent> bar isbar
671 + :call append('$', maparg('foo<C-V>'))
672 + :call append('$', string(maparg('foo<C-V>', '', 0, 1)))
673 + :call append('$', string(maparg('bar', '', 0, 1)))
675 + :/^eof/+1,$w! test.out
680 *** ../vim-7.3.031/src/testdir/test75.ok 2010-10-20 21:13:30.000000000 +0200
681 --- src/testdir/test75.ok 2010-10-20 20:54:08.000000000 +0200
686 + {'silent': 0, 'noremap': 0, 'lhs': 'foo<C-V>', 'mode': ' ', 'expr': 0, 'sid': 0, 'rhs': 'is<F4>foo', 'buffer': 0}
687 + {'silent': 1, 'noremap': 1, 'lhs': 'bar', 'mode': 'v', 'expr': 1, 'sid': 0, 'rhs': 'isbar', 'buffer': 1}
688 *** ../vim-7.3.031/src/version.c 2010-10-20 19:17:43.000000000 +0200
689 --- src/version.c 2010-10-20 21:13:18.000000000 +0200
693 { /* Add new patch number below this line */
699 Not too long ago, compress was something you did to garbage...
701 /// Bram Moolenaar -- Bram@Moolenaar.net -- http://www.Moolenaar.net \\\
702 /// sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ \\\
703 \\\ download, build and distribute -- http://www.A-A-P.org ///
704 \\\ help me help AIDS victims -- http://ICCF-Holland.org ///