mirror of
				https://github.com/neovim/neovim.git
				synced 2025-10-26 12:27:24 +00:00 
			
		
		
		
	vim-patch:8.1.1354: getting a list of text lines is clumsy
Problem:    Getting a list of text lines is clumsy.
Solution:   Add the =<< assignment. (Yegappan Lakshmanan, closes vim/vim#4386)
f5842c5a53
			
			
This commit is contained in:
		| @@ -9779,6 +9779,44 @@ This does NOT work: > | |||||||
| 			Like above, but append/add/subtract the value for each | 			Like above, but append/add/subtract the value for each | ||||||
| 			|List| item. | 			|List| item. | ||||||
|  |  | ||||||
|  | 					*:let=<<* *:let-heredoc* *E990* *E991* | ||||||
|  | :let {var-name} =<< [trim] {marker} | ||||||
|  | text... | ||||||
|  | text... | ||||||
|  | {marker} | ||||||
|  | 			Set internal variable {var-name} to a List containing | ||||||
|  | 			the lines of text bounded by the string {marker}. | ||||||
|  | 			{marker} must not contain white space. | ||||||
|  | 			The last line should end only with the {marker} string | ||||||
|  | 			without any other character.  Watch out for white | ||||||
|  | 			space after {marker}! | ||||||
|  | 			If {marker} is not supplied, then "." is used as the | ||||||
|  | 			default marker. | ||||||
|  |  | ||||||
|  | 			Any white space characters in the lines of text are | ||||||
|  | 			preserved.  If "trim" is specified before {marker}, | ||||||
|  | 			then all the leading indentation exactly matching the | ||||||
|  | 			leading indentation before `let` is stripped from the | ||||||
|  | 			input lines and the line containing {marker}.  Note | ||||||
|  | 			that the difference between space and tab matters | ||||||
|  | 			here. | ||||||
|  |  | ||||||
|  | 			If {var-name} didn't exist yet, it is created. | ||||||
|  | 			Cannot be followed by another command, but can be | ||||||
|  | 			followed by a comment. | ||||||
|  |  | ||||||
|  | 			Examples: > | ||||||
|  | 				let var1 =<< END | ||||||
|  | 			Sample text 1 | ||||||
|  | 			    Sample text 2 | ||||||
|  | 			Sample text 3 | ||||||
|  | 			END | ||||||
|  |  | ||||||
|  | 				let data =<< trim DATA | ||||||
|  | 				1 2 3 4 | ||||||
|  | 				5 6 7 8 | ||||||
|  | 				DATA | ||||||
|  | < | ||||||
| 								*E121* | 								*E121* | ||||||
| :let {var-name}	..	List the value of variable {var-name}.  Multiple | :let {var-name}	..	List the value of variable {var-name}.  Multiple | ||||||
| 			variable names may be given.  Special names recognized | 			variable names may be given.  Special names recognized | ||||||
|   | |||||||
| @@ -1504,6 +1504,87 @@ void ex_const(exarg_T *eap) | |||||||
|   ex_let_const(eap, true); |   ex_let_const(eap, true); | ||||||
| } | } | ||||||
|  |  | ||||||
|  | // Get a list of lines from a HERE document. The here document is a list of | ||||||
|  | // lines surrounded by a marker. | ||||||
|  | //     cmd << {marker} | ||||||
|  | //       {line1} | ||||||
|  | //       {line2} | ||||||
|  | //       .... | ||||||
|  | //     {marker} | ||||||
|  | // | ||||||
|  | // The {marker} is a string. If the optional 'trim' word is supplied before the | ||||||
|  | // marker, then the leading indentation before the lines (matching the | ||||||
|  | // indentation in the 'cmd' line) is stripped. | ||||||
|  | // Returns a List with {lines} or NULL. | ||||||
|  | static list_T * | ||||||
|  | heredoc_get(exarg_T *eap, char_u *cmd) | ||||||
|  | { | ||||||
|  |   char_u *marker; | ||||||
|  |   char_u *p; | ||||||
|  |   int indent_len = 0; | ||||||
|  |  | ||||||
|  |   if (eap->getline == NULL) { | ||||||
|  |     EMSG(_("E991: cannot use =<< here")); | ||||||
|  |     return NULL; | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   // Check for the optional 'trim' word before the marker | ||||||
|  |   cmd = skipwhite(cmd); | ||||||
|  |   if (STRNCMP(cmd, "trim", 4) == 0 | ||||||
|  |       && (cmd[4] == NUL || ascii_iswhite(cmd[4]))) { | ||||||
|  |     cmd = skipwhite(cmd + 4); | ||||||
|  |  | ||||||
|  |     // Trim the indentation from all the lines in the here document | ||||||
|  |     // The amount of indentation trimmed is the same as the indentation of | ||||||
|  |     // the :let command line. | ||||||
|  |     p = *eap->cmdlinep; | ||||||
|  |     while (ascii_iswhite(*p)) { | ||||||
|  |       p++; | ||||||
|  |       indent_len++; | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   // The marker is the next word.  Default marker is "." | ||||||
|  |   if (*cmd != NUL && *cmd != '"') { | ||||||
|  |     marker = skipwhite(cmd); | ||||||
|  |     p = skiptowhite(marker); | ||||||
|  |     if (*skipwhite(p) != NUL && *skipwhite(p) != '"') { | ||||||
|  |       EMSG(_(e_trailing)); | ||||||
|  |       return NULL; | ||||||
|  |     } | ||||||
|  |     *p = NUL; | ||||||
|  |   } else { | ||||||
|  |     marker = (char_u *)"."; | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   list_T *l = tv_list_alloc(0); | ||||||
|  |   for (;;) { | ||||||
|  |     int i = 0; | ||||||
|  |  | ||||||
|  |     char_u *theline = eap->getline(NUL, eap->cookie, 0); | ||||||
|  |     if (theline != NULL && indent_len > 0) { | ||||||
|  |       // trim the indent matching the first line | ||||||
|  |       if (STRNCMP(theline, *eap->cmdlinep, indent_len) == 0) { | ||||||
|  |         i = indent_len; | ||||||
|  |       } | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     if (theline == NULL) { | ||||||
|  |       EMSG2(_("E990: Missing end marker '%s'"), marker); | ||||||
|  |       break; | ||||||
|  |     } | ||||||
|  |     if (STRCMP(marker, theline + i) == 0) { | ||||||
|  |       xfree(theline); | ||||||
|  |       break; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     tv_list_append_string(l, (char *)(theline + i), -1); | ||||||
|  |     xfree(theline); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   return l; | ||||||
|  | } | ||||||
|  |  | ||||||
| // ":let" list all variable values | // ":let" list all variable values | ||||||
| // ":let var1 var2" list variable values | // ":let var1 var2" list variable values | ||||||
| // ":let var = expr" assignment command. | // ":let var = expr" assignment command. | ||||||
| @@ -1560,6 +1641,17 @@ static void ex_let_const(exarg_T *eap, const bool is_const) | |||||||
|       list_vim_vars(&first); |       list_vim_vars(&first); | ||||||
|     } |     } | ||||||
|     eap->nextcmd = check_nextcmd(arg); |     eap->nextcmd = check_nextcmd(arg); | ||||||
|  |   } else if (expr[0] == '=' && expr[1] == '<' && expr[2] == '<') { | ||||||
|  |     // HERE document | ||||||
|  |     list_T *l = heredoc_get(eap, expr + 3); | ||||||
|  |     if (l != NULL) { | ||||||
|  |       tv_list_set_ret(&rettv, l); | ||||||
|  |       op[0] = '='; | ||||||
|  |       op[1] = NUL; | ||||||
|  |       (void)ex_let_vars(eap->arg, &rettv, false, semicolon, var_count, | ||||||
|  |                         is_const, op); | ||||||
|  |       tv_clear(&rettv); | ||||||
|  |     } | ||||||
|   } else { |   } else { | ||||||
|     op[0] = '='; |     op[0] = '='; | ||||||
|     op[1] = NUL; |     op[1] = NUL; | ||||||
|   | |||||||
| @@ -140,3 +140,58 @@ func Test_let_varg_fail() | |||||||
|   call assert_fails('call s:set_varg7(1)', 'E742:') |   call assert_fails('call s:set_varg7(1)', 'E742:') | ||||||
|   call s:set_varg8([0]) |   call s:set_varg8([0]) | ||||||
| endfunction | endfunction | ||||||
|  |  | ||||||
|  |  | ||||||
|  | " Test for the setting a variable using the heredoc syntax | ||||||
|  | func Test_let_heredoc() | ||||||
|  |   let var1 =<< END | ||||||
|  | Some sample text | ||||||
|  | 	Text with indent | ||||||
|  |   !@#$%^&*()-+_={}|[]\~`:";'<>?,./ | ||||||
|  | END | ||||||
|  |  | ||||||
|  |   call assert_equal(["Some sample text", "\tText with indent", "  !@#$%^&*()-+_={}|[]\\~`:\";'<>?,./"], var1) | ||||||
|  |  | ||||||
|  |   let var2 =<< | ||||||
|  | Editor | ||||||
|  | . | ||||||
|  |   call assert_equal(['Editor'], var2) | ||||||
|  |  | ||||||
|  |   let var3 =<<END | ||||||
|  | END | ||||||
|  |   call assert_equal([], var3) | ||||||
|  |  | ||||||
|  |   let var3 =<<END | ||||||
|  | vim | ||||||
|  |  | ||||||
|  | end | ||||||
|  |   END | ||||||
|  | END  | ||||||
|  | END | ||||||
|  |   call assert_equal(['vim', '', 'end', '  END', 'END '], var3) | ||||||
|  |  | ||||||
|  |         let var1 =<< trim END | ||||||
|  |         Line1 | ||||||
|  |           Line2 | ||||||
|  |         	Line3 | ||||||
|  |          END | ||||||
|  |         END | ||||||
|  |   call assert_equal(['Line1', '  Line2', "\tLine3", ' END'], var1) | ||||||
|  |  | ||||||
|  |   let var1 =<< trim | ||||||
|  |     Line1 | ||||||
|  |   . | ||||||
|  |   call assert_equal(['  Line1'], var1) | ||||||
|  |  | ||||||
|  |   call assert_fails('let v =<< marker', 'E991:') | ||||||
|  |   call assert_fails('call WrongSyntax()', 'E488:') | ||||||
|  |   call assert_fails('call MissingEnd()', 'E990:') | ||||||
|  | endfunc | ||||||
|  |  | ||||||
|  | func WrongSyntax() | ||||||
|  |   let fail =<< that there | ||||||
|  | endfunc | ||||||
|  |  | ||||||
|  | func MissingEnd() | ||||||
|  |   let fail =<< END | ||||||
|  | endfunc | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user
	 Jurica Bradaric
					Jurica Bradaric