4

I have written a command using expl3 that is supposed to behave differently if the optional argument is specified as * or **. The command is intended for a math environment, and is supposed to render the second parameter with an upright underset depending on the first parameter. I see three problems in the behavior of this command:

  1. The * and ** are not recognized
  2. An extraneous hyphen (-) is displayed
  3. An extraneous quote (") is displayed

\documentclass{article}
\usepackage{mathtools}
\usepackage{xparse}

\ExplSyntaxOn

% Render underscored with some variation of strict
\NewDocumentCommand{\strict}{O{strict} m}
  {
    \str_if_eq:eeTF {\str_item:nn {#1} {-1}} {-}
      {
        \show_strict:nn {{#1}strict} {#2}
      }
      {
        \show_strict:nn {#1} {#2}
      }
  }

\cs_new_protected:Npn \show_strict:nn #1 #2
  {
   \msg_term:n {show_strict \ P1 \ = \ #1}
   \msg_term:n {show_strict \ P2 \ = \ #2}
    \str_set:Nn \l_tmpa_str {#1}
    \str_set:Nn \l_tmpb_str {#2}
    \msg_term:n {\l_tmpa_str =  \l_tmpa_str}
    \str_case:nnF {\l_tmpa_str}
      {
        {
          {*}
          {  \underset {\mathrm{(semi-strict,strict)}} {#2} }
        }
        {
          {**}
          { \underset {\mathrm{semi-strict (strict)}} {#2} }
        }
      }
      {
        \underset {\mathrm{\l_tmpa_str}} {\l_tmpb_str}
      }
  }

\ExplSyntaxOff

\begin{document}

\begin{enumerate}
\item Test $\strict{{default}}$ \\*
      expect underset with upright "strict" 
\item Test $\strict[semi-]{{hyphen}}$
      expect underset with upright "semi-strict"
\item Test $\strict[*]{{star}}$
      expect underset with upright "(semi-strict,strict)"
\item Test $\strict[**]{{starstar}}$
      expect underset with upright "semi-strict (strict)"
\end{enumerate}
\foo

\end{document}
4
  • You don't want to output \str_... variables here, that cause the - -- use \tl_... variables for the output and the \str_case:nnF is wrongly setup, in my point of view
    – user31729
    Feb 3, 2019 at 22:08
  • Why not using a \NewDocumentCommand{ssO{strict}m} - approach, leaving the 'tricky' * handling to the features of xparse
    – user31729
    Feb 3, 2019 at 22:27
  • Regarding your latest edit: 1) You have an extra } in the definition of \show_strict:nn. 2) It's not a good idea to edit your question asking something else, as may invalidate the answers. The best approach is to ask a new question. Feb 5, 2019 at 21:40
  • @I want * and ** as alternatives to the text string, i.e., \strict [foo]{bar}, \strict []{bar} or \strict [*]{bar}, as they all specify what to underset foo with.
    – shmuel
    Feb 5, 2019 at 21:54

2 Answers 2

4

You have the syntax for \str_case:nnF wrong; the first argument is the string to look for matches; the second argument should be of the form

{<string-a>}{<code>}
{<string-b>}{<code>}
...

and you have additional braces that are wrong.

\documentclass{article}
\usepackage{mathtools}
\usepackage{xparse}

\ExplSyntaxOn

% Render underscored with some variation of strict
\NewDocumentCommand{\strict}{O{strict} m}
  {
    \str_if_eq:eeTF {\str_item:nn {#1} {-1}} {-}
      {
        \show_strict:nn {{#1}strict} {#2}
      }
      {
        \show_strict:nn {#1} {#2}
      }
  }

\cs_new_protected:Npn \show_strict:nn #1 #2
  {
   \iow_term:n {show_strict ~ P1 ~ = ~ #1}
   \iow_term:n {show_strict ~ P2 ~ = ~ #2}
    \str_case:nnF {#1}
      {
       {*}  { \underset {\textup{(semi-strict,~strict)}} {#2} }
       {**} { \underset {\textup{semi-strict~(strict)}} {#2} }
      }
      {
        \underset {\textup{#1}} {#2}
      }
  }

\ExplSyntaxOff

\begin{document}

\begin{enumerate}
\item Test $\strict{{default}}$ \\*
      expect underset with upright "strict" 
\item Test $\strict[semi-]{{hyphen}}$
      expect underset with upright "semi-strict"
\item Test $\strict[*]{{star}}$
      expect underset with upright "(semi-strict,strict)"
\item Test $\strict[**]{{starstar}}$
      expect underset with upright "semi-strict (strict)"
\end{enumerate}

\end{document}

enter image description here

Rather than \mathrm you should use \textup (the hyphens would be minus signs otherwise and spaces would be ignored).

Here's the console output:

*************************************************
* show_strict P1 = strict
*************************************************
*************************************************
* show_strict P2 = {default}
*************************************************
*************************************************
* show_strict P1 = {semi-}strict
*************************************************
*************************************************
* show_strict P2 = {hyphen}
*************************************************
*************************************************
* show_strict P1 = *
*************************************************
*************************************************
* show_strict P2 = {star}
*************************************************
*************************************************
* show_strict P1 = **
*************************************************
*************************************************
* show_strict P2 = {starstar}
*************************************************
5
  • How did you avoid the "! You can't use `macro parameter character #' in math mode. <recently read> ## l.42 \underset {\textup{#1}} {#2}" message?
    – shmuel
    Feb 5, 2019 at 21:09
  • @shmuel Do you get it with my code? I don't.
    – egreg
    Feb 5, 2019 at 21:13
  • @shmuel Check your braces. You have a } too much.
    – egreg
    Feb 5, 2019 at 21:42
  • @egreg, sorry again, you can update this response...just in order to keep the forum updated. Oct 28, 2019 at 22:37
  • @PabloGonzálezL Thanks for the search!
    – egreg
    Oct 28, 2019 at 23:01
3

When you do

\str_set:Nn \l_tmpa_str {#1}
\str_set:Nn \l_tmpb_str {#2}

you are setting the variables to TeX strings, removing the meaning from the tokens. In particular, { and } cease to be 'special', and come out as the 'random' quote mark/hyphen you are seeing. In your example, there's no reason to store these at all, but if you do, use a tl.

The second issue is

\str_case:nnF {\l_tmpa_str}

which compares exactly the text \l_tmpa_str with each case. They never match, so you get the F branch. You want to look at the text itself, easiest with

\str_case:nnF {#2}

or if you really want to store it, perhaps

\cs_generate_variant:Nn \str_case:nnF { V }

...

\str_case:VnF \l_tmpb_str

to access the value of the variable. Again, I suspect you want a token list test here, not a string one:

\tl_set:Nn \l_tmpb_tl {#2}
\tl_case:NnF \l_tmpb_tl

although as previously-mentioned, I don't see the need to store the input.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .