0

I'm writing a discussion document where contributors get their own pages and I want to mention these pages in the general text So I have this which seems to do the trick

% usage: create printed page space for artist and the short form reference
% \artist{Jo Blow}{JoBl}
\newcommand{\artist}[2]{
\newpage
\subsection{#1}
Lorem ipsum
\newpage 
Et tu quoque! #2\label{artist:#2}
% page reserved for artwork by #1
}

% obtain page numbering for artist image page given shortform reference % \mention{JoBl} \newcommand{ \mention}[1] { \emph{[p.\pageref{artist:#1}]}}

but I wanted to extend mention{} to take a variable length list of arguments

I found this iterating-through-comma-separated-arguments

A case of running before I can walk, but bear with me I'm only a stupid artist, I tried this

%!TEX TS-program = lualatex
%!TEX encoding = UTF-8 Unicode
\documentclass{article}

\newcommand{\artist}[2]{ \newpage \subsection{#1} Lorem ipsum \newpage Et tu quoque! #2\label{artist:#2} % page reserved for artwork by #1 }

% obtain page numbering for artist image page given short form reference % \mention{HoBu} \newcommand{ \mention}[1] { \emph{[p.\pageref{artist:#1}]}}

\makeatletter \newcommand{\lmention}[2][$,$]{% \def\nextitem{\def\nextitem{#1}}% @for \el:=#2\do{\nextitem\el}% } \makeatother

\begin{document} \artist{Arty Blow}{Arty}

\artist{Jo Blow}{Jo}

What I want is the stylised \mention{Arty} What would be nice would be an arg count to say p.18 or pp.18,23,24

A list of mentions is \lmention{Arty,Jo,Fred} tho we havent talked about Fred Did I forget \lmention{Bart} who is yet to be referenced \artist{Bart Beast}{Bart} \artist{Fred Geest}{Fred}

\end{document}

Long story, short question? How can I get it to do the \pageref lookup on an arg by arg basis

I try

\newcommand{\lmention}[2][$:$]{%
  \def\nextitem{\def\nextitem{#1}}%
  \@for \el:=#2\do{\pageref{artist:#2}\nextitem\el}%
}

but get

A list of mentions is ??Arty??:Jo??:Fred tho we havent talked about Fred

Well out of my depth here

  • Untested but to provide two arguments to \artist you need the syntax \artist{Arty Blow}{Arty}, so no commas and no extra pair of {}. – Marijn Jun 23 '23 at 13:07
  • Thank you Marijn, my inexperience shows. I have changed the question as above and moved the question on Or is that bad etiquette and a new question is necessary? – aldobranti Jun 23 '23 at 17:15
  • It's fine to keep the new version of the question, as long as there are no answers that address the old issue. – Marijn Jun 23 '23 at 21:17

3 Answers3

2

You can define your \lmention using TeX primitives and classical TeX recursive loop.

\def\lmention#1{\lmentionA#1,\end,}
\def\lmentionA#1,#2,{\ifx\end#2 [p.\pageref{artist:#1}]\else
   [pp.\pageref{artist:#1}\afterfi{\lmentionB#2,}\fi
}
\def\lmentionB#1,#2,{,\pageref{artist:#1}%
   \ifx\end#2]\else \afterfi{\lmentionB#2,}\fi
}
\def\afterfi #1#2\fi{\fi#1}

Note that this macro works with single parameter like your \mention, i.e. expands to the [p.page]. In other cases it expands to [pp.list-of-pages].

wipet
  • 74,238
1

You can use expl3 that provides all the tools you need.

As you see, there's just the \mention command, that can distinguish whether one or more references are provided.

\documentclass{article}

\newcommand{\artist}[2]{% \newpage \subsection{#1} Lorem ipsum \newpage Et tu quoque! #2\label{artist:#2} % page reserved for artwork by #1 }

\ExplSyntaxOn

\NewDocumentCommand{\mention}{m} { \aldobranti_mention:n { #1 } }

\seq_new:N \l__aldobranti_mention_ref_seq \tl_new:N \l__aldobranti_mention_first_tl

\cs_new_protected:Nn \aldobranti_mention:nn { % divide the item at the given delimiter \seq_set_from_clist:Nn \l__aldobranti_mention_ref_seq { #1 } % detach the last item \seq_pop_right:NN \l__aldobranti_mention_ref_seq \l__aldobranti_mention_first_tl % now process \aldobranti_mention_format:n { % if the sequence is empty, there was just one item: issue 'p.'; otherwise 'pp.' \seq_if_empty:NTF \l__aldobranti_mention_ref_seq { p. } { pp. } \nobreakspace % now map the sequence to give 'pageref,<space>' \seq_map_inline:Nn \l__aldobranti_mention_ref_seq { \pageref{artist:##1},~ } % last item should not have comma and space \pageref{artist:\l__aldobranti_mention_first_tl} } }

\cs_new_protected:Nn \aldobranti_mention_format:n {% format the whole block (change as desired) \textup{[} \hspace{0.1em} \textit{#1} \hspace{0.1em} \textup{]} }

\ExplSyntaxOff

\begin{document}

\artist{Arty Blow}{Arty}

\artist{Jo Blow}{Jo}

What I want is the stylised \mention{Arty} What would be nice would be an arg count to say p.18 or pp.18,23,24

A list of mentions is \mention{Arty,Jo,Fred} tho we haven't talked about Fred Did I forget \mention{Bart} who is yet to be referenced

\artist{Bart Beast}{Bart} \artist{Fred Geest}{Fred}

\end{document}

enter image description here

egreg
  • 1,121,712
0

The first thing to realize is that the current element of the list is not #2 but \el. The argument #2 is the full list. Therefore you need \pageref{artist:\el}.

The second thing relates to the position of the separator. Normally when constructing a comma separated list you might be inclined to do something like:

for each element {
   print element
   print separator
}

Note that the above is pseudocode, not actual LaTeX or TeX.

However, by doing that you would get the list element1,element2,element3, which has an unwanted comma at the end. Therefore the code in the other question uses a trick: it puts the separator before each element but makes sure that the first separator is not printed. This is easier than to ensure that the last separator is not printed, because in the loop you don't know what the last element is. The trick is that the command \nextitem is originally defined to print nothing and instead perform the definition \def\nextitem{#1}. Argument #1 is a comma, so from the second call onwards, \nextitem prints a comma. Therefore you need the same structure as in the referenced question, i.e., \do{\nextitem\el} but instead of printing just \el you want to print \pageref{artist:\el}, so in full it becomes \do{\nextitem\pageref{artist:\el}}.

For counting the arguments you can loop the list first and increment a counter for each element, then test the value of that counter. If it is 1, print p., otherwise print pp.. Afterwards you loop the list again for the actual \pageref calls.

Side remark is that you don't need $,$ as the separator, this was only needed in the original question because the separator used there was a math command (\triangleright) which requires math mode with $. A comma is a regular character so there math mode is not needed.

Full code:

\documentclass{article}

\newcommand{\artist}[2]{ \newpage \subsection{#1} Lorem ipsum \newpage Et tu quoque! #2\label{artist:#2} % page reserved for artwork by #1 }

% obtain page numbering for artist image page given short form reference % \mention{HoBu} \newcommand{ \mention}[1] { \emph{[p.\pageref{artist:#1}]}}

\makeatletter \newcounter{mentionargs} \newcommand{\lmention}[2][,]{% \setcounter{mentionargs}{0}% @for \el:=#2\do{\stepcounter{mentionargs}}% \ifnum\value{mentionargs}=1% p.% \else% pp.% \fi% \def\nextitem{\def\nextitem{#1}}% @for \el:=#2\do{\nextitem\pageref{artist:\el}}% } \makeatother

\begin{document} \artist{Arty Blow}{Arty}

\artist{Jo Blow}{Jo}

What I want is the stylised \mention{Arty}, \mention{Jo}, \mention{Fred} What would be nice would be an arg count to say p.2 or pp.18,23,24

A list of mentions is \lmention{Arty,Jo,Fred} tho we havent talked about Fred Did I forget \lmention{Bart} who is yet to be referenced \artist{Bart Beast}{Bart} \artist{Fred Geest}{Fred}

\end{document}

Result:

enter image description here

Marijn
  • 37,699