• R/O
  • SSH

vim: Commit

Mirror of the Vim source from https://github.com/vim/vim


Commit MetaInfo

Révisiona9eeb18e749c45731e0973ba2f38f7bc0b2b6524 (tree)
l'heure2022-01-16 03:30:04
AuteurBram Moolenaar <Bram@vim....>
CommiterBram Moolenaar

Message de Log

patch 8.2.4099: Vim9: cannot use Vim9 syntax in mapping

Commit: https://github.com/vim/vim/commit/e32c3c462ce9b3163a4a4bffd985897910885d29
Author: Bram Moolenaar <Bram@vim.org>
Date: Sat Jan 15 18:26:04 2022 +0000

patch 8.2.4099: Vim9: cannot use Vim9 syntax in mapping
Problem: Vim9: cannot use Vim9 syntax in mapping.
Solution: Add <ScriptCmd> to use the script context for a command.

Change Summary

Modification

diff -r fd4193f6d59e -r a9eeb18e749c runtime/doc/map.txt
--- a/runtime/doc/map.txt Sat Jan 15 16:30:03 2022 +0100
+++ b/runtime/doc/map.txt Sat Jan 15 19:30:04 2022 +0100
@@ -284,6 +284,10 @@
284284 expression-mapped: >
285285 nmap ! f!<Ignore>x
286286
287+When defining a mapping in a |Vim9| script, the expression will be evaluated
288+in the context of that script. This means that script-local items can be
289+accessed in the expression.
290+
287291 Be very careful about side effects! The expression is evaluated while
288292 obtaining characters, you may very well make the command dysfunctional.
289293 For this reason the following is blocked:
@@ -342,9 +346,24 @@
342346 Unlike <expr> mappings, there are no special restrictions on the <Cmd>
343347 command: it is executed as if an (unrestricted) |autocommand| was invoked.
344348
349+ *<ScriptCmd>*
350+<ScriptCmd> is like <Cmd> but sets the context to the script the mapping was
351+defined in, for the duration of the command execution. This is especially
352+useful for |Vim9| script. It also works to access an import, which is useful
353+in a plugin using an autoload script: >
354+ vim9script
355+ import autoload 'implementation.vim' as impl
356+ nnoremap <silent> <F4> <ScriptCmd>impl.DoTheWork()<CR>
357+
358+No matter where <F4> is typed, the "impl" import will be found in the script
359+context of where the mapping was defined. And since it's an autoload import,
360+the "implementation.vim" script will only be loaded once <F4> is typed, not
361+when the mapping is defined.
362+
345363 Note:
346-- Because <Cmd> avoids mode-changes it does not trigger |CmdlineEnter| and
347- |CmdlineLeave| events, because no user interaction is expected.
364+- Because <Cmd> and <ScriptCmd> avoid mode-changes it does not trigger
365+ |CmdlineEnter| and |CmdlineLeave| events, because no user interaction is
366+ expected.
348367 - For the same reason, |keycodes| like <C-R><C-W> are interpreted as plain,
349368 unmapped keys.
350369 - The command is not echo'ed, no need for <silent>.
@@ -356,12 +375,13 @@
356375 Visual mode. Use |:smap| to handle Select mode differently.
357376
358377 *E1255* *E1136*
359-<Cmd> commands must terminate, that is, they must be followed by <CR> in the
360-{rhs} of the mapping definition. |Command-line| mode is never entered.
378+<Cmd> and <ScriptCmd> commands must terminate, that is, they must be followed
379+by <CR> in the {rhs} of the mapping definition. |Command-line| mode is never
380+entered.
361381
362382 *E1137*
363-<Cmd> commands can have only normal characters and cannot contain special
364-characters like function keys.
383+<Cmd> and <ScriptCmd> commands can have only normal characters and cannot
384+contain special characters like function keys.
365385
366386
367387 1.3 MAPPING AND MODES *:map-modes*
diff -r fd4193f6d59e -r a9eeb18e749c src/edit.c
--- a/src/edit.c Sat Jan 15 16:30:03 2022 +0100
+++ b/src/edit.c Sat Jan 15 19:30:04 2022 +0100
@@ -1055,8 +1055,9 @@
10551055 case K_IGNORE: // Something mapped to nothing
10561056 break;
10571057
1058- case K_COMMAND: // <Cmd>command<CR>
1059- do_cmdline(NULL, getcmdkeycmd, NULL, 0);
1058+ case K_COMMAND: // <Cmd>command<CR>
1059+ case K_SCRIPT_COMMAND: // <ScriptCmd>command<CR>
1060+ do_cmdkey_command(c, 0);
10601061 #ifdef FEAT_TERMINAL
10611062 if (term_use_loop())
10621063 // Started a terminal that gets the input, exit Insert mode.
diff -r fd4193f6d59e -r a9eeb18e749c src/ex_getln.c
--- a/src/ex_getln.c Sat Jan 15 16:30:03 2022 +0100
+++ b/src/ex_getln.c Sat Jan 15 19:30:04 2022 +0100
@@ -1772,11 +1772,11 @@
17721772 c = safe_vgetc();
17731773 } while (c == K_IGNORE || c == K_NOP);
17741774
1775- if (c == K_COMMAND)
1775+ if (c == K_COMMAND || c == K_SCRIPT_COMMAND)
17761776 {
17771777 int clen = ccline.cmdlen;
17781778
1779- if (do_cmdline(NULL, getcmdkeycmd, NULL, DOCMD_NOWAIT) == OK)
1779+ if (do_cmdkey_command(c, DOCMD_NOWAIT) == OK)
17801780 {
17811781 if (clen == ccline.cmdlen)
17821782 trigger_cmdlinechanged = FALSE;
diff -r fd4193f6d59e -r a9eeb18e749c src/getchar.c
--- a/src/getchar.c Sat Jan 15 16:30:03 2022 +0100
+++ b/src/getchar.c Sat Jan 15 19:30:04 2022 +0100
@@ -83,6 +83,10 @@
8383
8484 static int last_recorded_len = 0; // number of last recorded chars
8585
86+#ifdef FEAT_EVAL
87+mapblock_T *last_used_map = NULL;
88+#endif
89+
8690 static int read_readbuf(buffheader_T *buf, int advance);
8791 static void init_typebuf(void);
8892 static void may_sync_undo(void);
@@ -2893,6 +2897,7 @@
28932897 #ifdef FEAT_EVAL
28942898 if (save_m_expr)
28952899 vim_free(map_str);
2900+ last_used_map = mp;
28962901 #endif
28972902 }
28982903 #ifdef FEAT_EVAL
@@ -3708,7 +3713,7 @@
37083713 * Function passed to do_cmdline() to get the command after a <Cmd> key from
37093714 * typeahead.
37103715 */
3711- char_u *
3716+ static char_u *
37123717 getcmdkeycmd(
37133718 int promptc UNUSED,
37143719 void *cookie UNUSED,
@@ -3774,7 +3779,7 @@
37743779 c1 = NUL; // end the line
37753780 else if (c1 == ESC)
37763781 aborted = TRUE;
3777- else if (c1 == K_COMMAND)
3782+ else if (c1 == K_COMMAND || c1 == K_SCRIPT_COMMAND)
37783783 {
37793784 // give a nicer error message for this special case
37803785 emsg(_(e_cmd_mapping_must_end_with_cr_before_second_cmd));
@@ -3804,3 +3809,35 @@
38043809
38053810 return (char_u *)line_ga.ga_data;
38063811 }
3812+
3813+ int
3814+do_cmdkey_command(int key, int flags)
3815+{
3816+ int res;
3817+#ifdef FEAT_EVAL
3818+ sctx_T save_current_sctx = {0, 0, 0, 0};
3819+
3820+ if (key == K_SCRIPT_COMMAND && last_used_map != NULL)
3821+ {
3822+ save_current_sctx = current_sctx;
3823+ current_sctx = last_used_map->m_script_ctx;
3824+ }
3825+#endif
3826+
3827+ res = do_cmdline(NULL, getcmdkeycmd, NULL, flags);
3828+
3829+#ifdef FEAT_EVAL
3830+ if (save_current_sctx.sc_sid > 0)
3831+ current_sctx = save_current_sctx;
3832+#endif
3833+
3834+ return res;
3835+}
3836+
3837+#if defined(FEAT_EVAL) || defined(PROTO)
3838+ void
3839+reset_last_used_map(void)
3840+{
3841+ last_used_map = NULL;
3842+}
3843+#endif
diff -r fd4193f6d59e -r a9eeb18e749c src/insexpand.c
--- a/src/insexpand.c Sat Jan 15 16:30:03 2022 +0100
+++ b/src/insexpand.c Sat Jan 15 19:30:04 2022 +0100
@@ -2281,7 +2281,8 @@
22812281
22822282 // Ignore end of Select mode mapping and mouse scroll buttons.
22832283 if (c == K_SELECT || c == K_MOUSEDOWN || c == K_MOUSEUP
2284- || c == K_MOUSELEFT || c == K_MOUSERIGHT || c == K_COMMAND)
2284+ || c == K_MOUSELEFT || c == K_MOUSERIGHT
2285+ || c == K_COMMAND || c == K_SCRIPT_COMMAND)
22852286 return retval;
22862287
22872288 #ifdef FEAT_PROP_POPUP
diff -r fd4193f6d59e -r a9eeb18e749c src/keymap.h
--- a/src/keymap.h Sat Jan 15 16:30:03 2022 +0100
+++ b/src/keymap.h Sat Jan 15 19:30:04 2022 +0100
@@ -276,6 +276,7 @@
276276 , KE_MOUSEMOVE_XY = 101 // KE_MOUSEMOVE with coordinates
277277 , KE_CANCEL = 102 // return from vgetc()
278278 , KE_COMMAND = 103 // <Cmd> special key
279+ , KE_SCRIPT_COMMAND = 104 // <ScriptCmd> special key
279280 };
280281
281282 /*
@@ -480,6 +481,7 @@
480481 #define K_CURSORHOLD TERMCAP2KEY(KS_EXTRA, KE_CURSORHOLD)
481482
482483 #define K_COMMAND TERMCAP2KEY(KS_EXTRA, KE_COMMAND)
484+#define K_SCRIPT_COMMAND TERMCAP2KEY(KS_EXTRA, KE_SCRIPT_COMMAND)
483485
484486 // Bits for modifier mask
485487 // 0x01 cannot be used, because the modifier must be 0x02 or higher
diff -r fd4193f6d59e -r a9eeb18e749c src/misc2.c
--- a/src/misc2.c Sat Jan 15 16:30:03 2022 +0100
+++ b/src/misc2.c Sat Jan 15 19:30:04 2022 +0100
@@ -1057,6 +1057,7 @@
10571057 {K_CURSORHOLD, (char_u *)"CursorHold"},
10581058 {K_IGNORE, (char_u *)"Ignore"},
10591059 {K_COMMAND, (char_u *)"Cmd"},
1060+ {K_SCRIPT_COMMAND, (char_u *)"ScriptCmd"},
10601061 {K_FOCUSGAINED, (char_u *)"FocusGained"},
10611062 {K_FOCUSLOST, (char_u *)"FocusLost"},
10621063 {0, NULL}
diff -r fd4193f6d59e -r a9eeb18e749c src/normal.c
--- a/src/normal.c Sat Jan 15 16:30:03 2022 +0100
+++ b/src/normal.c Sat Jan 15 19:30:04 2022 +0100
@@ -373,6 +373,7 @@
373373 {K_CURSORHOLD, nv_cursorhold, NV_KEEPREG, 0},
374374 {K_PS, nv_edit, 0, 0},
375375 {K_COMMAND, nv_colon, 0, 0},
376+ {K_SCRIPT_COMMAND, nv_colon, 0, 0},
376377 };
377378
378379 // Number of commands in nv_cmds[].
@@ -3429,7 +3430,9 @@
34293430 {
34303431 int old_p_im;
34313432 int cmd_result;
3432- int is_cmdkey = cap->cmdchar == K_COMMAND;
3433+ int is_cmdkey = cap->cmdchar == K_COMMAND
3434+ || cap->cmdchar == K_SCRIPT_COMMAND;
3435+ int flags;
34333436
34343437 if (VIsual_active && !is_cmdkey)
34353438 nv_operator(cap);
@@ -3459,8 +3462,11 @@
34593462 old_p_im = p_im;
34603463
34613464 // get a command line and execute it
3462- cmd_result = do_cmdline(NULL, is_cmdkey ? getcmdkeycmd : getexline, NULL,
3463- cap->oap->op_type != OP_NOP ? DOCMD_KEEPLINE : 0);
3465+ flags = cap->oap->op_type != OP_NOP ? DOCMD_KEEPLINE : 0;
3466+ if (is_cmdkey)
3467+ cmd_result = do_cmdkey_command(cap->cmdchar, flags);
3468+ else
3469+ cmd_result = do_cmdline(NULL, getexline, NULL, flags);
34643470
34653471 // If 'insertmode' changed, enter or exit Insert mode
34663472 if (p_im != old_p_im)
diff -r fd4193f6d59e -r a9eeb18e749c src/ops.c
--- a/src/ops.c Sat Jan 15 16:30:03 2022 +0100
+++ b/src/ops.c Sat Jan 15 19:30:04 2022 +0100
@@ -3501,6 +3501,14 @@
35013501 int rv_arg; // extra argument
35023502 } redo_VIsual_T;
35033503
3504+ static int
3505+is_ex_cmdchar(cmdarg_T *cap)
3506+{
3507+ return cap->cmdchar == ':'
3508+ || cap->cmdchar == K_COMMAND
3509+ || cap->cmdchar == K_SCRIPT_COMMAND;
3510+}
3511+
35043512 /*
35053513 * Handle an operator after Visual mode or when the movement is finished.
35063514 * "gui_yank" is true when yanking text for the clipboard.
@@ -3583,8 +3591,7 @@
35833591 && ((!VIsual_active || oap->motion_force)
35843592 // Also redo Operator-pending Visual mode mappings
35853593 || (VIsual_active
3586- && (cap->cmdchar == ':' || cap->cmdchar == K_COMMAND)
3587- && oap->op_type != OP_COLON))
3594+ && is_ex_cmdchar(cap) && oap->op_type != OP_COLON))
35883595 && cap->cmdchar != 'D'
35893596 #ifdef FEAT_FOLDING
35903597 && oap->op_type != OP_FOLD
@@ -3608,7 +3615,7 @@
36083615 AppendToRedobuffLit(cap->searchbuf, -1);
36093616 AppendToRedobuff(NL_STR);
36103617 }
3611- else if (cap->cmdchar == ':' || cap->cmdchar == K_COMMAND)
3618+ else if (is_ex_cmdchar(cap))
36123619 {
36133620 // do_cmdline() has stored the first typed line in
36143621 // "repeat_cmdline". When several lines are typed repeating
@@ -3806,7 +3813,7 @@
38063813 get_op_char(oap->op_type),
38073814 get_extra_op_char(oap->op_type),
38083815 oap->motion_force, cap->cmdchar, cap->nchar);
3809- else if (cap->cmdchar != ':' && cap->cmdchar != K_COMMAND)
3816+ else if (!is_ex_cmdchar(cap))
38103817 {
38113818 int opchar = get_op_char(oap->op_type);
38123819 int extra_opchar = get_extra_op_char(oap->op_type);
diff -r fd4193f6d59e -r a9eeb18e749c src/proto/getchar.pro
--- a/src/proto/getchar.pro Sat Jan 15 16:30:03 2022 +0100
+++ b/src/proto/getchar.pro Sat Jan 15 19:30:04 2022 +0100
@@ -52,5 +52,6 @@
5252 void vungetc(int c);
5353 int fix_input_buffer(char_u *buf, int len);
5454 int input_available(void);
55-char_u *getcmdkeycmd(int promptc, void *cookie, int indent, getline_opt_T do_concat);
55+int do_cmdkey_command(int key, int flags);
56+void reset_last_used_map(void);
5657 /* vim: set ft=c : */
diff -r fd4193f6d59e -r a9eeb18e749c src/terminal.c
--- a/src/terminal.c Sat Jan 15 16:30:03 2022 +0100
+++ b/src/terminal.c Sat Jan 15 19:30:04 2022 +0100
@@ -2229,7 +2229,8 @@
22292229 break;
22302230
22312231 case K_COMMAND:
2232- return do_cmdline(NULL, getcmdkeycmd, NULL, 0);
2232+ case K_SCRIPT_COMMAND:
2233+ return do_cmdkey_command(c, 0);
22332234 }
22342235 if (typed)
22352236 mouse_was_outside = FALSE;
diff -r fd4193f6d59e -r a9eeb18e749c src/testdir/test_vim9_import.vim
--- a/src/testdir/test_vim9_import.vim Sat Jan 15 16:30:03 2022 +0100
+++ b/src/testdir/test_vim9_import.vim Sat Jan 15 19:30:04 2022 +0100
@@ -1337,6 +1337,9 @@
13371337 export def Toggle(): string
13381338 return ":g:toggle_called = 'yes'\<CR>"
13391339 enddef
1340+ export def Doit()
1341+ g:doit_called = 'yes'
1342+ enddef
13401343 END
13411344 writefile(lines, 'Xdir/autoload/toggle.vim')
13421345
@@ -1346,6 +1349,8 @@
13461349 import autoload 'toggle.vim'
13471350
13481351 nnoremap <silent> <expr> tt toggle.Toggle()
1352+ nnoremap <silent> xx <ScriptCmd>toggle.Doit()<CR>
1353+ nnoremap <silent> yy <Cmd>toggle.Doit()<CR>
13491354 END
13501355 CheckScriptSuccess(lines)
13511356 assert_false(exists("g:toggle_loaded"))
@@ -1355,7 +1360,14 @@
13551360 assert_equal('yes', g:toggle_loaded)
13561361 assert_equal('yes', g:toggle_called)
13571362
1363+ feedkeys("xx", 'xt')
1364+ assert_equal('yes', g:doit_called)
1365+
1366+ assert_fails('call feedkeys("yy", "xt")', 'E121: Undefined variable: toggle')
1367+
13581368 nunmap tt
1369+ nunmap xx
1370+ nunmap yy
13591371 unlet g:toggle_loaded
13601372 unlet g:toggle_called
13611373 delete('Xdir', 'rf')
diff -r fd4193f6d59e -r a9eeb18e749c src/version.c
--- a/src/version.c Sat Jan 15 16:30:03 2022 +0100
+++ b/src/version.c Sat Jan 15 19:30:04 2022 +0100
@@ -751,6 +751,8 @@
751751 static int included_patches[] =
752752 { /* Add new patch number below this line */
753753 /**/
754+ 4099,
755+/**/
754756 4098,
755757 /**/
756758 4097,
Afficher sur ancien navigateur de dépôt.