3

For some sequence of characters, I want to change the case of all characters to match that of the first. So for example, aBCD → abcd and Abcd → ABCD.

My naïve attempt to do this in LaTeX3 did not work:

\documentclass{article}
\usepackage{expl3}
\ExplSyntaxOn

\regex_const:Nn \capitals {[A-Z]}

\cs_new:Npn \change_case:n #1 {
  \tl_head:n {#1}
  \regex_match:NnTF \capitals {\tl_head:n {#1}}
    {\tl_use:N \tl_upper_case:n {\tl_tail:n {#1}}}
    {\tl_use:N \tl_lower_case:n {\tl_tail:n {#1}}}
}

\begin{document}

\change_case:n {aBcD}~ \change_case:n {AbcD}

\end{document}

This gave the output of aBCD ABCD instead of the expected abcd ABCD.

It seems like there must be something obvious I'm doing wrong here.

  • I'm not sure what you expect \tl_use:N to do but it's not correct (albeit harmless) to use it before a function. The only (?) use case for \tl_use:N is before a variable to indicate unambiguously that you intend to ‘use’ the contents of the variable at that point in time. E.g., \tl_use:N \c_string_tl will print a space. \tl_use:N also serves as a basis for \tl_use:c, which is a more useful function in its own right. – Will Robertson Jan 30 '18 at 10:32
4

You need to expand the argument before doing the regex, else it is just looking at it as-is and \tl_head:n is not in your list of capitals.

[Somebody please correct me if this explanation is hopelessly naïve.]

Please do read the naming guidelines for expl3. Although your code will work even if you violate them, there are very strong reasons not to do so. In essence, as I understand their purpose, the syntax is designed to avoid the conflicts which plague 2e and improve the consistency and, therefore, transparency of code.

\documentclass{article}
\usepackage{expl3}
\ExplSyntaxOn
\regex_const:Nn \c_kevin_capitals_regex {[A-Z]}
\cs_new_protected:Npn \keven_change_case:n #1 {
  \tl_head:n {#1}
  \regex_match:NxTF \c_kevin_capitals_regex {\tl_head:n {#1}}
    {\tl_upper_case:n {\tl_tail:n {#1}}}
    {\tl_lower_case:n {\tl_tail:n {#1}}}
}
\cs_generate_variant:Nn \regex_match:NnTF {NxTF}
\ExplSyntaxOff
\begin{document}
\ExplSyntaxOn
\keven_change_case:n {aBcD}~ \keven_change_case:n {AbcD}
\ExplSyntaxOff
\end{document}

abcd/ABCD

  • I think it would be better to use f expansion rather than x expansion because it suffices to expand the \tl_head:n and won't break if the argument contains fragile macros. – Hood Chatham Jan 30 '18 at 3:33
  • @HoodChatham In light of the OP's other questions, I suspect that x is going to be needed here because the OP wants the processing done from the inside out when things are nested, and that's going to require x rather than o. However, if I'm wrong about the OP's use-case, then o would indeed be better. (At least, I think it'll require x.) – cfr Jan 30 '18 at 3:46
  • @HoodChatham However, my names were all wrong, of course, as I didn't think to check them. – cfr Jan 30 '18 at 3:55
  • Yeah everyone expects things to be done inside out. I'm just wary of \edefing content that is intended to be typeset -- it seems to me that you should at least use \protected@edef here. – Hood Chatham Jan 30 '18 at 4:51
  • @HoodChatham I don't see that o is really much improvement over x in that case, though. Either way, there could be stuff in the stream which the user wants \protected. Or am I confused? – cfr Jan 30 '18 at 23:10

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.