vim-patch:8.2.4594: need to write script to a file to be able to source them

Problem:    Need to write script to a file to be able to source them.
Solution:   Make ":source" use lines from the current buffer. (Yegappan
            Lakshmanan et al., closes vim/vim#9967)

36a5b6867b

Most code and test changes are reverted or modified again in patch
8.2.4603, so only port parts that are untouched in patch 8.2.4603.

Co-authored-by: Yegappan Lakshmanan <yegappan@yahoo.com>
This commit is contained in:
zeertzjq
2025-02-28 13:40:26 +08:00
parent 9b25c68db2
commit a3a9f86d4a
6 changed files with 48 additions and 16 deletions

View File

@@ -192,14 +192,19 @@ Using Vim scripts *using-scripts*
For writing a Vim script, see chapter 41 of the user manual |usr_41.txt|.
*:so* *:source* *load-vim-script*
:[range]so[urce] [file] Runs |Ex-commands| or Lua code (".lua" files) from
[file].
If no [file], the current buffer is used and treated
as Lua code if 'filetype' is "lua" or its filename
ends with ".lua".
:so[urce] {file} Runs |Ex-commands| or Lua code (".lua" files) from
{file}.
Triggers the |SourcePre| autocommand.
:[range]so[urce] Read Ex commands or Lua code from the [range] of lines
in the current buffer. The buffer is treated as Lua
code if 'filetype' is "lua" or its filename ends with
".lua". When sourcing commands or Lua code from the
current buffer, the same script-ID |<SID>| is used
even if the buffer is sourced multiple times.
*:source!*
:[range]so[urce]! {file}
:so[urce]! {file}
Runs |Normal-mode| commands from {file}. When used
after |:global|, |:argdo|, |:windo|, |:bufdo|, in
a loop or when another command follows the display

View File

@@ -759,7 +759,7 @@ void fill_evalarg_from_eap(evalarg_T *evalarg, exarg_T *eap, bool skip)
return;
}
if (getline_equal(eap->ea_getline, eap->cookie, getsourceline)) {
if (sourcing_a_script(eap)) {
evalarg->eval_getline = eap->ea_getline;
evalarg->eval_cookie = eap->cookie;
}

View File

@@ -2533,7 +2533,7 @@ M.cmds = {
},
{
command = 'source',
flags = bit.bor(RANGE, DFLALL, WHOLEFOLD, BANG, FILE1, TRLBAR, SBOXOK, CMDWIN, LOCK_OK),
flags = bit.bor(RANGE, DFLALL, BANG, FILE1, TRLBAR, SBOXOK, CMDWIN, LOCK_OK),
addr_type = 'ADDR_LINES',
func = 'ex_source',
},

View File

@@ -198,12 +198,13 @@ void ga_concat(garray_T *gap, const char *restrict s)
void ga_concat_len(garray_T *const gap, const char *restrict s, const size_t len)
FUNC_ATTR_NONNULL_ALL
{
if (len) {
if (len == 0) {
return;
}
ga_grow(gap, (int)len);
char *data = gap->ga_data;
memcpy(data + gap->ga_len, s, len);
gap->ga_len += (int)len;
}
}
/// Append one byte to a growarray which contains bytes.

View File

@@ -106,6 +106,7 @@ garray_T script_items = { 0, 0, sizeof(scriptitem_T *), 20, NULL };
/// The names of packages that once were loaded are remembered.
static garray_T ga_loaded = { 0, 0, sizeof(char *), 4, NULL };
/// last used sequence number for sourcing scripts (current_sctx.sc_seq)
static int last_current_SID_seq = 0;
/// Initialize the execution stack.
@@ -1825,8 +1826,20 @@ freeall:
static void cmd_source(char *fname, exarg_T *eap)
{
if (*fname != NUL && eap != NULL && eap->addr_count > 0) {
// if a filename is specified to :source, then a range is not allowed
emsg(_(e_norange));
return;
}
if (eap != NULL && *fname == NUL) {
if (eap->forceit) {
// a file name is needed to source normal mode commands
emsg(_(e_argreq));
} else {
// source ex commands from the current buffer
cmd_source_buffer(eap, false);
}
} else if (eap != NULL && eap->forceit) {
// ":source!": read Normal mode commands
// Need to execute the commands directly. This is required at least
@@ -2784,11 +2797,18 @@ retry:
return NULL;
}
/// Returns true if sourcing a script either from a file or a buffer.
/// Otherwise returns false.
int sourcing_a_script(exarg_T *eap)
{
return getline_equal(eap->ea_getline, eap->cookie, getsourceline);
}
/// ":scriptencoding": Set encoding conversion for a sourced script.
/// Without the multi-byte feature it's simply ignored.
void ex_scriptencoding(exarg_T *eap)
{
if (!getline_equal(eap->ea_getline, eap->cookie, getsourceline)) {
if (!sourcing_a_script(eap)) {
emsg(_("E167: :scriptencoding used outside of a sourced file"));
return;
}
@@ -2807,7 +2827,7 @@ void ex_scriptencoding(exarg_T *eap)
/// ":finish": Mark a sourced file as finished.
void ex_finish(exarg_T *eap)
{
if (getline_equal(eap->ea_getline, eap->cookie, getsourceline)) {
if (sourcing_a_script(eap)) {
do_finish(eap, false);
} else {
emsg(_("E168: :finish used outside of a sourced file"));

View File

@@ -92,6 +92,12 @@ func Test_source_error()
call assert_fails('scriptencoding utf-8', 'E167:')
call assert_fails('finish', 'E168:')
" call assert_fails('scriptversion 2', 'E984:')
call assert_fails('source!', 'E471:')
new
call setline(1, ['', '', '', ''])
call assert_fails('1,3source Xscript.vim', 'E481:')
call assert_fails('1,3source! Xscript.vim', 'E481:')
bw!
endfunc
" Test for sourcing a script recursively