2

[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?

9
  • I'm trying to add a complete test file, but my comment is limited to 600 characters.
    – Jay Turner
    Oct 15, 2021 at 21:15
  • Does anyone know how to get a value from a variable and lowercase I assume you mean \def\zzz{ABC} \lowercase\expandafter{\zzz} which returns abc but I have no idea how that fits the rest of your question Oct 15, 2021 at 21:20
  • {Removed test file that had no spacing, HA} {But I don't have the reputation to edit my Post, apparently}
    – Jay Turner
    Oct 15, 2021 at 21:22
  • Found the tiny little Edit hyperlink while looking for a big red button with Edit in it. {Sorry}
    – Jay Turner
    Oct 15, 2021 at 21:32
  • 2
    please don;t change the title to SOLVED (otherwise we'd have tens of thousands of titles all starting that way) Oct 15, 2021 at 22:05

1 Answer 1

2

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
}
3
  • This works! I was trying \expand* lots of places, but not the Right places. I still can't figure out how \lowercase{\edef\tmpb{#2}} didn't work, but \expanded{\lowercase{\def\noexpand\tmpb{#2}}} did. If #2 became \DEFVariable, then \lowercase should have made \defvariable and failed to find the variable.
    – Jay Turner
    Oct 15, 2021 at 22:01
  • @JayTurner \lowercase does no expansion: it simply passes the token list to the inner level, from which it is “regurgitated” after changing character tokens to their lowercase variant; hence \lowercase{\edef\tmpa{\var}} is the same as \edef\tmpa{\var}. With \expanded or the other trick, \var is expanded before \lowercase enters into action. I added some comments.
    – egreg
    Oct 15, 2021 at 22:23
  • I was confused about "\lowercase is non-expandable" and was thinking it meant that \lowercase had to be the outermost \command so that it would execute at all. That if it was nested it wouldn't "expand". But this makes more sense. Nesting works, #2 expands to \DEFVariable, then \lowercase executes and lowercase text, but not \variables, then \expanded says to expand \variables, expect for the \noexpand ones, then it executes the result. Thanks!
    – Jay Turner
    Oct 18, 2021 at 15:21

You must log in to answer this question.

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