mirror of
https://github.com/vim/vim.git
synced 2025-09-24 03:44:06 -04:00
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 #4386)
This commit is contained in:
@@ -11416,6 +11416,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
|
||||||
|
112
src/eval.c
112
src/eval.c
@@ -1224,6 +1224,102 @@ eval_foldexpr(char_u *arg, int *cp)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 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 *theline;
|
||||||
|
char_u *marker;
|
||||||
|
list_T *l;
|
||||||
|
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 || VIM_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 (VIM_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 *)".";
|
||||||
|
|
||||||
|
l = list_alloc();
|
||||||
|
if (l == NULL)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
for (;;)
|
||||||
|
{
|
||||||
|
int i = 0;
|
||||||
|
|
||||||
|
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)
|
||||||
|
{
|
||||||
|
semsg(_("E990: Missing end marker '%s'"), marker);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (STRCMP(marker, theline + i) == 0)
|
||||||
|
{
|
||||||
|
vim_free(theline);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (list_append_string(l, theline + i, -1) == FAIL)
|
||||||
|
break;
|
||||||
|
vim_free(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
|
||||||
@@ -1286,6 +1382,22 @@ ex_let(exarg_T *eap)
|
|||||||
}
|
}
|
||||||
eap->nextcmd = check_nextcmd(arg);
|
eap->nextcmd = check_nextcmd(arg);
|
||||||
}
|
}
|
||||||
|
else if (expr[0] == '=' && expr[1] == '<' && expr[2] == '<')
|
||||||
|
{
|
||||||
|
list_T *l;
|
||||||
|
|
||||||
|
// HERE document
|
||||||
|
l = heredoc_get(eap, expr + 3);
|
||||||
|
if (l != NULL)
|
||||||
|
{
|
||||||
|
rettv_list_set(&rettv, l);
|
||||||
|
op[0] = '=';
|
||||||
|
op[1] = NUL;
|
||||||
|
(void)ex_let_vars(eap->arg, &rettv, FALSE, semicolon, var_count,
|
||||||
|
op);
|
||||||
|
clear_tv(&rettv);
|
||||||
|
}
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
op[0] = '=';
|
op[0] = '=';
|
||||||
|
@@ -151,3 +151,57 @@ func Test_let_utf8_environment()
|
|||||||
let $a = 'ĀĒĪŌŪあいうえお'
|
let $a = 'ĀĒĪŌŪあいうえお'
|
||||||
call assert_equal('ĀĒĪŌŪあいうえお', $a)
|
call assert_equal('ĀĒĪŌŪあいうえお', $a)
|
||||||
endfunc
|
endfunc
|
||||||
|
|
||||||
|
" 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
|
||||||
|
@@ -767,6 +767,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 */
|
||||||
|
/**/
|
||||||
|
1354,
|
||||||
/**/
|
/**/
|
||||||
1353,
|
1353,
|
||||||
/**/
|
/**/
|
||||||
|
Reference in New Issue
Block a user