comparison src/getchar.c @ 30102:539fb427124d v9.0.0387

patch 9.0.0387: repeat <ScriptCmd> mapping doesn't use right script context Commit: https://github.com/vim/vim/commit/ddf7dba96e05a41c7a228b153146237e0a21b146 Author: Bram Moolenaar <Bram@vim.org> Date: Mon Sep 5 16:53:21 2022 +0100 patch 9.0.0387: repeat <ScriptCmd> mapping doesn't use right script context Problem: repeating a <ScriptCmd> mapping does not use the right script context. Solution: When using a mapping put <SID>{sid}; in the redo buffer. (closes #11049)
author Bram Moolenaar <Bram@vim.org>
date Mon, 05 Sep 2022 18:00:05 +0200
parents 5b4f3129cadc
children cabceac53ade
comparison
equal deleted inserted replaced
30101:50cb1d7be810 30102:539fb427124d
83 83
84 static int last_recorded_len = 0; // number of last recorded chars 84 static int last_recorded_len = 0; // number of last recorded chars
85 85
86 #ifdef FEAT_EVAL 86 #ifdef FEAT_EVAL
87 mapblock_T *last_used_map = NULL; 87 mapblock_T *last_used_map = NULL;
88 int last_used_sid = -1;
88 #endif 89 #endif
89 90
90 static int read_readbuf(buffheader_T *buf, int advance); 91 static int read_readbuf(buffheader_T *buf, int advance);
91 static void init_typebuf(void); 92 static void init_typebuf(void);
92 static void may_sync_undo(void); 93 static void may_sync_undo(void);
835 if (read_redo(TRUE, old_redo) == FAIL) 836 if (read_redo(TRUE, old_redo) == FAIL)
836 return FAIL; 837 return FAIL;
837 838
838 c = read_redo(FALSE, old_redo); 839 c = read_redo(FALSE, old_redo);
839 840
841 #ifdef FEAT_EVAL
842 if (c == K_SID)
843 {
844 // Copy the <SID>{sid}; sequence
845 add_char_buff(&readbuf2, c);
846 for (;;)
847 {
848 c = read_redo(FALSE, old_redo);
849 add_char_buff(&readbuf2, c);
850 if (!isdigit(c))
851 break;
852 }
853 c = read_redo(FALSE, old_redo);
854 }
855 #endif
856
840 // copy the buffer name, if present 857 // copy the buffer name, if present
841 if (c == '"') 858 if (c == '"')
842 { 859 {
843 add_buff(&readbuf2, (char_u *)"\"", 1L); 860 add_buff(&readbuf2, (char_u *)"\"", 1L);
844 c = read_redo(FALSE, old_redo); 861 c = read_redo(FALSE, old_redo);
874 while (VIM_ISDIGIT(c)) // skip "old" count 891 while (VIM_ISDIGIT(c)) // skip "old" count
875 c = read_redo(FALSE, old_redo); 892 c = read_redo(FALSE, old_redo);
876 add_num_buff(&readbuf2, count); 893 add_num_buff(&readbuf2, count);
877 } 894 }
878 895
879 // copy from the redo buffer into the stuff buffer 896 // copy the rest from the redo buffer into the stuff buffer
880 add_char_buff(&readbuf2, c); 897 add_char_buff(&readbuf2, c);
881 copy_redo(old_redo); 898 copy_redo(old_redo);
882 return OK; 899 return OK;
883 } 900 }
884 901
1794 // Translate K_CSI to CSI. The special key is only used to 1811 // Translate K_CSI to CSI. The special key is only used to
1795 // avoid it being recognized as the start of a special key. 1812 // avoid it being recognized as the start of a special key.
1796 if (c == K_CSI) 1813 if (c == K_CSI)
1797 c = CSI; 1814 c = CSI;
1798 #endif 1815 #endif
1816 #ifdef FEAT_EVAL
1817 if (c == K_SID)
1818 {
1819 int j;
1820
1821 // Handle <SID>{sid}; Do up to 20 digits for safety.
1822 last_used_sid = 0;
1823 for (j = 0; j < 20 && isdigit(c = vgetorpeek(TRUE)); ++j)
1824 last_used_sid = last_used_sid * 10 + (c - '0');
1825 last_used_map = NULL;
1826 continue;
1827 }
1828 #endif
1799 } 1829 }
1830
1800 // a keypad or special function key was not mapped, use it like 1831 // a keypad or special function key was not mapped, use it like
1801 // its ASCII equivalent 1832 // its ASCII equivalent
1802 switch (c) 1833 switch (c)
1803 { 1834 {
1804 case K_KPLUS: c = '+'; break; 1835 case K_KPLUS: c = '+'; break;
2920 i = FAIL; 2951 i = FAIL;
2921 else 2952 else
2922 { 2953 {
2923 int noremap; 2954 int noremap;
2924 2955
2956 #ifdef FEAT_EVAL
2957 last_used_map = mp;
2958 last_used_sid = -1;
2959 #endif
2925 if (save_m_noremap != REMAP_YES) 2960 if (save_m_noremap != REMAP_YES)
2926 noremap = save_m_noremap; 2961 noremap = save_m_noremap;
2927 else if ( 2962 else if (
2928 #ifdef FEAT_EVAL 2963 #ifdef FEAT_EVAL
2929 STRNCMP(map_str, save_m_keys != NULL ? save_m_keys : mp->m_keys, 2964 STRNCMP(map_str, save_m_keys != NULL ? save_m_keys : mp->m_keys,
2938 i = ins_typebuf(map_str, noremap, 2973 i = ins_typebuf(map_str, noremap,
2939 0, TRUE, cmd_silent || save_m_silent); 2974 0, TRUE, cmd_silent || save_m_silent);
2940 #ifdef FEAT_EVAL 2975 #ifdef FEAT_EVAL
2941 if (save_m_expr) 2976 if (save_m_expr)
2942 vim_free(map_str); 2977 vim_free(map_str);
2943 last_used_map = mp;
2944 #endif 2978 #endif
2945 } 2979 }
2946 #ifdef FEAT_EVAL 2980 #ifdef FEAT_EVAL
2947 vim_free(save_m_keys); 2981 vim_free(save_m_keys);
2948 #endif 2982 #endif
3894 ga_clear(&line_ga); 3928 ga_clear(&line_ga);
3895 3929
3896 return (char_u *)line_ga.ga_data; 3930 return (char_u *)line_ga.ga_data;
3897 } 3931 }
3898 3932
3933 #if defined(FEAT_EVAL) || defined(PROTO)
3934 /*
3935 * If there was a mapping put info about it in the redo buffer, so that "."
3936 * will use the same script context. We only need the SID.
3937 */
3938 void
3939 may_add_last_used_map_to_redobuff(void)
3940 {
3941 char_u buf[3 + 20];
3942
3943 if (last_used_map == NULL || last_used_map->m_script_ctx.sc_sid < 0)
3944 return;
3945
3946 // <K_SID>{nr};
3947 buf[0] = K_SPECIAL;
3948 buf[1] = KS_EXTRA;
3949 buf[2] = KE_SID;
3950 vim_snprintf((char *)buf + 3, 20, "%d;",
3951 last_used_map->m_script_ctx.sc_sid);
3952 add_buff(&redobuff, buf, -1L);
3953 }
3954 #endif
3955
3899 int 3956 int
3900 do_cmdkey_command(int key UNUSED, int flags) 3957 do_cmdkey_command(int key UNUSED, int flags)
3901 { 3958 {
3902 int res; 3959 int res;
3903 #ifdef FEAT_EVAL 3960 #ifdef FEAT_EVAL
3904 sctx_T save_current_sctx = {-1, 0, 0, 0}; 3961 sctx_T save_current_sctx = {-1, 0, 0, 0};
3905 3962
3906 if (key == K_SCRIPT_COMMAND && last_used_map != NULL) 3963 if (key == K_SCRIPT_COMMAND
3964 && (last_used_map != NULL || SCRIPT_ID_VALID(last_used_sid)))
3907 { 3965 {
3908 save_current_sctx = current_sctx; 3966 save_current_sctx = current_sctx;
3909 current_sctx = last_used_map->m_script_ctx; 3967 if (last_used_map != NULL)
3968 current_sctx = last_used_map->m_script_ctx;
3969 else
3970 {
3971 current_sctx.sc_sid = last_used_sid;
3972 current_sctx.sc_lnum = 0;
3973 current_sctx.sc_version = SCRIPT_ITEM(last_used_sid)->sn_version;
3974 }
3910 } 3975 }
3911 #endif 3976 #endif
3912 3977
3913 res = do_cmdline(NULL, getcmdkeycmd, NULL, flags); 3978 res = do_cmdline(NULL, getcmdkeycmd, NULL, flags);
3914 3979
3923 #if defined(FEAT_EVAL) || defined(PROTO) 3988 #if defined(FEAT_EVAL) || defined(PROTO)
3924 void 3989 void
3925 reset_last_used_map(mapblock_T *mp) 3990 reset_last_used_map(mapblock_T *mp)
3926 { 3991 {
3927 if (last_used_map == mp) 3992 if (last_used_map == mp)
3993 {
3928 last_used_map = NULL; 3994 last_used_map = NULL;
3929 } 3995 last_used_sid = -1;
3930 #endif 3996 }
3997 }
3998 #endif