mirror of
https://github.com/vim/vim.git
synced 2025-09-24 03:44:06 -04:00
patch 8.2.4607: sourcing buffer lines may lead to errors for conflicts
Problem: Sourcing buffer lines may lead to errors for conflicts. Solution: Add the ++clear argument. (Yegappan Lakshmanan, closes #9991)
This commit is contained in:
committed by
Bram Moolenaar
parent
e18acb02bb
commit
35dc17634d
@@ -198,16 +198,35 @@ For writing a Vim script, see chapter 41 of the user manual |usr_41.txt|.
|
|||||||
start with a ":".
|
start with a ":".
|
||||||
Triggers the |SourcePre| autocommand.
|
Triggers the |SourcePre| autocommand.
|
||||||
|
|
||||||
:[range]so[urce] Read Ex commands from the [range] of lines in the
|
:[range]so[urce] [++clear]
|
||||||
current buffer. When sourcing commands from the
|
Read Ex commands from the [range] of lines in the
|
||||||
current buffer, the same script-ID |<SID>| is used
|
current buffer.
|
||||||
even if the buffer is sourced multiple times. If a
|
|
||||||
buffer is sourced more than once, then the functions
|
When sourcing commands from the current buffer, the
|
||||||
in the buffer are redefined again.
|
same script-ID |<SID>| is used even if the buffer is
|
||||||
Sourcing a buffer with a Vim9 script more than once
|
sourced multiple times. If a buffer is sourced more
|
||||||
works like |vim9-reload|.
|
than once, then the functions in the buffer are
|
||||||
To source a script in the Vim9 context, the |:vim9cmd|
|
defined again.
|
||||||
modifier can be used.
|
|
||||||
|
To source a range of lines that doesn't start with the
|
||||||
|
|:vim9script| command in Vim9 script context, the
|
||||||
|
|:vim9cmd| modifier can be used.
|
||||||
|
|
||||||
|
When a range of lines in a buffer is sourced in the
|
||||||
|
Vim9 script context, the previously defined
|
||||||
|
script-local variables and functions are not cleared.
|
||||||
|
This works like the range started with the
|
||||||
|
":vim9script noclear" command. The "++clear" argument
|
||||||
|
can be used to clear the script-local variables and
|
||||||
|
functions before sourcing the script. This works like
|
||||||
|
the range started with the |:vimscript| command
|
||||||
|
without the "noclear" argument. See |vim9-reload| for
|
||||||
|
more information.
|
||||||
|
Examples: >
|
||||||
|
|
||||||
|
:4,5source
|
||||||
|
:vim9cmd :'<,'>source
|
||||||
|
:10,18source ++clear
|
||||||
|
|
||||||
*:source!*
|
*:source!*
|
||||||
:so[urce]! {file} Read Vim commands from {file}. These are commands
|
:so[urce]! {file} Read Vim commands from {file}. These are commands
|
||||||
|
@@ -2,6 +2,7 @@
|
|||||||
int in_vim9script(void);
|
int in_vim9script(void);
|
||||||
int in_old_script(int max_version);
|
int in_old_script(int max_version);
|
||||||
int current_script_is_vim9(void);
|
int current_script_is_vim9(void);
|
||||||
|
void clear_vim9_scriptlocal_vars(int sid);
|
||||||
void ex_vim9script(exarg_T *eap);
|
void ex_vim9script(exarg_T *eap);
|
||||||
int not_in_vim9(exarg_T *eap);
|
int not_in_vim9(exarg_T *eap);
|
||||||
int vim9_bad_comment(char_u *p);
|
int vim9_bad_comment(char_u *p);
|
||||||
|
@@ -23,7 +23,7 @@ static garray_T ga_loaded = {0, 0, sizeof(char_u *), 4, NULL};
|
|||||||
static int last_current_SID_seq = 0;
|
static int last_current_SID_seq = 0;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static int do_source_ext(char_u *fname, int check_other, int is_vimrc, int *ret_sid, exarg_T *eap);
|
static int do_source_ext(char_u *fname, int check_other, int is_vimrc, int *ret_sid, exarg_T *eap, int clearvars);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Initialize the execution stack.
|
* Initialize the execution stack.
|
||||||
@@ -1084,6 +1084,20 @@ ExpandPackAddDir(
|
|||||||
static void
|
static void
|
||||||
cmd_source(char_u *fname, exarg_T *eap)
|
cmd_source(char_u *fname, exarg_T *eap)
|
||||||
{
|
{
|
||||||
|
int clearvars = FALSE;
|
||||||
|
|
||||||
|
if (*fname != NUL && STRNCMP(fname, "++clear", 7) == 0)
|
||||||
|
{
|
||||||
|
// ++clear argument is supplied
|
||||||
|
clearvars = TRUE;
|
||||||
|
fname = fname + 7;
|
||||||
|
if (*fname != NUL)
|
||||||
|
{
|
||||||
|
semsg(_(e_invalid_argument_str), eap->arg);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (*fname != NUL && eap != NULL && eap->addr_count > 0)
|
if (*fname != NUL && eap != NULL && eap->addr_count > 0)
|
||||||
{
|
{
|
||||||
// if a filename is specified to :source, then a range is not allowed
|
// if a filename is specified to :source, then a range is not allowed
|
||||||
@@ -1098,7 +1112,7 @@ cmd_source(char_u *fname, exarg_T *eap)
|
|||||||
emsg(_(e_argument_required));
|
emsg(_(e_argument_required));
|
||||||
else
|
else
|
||||||
// source ex commands from the current buffer
|
// source ex commands from the current buffer
|
||||||
do_source_ext(NULL, FALSE, FALSE, NULL, eap);
|
do_source_ext(NULL, FALSE, FALSE, NULL, eap, clearvars);
|
||||||
}
|
}
|
||||||
else if (eap != NULL && eap->forceit)
|
else if (eap != NULL && eap->forceit)
|
||||||
// ":source!": read Normal mode commands
|
// ":source!": read Normal mode commands
|
||||||
@@ -1292,6 +1306,10 @@ errret:
|
|||||||
* The 'eap' argument is used when sourcing lines from a buffer instead of a
|
* The 'eap' argument is used when sourcing lines from a buffer instead of a
|
||||||
* file.
|
* file.
|
||||||
*
|
*
|
||||||
|
* If 'clearvars' is TRUE, then for scripts which are loaded more than
|
||||||
|
* once, clear all the functions and variables previously defined in that
|
||||||
|
* script.
|
||||||
|
*
|
||||||
* This function may be called recursively!
|
* This function may be called recursively!
|
||||||
*
|
*
|
||||||
* Return FAIL if file could not be opened, OK otherwise.
|
* Return FAIL if file could not be opened, OK otherwise.
|
||||||
@@ -1303,7 +1321,8 @@ do_source_ext(
|
|||||||
int check_other, // check for .vimrc and _vimrc
|
int check_other, // check for .vimrc and _vimrc
|
||||||
int is_vimrc, // DOSO_ value
|
int is_vimrc, // DOSO_ value
|
||||||
int *ret_sid UNUSED,
|
int *ret_sid UNUSED,
|
||||||
exarg_T *eap)
|
exarg_T *eap,
|
||||||
|
int clearvars UNUSED)
|
||||||
{
|
{
|
||||||
source_cookie_T cookie;
|
source_cookie_T cookie;
|
||||||
char_u *p;
|
char_u *p;
|
||||||
@@ -1527,20 +1546,25 @@ do_source_ext(
|
|||||||
{
|
{
|
||||||
si->sn_state = SN_STATE_RELOAD;
|
si->sn_state = SN_STATE_RELOAD;
|
||||||
|
|
||||||
// Script-local variables remain but "const" can be set again.
|
if (!clearvars)
|
||||||
// In Vim9 script variables will be cleared when "vim9script" is
|
{
|
||||||
// encountered without the "noclear" argument.
|
// Script-local variables remain but "const" can be set again.
|
||||||
ht = &SCRIPT_VARS(sid);
|
// In Vim9 script variables will be cleared when "vim9script"
|
||||||
todo = (int)ht->ht_used;
|
// is encountered without the "noclear" argument.
|
||||||
for (hi = ht->ht_array; todo > 0; ++hi)
|
ht = &SCRIPT_VARS(sid);
|
||||||
if (!HASHITEM_EMPTY(hi))
|
todo = (int)ht->ht_used;
|
||||||
{
|
for (hi = ht->ht_array; todo > 0; ++hi)
|
||||||
--todo;
|
if (!HASHITEM_EMPTY(hi))
|
||||||
di = HI2DI(hi);
|
{
|
||||||
di->di_flags |= DI_FLAGS_RELOAD;
|
--todo;
|
||||||
}
|
di = HI2DI(hi);
|
||||||
// imports can be redefined once
|
di->di_flags |= DI_FLAGS_RELOAD;
|
||||||
mark_imports_for_reload(sid);
|
}
|
||||||
|
// imports can be redefined once
|
||||||
|
mark_imports_for_reload(sid);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
clear_vim9_scriptlocal_vars(sid);
|
||||||
|
|
||||||
// reset version, "vim9script" may have been added or removed.
|
// reset version, "vim9script" may have been added or removed.
|
||||||
si->sn_version = 1;
|
si->sn_version = 1;
|
||||||
@@ -1731,7 +1755,7 @@ do_source(
|
|||||||
int is_vimrc, // DOSO_ value
|
int is_vimrc, // DOSO_ value
|
||||||
int *ret_sid UNUSED)
|
int *ret_sid UNUSED)
|
||||||
{
|
{
|
||||||
return do_source_ext(fname, check_other, is_vimrc, ret_sid, NULL);
|
return do_source_ext(fname, check_other, is_vimrc, ret_sid, NULL, FALSE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@@ -608,6 +608,34 @@ func Test_source_buffer_vim9()
|
|||||||
source
|
source
|
||||||
call assert_equal('red', g:Color)
|
call assert_equal('red', g:Color)
|
||||||
|
|
||||||
|
" test for ++clear argument to clear all the functions/variables
|
||||||
|
%d _
|
||||||
|
let lines =<< trim END
|
||||||
|
g:ScriptVarFound = exists("color")
|
||||||
|
g:MyFuncFound = exists('*Myfunc')
|
||||||
|
if g:MyFuncFound
|
||||||
|
finish
|
||||||
|
endif
|
||||||
|
var color = 'blue'
|
||||||
|
def Myfunc()
|
||||||
|
enddef
|
||||||
|
END
|
||||||
|
call setline(1, lines)
|
||||||
|
vim9cmd source
|
||||||
|
call assert_false(g:MyFuncFound)
|
||||||
|
call assert_false(g:ScriptVarFound)
|
||||||
|
vim9cmd source
|
||||||
|
call assert_true(g:MyFuncFound)
|
||||||
|
call assert_true(g:ScriptVarFound)
|
||||||
|
vim9cmd source ++clear
|
||||||
|
call assert_false(g:MyFuncFound)
|
||||||
|
call assert_false(g:ScriptVarFound)
|
||||||
|
vim9cmd source ++clear
|
||||||
|
call assert_false(g:MyFuncFound)
|
||||||
|
call assert_false(g:ScriptVarFound)
|
||||||
|
call assert_fails('vim9cmd source ++clearx', 'E475:')
|
||||||
|
call assert_fails('vim9cmd source ++abcde', 'E484:')
|
||||||
|
|
||||||
%bw!
|
%bw!
|
||||||
endfunc
|
endfunc
|
||||||
|
|
||||||
|
@@ -750,6 +750,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 */
|
||||||
|
/**/
|
||||||
|
4607,
|
||||||
/**/
|
/**/
|
||||||
4606,
|
4606,
|
||||||
/**/
|
/**/
|
||||||
|
@@ -59,6 +59,24 @@ current_script_is_vim9(void)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef FEAT_EVAL
|
||||||
|
/*
|
||||||
|
* Clear Vim9 script-local variables and functions.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
clear_vim9_scriptlocal_vars(int sid)
|
||||||
|
{
|
||||||
|
hashtab_T *ht = &SCRIPT_VARS(sid);
|
||||||
|
|
||||||
|
hashtab_free_contents(ht);
|
||||||
|
hash_init(ht);
|
||||||
|
delete_script_functions(sid);
|
||||||
|
|
||||||
|
// old imports and script variables are no longer valid
|
||||||
|
free_imports_and_script_vars(sid);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* ":vim9script".
|
* ":vim9script".
|
||||||
*/
|
*/
|
||||||
@@ -103,18 +121,9 @@ ex_vim9script(exarg_T *eap UNUSED)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (si->sn_state == SN_STATE_RELOAD && !found_noclear)
|
if (si->sn_state == SN_STATE_RELOAD && !found_noclear)
|
||||||
{
|
|
||||||
hashtab_T *ht = &SCRIPT_VARS(sid);
|
|
||||||
|
|
||||||
// Reloading a script without the "noclear" argument: clear
|
// Reloading a script without the "noclear" argument: clear
|
||||||
// script-local variables and functions.
|
// script-local variables and functions.
|
||||||
hashtab_free_contents(ht);
|
clear_vim9_scriptlocal_vars(sid);
|
||||||
hash_init(ht);
|
|
||||||
delete_script_functions(sid);
|
|
||||||
|
|
||||||
// old imports and script variables are no longer valid
|
|
||||||
free_imports_and_script_vars(sid);
|
|
||||||
}
|
|
||||||
si->sn_state = SN_STATE_HAD_COMMAND;
|
si->sn_state = SN_STATE_HAD_COMMAND;
|
||||||
|
|
||||||
// Store the prefix with the script, it is used to find exported functions.
|
// Store the prefix with the script, it is used to find exported functions.
|
||||||
|
Reference in New Issue
Block a user