feat: Support \Braket, \set, and \Set (#3214)

* feat: Support \Braket, \set, and \Set

* Update screenshots.

* Rewrite to redefine | via macros

* Update screenshot after merge

* Rename \bra@ket@one -> \bra@set

* Fix spacing in \set and \Set to match braket.sty

* Add || and \| support

* Update tests

* Update screenshots

Co-authored-by: Ron Kok <ronkok@comcast.net>
This commit is contained in:
Erik Demaine
2022-05-20 13:26:04 -04:00
committed by GitHub
parent 8319467151
commit 9e3ae4d5a8
10 changed files with 89 additions and 4 deletions

View File

@@ -356,7 +356,9 @@ export default class MacroExpander implements MacroContextInterface {
}
/**
* Fully expand the given token stream and return the resulting list of tokens
* Fully expand the given token stream and return the resulting list of
* tokens. Note that the input tokens are in reverse order, but the
* output tokens are in forward order.
*/
expandTokens(tokens: Token[]): Token[] {
const output = [];

View File

@@ -61,6 +61,13 @@ export interface MacroContextInterface {
*/
expandMacroAsText(name: string): string | void;
/**
* Fully expand the given token stream and return the resulting list of
* tokens. Note that the input tokens are in reverse order, but the
* output tokens are in forward order.
*/
expandTokens(tokens: Token[]): Token[];
/**
* Consume an argument from the token stream, and return the resulting array
* of tokens and start/end token.

View File

@@ -912,6 +912,58 @@ defineMacro("\\ket", "\\mathinner{|{#1}\\rangle}");
defineMacro("\\braket", "\\mathinner{\\langle{#1}\\rangle}");
defineMacro("\\Bra", "\\left\\langle#1\\right|");
defineMacro("\\Ket", "\\left|#1\\right\\rangle");
const braketHelper = (one) => (context) => {
const left = context.consumeArg().tokens;
const middle = context.consumeArg().tokens;
const middleDouble = context.consumeArg().tokens;
const right = context.consumeArg().tokens;
const oldMiddle = context.macros.get("|");
const oldMiddleDouble = context.macros.get("\\|");
context.macros.beginGroup();
const midMacro = (double) => (context) => {
if (one) {
// Only modify the first instance of | or \|
context.macros.set("|", oldMiddle);
if (middleDouble.length) {
context.macros.set("\\|", oldMiddleDouble);
}
}
let doubled = double;
if (!double && middleDouble.length) {
// Mimic \@ifnextchar
const nextToken = context.future();
if (nextToken.text === "|") {
context.popToken();
doubled = true;
}
}
return {
tokens: doubled ? middleDouble : middle,
numArgs: 0,
};
};
context.macros.set("|", midMacro(false));
if (middleDouble.length) {
context.macros.set("\\|", midMacro(true));
}
const arg = context.consumeArg().tokens;
const expanded = context.expandTokens([
...right, ...arg, ...left, // reversed
]);
context.macros.endGroup();
return {
tokens: expanded.reverse(),
numArgs: 0,
};
};
defineMacro("\\bra@ket", braketHelper(false));
defineMacro("\\bra@set", braketHelper(true));
defineMacro("\\Braket", "\\bra@ket{\\left\\langle}" +
"{\\,\\middle\\vert\\,}{\\,\\middle\\vert\\,}{\\right\\rangle}");
defineMacro("\\Set", "\\bra@set{\\left\\{\\:}" +
"{\\;\\middle\\vert\\;}{\\;\\middle\\Vert\\;}{\\:\\right\\}}");
defineMacro("\\set", "\\bra@set{\\{\\,}{\\mid}{}{\\,\\}}");
// has no support for special || or \|
//////////////////////////////////////////////////////////////////////
// actuarialangle.dtx