forked from aniani/vim
patch 8.2.4748: cannot use an imported function in a mapping
Problem: Cannot use an imported function in a mapping. Solution: Recognize <SID>name.Func.
This commit is contained in:
@@ -1720,7 +1720,15 @@ line, there can be no line break: >
|
|||||||
name # Error!
|
name # Error!
|
||||||
echo that
|
echo that
|
||||||
.name # Error!
|
.name # Error!
|
||||||
< *:import-cycle*
|
|
||||||
|
To refer to a function in an imported script in a mapping, |<SID>| can be
|
||||||
|
used: >
|
||||||
|
noremap <silent> ,a :call <SID>name.Function()<CR>
|
||||||
|
|
||||||
|
When the mapping is defined "<SID>name." will be replaced with <SNR> and the
|
||||||
|
script ID of the imported script.
|
||||||
|
|
||||||
|
*:import-cycle*
|
||||||
The `import` commands are executed when encountered. If script A imports
|
The `import` commands are executed when encountered. If script A imports
|
||||||
script B, and B (directly or indirectly) imports A, this will be skipped over.
|
script B, and B (directly or indirectly) imports A, this will be skipped over.
|
||||||
At this point items in A after "import B" will not have been processed and
|
At this point items in A after "import B" will not have been processed and
|
||||||
|
@@ -6,6 +6,7 @@ int set_ref_in_funcstacks(int copyID);
|
|||||||
char_u *char_from_string(char_u *str, varnumber_T index);
|
char_u *char_from_string(char_u *str, varnumber_T index);
|
||||||
char_u *string_slice(char_u *str, varnumber_T first, varnumber_T last, int exclusive);
|
char_u *string_slice(char_u *str, varnumber_T first, varnumber_T last, int exclusive);
|
||||||
int fill_partial_and_closure(partial_T *pt, ufunc_T *ufunc, ectx_T *ectx);
|
int fill_partial_and_closure(partial_T *pt, ufunc_T *ufunc, ectx_T *ectx);
|
||||||
|
int may_load_script(int sid, int *loaded);
|
||||||
typval_T *lookup_debug_var(char_u *name);
|
typval_T *lookup_debug_var(char_u *name);
|
||||||
int may_break_in_function(ufunc_T *ufunc);
|
int may_break_in_function(ufunc_T *ufunc);
|
||||||
int exe_typval_instr(typval_T *tv, typval_T *rettv);
|
int exe_typval_instr(typval_T *tv, typval_T *rettv);
|
||||||
|
@@ -117,7 +117,7 @@ estack_pop(void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Get the current value for <sfile> in allocated memory.
|
* Get the current value for "which" in allocated memory.
|
||||||
* "which" is ESTACK_SFILE for <sfile>, ESTACK_STACK for <stack> or
|
* "which" is ESTACK_SFILE for <sfile>, ESTACK_STACK for <stack> or
|
||||||
* ESTACK_SCRIPT for <script>.
|
* ESTACK_SCRIPT for <script>.
|
||||||
*/
|
*/
|
||||||
@@ -2468,6 +2468,18 @@ script_autoload(
|
|||||||
int i;
|
int i;
|
||||||
int ret_sid;
|
int ret_sid;
|
||||||
|
|
||||||
|
// If the name starts with "<SNR>123_" then "123" is the script ID.
|
||||||
|
if (name[0] == K_SPECIAL && name[1] == KS_EXTRA && name[2] == KE_SNR)
|
||||||
|
{
|
||||||
|
p = name + 3;
|
||||||
|
ret_sid = (int)getdigits(&p);
|
||||||
|
if (*p == '_' && SCRIPT_ID_VALID(ret_sid))
|
||||||
|
{
|
||||||
|
may_load_script(ret_sid, &ret);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// If there is no '#' after name[0] there is no package name.
|
// If there is no '#' after name[0] there is no package name.
|
||||||
p = vim_strchr(name, AUTOLOAD_CHAR);
|
p = vim_strchr(name, AUTOLOAD_CHAR);
|
||||||
if (p == NULL || p == name)
|
if (p == NULL || p == name)
|
||||||
|
23
src/term.c
23
src/term.c
@@ -6010,8 +6010,11 @@ replace_termcodes(
|
|||||||
{
|
{
|
||||||
#ifdef FEAT_EVAL
|
#ifdef FEAT_EVAL
|
||||||
/*
|
/*
|
||||||
* Replace <SID> by K_SNR <script-nr> _.
|
* Change <SID>Func to K_SNR <script-nr> _Func. This name is used
|
||||||
|
* for script-locla user functions.
|
||||||
* (room: 5 * 6 = 30 bytes; needed: 3 + <nr> + 1 <= 14)
|
* (room: 5 * 6 = 30 bytes; needed: 3 + <nr> + 1 <= 14)
|
||||||
|
* Also change <SID>name.Func to K_SNR <import-script-nr> _Func.
|
||||||
|
* Only if "name" is recognized as an import.
|
||||||
*/
|
*/
|
||||||
if (STRNICMP(src, "<SID>", 5) == 0)
|
if (STRNICMP(src, "<SID>", 5) == 0)
|
||||||
{
|
{
|
||||||
@@ -6019,12 +6022,26 @@ replace_termcodes(
|
|||||||
emsg(_(e_using_sid_not_in_script_context));
|
emsg(_(e_using_sid_not_in_script_context));
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
char_u *dot;
|
||||||
|
long sid = current_sctx.sc_sid;
|
||||||
|
|
||||||
src += 5;
|
src += 5;
|
||||||
|
if (in_vim9script()
|
||||||
|
&& (dot = vim_strchr(src, '.')) != NULL)
|
||||||
|
{
|
||||||
|
imported_T *imp = find_imported(src, dot - src, FALSE);
|
||||||
|
|
||||||
|
if (imp != NULL)
|
||||||
|
{
|
||||||
|
sid = imp->imp_sid;
|
||||||
|
src = dot + 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
result[dlen++] = K_SPECIAL;
|
result[dlen++] = K_SPECIAL;
|
||||||
result[dlen++] = (int)KS_EXTRA;
|
result[dlen++] = (int)KS_EXTRA;
|
||||||
result[dlen++] = (int)KE_SNR;
|
result[dlen++] = (int)KE_SNR;
|
||||||
sprintf((char *)result + dlen, "%ld",
|
sprintf((char *)result + dlen, "%ld", sid);
|
||||||
(long)current_sctx.sc_sid);
|
|
||||||
dlen += (int)STRLEN(result + dlen);
|
dlen += (int)STRLEN(result + dlen);
|
||||||
result[dlen++] = '_';
|
result[dlen++] = '_';
|
||||||
continue;
|
continue;
|
||||||
|
@@ -642,8 +642,8 @@ enddef
|
|||||||
def Test_use_import_in_mapping()
|
def Test_use_import_in_mapping()
|
||||||
var lines =<< trim END
|
var lines =<< trim END
|
||||||
vim9script
|
vim9script
|
||||||
export def Funcx()
|
export def Funcx(nr: number)
|
||||||
g:result = 42
|
g:result = nr
|
||||||
enddef
|
enddef
|
||||||
END
|
END
|
||||||
writefile(lines, 'XsomeExport.vim')
|
writefile(lines, 'XsomeExport.vim')
|
||||||
@@ -651,18 +651,48 @@ def Test_use_import_in_mapping()
|
|||||||
vim9script
|
vim9script
|
||||||
import './XsomeExport.vim' as some
|
import './XsomeExport.vim' as some
|
||||||
var Funcy = some.Funcx
|
var Funcy = some.Funcx
|
||||||
nnoremap <F3> :call <sid>Funcy()<cr>
|
nnoremap <F3> :call <sid>Funcy(42)<cr>
|
||||||
|
nnoremap <F4> :call <sid>some.Funcx(44)<cr>
|
||||||
END
|
END
|
||||||
writefile(lines, 'Xmapscript.vim')
|
writefile(lines, 'Xmapscript.vim')
|
||||||
|
|
||||||
source Xmapscript.vim
|
source Xmapscript.vim
|
||||||
feedkeys("\<F3>", "xt")
|
feedkeys("\<F3>", "xt")
|
||||||
assert_equal(42, g:result)
|
assert_equal(42, g:result)
|
||||||
|
feedkeys("\<F4>", "xt")
|
||||||
|
assert_equal(44, g:result)
|
||||||
|
|
||||||
unlet g:result
|
unlet g:result
|
||||||
delete('XsomeExport.vim')
|
delete('XsomeExport.vim')
|
||||||
delete('Xmapscript.vim')
|
delete('Xmapscript.vim')
|
||||||
nunmap <F3>
|
nunmap <F3>
|
||||||
|
nunmap <F4>
|
||||||
|
enddef
|
||||||
|
|
||||||
|
def Test_use_autoload_import_in_mapping()
|
||||||
|
var lines =<< trim END
|
||||||
|
vim9script
|
||||||
|
export def Func()
|
||||||
|
g:result = 42
|
||||||
|
enddef
|
||||||
|
END
|
||||||
|
writefile(lines, 'XautoloadExport.vim')
|
||||||
|
lines =<< trim END
|
||||||
|
vim9script
|
||||||
|
import autoload './XautoloadExport.vim' as some
|
||||||
|
nnoremap <F3> :call <SID>some.Func()<CR>
|
||||||
|
END
|
||||||
|
writefile(lines, 'Xmapscript.vim')
|
||||||
|
|
||||||
|
source Xmapscript.vim
|
||||||
|
assert_match('\d\+ A: .*XautoloadExport.vim', execute('scriptnames')->split("\n")[-1])
|
||||||
|
feedkeys("\<F3>", "xt")
|
||||||
|
assert_equal(42, g:result)
|
||||||
|
|
||||||
|
unlet g:result
|
||||||
|
delete('XautoloadExport.vim')
|
||||||
|
delete('Xmapscript.vim')
|
||||||
|
nunmap <F3>
|
||||||
enddef
|
enddef
|
||||||
|
|
||||||
def Test_use_import_in_command_completion()
|
def Test_use_import_in_command_completion()
|
||||||
|
@@ -746,6 +746,8 @@ static char *(features[]) =
|
|||||||
|
|
||||||
static int included_patches[] =
|
static int included_patches[] =
|
||||||
{ /* Add new patch number below this line */
|
{ /* Add new patch number below this line */
|
||||||
|
/**/
|
||||||
|
4748,
|
||||||
/**/
|
/**/
|
||||||
4747,
|
4747,
|
||||||
/**/
|
/**/
|
||||||
|
@@ -1658,6 +1658,29 @@ exec_command(isn_T *iptr)
|
|||||||
return OK;
|
return OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If script "sid" is not loaded yet then load it now.
|
||||||
|
* Caller must make sure "sid" is a valid script ID.
|
||||||
|
* "loaded" is set to TRUE if the script had to be loaded.
|
||||||
|
* Returns FAIL if loading fails, OK if already loaded or loaded now.
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
may_load_script(int sid, int *loaded)
|
||||||
|
{
|
||||||
|
scriptitem_T *si = SCRIPT_ITEM(sid);
|
||||||
|
|
||||||
|
if (si->sn_state == SN_STATE_NOT_LOADED)
|
||||||
|
{
|
||||||
|
*loaded = TRUE;
|
||||||
|
if (do_source(si->sn_name, FALSE, DOSO_NONE, NULL) == FAIL)
|
||||||
|
{
|
||||||
|
semsg(_(e_cant_open_file_str), si->sn_name);
|
||||||
|
return FAIL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return OK;
|
||||||
|
}
|
||||||
|
|
||||||
// used for v_instr of typval of VAR_INSTR
|
// used for v_instr of typval of VAR_INSTR
|
||||||
struct instr_S {
|
struct instr_S {
|
||||||
ectx_T *instr_ectx;
|
ectx_T *instr_ectx;
|
||||||
@@ -2632,19 +2655,12 @@ exec_instructions(ectx_T *ectx)
|
|||||||
|
|
||||||
case ISN_SOURCE:
|
case ISN_SOURCE:
|
||||||
{
|
{
|
||||||
scriptitem_T *si = SCRIPT_ITEM(iptr->isn_arg.number);
|
int notused;
|
||||||
|
|
||||||
if (si->sn_state == SN_STATE_NOT_LOADED)
|
|
||||||
{
|
|
||||||
SOURCING_LNUM = iptr->isn_lnum;
|
SOURCING_LNUM = iptr->isn_lnum;
|
||||||
if (do_source(si->sn_name, FALSE, DOSO_NONE, NULL)
|
if (may_load_script((int)iptr->isn_arg.number, ¬used)
|
||||||
== FAIL)
|
== FAIL)
|
||||||
{
|
|
||||||
semsg(_(e_cant_open_file_str), si->sn_name);
|
|
||||||
goto on_error;
|
goto on_error;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
// execute :substitute with an expression
|
// execute :substitute with an expression
|
||||||
|
Reference in New Issue
Block a user