@@ -2283,7 +2283,8 @@ mapblock2dict(
22832283 mapblock_T * mp ,
22842284 dict_T * dict ,
22852285 char_u * lhsrawalt , // may be NULL
2286- int buffer_local ) // false if not buffer local mapping
2286+ int buffer_local , // false if not buffer local mapping
2287+ int abbr ) // true if abbreviation
22872288{
22882289 char_u * lhs = str2special_save (mp -> m_keys , TRUE);
22892290 char_u * mapmode = map_mode_to_chars (mp -> m_mode );
@@ -2307,6 +2308,7 @@ mapblock2dict(
23072308 dict_add_number (dict , "buffer" , (long )buffer_local );
23082309 dict_add_number (dict , "nowait" , mp -> m_nowait ? 1L : 0L );
23092310 dict_add_string (dict , "mode" , mapmode );
2311+ dict_add_number (dict , "abbr" , abbr ? 1L : 0L );
23102312
23112313 vim_free (mapmode );
23122314}
@@ -2381,7 +2383,8 @@ get_maparg(typval_T *argvars, typval_T *rettv, int exact)
23812383 }
23822384 else if (rettv_dict_alloc (rettv ) != FAIL && rhs != NULL )
23832385 mapblock2dict (mp , rettv -> vval .v_dict ,
2384- did_simplify ? keys_simplified : NULL , buffer_local );
2386+ did_simplify ? keys_simplified : NULL ,
2387+ buffer_local , abbr );
23852388
23862389 vim_free (keys_buf );
23872390 vim_free (alt_keys_buf );
@@ -2448,7 +2451,8 @@ f_maplist(typval_T *argvars UNUSED, typval_T *rettv)
24482451 vim_free (lhs );
24492452
24502453 mapblock2dict (mp , d ,
2451- did_simplify ? keys_buf : NULL , buffer_local );
2454+ did_simplify ? keys_buf : NULL ,
2455+ buffer_local , abbr );
24522456 vim_free (keys_buf );
24532457 }
24542458 }
@@ -2489,6 +2493,56 @@ f_mapcheck(typval_T *argvars, typval_T *rettv)
24892493 get_maparg (argvars , rettv , FALSE);
24902494}
24912495
2496+ /*
2497+ * Get the mapping mode from the mode string.
2498+ * It may contain multiple characters, eg "nox", or "!", or ' '
2499+ * Return 0 if there is an error.
2500+ */
2501+ static int
2502+ get_map_mode_string (char_u * mode_string , int abbr )
2503+ {
2504+ char_u * p = mode_string ;
2505+ int mode = 0 ;
2506+ int tmode ;
2507+ int modec ;
2508+ const int MASK_V = VISUAL + SELECTMODE ;
2509+ const int MASK_MAP = VISUAL + SELECTMODE + NORMAL + OP_PENDING ;
2510+ const int MASK_BANG = INSERT + CMDLINE ;
2511+
2512+ if (* p == NUL )
2513+ p = (char_u * )" " ; // compatibility
2514+ while ((modec = * p ++ ))
2515+ {
2516+ switch (modec )
2517+ {
2518+ case 'i' : tmode = INSERT ; break ;
2519+ case 'l' : tmode = LANGMAP ; break ;
2520+ case 'c' : tmode = CMDLINE ; break ;
2521+ case 'n' : tmode = NORMAL ; break ;
2522+ case 'x' : tmode = VISUAL ; break ;
2523+ case 's' : tmode = SELECTMODE ; break ;
2524+ case 'o' : tmode = OP_PENDING ; break ;
2525+ case 't' : tmode = TERMINAL ; break ;
2526+ case 'v' : tmode = MASK_V ; break ;
2527+ case '!' : tmode = MASK_BANG ; break ;
2528+ case ' ' : tmode = MASK_MAP ; break ;
2529+ default :
2530+ return 0 ; // error, unknown mode character
2531+ }
2532+ mode |= tmode ;
2533+ }
2534+ if ((abbr && (mode & ~MASK_BANG ) != 0 )
2535+ || (!abbr && (mode & (mode - 1 )) != 0 // more than one bit set
2536+ && (
2537+ // false if multiple bits set in mode and mode is fully
2538+ // contained in one mask
2539+ !(((mode & MASK_BANG ) != 0 && (mode & ~MASK_BANG ) == 0 )
2540+ || ((mode & MASK_MAP ) != 0 && (mode & ~MASK_MAP ) == 0 )))))
2541+ return 0 ;
2542+
2543+ return mode ;
2544+ }
2545+
24922546/*
24932547 * "mapset()" function
24942548 */
@@ -2518,25 +2572,51 @@ f_mapset(typval_T *argvars, typval_T *rettv UNUSED)
25182572 mapblock_T * * abbr_table = & first_abbr ;
25192573 int nowait ;
25202574 char_u * arg ;
2575+ int dict_only ;
25212576
2577+ // If first arg is a dict, then that's the only arg permitted.
2578+ dict_only = argvars [0 ].v_type == VAR_DICT ;
25222579 if (in_vim9script ()
2523- && (check_for_string_arg (argvars , 0 ) == FAIL
2524- || check_for_bool_arg (argvars , 1 ) == FAIL
2525- || check_for_dict_arg (argvars , 2 ) == FAIL ))
2580+ && (check_for_string_or_dict_arg (argvars , 0 ) == FAIL
2581+ || (dict_only && check_for_unknown_arg (argvars , 1 ) == FAIL )
2582+ || (!dict_only
2583+ && (check_for_string_arg (argvars , 0 ) == FAIL
2584+ || check_for_bool_arg (argvars , 1 ) == FAIL
2585+ || check_for_dict_arg (argvars , 2 ) == FAIL ))))
25262586 return ;
25272587
2528- which = tv_get_string_buf_chk (& argvars [0 ], buf );
2529- if (which == NULL )
2530- return ;
2531- mode = get_map_mode (& which , 0 );
2532- is_abbr = (int )tv_get_bool (& argvars [1 ]);
2588+ if (dict_only )
2589+ {
2590+ d = argvars [0 ].vval .v_dict ;
2591+ which = dict_get_string (d , (char_u * )"mode" , FALSE);
2592+ is_abbr = dict_get_bool (d , (char_u * )"abbr" , -1 );
2593+ if (which == NULL || is_abbr < 0 )
2594+ {
2595+ emsg (_ (e_entries_missing_in_mapset_dict_argument ));
2596+ return ;
2597+ }
2598+ }
2599+ else
2600+ {
2601+ which = tv_get_string_buf_chk (& argvars [0 ], buf );
2602+ if (which == NULL )
2603+ return ;
2604+ is_abbr = (int )tv_get_bool (& argvars [1 ]);
25332605
2534- if (argvars [2 ].v_type != VAR_DICT )
2606+ if (argvars [2 ].v_type != VAR_DICT )
2607+ {
2608+ emsg (_ (e_dictionary_required ));
2609+ return ;
2610+ }
2611+ d = argvars [2 ].vval .v_dict ;
2612+ }
2613+ mode = get_map_mode_string (which , is_abbr );
2614+ if (mode == 0 )
25352615 {
2536- emsg (_ (e_key_not_present_in_dictionary ) );
2616+ semsg (_ (e_illegal_map_mode_string_str ), which );
25372617 return ;
25382618 }
2539- d = argvars [ 2 ]. vval . v_dict ;
2619+
25402620
25412621 // Get the values in the same order as above in get_maparg().
25422622 lhs = dict_get_string (d , (char_u * )"lhs" , FALSE);
0 commit comments