\@ifnextchar consumes spaces (#2118)

* \@ifnextchar consumes spaces

Fix #2117 by fixing our implementation of \@ifnextchar to match LaTeX's:
consuming spaces before checking the next character.  See #2117 for details.

* Update MacroContextInterface
This commit is contained in:
Erik Demaine
2019-10-12 11:33:30 -04:00
committed by ylemkimon
parent 1eda0e86a0
commit 0cdb28b256
2 changed files with 15 additions and 3 deletions

View File

@@ -36,6 +36,11 @@ export interface MacroContextInterface {
*/
popToken(): Token;
/**
* Consume all following space tokens, without expansion.
*/
consumeSpaces(): void;
/**
* Expand the next token only once (if possible), and return the resulting
* top token on the stack (without removing anything from the stack).
@@ -108,10 +113,12 @@ defineMacro("\\@secondoftwo", function(context) {
});
// LaTeX's \@ifnextchar{#1}{#2}{#3} looks ahead to the next (unexpanded)
// symbol. If it matches #1, then the macro expands to #2; otherwise, #3.
// Note, however, that it does not consume the next symbol in either case.
// symbol that isn't a space, consuming any spaces but not consuming the
// first nonspace character. If that nonspace character matches #1, then
// the macro expands to #2; otherwise, it expands to #3.
defineMacro("\\@ifnextchar", function(context) {
const args = context.consumeArgs(3); // symbol, if, else
context.consumeSpaces();
const nextToken = context.future();
if (args[0].length === 1 && args[0][0].text === nextToken.text) {
return {tokens: args[1], numArgs: 0};

View File

@@ -3008,11 +3008,16 @@ describe("A macro expander", function() {
expect`\@ifstar{yes}{no}?!`.toParseLike`no?!`;
});
it("\\@ifnextchar should not consume anything", function() {
it("\\@ifnextchar should not consume nonspaces", function() {
expect`\@ifnextchar!{yes}{no}!!`.toParseLike`yes!!`;
expect`\@ifnextchar!{yes}{no}?!`.toParseLike`no?!`;
});
it("\\@ifnextchar should consume spaces", function() {
expect`\def\x#1{\@ifnextchar x{yes}{no}}\x{}x\x{} x`
.toParseLike`yesxyesx`;
});
it("\\@ifstar should consume star but nothing else", function() {
expect`\@ifstar{yes}{no}*!`.toParseLike`yes!`;
expect`\@ifstar{yes}{no}?!`.toParseLike`no?!`;