3

A Command, e.g. \Subentry, works fine when defined outside a LaTeX3 Environment, e.g. {mainentry}, but as soon as one would like to put its definition inside the (definition of the) mentioned Environment a Undefined control sequence-error for that mentioned Command is yielded, meaning somehow LaTeX can not read its definition.

In MWE 1, no error is produced, apparently because the lines containing the \Subentry command, namely the following lines:

\def\Subentry{\def\SubentryS{\def\SubentryS{ \endgraf }}\futurelet\next\SubentryA}
\def\SubentryA{\ifx\bgroup\next\expandafter\SubentryB\fi}
\def\SubentryB#1#2{\SubentryS { #1 #2 {\bfseries #1} } \futurelet\next\SubentryA}

are defined outside of the Environment {mainentry}.

  • In MWE 1, no Undefined control sequence is produced.
  • In MWE 2, those lines will be placed inside the Environment {mainentry}, at the place of % ??? inside MWE 1. We also put the issuing of the Command, namely \Subentry{C}{D} within the issuing of the Environment. Then, we shift the definitions of the Command to the beginning of the Environment, instead of putting them at the end (following User Wipet's comment).

MWE 1 (no error)

% !TEX TS-program = lualatexmk

\documentclass[a4paper]{scrreprt}

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Declare packages and commands
%
\usepackage{xparse}
\ExplSyntaxOn
\cs_set_eq:NN
\IfEmptyTF
\tl_if_blank:nTF
\ExplSyntaxOff
%
\NewDocumentEnvironment {mainentry} { m m m } {%
% ???
  \IfEmptyTF{#3}{%
#1 #2
  }{%
#1 #2 \endgraf #3
  }
  }{%
}
%
%
%
\def\Subentry{\def\SubentryS{\def\SubentryS{ \endgraf }}\futurelet\next\SubentryA}
\def\SubentryA{\ifx\bgroup\next\expandafter\SubentryB\fi}
\def\SubentryB#1#2{\SubentryS { #1 #2 {\bfseries #1} } \futurelet\next\SubentryA}
%
%
%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

\begin{document}

\begin{mainentry}{A}{B}{}
\end{mainentry}

Some text.

\Subentry{C}{D}

\end{document}

MWE 2 (error)

Please note that I would like to put the (definition of the) Command \Subentry inside the (definition of the) Environment {mainentry} because I would like {\textbf #1} (which occurs inside that Command), to be replaced with {\textbf ##1} (or whatever code necessary ... I don't know exactly what syntax to use) so that it actually takes in the first argument of the Environment (so then {mainentry}) where it is placed in (speaking about definitions of), not just the Commands' own first argument.

Currently, the instance of {\textbf #1} yields C (in casu, the first argument of the Command it finds itself in), whereas I would like it to yield A (the first argument of the encompassing Environment, one level up in hierarchy, in which that Command may find itself) (speaking about definitions of).

Therefor, MWE 2 uses {\textbf ##1} instead of {\textbf #1}. (following User David Carlisle's comment). ---> PLEASE NOTE THAT I MISINTERPRETED THIS COMMENT ... NOTE BY OP AFTER FURTHER UNDERSTANDING ... ##1 actually refers to the inner argument, not the outer argument <---

The error will look something as follows:

./test.tex:69: Use of \SubentryB doesn't match its definition.

% !TEX TS-program = lualatexmk

\documentclass[a4paper]{scrreprt}

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Declare packages and commands
%
\usepackage{xparse}
\ExplSyntaxOn
\cs_set_eq:NN
\IfEmptyTF
\tl_if_blank:nTF
\ExplSyntaxOff
%
\NewDocumentEnvironment {mainentry} { m m m } {%

\def\Subentry{\def\SubentryS{\def\SubentryS{ \endgraf }}\futurelet\next\SubentryA}
\def\SubentryA{\ifx\bgroup\next\expandafter\SubentryB\fi}
\def\SubentryB#1#2##1{\SubentryS { #1 #2 {\bfseries ##1} } \futurelet\next\SubentryA}

  \IfEmptyTF{#3}{%
#1 #2
  }{%
#1 #2 \endgraf #3
  }
  }{%

}
%
%
%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

\begin{document}

\begin{mainentry}{A}{B}{}

\Subentry{C}{D}

\end{mainentry}

Some text.

\end{document}
  • If I put \Subentry at the place you have ??? I get no error, but you don't say what you did, what error you got or what output you expected so it is hard to help. – David Carlisle Oct 9 '17 at 6:59
  • you do not want to put the definition of \Subentry into your environment, presumably you want to use it don't you???? – David Carlisle Oct 9 '17 at 11:52
  • if you do just locally define it in the environment then as previously commented you need ##1##2 not #1#2 but also it should be used inside the environment where it is defined not outside. – David Carlisle Oct 9 '17 at 11:54
  • Why do you insert the definitions at the END of the environment (into the last parameter of environment definition) and not at the START of the environment. Sorry, I totally don't understand what is your intend. If I know it then I am able to solve it without any LaTeX specialities like newenvirnoment, ExplSyntaxOn etc. Pure TeX language is sufficient. The mix of languages (in your example) looks horrible. On the other hand somebody else can solve it pure in ExplSyntaxOn or pure \directlua etc. – wipet Oct 9 '17 at 17:08
  • Why you keep errors: because you are using \Subentry before it is defined. I don't have another MWE which shows other errors. If I put the definitions into the starting paramater immediately before \IfEmptyTF{#3} then there is no errors. Of course, you must to double all hash marks in definitions as mentioned by David Carlisle. – wipet Oct 9 '17 at 17:58
2

You can be experimenting and thinking about the following code:

\documentclass[a4paper]{scrreprt}

\newenvironment {mainentry} {\mainentryA}{}
\def\mainentryA#1#2#3{%
   \def\SubentryC##1##2{%
      Here is external parameter (#1) and second external (#2).
      And internal parameter is (##1) and second internal (##2).
   }%
   \ifx\mainentryA#3\mainentryA  % if #3 is empty
   #1 #2
   \else
   #1 #2\endgraf #3
   \fi
}
\def\Subentry{\def\SubentryS{\def\SubentryS{\endgraf}}\futurelet\next\SubentryA}
\def\SubentryA{\ifx\bgroup\next\expandafter\SubentryB\fi}
\def\SubentryB#1#2{\SubentryS\SubentryC{#1}{#2}\futurelet\next\SubentryA}

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

\begin{document}
\begin{mainentry}{A}{B}{}
\Subentry{C}{D}{E}{F}
NEXT
\Subentry{U}{V}{W}{X}{Y}{Z}
\end{mainentry}
Some text.
\end{document}

You can use LaTeX and see the output. The code is derived from your code but I didn't use redundant packages (specially, I use none packages) and redundant code in order to focus only on your problem.

  • Interesting. So it is impossible to stick with the LaTeX3-way (\NewDocumentEnvironment {mainentry} { m m m } {%)? – Vincent Mia Edie Verheyen Oct 11 '17 at 4:29
  • I don't see any reason to use this special package when solving your problem. Of course, I don't see any reason to use LaTeX at all, but this is another story... – wipet Oct 11 '17 at 4:32
  • I don't want to mix my pure TeX code with something like LaTeX3. – wipet Oct 11 '17 at 4:38
  • I have tried to use your code, but some more questions arose (cf. a new OP here). Thank you so much. – Vincent Mia Edie Verheyen Oct 11 '17 at 5:53
2

The error you get (at least from the last example) is not “Undefined control sequence”, but “Use of \SubentryB doesn't match its definition”. Indeed you do

\def\SubentryB#1#2##1{\SubentryS { #1 #2 \href{http://a.beautiful.url/?q=\percentifier{##1}}{test-link} } \futurelet\next\SubentryA}

which defines \SubentryB to require being followed by whatever the first two arguments to the current mainentry environment are. You probably mean something like

\def\SubentryB##1##2{\SubentryS { ##1 ##2 \href{http://a.beautiful.url/?q=\percentifier{##1}}{test-link} } \futurelet\next\SubentryA}

but it's difficult to guess based on your example. In your case, you are doing

\def\SubentryB AB#1{\SubentryS { A B \href{http://a.beautiful.url/?q=\percentifier{#1}}{test-link} } \futurelet\next\SubentryA}

because TeX performs replacement of parameter with arguments and then turns ## into # when doing the definition. So you see why \SubentryB has to be followed by AB, but none of its calls is.

  • Thank you. So how could I get, inside \SubentryB, both its own arguments as well as arguments of an encompassing Environment? – Vincent Mia Edie Verheyen Oct 10 '17 at 15:27
  • @VincentMiaEdieVerheyen You can use #1 and #2 in the body of the definition wherever you'd like to. – egreg Oct 10 '17 at 15:31
  • Thanks. So why is \def\SubentryB##1{\SubentryS { #1 #2 \href{http://a.beautiful.url/?q=\percentifier{##1}}{test-link} } not working then please? Is this not the body of the definition? – Vincent Mia Edie Verheyen Oct 11 '17 at 0:57
  • @VincentMiaEdieVerheyen If you don't explain what the macro is supposed to do, I can only guess. Your final version seems to be good. – egreg Oct 11 '17 at 6:58
  • Following User David Carlisle's comment I understand what I wanted was \def\SubentryB##1##2{\SubentryS { ##1 ##2 \href{http://a.beautiful.url/?q=\percentifier{#1}}{test-link} } \futurelet\next\SubentryA}. This solves the compilation errors described in the OP. Sorry for not having been able to explain myself more clearly and having a messy OP (now revised and simplified somewhat). – Vincent Mia Edie Verheyen Oct 11 '17 at 7:47

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.