Skip to content

Commit ecf2a60

Browse files
committed
[Fix] parse: preserve whitespace in comments
Fixes #6
1 parent 1d58679 commit ecf2a60

File tree

3 files changed

+32
-9
lines changed

3 files changed

+32
-9
lines changed

parse.js

Lines changed: 25 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,24 @@ for (var i = 0; i < 4; i++) {
3131
}
3232
var startsWithToken = new RegExp('^' + TOKEN);
3333

34+
function matchAll(s, r) {
35+
var origIndex = r.lastIndex;
36+
37+
var matches = [];
38+
var matchObj;
39+
40+
while ((matchObj = r.exec(s))) {
41+
matches.push(matchObj);
42+
if (r.lastIndex === matchObj.index) {
43+
r.lastIndex += 1;
44+
}
45+
}
46+
47+
r.lastIndex = origIndex;
48+
49+
return matches;
50+
}
51+
3452
function parseInternal(string, env, opts) {
3553
if (!opts) {
3654
opts = {};
@@ -43,9 +61,9 @@ function parseInternal(string, env, opts) {
4361
'(' + BAREWORD + '|' + SINGLE_QUOTE + '|' + DOUBLE_QUOTE + ')+'
4462
].join('|'), 'g');
4563

46-
var matches = string.match(chunker);
64+
var matches = matchAll(string, chunker);
4765

48-
if (!matches) {
66+
if (matches.length === 0) {
4967
return [];
5068
}
5169
if (!env) {
@@ -68,8 +86,9 @@ function parseInternal(string, env, opts) {
6886
return pre + r;
6987
}
7088

71-
return matches.filter(Boolean).map(function (s, j, match) {
72-
if (commented) {
89+
return matches.map(function (match) {
90+
var s = match[0];
91+
if (!s || commented) {
7392
return void undefined;
7493
}
7594
if (controlRE.test(s)) {
@@ -157,7 +176,7 @@ function parseInternal(string, env, opts) {
157176
return { op: s };
158177
} else if (hash.test(c)) {
159178
commented = true;
160-
var commentObj = { comment: s.slice(i + 1) + match.slice(j + 1).join(' ') };
179+
var commentObj = { comment: string.slice(match.index + i + 1) };
161180
if (out.length) {
162181
return [out, commentObj];
163182
}
@@ -177,6 +196,7 @@ function parseInternal(string, env, opts) {
177196

178197
return out;
179198
}).reduce(function (prev, arg) { // finalize parsed arguments
199+
// TODO: replace this whole reduce with a concat
180200
return typeof arg === 'undefined' ? prev : prev.concat(arg);
181201
}, []);
182202
}

test/comment.js

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,11 @@ var parse = require('../').parse;
66
test('comment', function (t) {
77
t.same(parse('beep#boop'), ['beep', { comment: 'boop' }]);
88
t.same(parse('beep #boop'), ['beep', { comment: 'boop' }]);
9-
t.same(parse('beep # boop'), ['beep', { comment: 'boop' }]);
10-
t.same(parse('beep # > boop'), ['beep', { comment: '> boop' }]);
11-
t.same(parse('beep # "> boop"'), ['beep', { comment: '"> boop"' }]);
9+
t.same(parse('beep # boop'), ['beep', { comment: ' boop' }]);
10+
t.same(parse('beep # > boop'), ['beep', { comment: ' > boop' }]);
11+
t.same(parse('beep # "> boop"'), ['beep', { comment: ' "> boop"' }]);
1212
t.same(parse('beep "#"'), ['beep', '#']);
1313
t.same(parse('beep #"#"#'), ['beep', { comment: '"#"#' }]);
14-
t.same(parse('beep > boop # > foo'), ['beep', { op: '>' }, 'boop', { comment: '> foo' }]);
14+
t.same(parse('beep > boop # > foo'), ['beep', { op: '>' }, 'boop', { comment: ' > foo' }]);
1515
t.end();
1616
});

test/parse.js

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,5 +24,8 @@ test('parse shell commands', function (t) {
2424
t.same(parse("x bl^'a^'h'", {}, { escape: '^' }), ['x', "bl'a'h"]);
2525
t.same(parse('abcH def', {}, { escape: 'H' }), ['abc def']);
2626

27+
t.deepEqual(parse('# abc def ghi'), [{ comment: ' abc def ghi' }], 'start-of-line comment content is unparsed');
28+
t.deepEqual(parse('xyz # abc def ghi'), ['xyz', { comment: ' abc def ghi' }], 'comment content is unparsed');
29+
2730
t.end();
2831
});

0 commit comments

Comments
 (0)