Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commitcc0f6ac

Browse files
committed
feat(mapset): support restoring Lua callback
vim-patch:9.0.0341: mapset() does not restore <Nop> mapping properlyProblem: mapset() does not restore <Nop> mapping properly.Solution: Use an empty string for <Nop>. (closesvim/vim#11022)vim/vim@92a3d20
1 parentc0050b7 commitcc0f6ac

File tree

4 files changed

+100
-30
lines changed

4 files changed

+100
-30
lines changed

‎runtime/pack/dist/opt/termdebug/plugin/termdebug.vim‎

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -964,14 +964,7 @@ func s:DeleteCommands()
964964
nunmapK
965965
else
966966
" call mapset(s:k_map_saved)
967-
letmode=s:k_map_saved.mode!=#'' ?s:k_map_saved.mode :''
968-
callnvim_set_keymap(mode,'K',s:k_map_saved.rhs, {
969-
\'expr':s:k_map_saved.expr ?v:true :v:false,
970-
\'noremap':s:k_map_saved.noremap?v:true : v:false,
971-
\ 'nowait': s:k_map_saved.nowait ? v:true : v:false,
972-
\ 'script': s:k_map_saved.script ? v:true : v:false,
973-
\ 'silent': s:k_map_saved.silent ? v:true : v:false,
974-
\ })
967+
callmapset('n',0,s:k_map_saved)
975968
endif
976969
unlets:k_map_saved
977970
endif

‎src/nvim/mapping.c‎

Lines changed: 30 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -277,21 +277,29 @@ static bool set_maparg_lhs_rhs(const char *const orig_lhs, const size_t orig_lhs
277277
mapargs->alt_lhs_len=0;
278278
}
279279

280+
set_maparg_rhs(orig_rhs,orig_rhs_len,rhs_lua,cpo_flags,mapargs);
281+
282+
return true;
283+
}
284+
285+
/// @see set_maparg_lhs_rhs
286+
staticvoidset_maparg_rhs(constchar*constorig_rhs,constsize_torig_rhs_len,
287+
constLuaRefrhs_lua,constintcpo_flags,MapArguments*constmapargs)
288+
{
280289
mapargs->rhs_lua=rhs_lua;
281290

282291
if (rhs_lua==LUA_NOREF) {
283292
mapargs->orig_rhs_len=orig_rhs_len;
284293
mapargs->orig_rhs=xcalloc(mapargs->orig_rhs_len+1,sizeof(char_u));
285294
STRLCPY(mapargs->orig_rhs,orig_rhs,mapargs->orig_rhs_len+1);
286-
287295
if (STRICMP(orig_rhs,"<nop>")==0) {// "<Nop>" means nothing
288-
mapargs->rhs=xcalloc(1,sizeof(char_u));// singlenull-char
296+
mapargs->rhs=xcalloc(1,sizeof(char_u));// singleNUL-char
289297
mapargs->rhs_len=0;
290298
mapargs->rhs_is_noop= true;
291299
}else {
292300
char*rhs_buf=NULL;
293-
replaced=replace_termcodes(orig_rhs,orig_rhs_len,&rhs_buf,REPTERM_DO_LT,NULL,
294-
cpo_flags);
301+
char*replaced=replace_termcodes(orig_rhs,orig_rhs_len,&rhs_buf,REPTERM_DO_LT,NULL,
302+
cpo_flags);
295303
mapargs->rhs_len=STRLEN(replaced);
296304
// NB: replace_termcodes may produce an empty string even if orig_rhs is non-empty
297305
// (e.g. a single ^V, see :h map-empty-rhs)
@@ -308,7 +316,6 @@ static bool set_maparg_lhs_rhs(const char *const orig_lhs, const size_t orig_lhs
308316
(char_u)KS_EXTRA,KE_LUA,rhs_lua);
309317
mapargs->rhs=vim_strsave((char_u*)tmp_buf);
310318
}
311-
return true;
312319
}
313320

314321
/// Parse a string of |:map-arguments| into a @ref MapArguments struct.
@@ -2150,29 +2157,36 @@ void f_mapset(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
21502157
char*lhs=tv_dict_get_string(d,"lhs", false);
21512158
char*lhsraw=tv_dict_get_string(d,"lhsraw", false);
21522159
char*lhsrawalt=tv_dict_get_string(d,"lhsrawalt", false);
2153-
char*rhs=tv_dict_get_string(d,"rhs", false);
2154-
if (lhs==NULL||lhsraw==NULL||rhs==NULL) {
2160+
char*orig_rhs=tv_dict_get_string(d,"rhs", false);
2161+
LuaRefrhs_lua=LUA_NOREF;
2162+
dictitem_T*callback_di=tv_dict_find(d,S_LEN("callback"));
2163+
if (callback_di!=NULL) {
2164+
Objectcallback_obj=vim_to_object(&callback_di->di_tv);
2165+
if (callback_obj.type==kObjectTypeLuaRef&&callback_obj.data.luaref!=LUA_NOREF) {
2166+
rhs_lua=callback_obj.data.luaref;
2167+
orig_rhs="";// need non-NULL for strlen()
2168+
callback_obj.data.luaref=LUA_NOREF;
2169+
}
2170+
api_free_object(callback_obj);
2171+
}
2172+
if (lhs==NULL||lhsraw==NULL|| (orig_rhs==NULL&&rhs_lua==LUA_NOREF)) {
21552173
emsg(_("E460: entries missing in mapset() dict argument"));
2174+
api_free_luaref(rhs_lua);
21562175
return;
21572176
}
2158-
char*orig_rhs=rhs;
2159-
char*arg_buf=NULL;
2160-
rhs=replace_termcodes(rhs,STRLEN(rhs),&arg_buf,REPTERM_DO_LT,NULL,CPO_TO_CPO_FLAGS);
21612177

2162-
intnoremap=tv_dict_get_number(d,"noremap") ?REMAP_NONE :0;
2178+
intnoremap=tv_dict_get_number(d,"noremap")!=0?REMAP_NONE :0;
21632179
if (tv_dict_get_number(d,"script")!=0) {
21642180
noremap=REMAP_SCRIPT;
21652181
}
2166-
MapArgumentsargs= {// TODO(zeertzjq): support restoring "callback"?
2167-
.rhs= (char_u*)rhs,
2168-
.rhs_lua=LUA_NOREF,
2169-
.orig_rhs=vim_strsave((char_u*)orig_rhs),
2182+
MapArgumentsargs= {
21702183
.expr=tv_dict_get_number(d,"expr")!=0,
21712184
.silent=tv_dict_get_number(d,"silent")!=0,
21722185
.nowait=tv_dict_get_number(d,"nowait")!=0,
21732186
.replace_keycodes=tv_dict_get_number(d,"replace_keycodes")!=0,
21742187
.desc=tv_dict_get_string(d,"desc", false),
21752188
};
2189+
set_maparg_rhs(orig_rhs,strlen(orig_rhs),rhs_lua,CPO_TO_CPO_FLAGS,&args);
21762190
scid_Tsid= (scid_T)tv_dict_get_number(d,"sid");
21772191
linenr_Tlnum= (linenr_T)tv_dict_get_number(d,"lnum");
21782192
boolbuffer=tv_dict_get_number(d,"buffer")!=0;
@@ -2183,7 +2197,7 @@ void f_mapset(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
21832197

21842198
// Delete any existing mapping for this lhs and mode.
21852199
MapArgumentsunmap_args=MAP_ARGUMENTS_INIT;
2186-
set_maparg_lhs_rhs(lhs,strlen(lhs),rhs,strlen(rhs),LUA_NOREF,0,&unmap_args);
2200+
set_maparg_lhs_rhs(lhs,strlen(lhs),"",0,LUA_NOREF,0,&unmap_args);
21872201
unmap_args.buffer=buffer;
21882202
buf_do_map(MAPTYPE_UNMAP,&unmap_args,mode, false,curbuf);
21892203
xfree(unmap_args.rhs);

‎src/nvim/testdir/test_maparg.vim‎

Lines changed: 27 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -158,11 +158,11 @@ func Test_range_map()
158158
callassert_equal("abcd",getline(1))
159159
endfunc
160160

161-
funcOne_mapset_test(keys)
162-
exe'nnoremap' ..a:keys ..'original<CR>'
161+
funcOne_mapset_test(keys, rhs)
162+
exe'nnoremap' ..a:keys ..'' ..a:rhs
163163
let orig=maparg(a:keys,'n',0,1)
164164
callassert_equal(a:keys, orig.lhs)
165-
callassert_equal('original<CR>', orig.rhs)
165+
callassert_equal(a:rhs, orig.rhs)
166166
callassert_equal('n', orig.mode)
167167

168168
exe'nunmap' ..a:keys
@@ -172,15 +172,16 @@ func One_mapset_test(keys)
172172
callmapset('n',0, orig)
173173
letd=maparg(a:keys,'n',0,1)
174174
callassert_equal(a:keys,d.lhs)
175-
callassert_equal('original<CR>',d.rhs)
175+
callassert_equal(a:rhs,d.rhs)
176176
callassert_equal('n',d.mode)
177177

178178
exe'nunmap' ..a:keys
179179
endfunc
180180

181181
funcTest_mapset()
182-
callOne_mapset_test('K')
183-
callOne_mapset_test('<F3>')
182+
callOne_mapset_test('K','original<CR>')
183+
callOne_mapset_test('<F3>','original<CR>')
184+
callOne_mapset_test('<F3>','<lt>Nop>')
184185

185186
" Check <> key conversion
186187
new
@@ -203,6 +204,26 @@ func Test_mapset()
203204

204205
iunmapK
205206

207+
" Test that <Nop> is restored properly
208+
inoremapK<Nop>
209+
callfeedkeys("SK\<Esc>",'xt')
210+
callassert_equal('',getline(1))
211+
212+
let orig=maparg('K','i',0,1)
213+
callassert_equal('K', orig.lhs)
214+
callassert_equal('<Nop>', orig.rhs)
215+
callassert_equal('i', orig.mode)
216+
217+
inoremapKfoo
218+
callfeedkeys("SK\<Esc>",'xt')
219+
callassert_equal('foo',getline(1))
220+
221+
callmapset('i',0, orig)
222+
callfeedkeys("SK\<Esc>",'xt')
223+
callassert_equal('',getline(1))
224+
225+
iunmapK
226+
206227
" Test literal <CR> using a backslash
207228
let cpo_save= &cpo
208229
setcpo-=B

‎test/functional/vimscript/map_functions_spec.lua‎

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,16 @@ local helpers = require('test.functional.helpers')(after_each)
33
localclear=helpers.clear
44
localeq=helpers.eq
55
localeval=helpers.eval
6+
localexec=helpers.exec
7+
localexec_lua=helpers.exec_lua
68
localexpect=helpers.expect
79
localfeed=helpers.feed
810
localfuncs=helpers.funcs
911
localmeths=helpers.meths
1012
localnvim=helpers.nvim
1113
localsource=helpers.source
1214
localcommand=helpers.command
15+
localpcall_err=helpers.pcall_err
1316

1417
describe('maparg()',function()
1518
before_each(clear)
@@ -194,4 +197,43 @@ describe('mapset()', function()
194197
feed('foo')
195198
expect('<<lt><')
196199
end)
200+
201+
it('can restore Lua callback from the dict returned by maparg()',function()
202+
eq(0,exec_lua([[
203+
GlobalCount = 0
204+
vim.api.nvim_set_keymap('n', 'asdf', '', {callback = function() GlobalCount = GlobalCount + 1 end })
205+
return GlobalCount
206+
]]))
207+
feed('asdf')
208+
eq(1,exec_lua([[return GlobalCount]]))
209+
210+
exec_lua([[
211+
_G.saved_asdf_map = vim.fn.maparg('asdf', 'n', false, true)
212+
vim.api.nvim_set_keymap('n', 'asdf', '', {callback = function() GlobalCount = GlobalCount + 10 end })
213+
]])
214+
feed('asdf')
215+
eq(11,exec_lua([[return GlobalCount]]))
216+
217+
exec_lua([[vim.fn.mapset('n', false, _G.saved_asdf_map)]])
218+
feed('asdf')
219+
eq(12,exec_lua([[return GlobalCount]]))
220+
221+
exec([[
222+
let g:saved_asdf_map = maparg('asdf', 'n', v:false, v:true)
223+
lua vim.api.nvim_set_keymap('n', 'asdf', '', {callback = function() GlobalCount = GlobalCount + 10 end })
224+
]])
225+
feed('asdf')
226+
eq(22,exec_lua([[return GlobalCount]]))
227+
228+
command([[call mapset('n', v:false, g:saved_asdf_map)]])
229+
feed('asdf')
230+
eq(23,exec_lua([[return GlobalCount]]))
231+
end)
232+
233+
it('does not leak memory if lhs is missing',function()
234+
eq('Error executing lua: Vim:E460: entries missing in mapset() dict argument',
235+
pcall_err(exec_lua,[[vim.fn.mapset('n', false, {rhs = 'foo'})]]))
236+
eq('Error executing lua: Vim:E460: entries missing in mapset() dict argument',
237+
pcall_err(exec_lua,[[vim.fn.mapset('n', false, {callback = function() end})]]))
238+
end)
197239
end)

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp