Skip to content

Commit 9766ea9

Browse files
authored
Merge pull request #190 from lehmacdj/master
allow leading spaces for heredoc end marker
2 parents 71b3b3f + afee7b1 commit 9766ea9

File tree

5 files changed

+122
-9
lines changed

5 files changed

+122
-9
lines changed

Diff for: autoload/vimlparser.vim

+32-3
Original file line numberDiff line numberDiff line change
@@ -1509,13 +1509,15 @@ function! s:VimLParser.parse_cmd_call() abort
15091509
call self.add_node(node)
15101510
endfunction
15111511

1512-
function! s:VimLParser.parse_heredoc() abort
1512+
function! s:VimLParser.parse_heredoc(prefix) abort
15131513
let node = s:Node(s:NODE_HEREDOC)
15141514
let node.pos = self.ea.cmdpos
15151515
let node.op = ''
15161516
let node.rlist = []
15171517
let node.body = []
15181518

1519+
" allow prefix to precede heredoc end marker if true
1520+
let is_trim = s:FALSE
15191521
while s:TRUE
15201522
call self.reader.skip_white()
15211523
let pos = self.reader.getpos()
@@ -1531,6 +1533,9 @@ function! s:VimLParser.parse_heredoc() abort
15311533
let keynode.pos = pos
15321534
let keynode.value = key
15331535
call add(node.rlist, keynode)
1536+
if key ==# 'trim'
1537+
let is_trim = s:TRUE
1538+
endif
15341539
endif
15351540
endwhile
15361541
if node.op ==# ''
@@ -1543,7 +1548,7 @@ function! s:VimLParser.parse_heredoc() abort
15431548
endif
15441549
let pos = self.reader.getpos()
15451550
let line = self.reader.getn(-1)
1546-
if line ==# node.op
1551+
if line ==# node.op || is_trim && line ==# a:prefix . node.op
15471552
return node
15481553
endif
15491554
let linenode = s:Node(s:NODE_STRING)
@@ -1600,7 +1605,31 @@ function! s:VimLParser.parse_cmd_let() abort
16001605
call self.reader.getn(len(s2))
16011606
call self.reader.skip_white()
16021607
let node.op = s2
1603-
let node.right = self.parse_heredoc()
1608+
1609+
" compute allowed prefix for heredoc end marker (e.g. EOF)
1610+
let pos = self.reader.tell()
1611+
while self.reader.tell() > 0
1612+
if self.reader.peek() ==# '<EOL>'
1613+
call self.reader.seek_cur(1)
1614+
break
1615+
endif
1616+
call self.reader.seek_cur(-1)
1617+
endwhile
1618+
let prefix = ''
1619+
while s:TRUE
1620+
let c = self.reader.getn(1)
1621+
if c ==# ':'
1622+
" any presence of leading ':' disables prefix for heredoc end marker
1623+
let prefix = ''
1624+
break
1625+
elseif !s:iswhite(c)
1626+
break
1627+
endif
1628+
let prefix .= c
1629+
endwhile
1630+
call self.reader.seek_set(pos)
1631+
1632+
let node.right = self.parse_heredoc(prefix)
16041633
call self.add_node(node)
16051634
return
16061635
elseif s1 ==# '='

Diff for: js/vimlparser.js

+31-3
Original file line numberDiff line numberDiff line change
@@ -1805,12 +1805,14 @@ VimLParser.prototype.parse_cmd_call = function() {
18051805
this.add_node(node);
18061806
}
18071807

