13

As below, I would like to test whether a user has input some custom text, and if not, then to display default text.

\documentclass{article}
\usepackage{xparse}
\ExplSyntaxOn
\tl_new:N \l_empty_tl

\NewDocumentCommand{\dostuff}{}{
    \tl_if_empty:NTF \l_empty_tl
        {Here is a large block of default text that I would like use.}
        {\tl_use:N \l_empty_tl}
}

\ExplSyntaxOff
\begin{document}

\dostuff

\end{document}

I would prefer not to type Here~is~a~large... and wonder whether there is a simple way to have the spaces recognized. I have tried

{\cctab_begin:N \c_document_cctab Here is a large..\cctab_end:}

to no avail. I feel like this might be a dupe, but can't seem to find a relevant question.

Scott H.
  • 11,047

2 Answers2

12

There are a few approaches one could use. If it's a simple one-shot where you just want that piece of text, then something like

\documentclass{article}
\usepackage{xparse}
\ExplSyntaxOn
\tl_new:N \l_my_tl
\NewDocumentCommand { \dostuff } { }
  {
    \tl_if_empty:NTF \l_my_tl
      { \tl_use:N \c_my_tl }
      { \tl_use:N \l_my_tl }
  }
\use:n
  {
    \ExplSyntaxOff
    \tl_const:Nn \c_my_tl
  }
  {Here is a large block of default text that I would like use.}
\begin{document}

\dostuff

\end{document}

is probably easiest. The idea here is that \use:n tokenizes the input, but I leave the text part 'after' that so it is read with document catcodes.

Another approach is simply to alter the behaviour of , either using grouping:

\documentclass{article}
\usepackage{xparse}
\ExplSyntaxOn
\tl_new:N \l_my_tl
\NewDocumentCommand { \dostuff } { }
  {
    \tl_if_empty:NTF \l_my_tl
      { \tl_use:N \c_my_tl }
      { \tl_use:N \l_my_tl }
  }
\group_begin:
  \char_set_catcode_space:n {`\ }%
  \tl_const:Nn\c_my_tl{Here is a large block of default text that I would like use.}%
\group_end:
\ExplSyntaxOff
\begin{document}

\dostuff

\end{document}

or otherwise:

\documentclass{article}
\usepackage{xparse}
\ExplSyntaxOn
\tl_new:N \l_my_tl
\NewDocumentCommand { \dostuff } { }
  {
    \tl_if_empty:NTF \l_my_tl
      { \tl_use:N \c_my_tl }
      { \tl_use:N \l_my_tl }
  }
\char_set_catcode_space:n {`\ }%
\tl_const:Nn\c_my_tl{Here is a large block of default text that I would like use.}%
\char_set_catcode_ignore:n{`\ }%
\ExplSyntaxOff
\begin{document}

\dostuff

\end{document}

(It's not clear if the text asked for is a constant: if not then I'll modify the above.)

I'd strongly recommend not using a rescan method. To be honest, I've found rescanning to be a good way to break things, and would be extremely cautious about using it in any new code (to the point where I'd probably be happy if we dropped the \tl_rescan: family entirely!).

Joseph Wright
  • 259,911
  • 34
  • 706
  • 1,036
  • 1
    Method 2 is basically what I used for kantlipsum; perhaps \char_set_catcode_space:n {`\ } is better as it avoids the need of % to end the line. – egreg Apr 10 '13 at 08:19
  • 1
    @egreg You are right the n version is probably preferable (as it's more general). I'm keeping the % as my feeling is that once you start messing with the normal expl3 set up you should use 'traditional' commenting-end-of-lines. – Joseph Wright Apr 10 '13 at 08:22
  • Thanks for the detailed answer. The text itself would indeed by constant, no need to modify the above :) – Scott H. Apr 10 '13 at 22:03
5

That won't work, because \cctab_begin:N \c_document_cctab only sets the catcodes to the "document" ones after the macro \dostuff is expanded, and that is already far too late to save the spaces in your block of text. Now, one could get around this using \scantokens or the LaTeX3 equivalent, but I might propose simply storing your text in a macro that is created outside the expl3 syntax, i.e.

\usepackage{xparse,expl3}

\NewDocumentCommand \mytext { } {%
 Here is a large...%
}

\ExplSyntaxOn
\tl_new:N \l_empty_tl

\NewDocumentCommand{\dostuff}{}{
    \tl_if_empty:NTF \l_empty_tl
        {\mytext}
        {\tl_use:N \l_empty_tl}
}

\ExplSyntaxOff

Then \mytext contains correctly formated text that is not disturbed by the LaTeX3 coding syntax.

Ryan Reich
  • 37,958
  • I had thought of doing it outside of ExplSyntaxOn but it seemed rather artificial. It would be nice to have a direct method of doing so. I looked at \tl_rescan:nn but the documentation doesn't have an example of how to set up a catcode regime. It would be great if you had the time to give a small example of its use. Thanks for the information on \cctab as well. – Scott H. Apr 10 '13 at 04:35
  • Actually, I asked a question a while back involving rescan I'll have a look at that and see if I can figure it out. – Scott H. Apr 10 '13 at 04:39
  • 1
    \mytext looks to me like a variable, not a document command. At the moment we don't have a LaTeX3 document variable interface, so I'd use \newcommand* here. – Joseph Wright Apr 10 '13 at 07:48
  • @JosephWright Ah, I was wondering about that. I just used \NewDocumentCommand to make it look "LaTeX3-y". But yeah. – Ryan Reich Apr 10 '13 at 13:50
  • @ScottH. - All of Joseph's solutions involve moving the text out of the \dostuff command, so I guess you have a choice of artificial solutions. That has the advantage of simplicity. – Charles Stewart Apr 11 '13 at 08:02
  • @CharlesStewart Well one of the LaTeX3 principals is that 'document commands' should really be interfaces to some defined code level stuff, with no 'programming' in them at all (see issues with patching LaTeX2e commands for reasons). So moving 'some text' out of commands is a general idea: we've done that with error messages (name the message, but put the text of the message separately so it can be varied without impact on the calling command). – Joseph Wright Apr 11 '13 at 08:53
  • @JosephWright - If I understand the point you're making, I think this is something we shouldn't be imposing on the user. If you listen to i18n people, separating the text from the code allows best practices for internationalisation to be applied. If you listen to Rob Pike, keeping text close to code reduces the defect rate in the code. – Charles Stewart Apr 11 '13 at 09:25
  • @CharlesStewart There is nothing to stop you simply altering the treatment of for an entire block including the definition of a command. Experience with LaTeX2e though suggests this makes altering behaviour tricky, as you have large macros which either have to be copy-pasted or fixed using something like xpatch when issues arise. I'm not sure also what 'close' means: does that mean within the definition of a command or simply on the next line of the input? – Joseph Wright Apr 11 '13 at 09:53
  • @JosephWright - i18n usually wants text in separate files. Rob Pike is worried, I think, about the cognitive units that make up how the code is understood by the programmer - that's mostly pretty subjective, a few psychology PhDs notwithstanding. – Charles Stewart Apr 11 '13 at 10:10