3

First of all, I guess that will be a very easy answer for people who are experienced in expl3. But for me its new and I'm very willing to learn that stuff to understand Latex3 better. So I hope for some pro help here.

What i want to achieve is the following:

First an userdefined command which has a simple sentence as content. Let's say \NewDocumentCommand{\testcommand}{}{A Test Sentence for expl3}

Now I want to store the content of the command in a token list or string. So that it can be printed/used or counted. The latter is needed, because I want to use the number of characters in an if-condition which activates different commands depending on the total count.

My MWE looks like this:

\documentclass[%
]{article}
\usepackage[T1]{fontenc}

\NewDocumentCommand{\testcommand}{}{A Test Sentence for expl3}

\ExplSyntaxOn
\tl_new:N \test_tl

\tl_set:Nn \test_tl {\testcommand}

\NewDocumentCommand{\showteststring}{}{
    \tl_use:N \test_tl \par
    \tl_count:N \test_tl
}

\NewDocumentCommand{\countteststring}{}{
    \tl_to_str:N \test_tl \par
    \str_count:N \test_tl
}
\ExplSyntaxOff

\begin{document}

    \showteststring
    
    \countteststring
    
\end{document}

\showteststring prints the content of \testcommand correctly using \tl_use:N, but \tl_count:N only counts one token; of course this token is \testcommand.

The same for the for \countteststring. It converts only the command-sequence \testcommand into a string and counts the 13 characters of the command-sequence itself.

So I need to expand \testcommand first. But my tries so far didn't offer any success. For instance, I tried:

\tl_set:Nx \test_tl {\testcommand} (with x) instead of \tl_set:Nn \test_tl {\testcommand}. It compiles fine, but the output remains the same.

I also tried some variants with \exp_args:N, but didn't get it to work, because I don't fully understand where to place it and which argument specifier to use in expl3 syntax.

I also thought about the v/V argument specifier, but couldn't get it to work.

I looked into the interface3 doc. But its overwhelming in case of informations and I couldn't figure out the right commands so far. Further, I searched Tex.SE and read the blog by Ziyue Xiang; also very informative, but not the specific solution I'm looking for (or, of course, I may have overlooked something).

Thus, I am already thankful in advance for any help or hint! For an explanation I would also be very grateful, so I understand it better next time!

1
  • 3
    you should follow the expl3 naming scheme, so use \tl_new:N \l_lukeflo_test_tl Commented Jun 30, 2023 at 9:43

2 Answers 2

4

You have declared \testcommand as a document command: these are protected from expansion. That means that \tl_set:Nx \l_test_tl { \testcommand } doesn't change the result. I would declare \testcommand as an expandable command and use V-type expansion:

\newcommand*\testcommand{A Test Sentence for expl3}
\tl_set:NV \l_test_tl \testcommand

etc.

7
  • thank you, that did it. I just didn't had that option in mind. In ther interfache doc it looks like that \tl_set:(NV|Nv|No|Nf|Nx|cn|cV|cv|co|cf|cx), what makes it easy to overlook something.
    – lukeflo
    Commented Jun 30, 2023 at 10:09
  • Btw: Is there a possibility to use the xparse commands for it? Since, when I'm using \NewExpandableDocumentCommand{\testcommand}{}{<text>} it isn't working like expected. Only newcommand* does.
    – lukeflo
    Commented Jun 30, 2023 at 10:12
  • 1
    Expandable document commands will work, but here you are not using a document command, it's a variable containing text. (At the TeX level, the expandablity of something created by \newcommand and by \NewExpandableDocumentCommand are the same.)
    – Joseph Wright
    Commented Jun 30, 2023 at 10:14
  • 2
    @lukeflo what Joseph said, but notice that a \NewExpandableDocumentCommand doesn't work in \tl_set:NV, as it needs more expansion steps than a \newcommand-defined macro, so with it you'd have to use \tl_set:Nx.
    – Skillmon
    Commented Jun 30, 2023 at 11:02
  • 2
    @lukeflo remember that for a simple data-storage a \NewExpandableDocumentCommand isn't the correct thing to do! You only need \NewExpandableDocumentCommand in very few situations where you need the extra power for your argument processing and the expandability.
    – Skillmon
    Commented Jul 2, 2023 at 12:21
5

The \NewDocumentCommand facility is aimed at offering more powerful argument parsing than the legacy \newcommand. It is not at all suitable for defining “text containers”.

If you want text containers, define an infrastructure for them.

\documentclass{article}

\ExplSyntaxOn

\NewDocumentCommand{\definecontainer}{mm}
 {
  \tl_clear_new:c { g_lukeflo_cont_#1_tl }
  \tl_gset:cn { g_lukeflo_cont_#1_tl } { #2 }
 }

\NewExpandableDocumentCommand{\usecontainer}{m}
 {
  \tl_use:c { g_lukeflo_cont_#1_tl }
 }

\NewExpandableDocumentCommand{\countcontainer}{sm}
 {
  \IfBooleanTF { #1 }
   {% count as string
    \str_count:e { \tl_to_str:v { g_lukeflo_cont_#2_tl } }
   }
   {% count as tl
    \tl_count:c { g_lukeflo_cont_#2_tl }
   }
 }

\ExplSyntaxOff

\definecontainer{test}{A Test Sentence for expl3}
\definecontainer{test2}{abc}

\begin{document}

`\usecontainer{test}' has \countcontainer{test} items

`\usecontainer{test}' has \countcontainer*{test} tokens

`\usecontainer{test2}' has \countcontainer{test2} items

`\usecontainer{test2}' has \countcontainer*{test2} tokens

\end{document}

enter image description here

Note that \tl_count:N will not count spaces, whereas they're counted when the token list is first converted into a string.

14
  • 1
    Hi @egreg, your approach looks very interesting and also adaptable. But if I try to compile it, I get an undefined control sequence error for the lines containing the starred version \countcontainer*
    – lukeflo
    Commented Jun 30, 2023 at 11:19
  • 1
    @lukeflo What control sequence turns out to be undefined? Possibly it is \str_count:e. Ensure first to have an up-to-date TeX distribution.
    – egreg
    Commented Jun 30, 2023 at 12:45
  • Have to check it tomorrow or Sunday, when I'm back at home. But my Distro ist TexLive 2022 and therefore relatively up-to-date.
    – lukeflo
    Commented Jun 30, 2023 at 15:57
  • 1
    @lukeflo “relatively” ;-) Anyway, you may try to add \cs_generate_variant:Nn \str_count:n { e } just before \ExplSyntaxOff.
    – egreg
    Commented Jun 30, 2023 at 16:04
  • @greg. A blasting fast answer, thanks ;) I'll try it out. Notwithstanding, an update to TL 2023 is already planned. I will check afterwards, if that was the reason.
    – lukeflo
    Commented Jun 30, 2023 at 16:06

You must log in to answer this question.

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