Support negative comment offsets
This commit is contained in:
parent
ea00d550fe
commit
90e1664ed6
|
|
@ -555,6 +555,94 @@ Rest: 5:00 50%
|
||||||
`);
|
`);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it("parses intervals with negative comment offsets", () => {
|
||||||
|
expect(
|
||||||
|
parse(`
|
||||||
|
Name: My Workout
|
||||||
|
Interval: 10:00 90%
|
||||||
|
@ 0:10 Find your rythm.
|
||||||
|
@ -0:10 Final push. YOU GOT IT!
|
||||||
|
|
||||||
|
Rest: 5:00 50%
|
||||||
|
@ -4:30 Great effort!
|
||||||
|
@ -2:00 Cool down well after all of this.
|
||||||
|
`),
|
||||||
|
).toMatchInlineSnapshot(`
|
||||||
|
Object {
|
||||||
|
"author": "",
|
||||||
|
"description": "",
|
||||||
|
"intervals": Array [
|
||||||
|
Object {
|
||||||
|
"cadence": undefined,
|
||||||
|
"comments": Array [
|
||||||
|
Object {
|
||||||
|
"loc": Object {
|
||||||
|
"col": 4,
|
||||||
|
"row": 3,
|
||||||
|
},
|
||||||
|
"offset": Duration {
|
||||||
|
"seconds": 10,
|
||||||
|
},
|
||||||
|
"text": "Find your rythm.",
|
||||||
|
},
|
||||||
|
Object {
|
||||||
|
"loc": Object {
|
||||||
|
"col": 4,
|
||||||
|
"row": 4,
|
||||||
|
},
|
||||||
|
"offset": Duration {
|
||||||
|
"seconds": 590,
|
||||||
|
},
|
||||||
|
"text": "Final push. YOU GOT IT!",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
"duration": Duration {
|
||||||
|
"seconds": 600,
|
||||||
|
},
|
||||||
|
"intensity": ConstantIntensity {
|
||||||
|
"_value": 0.9,
|
||||||
|
},
|
||||||
|
"type": "Interval",
|
||||||
|
},
|
||||||
|
Object {
|
||||||
|
"cadence": undefined,
|
||||||
|
"comments": Array [
|
||||||
|
Object {
|
||||||
|
"loc": Object {
|
||||||
|
"col": 4,
|
||||||
|
"row": 7,
|
||||||
|
},
|
||||||
|
"offset": Duration {
|
||||||
|
"seconds": 30,
|
||||||
|
},
|
||||||
|
"text": "Great effort!",
|
||||||
|
},
|
||||||
|
Object {
|
||||||
|
"loc": Object {
|
||||||
|
"col": 4,
|
||||||
|
"row": 8,
|
||||||
|
},
|
||||||
|
"offset": Duration {
|
||||||
|
"seconds": 180,
|
||||||
|
},
|
||||||
|
"text": "Cool down well after all of this.",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
"duration": Duration {
|
||||||
|
"seconds": 300,
|
||||||
|
},
|
||||||
|
"intensity": ConstantIntensity {
|
||||||
|
"_value": 0.5,
|
||||||
|
},
|
||||||
|
"type": "Rest",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
"name": "My Workout",
|
||||||
|
"tags": Array [],
|
||||||
|
}
|
||||||
|
`);
|
||||||
|
});
|
||||||
|
|
||||||
it("throws error when comment offset is outside of interval length", () => {
|
it("throws error when comment offset is outside of interval length", () => {
|
||||||
expect(() =>
|
expect(() =>
|
||||||
parse(`
|
parse(`
|
||||||
|
|
|
||||||
|
|
@ -57,7 +57,7 @@ const parseHeader = (tokens: Token[]): [Header, Token[]] => {
|
||||||
return [header, tokens];
|
return [header, tokens];
|
||||||
};
|
};
|
||||||
|
|
||||||
const parseIntervalComments = (tokens: Token[]): [Comment[], Token[]] => {
|
const parseIntervalComments = (tokens: Token[], intervalDuration: Duration): [Comment[], Token[]] => {
|
||||||
const comments: Comment[] = [];
|
const comments: Comment[] = [];
|
||||||
while (tokens[0]) {
|
while (tokens[0]) {
|
||||||
const [start, offset, text, ...rest] = tokens;
|
const [start, offset, text, ...rest] = tokens;
|
||||||
|
|
@ -72,7 +72,8 @@ const parseIntervalComments = (tokens: Token[]): [Comment[], Token[]] => {
|
||||||
throw new ParseError(`Expected [comment text] instead got ${tokenToString(text)}`, text?.loc || offset.loc);
|
throw new ParseError(`Expected [comment text] instead got ${tokenToString(text)}`, text?.loc || offset.loc);
|
||||||
}
|
}
|
||||||
comments.push({
|
comments.push({
|
||||||
offset: new Duration(offset.value),
|
// when offset is negative, recalculate it based on interval length
|
||||||
|
offset: new Duration(offset.value >= 0 ? offset.value : intervalDuration.seconds + offset.value),
|
||||||
text: text.value,
|
text: text.value,
|
||||||
loc: offset.loc,
|
loc: offset.loc,
|
||||||
});
|
});
|
||||||
|
|
@ -115,7 +116,7 @@ const parseIntervalParams = (type: IntervalType, tokens: Token[], loc: SourceLoc
|
||||||
intensity = new FreeIntensity();
|
intensity = new FreeIntensity();
|
||||||
}
|
}
|
||||||
|
|
||||||
const [comments, rest] = parseIntervalComments(tokens);
|
const [comments, rest] = parseIntervalComments(tokens, duration);
|
||||||
|
|
||||||
return [{ type, duration, intensity, cadence, comments }, rest];
|
return [{ type, duration, intensity, cadence, comments }, rest];
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -89,16 +89,17 @@ const tokenizeParams = (text: string, loc: SourceLocation): Token[] => {
|
||||||
};
|
};
|
||||||
|
|
||||||
const tokenizeComment = (line: string, row: number): Token[] | undefined => {
|
const tokenizeComment = (line: string, row: number): Token[] | undefined => {
|
||||||
const [, commentHead, offset, commentText] = line.match(/^(\s*@\s*)([0-9:]+)(.*?)$/) || [];
|
const [, commentHead, minus, offset, commentText] = line.match(/^(\s*@\s*)(-?)([0-9:]+)(.*?)$/) || [];
|
||||||
if (!commentHead) {
|
if (!commentHead) {
|
||||||
return undefined;
|
return undefined;
|
||||||
}
|
}
|
||||||
|
const sign = minus ? -1 : 1;
|
||||||
if (!DURATION_REGEX.test(offset)) {
|
if (!DURATION_REGEX.test(offset)) {
|
||||||
throw new ParseError("Invalid comment offset", { row, col: commentHead.length });
|
throw new ParseError("Invalid comment offset", { row, col: commentHead.length });
|
||||||
}
|
}
|
||||||
return [
|
return [
|
||||||
{ type: "comment-start", loc: { row, col: line.indexOf("@") } },
|
{ type: "comment-start", loc: { row, col: line.indexOf("@") } },
|
||||||
{ type: "duration", value: toSeconds(offset), loc: { row, col: commentHead.length } },
|
{ type: "duration", value: sign * toSeconds(offset), loc: { row, col: commentHead.length } },
|
||||||
{ type: "text", value: commentText.trim(), loc: { row, col: commentHead.length + offset.length } },
|
{ type: "text", value: commentText.trim(), loc: { row, col: commentHead.length + offset.length } },
|
||||||
];
|
];
|
||||||
};
|
};
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue