@@ -1224,6 +1224,102 @@ eval_foldexpr(char_u *arg, int *cp)
12241224}
12251225#endif
12261226
1227+ /*
1228+ * Get a list of lines from a HERE document. The here document is a list of
1229+ * lines surrounded by a marker.
1230+ * cmd << {marker}
1231+ * {line1}
1232+ * {line2}
1233+ * ....
1234+ * {marker}
1235+ *
1236+ * The {marker} is a string. If the optional 'trim' word is supplied before the
1237+ * marker, then the leading indentation before the lines (matching the
1238+ * indentation in the 'cmd' line) is stripped.
1239+ * Returns a List with {lines} or NULL.
1240+ */
1241+ static list_T *
1242+ heredoc_get (exarg_T * eap , char_u * cmd )
1243+ {
1244+ char_u * theline ;
1245+ char_u * marker ;
1246+ list_T * l ;
1247+ char_u * p ;
1248+ int indent_len = 0 ;
1249+
1250+ if (eap -> getline == NULL )
1251+ {
1252+ emsg (_ ("E991: cannot use =<< here" ));
1253+ return NULL ;
1254+ }
1255+
1256+ // Check for the optional 'trim' word before the marker
1257+ cmd = skipwhite (cmd );
1258+ if (STRNCMP (cmd , "trim" , 4 ) == 0 && (cmd [4 ] == NUL || VIM_ISWHITE (cmd [4 ])))
1259+ {
1260+ cmd = skipwhite (cmd + 4 );
1261+
1262+ // Trim the indentation from all the lines in the here document
1263+ // The amount of indentation trimmed is the same as the indentation of
1264+ // the :let command line.
1265+ p = * eap -> cmdlinep ;
1266+ while (VIM_ISWHITE (* p ))
1267+ {
1268+ p ++ ;
1269+ indent_len ++ ;
1270+ }
1271+ }
1272+
1273+ // The marker is the next word. Default marker is "."
1274+ if (* cmd != NUL && * cmd != '"' )
1275+ {
1276+ marker = skipwhite (cmd );
1277+ p = skiptowhite (marker );
1278+ if (* skipwhite (p ) != NUL && * skipwhite (p ) != '"' )
1279+ {
1280+ emsg (_ (e_trailing ));
1281+ return NULL ;
1282+ }
1283+ * p = NUL ;
1284+ }
1285+ else
1286+ marker = (char_u * )"." ;
1287+
1288+ l = list_alloc ();
1289+ if (l == NULL )
1290+ return NULL ;
1291+
1292+ for (;;)
1293+ {
1294+ int i = 0 ;
1295+
1296+ theline = eap -> getline (NUL , eap -> cookie , 0 );
1297+ if (theline != NULL && indent_len > 0 )
1298+ {
1299+ // trim the indent matching the first line
1300+ if (STRNCMP (theline , * eap -> cmdlinep , indent_len ) == 0 )
1301+ i = indent_len ;
1302+ }
1303+
1304+ if (theline == NULL )
1305+ {
1306+ semsg (_ ("E990: Missing end marker '%s'" ), marker );
1307+ break ;
1308+ }
1309+ if (STRCMP (marker , theline + i ) == 0 )
1310+ {
1311+ vim_free (theline );
1312+ break ;
1313+ }
1314+
1315+ if (list_append_string (l , theline + i , -1 ) == FAIL )
1316+ break ;
1317+ vim_free (theline );
1318+ }
1319+
1320+ return l ;
1321+ }
1322+
12271323/*
12281324 * ":let" list all variable values
12291325 * ":let var1 var2" list variable values
@@ -1286,6 +1382,22 @@ ex_let(exarg_T *eap)
12861382 }
12871383 eap -> nextcmd = check_nextcmd (arg );
12881384 }
1385+ else if (expr [0 ] == '=' && expr [1 ] == '<' && expr [2 ] == '<' )
1386+ {
1387+ list_T * l ;
1388+
1389+ // HERE document
1390+ l = heredoc_get (eap , expr + 3 );
1391+ if (l != NULL )
1392+ {
1393+ rettv_list_set (& rettv , l );
1394+ op [0 ] = '=' ;
1395+ op [1 ] = NUL ;
1396+ (void )ex_let_vars (eap -> arg , & rettv , FALSE, semicolon , var_count ,
1397+ op );
1398+ clear_tv (& rettv );
1399+ }
1400+ }
12891401 else
12901402 {
12911403 op [0 ] = '=' ;
0 commit comments