2

As so many questions (respectively answers) on this sight point out, it is possible to exhaust (respectively, extend) the list of slots allocated to math alphabets. The following MWE accomplishes my goal, but is cumbersome. Because all math alphabet slots in mathversion "normal" are used, I decided to switch the mathversion to "normal2" but have only figured out how to do this on a per entry basis, as seen among the ABC entries in the table's last line.

\documentclass{article}
\newcommand\hmmax{0}
\newcommand\bmmax{0}
\usepackage{amsmath,amssymb,lmodern,bm,pxfonts}
\usepackage[mathscr]{euscript}
\let \eucal \mathscr
\usepackage{mathrsfs}

\DeclareMathAlphabet{\mathpzc}{OT1}{pzc}{m}{it}
\DeclareMathVersion{normal2}

\begin{document}
\begin{tabular}{r|*{3}{c@{~~}}}
rm   & \(\mathrm A\) & \(\mathrm B\) & \(\mathrm C\)\\
bf   & \(\mathbf A\) & \(\mathbf B\) & \(\mathbf C\)\\
tt   & \(\mathtt A\) & \(\mathtt B\) & \(\mathtt C\)\\
it   & \(\mathit A\) & \(\mathit B\) & \(\mathit C\)\\
sf   & \(\mathsf A\) & \(\mathsf B\) & \(\mathsf C\)\\
frak &\(\mathfrak A\) & \(\mathfrak B\) & \(\mathfrak C\)\\
frak+bm & \(\bm{\mathfrak A}\) & \(\bm{\mathfrak B}\) & \(\bm{\mathfrak C}\)\\
cal & \(\mathcal A\) & \(\mathcal B\) & \(\mathcal C\)\\
euc & \(\eucal A\) & \(\eucal B\) & \(\eucal C\)\\
cal+bm & \(\bm{\mathcal A}\) & \(\bm{\mathcal B}\) & \(\bm{\mathcal C}\)\\
euc+bm  & \(\bm{\eucal A}\) & \(\bm{\eucal B}\) & \(\bm{\eucal C}\)\\
pzc &\mathversion{normal2} \(\mathpzc A\)  & \mathversion{normal2}\(\mathpzc B\) & \mathversion{normal2}\(\mathpzc C\)\\
\end{tabular}
\end{document}

When any \mathversion{normal2} is removed from that final line, the compiled code throws up the "too many math alphabets" warning. On the other hand, it is quite cumbersome to include it in every entry (the actual table being the full 26 wide alphabet). This brings me to the question at hand.

Question: Is there a way to change the math version within tabular and/or array environments to span all entries in a given line, or (even better) to span multiple lines?

Aside 1: Of course, the cumbersome code can be relegated to a macro, which is what I am actually presently doing, but it seems to me that having the compiler switch back and forth between math versions is not a good idea, so an alternative would nice to have, if possible.

Aside 2: As the above is an MWE, it really is the bare minimum to get to the core question. The actual table I want to build is some 70 lines long and is the full alphabet wide. Its intent is to be a one-stop-shop for fonts; my colleagues can just go to it, determine quickly which fonts they want to use, and be redirected into the to-be-included reference material where they can just copy/paste the pertinent information into their LaTeX code, with the goal of starting the actual work as quickly as possible. In particular, in other portions of the document, I have need of the lmodern and pxfonts packages, even though their actual usages in this MWE are not as apparent (aside from eating up the math alphabets). I mention this because comments/answers along the lines of "why are you wasting math alphabets on \mathrm rather than just using text mode" are not helpful; I only wanted to use up the math alphabets as efficiently as possible within the MWE.

  • you don't need math mode at all here it seems, you could simply select the font and typeset it as text. That way the 16 limit would not matter. (Also you could use xetex or luatex and have 256 math families rather than 16) – David Carlisle May 3 '19 at 21:49
  • @DavidCarlisle Regarding your first two sentences, would you please be so kind as to read the second aside? In particular, the last sentence. – John McVey May 4 '19 at 0:08
  • There is no scope corresponding to a tabular row, so unless you constrain things so the only possible answer is a simple "No." you need to allow people to cheat somewhere, either fitting everything in one math version, or not using a standard tabular implementation or something. It is rather rare to need so many math alphabets, for example if you \let\mathtt\texttt and \let\mathsf\textsf and define some of the other math alphabets in the same way you have definitions that in the vast majority (not all) uses produce identical layout and fonts, without eating into the 16 math fam limit – David Carlisle May 4 '19 at 7:11
4

If you are going to generate lots of similar tables like this it is probably better to make LaTeX do most of the work and for you to provide just the alphabet, say A, B, C, D, and a list of "fonts" to use, like:

\MathCharacterTable{
  mathrm, mathbf, mathtt, mathit, mathsf, mathfrak, b!mathfrak,
  mathcal, eucal, b!mathcal, b!eucal, 2!mathpzc
}

