Katex: Support for \catcode

Created on 4 Jan 2020  路  8Comments  路  Source: KaTeX/KaTeX

I'm aware that this might be going beyond the scope of TeX's capabilities that KaTeX intends to copy. Just asking in case it's not.

In a similar use case to #2174, I'm trying to port the advice in this SE post over to KaTeX but getting the error

KaTeX parse error: Undefined control sequence: \catcode

Here's a minimal example.

enhancement

Most helpful comment

We've discussed \catcode before. It's not out of the question, but definitely not implemented yet. There is some internal support for catcodes (which switch %'s behavior when parsing URL arguments); see src/Lexer.js.

More useful to you might be that you can already "macro" individual Unicode characters in KaTeX. I thought that this required specifying a macros argument to the parser, but apparently it can already also be done with \def. Effectively, all characters are already in active mode in KaTeX, so you don't need \catcode in this case.

We don't currently support \string, but we do support \char. Unfortunately, \left and \right don't seem to accept \char arguments currently (maybe need \expandafter?):

\def({\left\char`(}
\def({\left\char`)}
() % causes error

Luckily, you can use the \lparen/\rparen interfaces to parentheses, as follows:

\def({\left\lparen}
\def){\right\rparen}
(\frac{(3-\frac{1}{x})^2}{(\frac4x-1)x})

demo
image

All 8 comments

We've discussed \catcode before. It's not out of the question, but definitely not implemented yet. There is some internal support for catcodes (which switch %'s behavior when parsing URL arguments); see src/Lexer.js.

More useful to you might be that you can already "macro" individual Unicode characters in KaTeX. I thought that this required specifying a macros argument to the parser, but apparently it can already also be done with \def. Effectively, all characters are already in active mode in KaTeX, so you don't need \catcode in this case.

We don't currently support \string, but we do support \char. Unfortunately, \left and \right don't seem to accept \char arguments currently (maybe need \expandafter?):

\def({\left\char`(}
\def({\left\char`)}
() % causes error

Luckily, you can use the \lparen/\rparen interfaces to parentheses, as follows:

\def({\left\lparen}
\def){\right\rparen}
(\frac{(3-\frac{1}{x})^2}{(\frac4x-1)x})

demo
image

@edemaine Damn, KaTeX's capabilities keep impressing me! This is great advice, thanks a lot!

Follow up question: Is there a way to add

\def({\left\lparen}
\def){\right\rparen}

to the global macros object?

I noticed that if replace \def with \gdef, these definitions clash with \tag for some reason.

Probably because \tag{1} produces (1) which contains ( and ).

You're right that \tag generates parentheses; the real issue is that the tag is formatting in text mode, and your definitions only work in math mode.

You can use \TextOrMath to define a macro that works differently in the two modes.

\gdef\Left{\mathopen{}\mathclose\bgroup\left}
\gdef\Right#1{\right#1\egroup}
\gdef({\TextOrMath{\char`(}{\Left\lparen}}
\gdef){\TextOrMath{\char`)}{\Right\rparen}}
(\frac{(3-\frac{1}{x})^2}{(\frac4x-1)x}) \tag{1}

image

demo

I had to use \char`( to make an unexpanding left-paren here because, to my surprise, \lparen doesn't work in text mode. Actually, LaTeX doesn't support \lparen at all; not sure where KaTeX got it from (maybe a macro package?).

If you prefer, you can put these definitions in a macro object instead:

macros: {
  "\\Left":"\\mathopen{}\\mathclose\\bgroup\\left",
  "\\Right":"\\right#1\\egroup",
  "(": "\\TextOrMath{\\char`(}{\\Left\\lparen}",
  ")": "\\TextOrMath{\\char`)}{\\Right\\rparen}"
}

demo

Very cool! 馃憤

One last question. Is there a way to still throw in the occasional \bigl( for manual control of delimiter sizing? Of course, \bigl\lparen would work. I'm just curious (partly on general grounds) if it's possible to prevent macro expansion based on conditions, i.e. in this case a certain preceding macro.

One option would be to redefine ( and ) back to their original behavior, e.g., via \def within a group. I guess this would do what you want (except you'll have to use \Bigl in place of \bigl and \Bigr in place of \bigr):

\gdef\resetparens{\def({\lparen}\def){\rparen}}
\gdef\Bigl{\bgroup\resetparens\bigl}
\gdef\Bigr#1{\bigr#1\egroup}

Demo using \gdef

I couldn't get this to work as a single macros argument. I'm surprised there's an asymmetry between macros and \def; perhaps I'm doing something wrong?

Was this page helpful?
0 / 5 - 0 ratings

Related issues

HughGrovesArup picture HughGrovesArup  路  4Comments

ylemkimon picture ylemkimon  路  3Comments

yawnoc picture yawnoc  路  3Comments

sophiebits picture sophiebits  路  3Comments

pvnr0082t picture pvnr0082t  路  4Comments