aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--runtime/doc/repeat.txt17
-rw-r--r--src/nvim/eval.c2
-rw-r--r--src/nvim/ex_cmds.lua2
-rw-r--r--src/nvim/garray.c11
-rw-r--r--src/nvim/runtime.c26
-rw-r--r--test/old/testdir/test_source.vim6
6 files changed, 48 insertions, 16 deletions
diff --git a/runtime/doc/repeat.txt b/runtime/doc/repeat.txt
index e65caa72ed..4c95066998 100644
--- a/runtime/doc/repeat.txt
+++ b/runtime/doc/repeat.txt
@@ -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
diff --git a/src/nvim/eval.c b/src/nvim/eval.c
index 2b6fefbf82..ee5dd25e93 100644
--- a/src/nvim/eval.c
+++ b/src/nvim/eval.c
@@ -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;
}
diff --git a/src/nvim/ex_cmds.lua b/src/nvim/ex_cmds.lua
index d118c808d3..d68d5a9afa 100644
--- a/src/nvim/ex_cmds.lua
+++ b/src/nvim/ex_cmds.lua
@@ -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',
},
diff --git a/src/nvim/garray.c b/src/nvim/garray.c
index a8d15a1fa8..b3dce90b11 100644
--- a/src/nvim/garray.c
+++ b/src/nvim/garray.c
@@ -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) {
- ga_grow(gap, (int)len);
- char *data = gap->ga_data;
- memcpy(data + gap->ga_len, s, len);
- gap->ga_len += (int)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.
diff --git a/src/nvim/runtime.c b/src/nvim/runtime.c
index 861a44cc05..f02c8660f1 100644
--- a/src/nvim/runtime.c
+++ b/src/nvim/runtime.c
@@ -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) {
- cmd_source_buffer(eap, false);
+ 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"));
diff --git a/test/old/testdir/test_source.vim b/test/old/testdir/test_source.vim
index 01c08b183c..130d859224 100644
--- a/test/old/testdir/test_source.vim
+++ b/test/old/testdir/test_source.vim
@@ -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