Pandoc – Using \IfSubStr with Lowercased Input Variables in LaTeX Commands

pandocrenewcommandtextcasexstring

[Similar questions]
I looked at \lowercase with \IfSubStr and \StrDel but the suggestions didn't work. I apparently may have expl3 since I can use \newcommand.

[Issue]
I want to pass a variable to a command, have it expand the variable, lowercase the value, do \IfSubStr, and create a new command if the lowercased value matches. The problem is that I can find no way to get the variable value lowercased for the \IfSubStr.

[Tools]

FMPP version 0.9.16, build 2018-09-03T21:47:30Z
Currently using FreeMarker version 2.3.28

pandoc 2.7.3
Compiled with pandoc-types 1.17.5.4, texmath 0.11.2.2, skylighting 0.8.1
Copyright (C) 2006-2019 John MacFarlane

[Build]

Execute the following in pdfTex

[Source]

\documentclass{report}
\usepackage{xstring}
\begin{document}

\def\abcVariable{abc}
\def\DEFVariable{DEF}
\def\refVariable{nothing}
\def\dbgstr{debug}

\newcommand{\setCmd}[3]{%
    \lowercase{\def\tmpa{#1}}%
    \lowercase{\edef\tmpb{#2}}%
    \IfSubStr{\tmpa}{\tmpb}
    {\renewcommand{#3}{#2}}{%
        \edef\dbgstr{inputs: #1, #2; lowercased: \tmpa, \tmpb}%
    }
}

\newcommand{\setVariable}[1]{%
    \setCmd{#1}{\abcVariable}{\refVariable}%
    \setCmd{#1}{\DEFVariable}{\refVariable}%
}

\setVariable{thishasdefinthemiddle}

\refVariable

\dbgstr
\end{document}

[Response]

nothing
inputs: thishasadefinthemiddle, DEF; lowercased: thishasadefinthemiddle, DEF

[Expected]

DEF
inputs: thishasadefinthemiddle, DEF; lowercased: thishasadefinthemiddle, def

[Debugging 1]

The use of \setCmd{#1}{\abcVariable}{\refVariable}% works, but not for the right reasons.
Then I consider \setCmd{#1}{\DEFVariable}{\refVariable}%.
I think \lowercase{\def\tmpa{#1}}% expanded to \lowercase{\def\tmpa{abcdef}}% and then assigned \tmpa with abcdef. Great.
I think \lowercase{\edef\tmpb{#2}}% expanded to \lowercase{\edef\tmpb{\DEFVariable}}% and then

  1. lowercased to \edef\tmpb{\DEFVariable}}% because \lowercase doesn't lowercase csnames, or
  2. lowercased to \edef\tmpb{\defvariable}}% and then should have complained that \defvariable does not exist, or
  3. lowercased and expanded \defvariable anyway to DEF, or
  4. just stopped expanding for some reason.

Then \IfSubStr{\tmpa}{\tmpb} expanded to \IfSubStr{abcdef}{\DEFVariable} which expanded to \IfSubStr{abcdef}{DEF}, which ran the {false} path.
I need \DEFVariable to fully expand to DEF and then get lowercased for the \IfSubStr.

[Debugging 2]

Then I tried making a command to do the lowercasing:

\newcommand{\mylwr}[1]{%
    \edef\x{%
        \noexpand\edef\noexpand\tmpb{\text_lowercase:n #1}}%
    \x}

and replaced \lowercase{\edef\tmpb{#2}}% with \mylwr{#2}, but got a Missing $ inserted / 1.88 dbgstr: \dbgstr, so I probably don't have the package with \text_lowercase:n. But using \lowercase gives an output of:

setVariable:
refVariable: nothing
dbgstr: inputs: abcdef, DEF; lowercased: abcdef, def

Looks great, until you realize the \IfSubStr failed and it was only when the output was written that the full expansion produced the lowercase def.

[Debugging 3]

Then I tried creating a substitute for the \IfSubStr command:

\newcommand{\IfSubStrIC}[2]{%
    \lowercase{\edef\x{\noexpand\IfSubStr{#1}{\expanded{#2}}}}%
    \x}

The output was back to:

setVariable:
refVariable: abc
dbgstr: inputs: abcdef, DEF; lowercased: abcdef, DEF

[Debugging 4]

I tried various \expanded and \expandafter and \expandafter\expandafter to try to get the variable expanded to lowercase it, but nothing worked.

Does anyone know how to get a value from a variable and lowercase it for \IfSubStr, or some way to do something equivalent?

Best Answer

You need that the macros are expanded before \lowercase processes the token list.

Let's say you have \def\foo{baz}. If you do

\lowercase{\edef\tmpa{\foo}}

you get exactly the same as \edef\tmpa{\foo}, because \lowercase only changes character tokens. You might do

\lowercase\expandafter{\expandafter\def\expandafter\tmpa\expandafter{\foo}}

so that \foo is expanded prior to \lowercase starting its job. But this wouldn't work if instead of just \foo you have something more complex that expands to character tokens, say two macros, for instance.

To overcome the issue you can use \expanded, if you're sure that a fairly recent version of pdftex (or other engine) is used.

\newcommand{\setCmd}[3]{%
  \expanded{\lowercase{\def\noexpand\tmpa{#1}}}%
  \expanded{\lowercase{\def\noexpand\tmpb{#2}}}%
  \IfSubStr{\tmpa}{\tmpb}
    {\renewcommand{#3}{#2}}% true
    {\edef\dbgstr{inputs: #1, #2; lowercased: \tmpa, \tmpb}}% false
}

Otherwise, the usual trick:

\newcommand{\setCmd}[3]{%
  \begingroup\edef\x{\endgroup
    \lowercase{\def\noexpand\tmpa{#1}}%
  }\x
  \begingroup\edef\x{\endgroup
    \lowercase{\def\noexpand\tmpb{#2}}%
  }\x
  \IfSubStr{\tmpa}{\tmpb}
    {\renewcommand{#3}{#2}}% true
    {\edef\dbgstr{inputs: #1, #2; lowercased: \tmpa, \tmpb}}% false
}
Related Question