4

Suppose I am writing a custom document class, where I would like to add a dynamic bulk of human-readable text (hence with spaces) to the title page:


\tl_set:N \l_my_var_tl {My Dynamic Variable}

\cs_new:Nn \my_titletext: {
  There ~ is ~ some ~ text.
  There ~ is ~ the ~ variable ~ \l_my_var_tl.
  And ~ it~ is ~ long. \par
}

I will have to type a lot of ~ in the code. I cannot temporarily \ExplSyntaxOff and \ExplSyntaxOn back. Because inside the function I will use expl3 variables and functions which contain _ character.

I wonder if there is something like '~'.join(str1, st2, ...) in expl3 (AFAIK there isn't such a function after searching through the document), or are there any other better practices to write long text literals in expl3 syntax?

4
  • 2
    You can have a look at how it is done in the kaptlipsum package (just not saying that it is he proper way to do it). That package is written in expl3 and hosts wast amounts of text.
    – daleif
    Jan 19, 2023 at 10:20
  • 2
    note you probably want~ for line ends as well, you have text.There You could locally set catcode of space to 10 but again you would have to choose whether to make line ends space (so add % to code lines) or not Jan 19, 2023 at 10:23
  • @daleif I could not find a package of that name. I looked at lipsum though. It has been rewritten in expl3. They define blind texts in external .txts and use file IO. It's a good choice if there are really tons of completely constant text.
    – fhfuih
    Jan 20, 2023 at 15:24
  • Typo from my part kantlipsum
    – daleif
    Jan 20, 2023 at 15:35

2 Answers 2

3

Under the scope of \ExplSyntaxOn, the space gets category code 9 (ignored) and \endlinechar is set to 32, so a space is effectively added at the end of every line (to be later ignored during tokenization).

So a good strategy for your problem is to locally set the category code of space to 10 and not worry about endlines, which will produce a space.

This is exactly what I do in kantlipsum.sty:

\group_begin:
\char_set_catcode_space:n {`\ }
\__kgl_newpara:n {As any dedicated reader can clearly see, the Ideal of
practical reason is a representation of, as far as I know, the things
[...]
what first give rise to human reason.}

I'm not sure you want to do \cs_new:Nn for those fixed texts because they're variables containing text, rather than functions.

% this will later be set in the document
% with an appropriate option
\tl_new:N \l_my_var_tl

% an auxiliary function to store fixed texts
\cs_new_protected:Nn \__my_define_text:nn
 {
  \tl_clear_new:c { g_my_container_#1_tl }
  \tl_gset:cn { g_my_container_#1_tl } { #2 }
 }

% the function for using fixed texts
\cs_new:Nn \my_use_text:n { \tl_use:c { g_my_container_#1_tl } }

% the fixed texts
\group_begin:
\char_set_catcode_space:n { `\  }

\__my_define_text:nn { title }
 {
  There is some text.
  There is the variable \l_my_var_tl.
  And it is long.\par
 }
% other fixed texts
\group_end:

Of course, the problem of spaces behind control sequence remains as usual. I also gloss over the naming of functions and variables that should be better pondered.

Instead of many tl variables, you might consider using a property list:

% this will later be set in the document
% with an appropriate option
\tl_new:N \l_my_var_tl

% an auxiliary function to store fixed texts
\prop_new:N \g_my_texts_prop

\cs_new_protected:Nn \__my_define_text:nn
 {
  \prop_gput:Nnn \g_my_texts_prop { #1 } { #2 }
 }

% the function for using fixed texts
\cs_new:Nn \my_use_text:n
 {
  \prop_item:Nn \g_my_texts_prop { #1 }
 }

% the fixed texts
\group_begin:
\char_set_catcode_space:n { `\  }

\__my_define_text:nn { title }
 {
  There is some text.
  There is the variable \l_my_var_tl.
  And it is long.\par
 }
% other fixed texts
\group_end:
2
  • Thanks for the reply! I make a function because I expose \l_my_var_tl to package users so they set the value later. From a traditional coding mindset, setting it to a variable means the current value of \l_my_var_tl is "baked" into the text at the time of definition, whereas setting it to a function means the value at the invocation will be read. I know expl3 is a text-expansion-based stuff and some may behave differently. But I'm not sure whether defining as function behaves as expected (e.g. \l_my_var is kept as-is as a token and not processed until the outer storage var is used)?
    – fhfuih
    Jan 20, 2023 at 15:01
  • Cuz I am new to expl3 and writing small stuff as practice. I think current expl3 document is blurry about the old concept text expansion (which I'm also not very familiar) and new function call / variable access. Also it is not clear about function return value type. E.g. if I don't know the answer to my question above, just reading your #1 I can clearly see the assembled text is stored in a tl variable, which may mean that \l_myvar is kept as a token? But in #2 the prop value type is dynamic so definitely I cannot make any assumption.
    – fhfuih
    Jan 20, 2023 at 15:06
2

You can define your macro with text outside Expl3. For example

\def\cs#1{\csname#1\endcsname}

\def\mytext {There is some text.
  There is the variable \cs{l_my_var_tl}.
  In fact, it is not a ``variable'' but it is simply \TeX{} macro,
  but Expl3 introduces a new terminology which differs
  from standard \TeX{} terminology.
}
\ExplSyntaxOn
\tl_set:Nn \l_my_var_tl {My Dynamic Variable}

\cs_new:Nn \my_titletext: { \mytext }
\ExplSyntaxOff
4
  • 4
    If the question would be “How do I do this in C?” your answer is “Here's an Assembler function that you can force into C, but don't use C, Assembler is better”. I've never told anyone “don't use plain TeX or variants thereof”; the choice of the programming language is personal and such recommendations are inane. Besides, but it's only a linguistic problem, the last paragraph means “I do recommend to use expl3”.
    – egreg
    Jan 19, 2023 at 13:53
  • Wait Friday to start a troll... :-) An expl3 human coder... ;-)
    – projetmbc
    Jan 19, 2023 at 13:57
  • I agree with @egreg 's comment here but anw that means there may be no "programmatic" way to work around to date. I still give an upvote, but I accept egreg's answer as it is more expl3-ish ;) (At least I totally accept "you can do B instead of A" answers in TeX forum. There are just too many solutions to a problem in the ecosystem that an individual may miss out.)
    – fhfuih
    Jan 20, 2023 at 15:11
  • I'd like to highlight in your answer that, although _ is not letter outside ExplSyntax, it is still okay to directly use it as part of the literal argument to a \def macro. Did'n realize that before; so I thought I have to\def another no-_ name for each of the dynamic variables manually. (Assume there are dozens).
    – fhfuih
    Jan 20, 2023 at 15:20

You must log in to answer this question.

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