1808-
VimLParser.prototype.parse_heredoc = function() {
1808+
VimLParser.prototype.parse_heredoc = function(prefix) {
18091809
var node = Node(NODE_HEREDOC);
18101810
node.pos = this.ea.cmdpos;
18111811
node.op = "";
18121812
node.rlist = [];
18131813
node.body = [];
1814+
// allow prefix to precede heredoc end marker if true
1815+
var is_trim = FALSE;
18141816
while (TRUE) {
18151817
this.reader.skip_white();
18161818
var pos = this.reader.getpos();
@@ -1827,6 +1829,9 @@ VimLParser.prototype.parse_heredoc = function() {
18271829
keynode.pos = pos;
18281830
keynode.value = key;
18291831
viml_add(node.rlist, keynode);
1832+
if (key == "trim") {
1833+
var is_trim = TRUE;
1834+
}
18301835
}
18311836
}
18321837
if (node.op == "") {
@@ -1839,7 +1844,7 @@ VimLParser.prototype.parse_heredoc = function() {
18391844
}
18401845
var pos = this.reader.getpos();
18411846
var line = this.reader.getn(-1);
1842-
if (line == node.op) {
1847+
if (line == node.op || is_trim && line == prefix + node.op) {
18431848
return node;
18441849
}
18451850
var linenode = Node(NODE_STRING);
@@ -1894,7 +1899,30 @@ VimLParser.prototype.parse_cmd_let = function() {
18941899
this.reader.getn(viml_len(s2));
18951900
this.reader.skip_white();
18961901
node.op = s2;
1897-
node.right = this.parse_heredoc();
1902+
// compute allowed prefix for heredoc end marker (e.g. EOF)
1903+
var pos = this.reader.tell();
1904+
while (this.reader.tell() > 0) {
1905+
if (this.reader.peek() == "<EOL>") {
1906+
this.reader.seek_cur(1);
1907+
break;
1908+
}
1909+
this.reader.seek_cur(-1);
1910+
}
1911+
var prefix = "";
1912+
while (TRUE) {
1913+
var c = this.reader.getn(1);
1914+
if (c == ":") {
1915+
// any presence of leading ':' disables prefix for heredoc end marker
1916+
var prefix = "";
1917+
break;
1918+
}
1919+
else if (!iswhite(c)) {
1920+
break;
1921+
}
1922+
prefix += c;
1923+
}
1924+
this.reader.seek_set(pos);
1925+
node.right = this.parse_heredoc(prefix);
18981926
this.add_node(node);
18991927
return;
19001928
}

Diff for: py/vimlparser.py

+25-3
Original file line numberDiff line numberDiff line change
@@ -1483,12 +1483,14 @@ def parse_cmd_call(self):
14831483
raise VimLParserException(Err("Not an function call", node.left.pos))
14841484
self.add_node(node)
14851485

1486-
def parse_heredoc(self):
1486+
def parse_heredoc(self, prefix):
14871487
node = Node(NODE_HEREDOC)
14881488
node.pos = self.ea.cmdpos
14891489
node.op = ""
14901490
node.rlist = []
14911491
node.body = []
1492+
# allow prefix to precede heredoc end marker if true
1493+
is_trim = FALSE
14921494
while TRUE:
14931495
self.reader.skip_white()
14941496
pos = self.reader.getpos()
@@ -1503,6 +1505,8 @@ def parse_heredoc(self):
15031505
keynode.pos = pos
15041506
keynode.value = key
15051507
viml_add(node.rlist, keynode)
1508+
if key == "trim":
1509+
is_trim = TRUE
15061510
if node.op == "":
15071511
raise VimLParserException(Err("E172: Missing marker", self.reader.getpos()))
15081512
self.parse_trail()
@@ -1511,7 +1515,7 @@ def parse_heredoc(self):
15111515
break
15121516
pos = self.reader.getpos()
15131517
line = self.reader.getn(-1)
1514-
if line == node.op:
1518+
if line == node.op or is_trim and line == prefix + node.op:
15151519
return node
15161520
linenode = Node(NODE_STRING)
15171521
linenode.pos = pos
@@ -1558,7 +1562,25 @@ def parse_cmd_let(self):
15581562
self.reader.getn(viml_len(s2))
15591563
self.reader.skip_white()
15601564
node.op = s2
1561-
node.right = self.parse_heredoc()
1565+
# compute allowed prefix for heredoc end marker (e.g. EOF)
1566+
pos = self.reader.tell()
1567+
while self.reader.tell() > 0:
1568+
if self.reader.peek() == "<EOL>":
1569+
self.reader.seek_cur(1)
1570+
break
1571+
self.reader.seek_cur(-1)
1572+
prefix = ""
1573+
while TRUE:
1574+
c = self.reader.getn(1)
1575+
if c == ":":
1576+
# any presence of leading ':' disables prefix for heredoc end marker
1577+
prefix = ""
1578+
break
1579+
elif not iswhite(c):
1580+
break
1581+
prefix += c
1582+
self.reader.seek_set(pos)
1583+
node.right = self.parse_heredoc(prefix)
15621584
self.add_node(node)
15631585
return
15641586
elif s1 == "=":

Diff for: test/test_heredoc.ok

+9
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,12 @@
11
(let =<< a (heredoc (list) "EOS" (list "hello" " world")))
22
(let =<< a (heredoc (list "trim") "EOS" (list "\thello" "world")))
33
(let =<< a (heredoc (list) "EOS" (list)))
4+
(if v:true
5+
; matching leading indentation is accepted
6+
(let =<< a (heredoc (list "trim") "EOS" (list "\t\thello" "\tworld")))
7+
(let =<< a (heredoc (list "trim") "EOS" (list " hello" " world")))
8+
; but isn't required
9+
(let =<< a (heredoc (list "trim") "EOS" (list " hello" " world"))))
10+
; we don't actually do the trimming for trim heredocs
11+
(let =<< a (heredoc (list "trim") "EOS" (list " hello" " world")))
12+
(let =<< a (heredoc (list "trim") "EOS" (list "\t hello" "\t\tworld")))

Diff for: test/test_heredoc.vim

+25
Original file line numberDiff line numberDiff line change
@@ -8,3 +8,28 @@ world
88
EOS
99
let a =<< EOS
1010
EOS
11+
if v:true
12+
" matching leading indentation is accepted
13+
let a =<< trim EOS
14+
hello
15+
world
16+
EOS
17+
let a =<< trim EOS
18+
hello
19+
world
20+
EOS
21+
" but isn't required
22+
let a =<< trim EOS
23+
hello
24+
world
25+
EOS
26+
endif
27+
" we don't actually do the trimming for trim heredocs
28+
let a =<< trim EOS
29+
hello
30+
world
31+
EOS
32+
: let a =<< trim EOS
33+
hello
34+
world
35+
EOS

0 commit comments

Comments
 (0)