mirror of
				https://github.com/neovim/neovim.git
				synced 2025-10-26 12:27:24 +00:00 
			
		
		
		
	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:
		| @@ -192,14 +192,19 @@ Using Vim scripts					*using-scripts* | |||||||
| For writing a Vim script, see chapter 41 of the user manual |usr_41.txt|. | For writing a Vim script, see chapter 41 of the user manual |usr_41.txt|. | ||||||
|  |  | ||||||
| 					*:so* *:source* *load-vim-script* | 					*:so* *:source* *load-vim-script* | ||||||
| :[range]so[urce] [file]	Runs |Ex-commands| or Lua code (".lua" files) from | :so[urce] {file}	Runs |Ex-commands| or Lua code (".lua" files) from | ||||||
| 			[file]. | 			{file}. | ||||||
| 			If no [file], the current buffer is used and treated |  | ||||||
| 			as Lua code if 'filetype' is "lua" or its filename |  | ||||||
| 			ends with ".lua". |  | ||||||
| 			Triggers the |SourcePre| autocommand. | 			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!* | 							*:source!* | ||||||
| :[range]so[urce]! {file} | :so[urce]! {file} | ||||||
| 			Runs |Normal-mode| commands from {file}. When used | 			Runs |Normal-mode| commands from {file}. When used | ||||||
| 			after |:global|, |:argdo|, |:windo|, |:bufdo|, in | 			after |:global|, |:argdo|, |:windo|, |:bufdo|, in | ||||||
| 			a loop or when another command follows the display | 			a loop or when another command follows the display | ||||||
|   | |||||||
| @@ -759,7 +759,7 @@ void fill_evalarg_from_eap(evalarg_T *evalarg, exarg_T *eap, bool skip) | |||||||
|     return; |     return; | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   if (getline_equal(eap->ea_getline, eap->cookie, getsourceline)) { |   if (sourcing_a_script(eap)) { | ||||||
|     evalarg->eval_getline = eap->ea_getline; |     evalarg->eval_getline = eap->ea_getline; | ||||||
|     evalarg->eval_cookie = eap->cookie; |     evalarg->eval_cookie = eap->cookie; | ||||||
|   } |   } | ||||||
|   | |||||||
| @@ -2533,7 +2533,7 @@ M.cmds = { | |||||||
|   }, |   }, | ||||||
|   { |   { | ||||||
|     command = 'source', |     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', |     addr_type = 'ADDR_LINES', | ||||||
|     func = 'ex_source', |     func = 'ex_source', | ||||||
|   }, |   }, | ||||||
|   | |||||||
| @@ -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) | void ga_concat_len(garray_T *const gap, const char *restrict s, const size_t len) | ||||||
|   FUNC_ATTR_NONNULL_ALL |   FUNC_ATTR_NONNULL_ALL | ||||||
| { | { | ||||||
|   if (len) { |   if (len == 0) { | ||||||
|  |     return; | ||||||
|  |   } | ||||||
|   ga_grow(gap, (int)len); |   ga_grow(gap, (int)len); | ||||||
|   char *data = gap->ga_data; |   char *data = gap->ga_data; | ||||||
|   memcpy(data + gap->ga_len, s, len); |   memcpy(data + gap->ga_len, s, len); | ||||||
|   gap->ga_len += (int)len; |   gap->ga_len += (int)len; | ||||||
|   } |  | ||||||
| } | } | ||||||
|  |  | ||||||
| /// Append one byte to a growarray which contains bytes. | /// Append one byte to a growarray which contains bytes. | ||||||
|   | |||||||
| @@ -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. | /// The names of packages that once were loaded are remembered. | ||||||
| static garray_T ga_loaded = { 0, 0, sizeof(char *), 4, NULL }; | 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; | static int last_current_SID_seq = 0; | ||||||
|  |  | ||||||
| /// Initialize the execution stack. | /// Initialize the execution stack. | ||||||
| @@ -1825,8 +1826,20 @@ freeall: | |||||||
|  |  | ||||||
| static void cmd_source(char *fname, exarg_T *eap) | 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 != 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); |       cmd_source_buffer(eap, false); | ||||||
|  |     } | ||||||
|   } else if (eap != NULL && eap->forceit) { |   } else if (eap != NULL && eap->forceit) { | ||||||
|     // ":source!": read Normal mode commands |     // ":source!": read Normal mode commands | ||||||
|     // Need to execute the commands directly.  This is required at least |     // Need to execute the commands directly.  This is required at least | ||||||
| @@ -2784,11 +2797,18 @@ retry: | |||||||
|   return NULL; |   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. | /// ":scriptencoding": Set encoding conversion for a sourced script. | ||||||
| /// Without the multi-byte feature it's simply ignored. | /// Without the multi-byte feature it's simply ignored. | ||||||
| void ex_scriptencoding(exarg_T *eap) | 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")); |     emsg(_("E167: :scriptencoding used outside of a sourced file")); | ||||||
|     return; |     return; | ||||||
|   } |   } | ||||||
| @@ -2807,7 +2827,7 @@ void ex_scriptencoding(exarg_T *eap) | |||||||
| /// ":finish": Mark a sourced file as finished. | /// ":finish": Mark a sourced file as finished. | ||||||
| void ex_finish(exarg_T *eap) | void ex_finish(exarg_T *eap) | ||||||
| { | { | ||||||
|   if (getline_equal(eap->ea_getline, eap->cookie, getsourceline)) { |   if (sourcing_a_script(eap)) { | ||||||
|     do_finish(eap, false); |     do_finish(eap, false); | ||||||
|   } else { |   } else { | ||||||
|     emsg(_("E168: :finish used outside of a sourced file")); |     emsg(_("E168: :finish used outside of a sourced file")); | ||||||
|   | |||||||
| @@ -92,6 +92,12 @@ func Test_source_error() | |||||||
|   call assert_fails('scriptencoding utf-8', 'E167:') |   call assert_fails('scriptencoding utf-8', 'E167:') | ||||||
|   call assert_fails('finish', 'E168:') |   call assert_fails('finish', 'E168:') | ||||||
|   " call assert_fails('scriptversion 2', 'E984:') |   " 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 | endfunc | ||||||
|  |  | ||||||
| " Test for sourcing a script recursively | " Test for sourcing a script recursively | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user
	 zeertzjq
					zeertzjq