diff --git a/runtime/doc/map.txt b/runtime/doc/map.txt index 7a194ccb8a110aed0d528947d48a6c642297f9ab..228b9a9f9840dda5475a69b97405c5f47ff23d4c 100644 --- a/runtime/doc/map.txt +++ b/runtime/doc/map.txt @@ -1,4 +1,4 @@ -*map.txt* For Vim version 7.0aa. Last change: 2006 Mar 06 +*map.txt* For Vim version 7.0aa. Last change: 2006 Mar 10 VIM REFERENCE MANUAL by Bram Moolenaar @@ -145,6 +145,9 @@ type "a", then "bar" will get inserted. 1.2 SPECIAL ARGUMENTS *:map-arguments* +"<buffer>", "<silent>", "<script>", "<expr>" and "<unique>" can be used in any +order. They must appear right after the command, before any other arguments. + *:map-local* *:map-<buffer>* *E224* *E225* If the first argument to one of these commands is "<buffer>" it will apply to mappings locally to the current buffer only. Example: > @@ -194,8 +197,35 @@ Example of what will fail: > If you want to map a key and then have it do what it was originally mapped to, have a look at |maparg()|. -"<buffer>", "<silent>", "<script>" and "<unique>" can be used in any order. -They must appear right after the command, before any other arguments. + *:map-<expr>* *:map-expression* +If the first argument to one of these commands is "<expr>" and it is used to +define a new mapping or abbreviation, the argument is an expression. The +expression is evaluated to obtain the {rhs} that is used. Example: > + :inoremap <expr> . InsertDot() +The result of the InsertDot() function will be inserted. It could check the +text before the cursor and start omni completion when some condition is met. + +Be very careful about side effects! The expression is evaluated while +obtaining characters, if you change buffer text, move the cursor, edit another +file, etc. you may very well make command disfunctional. + +Here is an example that inserts a list number that increases: > + let counter = 0 + inoremap <expr> <C-L> ListItem() + inoremap <expr> <C-R> ListReset() + + func ListItem() + let g:counter += 1 + return g:counter . '. ' + endfunc + + func ListReset() + let g:counter = 0 + return '' + endfunc + +CTRL-L inserts the next number, CTRL-E resets the count. CTRL-E returns an +empty string, so that nothing is inserted. 1.3 MAPPING AND MODES *:map-modes* diff --git a/runtime/optwin.vim b/runtime/optwin.vim index 8a8cf6f72fc43453f28d2a6c6ee8d06713c60e9d..7dff51319f948b9d10692001d1dd06d9f5ebdfae 100644 --- a/runtime/optwin.vim +++ b/runtime/optwin.vim @@ -1,7 +1,7 @@ " These commands create the option window. " " Maintainer: Bram Moolenaar <Bram@vim.org> -" Last Change: 2006 Mar 05 +" Last Change: 2006 Mar 10 " If there already is an option window, jump to that one. if bufwinnr("option-window") > 0 @@ -1163,6 +1163,8 @@ if has("multi_byte") call <SID>OptionG("ccv", &ccv) call append("$", "delcombine\tDelete combining (composing) characters on their own") call <SID>BinOptionG("deco", &deco) + call append("$", "maxcombine\tMaximum number of combining (composing) characters displayed") + call <SID>OptionG("mco", &mco) if has("xim") && has("gui_gtk") call append("$", "imactivatekey\tkey that activates the X input method") call <SID>OptionG("imak", &imak) diff --git a/src/getchar.c b/src/getchar.c index 5064c8d39b3ecb2bf3ccfa43fb326c0da78aebaf..5aa1b2594dd315b9910ca1eb18c65519acc0f66c 100644 --- a/src/getchar.c +++ b/src/getchar.c @@ -1792,8 +1792,8 @@ vgetorpeek(advance) int local_State; int mlen; int max_mlen; -#ifdef FEAT_CMDL_INFO int i; +#ifdef FEAT_CMDL_INFO int new_wcol, new_wrow; #endif #ifdef FEAT_GUI @@ -2309,6 +2309,17 @@ vgetorpeek(advance) } #endif +#ifdef FEAT_EVAL + /* + * Handle ":map <expr>": evaluate the {rhs} as an + * expression. + */ + if (mp->m_expr) + s = eval_to_string(mp->m_str, NULL, FALSE); + else +#endif + s = mp->m_str; + /* * Insert the 'to' part in the typebuf.tb_buf. * If 'from' field is the same as the start of the @@ -2317,13 +2328,23 @@ vgetorpeek(advance) * If m_noremap is set, don't remap the whole 'to' * part. */ - if (ins_typebuf(mp->m_str, - mp->m_noremap != REMAP_YES + if (s == NULL) + i = FAIL; + else + { + i = ins_typebuf(s, + mp->m_noremap != REMAP_YES ? mp->m_noremap - : STRNCMP(mp->m_str, mp->m_keys, + : STRNCMP(s, mp->m_keys, (size_t)keylen) != 0 ? REMAP_YES : REMAP_SKIP, - 0, TRUE, cmd_silent || mp->m_silent) == FAIL) + 0, TRUE, cmd_silent || mp->m_silent); +#ifdef FEAT_EVAL + if (mp->m_expr) + vim_free(s); +#endif + } + if (i == FAIL) { c = -1; break; @@ -2955,6 +2976,9 @@ do_map(maptype, arg, mode, abbrev) mapblock_T **map_table; int unique = FALSE; int silent = FALSE; +#ifdef FEAT_EVAL + int expr = FALSE; +#endif int noremap; keys = arg; @@ -2967,7 +2991,7 @@ do_map(maptype, arg, mode, abbrev) else noremap = REMAP_YES; - /* Accept <buffer>, <silent>, <script> and <unique> in any order. */ + /* Accept <buffer>, <silent>, <expr> <script> and <unique> in any order. */ for (;;) { #ifdef FEAT_LOCALMAP @@ -3003,6 +3027,16 @@ do_map(maptype, arg, mode, abbrev) noremap = REMAP_SCRIPT; continue; } + + /* + * Check for "<expr>": {rhs} is an expression. + */ + if (STRNCMP(keys, "<expr>", 6) == 0) + { + keys = skipwhite(keys + 6); + expr = TRUE; + continue; + } #endif /* * Check for "<unique>": don't overwrite an existing mapping. @@ -3328,6 +3362,7 @@ do_map(maptype, arg, mode, abbrev) mp->m_silent = silent; mp->m_mode = mode; #ifdef FEAT_EVAL + mp->m_expr = expr; mp->m_script_ID = current_SID; #endif did_it = TRUE; @@ -3413,6 +3448,7 @@ do_map(maptype, arg, mode, abbrev) mp->m_silent = silent; mp->m_mode = mode; #ifdef FEAT_EVAL + mp->m_expr = expr; mp->m_script_ID = current_SID; #endif @@ -3835,11 +3871,18 @@ set_context_in_map_cmd(xp, cmd, arg, forceit, isabbrev, isunmap, cmdidx) arg = skipwhite(arg + 8); continue; } +#ifdef FEAT_EVAL if (STRNCMP(arg, "<script>", 8) == 0) { arg = skipwhite(arg + 8); continue; } + if (STRNCMP(arg, "<expr>", 6) == 0) + { + arg = skipwhite(arg + 6); + continue; + } +#endif break; } xp->xp_pattern = arg; @@ -3879,7 +3922,7 @@ ExpandMappings(regmatch, num_file, file) { count = 0; - for (i = 0; i < 4; ++i) + for (i = 0; i < 5; ++i) { if (i == 0) p = (char_u *)"<silent>"; @@ -3888,9 +3931,11 @@ ExpandMappings(regmatch, num_file, file) #ifdef FEAT_EVAL else if (i == 2) p = (char_u *)"<script>"; + else if (i == 3) + p = (char_u *)"<expr>"; #endif #ifdef FEAT_LOCALMAP - else if (i == 3 && !expand_buffer) + else if (i == 4 && !expand_buffer) p = (char_u *)"<buffer>"; #endif else @@ -4002,6 +4047,7 @@ check_abbr(c, ptr, col, mincol) int len; int scol; /* starting column of the abbr. */ int j; + char_u *s; #ifdef FEAT_MBYTE char_u tb[MB_MAXBYTES + 4]; #else @@ -4148,10 +4194,23 @@ check_abbr(c, ptr, col, mincol) /* insert the last typed char */ (void)ins_typebuf(tb, 1, 0, TRUE, mp->m_silent); } +#ifdef FEAT_EVAL + if (mp->m_expr) + s = eval_to_string(mp->m_str, NULL, FALSE); + else +#endif + s = mp->m_str; + if (s != NULL) + { /* insert the to string */ - (void)ins_typebuf(mp->m_str, mp->m_noremap, 0, TRUE, mp->m_silent); + (void)ins_typebuf(s, mp->m_noremap, 0, TRUE, mp->m_silent); /* no abbrev. for these chars */ - typebuf.tb_no_abbr_cnt += (int)STRLEN(mp->m_str) + j + 1; + typebuf.tb_no_abbr_cnt += (int)STRLEN(s) + j + 1; +#ifdef FEAT_EVAL + if (mp->m_expr) + vim_free(s); +#endif + } tb[0] = Ctrl_H; tb[1] = NUL; @@ -4310,6 +4369,13 @@ makemap(fd, buf) return FAIL; if (mp->m_silent && fputs(" <silent>", fd) < 0) return FAIL; +#ifdef FEAT_EVAL + if (mp->m_noremap == REMAP_SCRIPT + && fputs("<script>", fd) < 0) + return FAIL; + if (mp->m_expr && fputs(" <expr>", fd) < 0) + return FAIL; +#endif if ( putc(' ', fd) < 0 || put_escstr(fd, mp->m_keys, 0) == FAIL diff --git a/src/vim.h b/src/vim.h index 0a08cd686a5144812ba86d89187157a235d3644b..e2514cf0a29544dae8da4467c959c5fdd8925bb1 100644 --- a/src/vim.h +++ b/src/vim.h @@ -1127,6 +1127,8 @@ enum auto_event EVENT_CURSORMOVEDI, /* cursor was moved in Insert mode */ EVENT_TABLEAVE, /* before leaving a tab page */ EVENT_TABENTER, /* after entering a tab page */ + EVENT_SHELLCMDPOST, /* after ":!cmd" */ + EVENT_SHELLFILTERPOST, /* after ":1,2!cmd", ":w !cmd", ":r !cmd". */ NUM_EVENTS /* MUST be the last one */ };