The important point here is that each of these is the name of a command: \mathbf{A}, \mathsf{A} etc all work. The only parts that need explanation are probably that b! means apply \bm and 2! means that \mathversion{normal2} is needed. With this in place the code below produces the table:

enter image description here

The lefthand side is generated by the \MathCharacterTable command whereas the righthand side, which is given for comparison, comes from the OP.

The code is written using latex3 and just comes down to processing two comma separated lists: the alphabet list and the list of "fonts". There is a little bit of trickery to turn the "exceptional" font descriptions, like b!eucal, into the correct command but otherwise this is mostly straightforward. The way that the code is structured it should be easy to add new "fonts" and to change the alpahbet.

Here is the code:

\documentclass{article}
\newcommand\hmmax{0}
\newcommand\bmmax{0}
\usepackage{amsmath,amssymb,lmodern,bm,pxfonts}
\usepackage[mathscr]{euscript}
\let \eucal \mathscr
\usepackage{mathrsfs}

\DeclareMathAlphabet{\mathpzc}{OT1}{pzc}{m}{it}
\DeclareMathVersion{normal2}

\usepackage{xparse}
\ExplSyntaxOn
% define the alphabet for the table as a comma separated list
\clist_const:Nn \c_alphabet_clist {A,B,C,D}
\str_new:N \l_mathopt_str
\str_new:N \l_mathstyle_str
\cs_new_protected_nopar:Nn \process_row:n {
   \str_if_in:nnTF {#1} {!}
   {% we have a ! : b=\bm or 2=\mathversion{2}
     \seq_set_split:Nnn \l_tmpa_seq {!} {#1}
     \str_set:Nx \l_mathopt_str {\seq_item:Nn \l_tmpa_seq {1}}
     \str_gset:Nx \l_mathstyle_str {\seq_item:Nn \l_tmpa_seq {2}}
     \cs_set_mathstyle:VV \l_mathopt_str \l_mathstyle_str
   }
   {% no ! => normal processing
      #1 % the row label
      \cs_gset_nopar:Npn \math_style:n ##1 { $\use:c{#1}{##1}$ }
   }
    % now apply the math style to the alphabet for the row
    \clist_map_inline:Nn \c_alphabet_clist { &\math_style:n ##1 }
    \\  % end the tabular row
}
% define the \math_style:n command for \bm and math version w
\cs_new_protected_nopar:Nn \cs_set_mathstyle:nn {
  \str_case:nn { #1 } {
     {b} { #2+bm % the row label
           \cs_gset_nopar:Npn \math_style:n ##1 { $\bm{\use:c{#2}{##1}}$ }
         }
     {2} { #2 % the row label
           \cs_gset_nopar:Npn \math_style:n ##1 {
               \mathversion{normal2}$\use:c{#2}##1$ 
           }
         }
     }
     % add new modifers <?!font> here
}
% force the strings to expand when we use \cs_set_mathstyle:nn
\cs_generate_variant:Nn \cs_set_mathstyle:nn {VV}

\NewDocumentCommand\MathCharacterTable{m}{
   \clist_set:Nn \l_mathstyles_clist {#1}
   \begin{tabular}{r|*{\clist_count:N \c_alphabet_clist}{c@{~~}}}
     \clist_map_function:nN {#1} \process_row:n
   \end{tabular}
}
\ExplSyntaxOff

\begin{document}

\begin{tabular}{l@{\qquad}l}
  Generated by MathCharacterTable & Explicitly entered\\[1mm]\hline
\MathCharacterTable{
  mathrm, mathbf, mathtt, mathit, mathsf, mathfrak, b!mathfrak,
  mathcal, eucal, b!mathcal, b!eucal, 2!mathpzc
}
&
\begin{tabular}{r|*{3}{c@{~~}}}
rm   & \(\mathrm A\) & \(\mathrm B\) & \(\mathrm C\)\\
bf   & \(\mathbf A\) & \(\mathbf B\) & \(\mathbf C\)\\
tt   & \(\mathtt A\) & \(\mathtt B\) & \(\mathtt C\)\\
it   & \(\mathit A\) & \(\mathit B\) & \(\mathit C\)\\
sf   & \(\mathsf A\) & \(\mathsf B\) & \(\mathsf C\)\\
frak &\(\mathfrak A\) & \(\mathfrak B\) & \(\mathfrak C\)\\
frak+bm & \(\bm{\mathfrak A}\) & \(\bm{\mathfrak B}\) & \(\bm{\mathfrak C}\)\\
cal & \(\mathcal A\) & \(\mathcal B\) & \(\mathcal C\)\\
euc & \(\eucal A\) & \(\eucal B\) & \(\eucal C\)\\
cal+bm & \(\bm{\mathcal A}\) & \(\bm{\mathcal B}\) & \(\bm{\mathcal C}\)\\
euc+bm  & \(\bm{\eucal A}\) & \(\bm{\eucal B}\) & \(\bm{\eucal C}\)\\
pzc &\mathversion{normal2} \(\mathpzc A\)  & \mathversion{normal2}\(\mathpzc B\) & \mathversion{normal2}\(\mathpzc C\)\\
\end{tabular}

\end{tabular}

\end{document}
|improve this answer|||||
0

Upon conducting further research, the reason that \mathversion{<name>} needed reissued in each entry of the original post is that the call only affects the scope of the environment within which it sits: the scope only lasted until the end of the local environment, the entry. Use of the word "local" led me to remember there are ways to make a command global.

With that in mind, and a little to my surprise, the answer to the original question is yes, and can be accomplished by prepending \global before the \mathversion conversion. (In the below code, this call was given within the first entry of the last line, but could also be given at the beginning of the second entry, or even anywhere in the previous line.)

\documentclass{article}

\newcommand\hmmax{0}
\newcommand\bmmax{0}
\usepackage{amsmath,amssymb,lmodern,bm,pxfonts}

\usepackage[mathscr]{euscript}
\let \eucal \mathscr
\usepackage{mathrsfs}

\DeclareMathAlphabet{\mathpzc}{OT1}{pzc}{m}{it}
\DeclareMathVersion{normal2}

\begin{document}
\begin{tabular}{r|*{3}{c@{~~}}}
rm   & \(\mathrm A\) & \(\mathrm B\) & \(\mathrm C\)\\
bf   & \(\mathbf A\) & \(\mathbf B\) & \(\mathbf C\)\\
tt   & \(\mathtt A\) & \(\mathtt B\) & \(\mathtt C\)\\
it   & \(\mathit A\) & \(\mathit B\) & \(\mathit C\)\\
sf   & \(\mathsf A\) & \(\mathsf B\) & \(\mathsf C\)\\
frak &\(\mathfrak A\) & \(\mathfrak B\) & \(\mathfrak C\)\\
frak+bm & \(\bm{\mathfrak A}\) & \(\bm{\mathfrak B}\) & \(\bm{\mathfrak C}\)\\
cal & \(\mathcal A\) & \(\mathcal B\) & \(\mathcal C\)\\
euc & \(\eucal A\) & \(\eucal B\) & \(\eucal C\)\\
cal+bm & \(\bm{\mathcal A}\) & \(\bm{\mathcal B}\) & \(\bm{\mathcal C}\)\\
euc+bm  & \(\bm{\eucal A}\) & \(\bm{\eucal B}\) & \(\bm{\eucal C}\)\\
\global\mathversion{normal2}
pzc & \(\mathpzc A\)  & \(\mathpzc B\) & \(\mathpzc C\)\\
\end{tabular}
\end{document}

Furthermore, the answer is yes even in array environments: just encase the \global\mathversion{normal2} call within an \mbox.

\documentclass{article}

\newcommand\hmmax{0}
\newcommand\bmmax{0}
\usepackage{amsmath,amssymb,lmodern,bm,pxfonts}

\usepackage[mathscr]{euscript}
\let \eucal \mathscr
\usepackage{mathrsfs}

\DeclareMathAlphabet{\mathpzc}{OT1}{pzc}{m}{it}
\DeclareMathVersion{normal2}

\begin{document}
\[
\begin{array}{r|*{3}{c@{~~}}}
\text{rm }  & \mathrm A & \mathrm B & \mathrm C\\
\text{bf}   & \mathbf A & \mathbf B & \mathbf C\\
\text{tt}   & \mathtt A & \mathtt B & \mathtt C\\
\text{it}   & \mathit A & \mathit B & \mathit C\\
\text{sf}   & \mathsf A & \mathsf B & \mathsf C\\
\text{frak} &\mathfrak A & \mathfrak B & \mathfrak C\\
\text{frak+bm} & \bm{\mathfrak A} & \bm{\mathfrak B} & \bm{\mathfrak C}\\
\text{cal} & \mathcal A & \mathcal B & \mathcal C\\
\text{euc} & \eucal A & \eucal B & \eucal C\\
\text{cal+bm} & \bm{\mathcal A} & \bm{\mathcal B} & \bm{\mathcal C}\\
\text{euc+bm}  & \bm{\eucal A} & \bm{\eucal B} & \bm{\eucal C}\\
\mbox{\global\mathversion{normal2}}
\text{pzc} & \mathpzc A  & \mathpzc B & \mathpzc C\\
\end{array}
\]
\end{document}

As a complete aside, I must plug David Carlisle's longtable package. What I'm actually creating is immensely longer than is presented in these examples, and that package beautifully provides page breaks within a table (provided, unlike me, you remember to recompile the file an appropriate number of times).

|improve this answer|||||
  • I'd still try and automate this as much as possible as it will make your document easier to edit and maintain and minimise the chance of errors. – Andrew May 7 '19 at 15:19
  • Agreed, and to an extent, what I did. E.g., the alphabet lists (in English and Greek) are given in macros, and the array package provides additional, one-time-per-table formatting needs. I'm not making enough tables for the additional preamble code to be beneficial. – John McVey May 7 '19 at 15:32

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.