0

I would first like to thank everyone who contributes on Stack Exchange as they have been an enormous help for everything LaTeX. I have searched all over SE for a solution to this current problem and yet haven't found a solution. Here is my project:

I am making a booklet for the singing of Vespers according to the Traditional rite using the Gregorio project and LuaLatex. Some pdf examples of the work already accomplished can be found here:

http://docs.sspx.org.za/index.php/s/1LRq234nkQGavAW

The layout is done quasi-automatically with the simple modification of the filenames for the import of the antiphons, etc. I am preparing to put all the source code online so that anyone else can use it and provide other translations [English and Polish I have done myself, but others can provide in more languages]. I would like to clean up the source code a bit however and make it as easy as possible for others to contribute. Part of this would be a simple macro to determine which Sunday of the Liturgical Year to typeset.

For those who know the Traditional Latin Rite, the antiphon changes each Sunday, but the overall structure of Vespers stays the same. What I would like to do is have the option of simply specifying the Sunday of the year as a variable and then have the LaTeX calculate the rest. However I am having a lot of trouble in passing the parameters of one command to another.

Here is my current working example of how to choose the antiphon (with imaginary cases to make the example shorter, the real macro has 52 choices, and what are given are actually the names of the .gabc files in another directory). I am using the package xstring which has the \IfEqCase command which I can nest in the following way :

\newcommand{\whichantifon}[2]{%
   \IfEqCase{#1}{%
     {advent}{\IfEqCase{#2}{%
       {i}{First Sunday of Advent, Magnificat-4a}
       {ii}{Second Sunday of Advent, Magnificat-6F}
      }}% end advent cases
     {pentecost}{\IfEqCase{#2}{%
      {i}{First Sunday after Pentecost, Magnifcat-1d}
      {ii}{Second Sunday after Pentecost, Magnifcat-3a}
      }}% end pentecost cases
  }% end choose instruction
}%end command

With this macro I can do something like this to pull out the proper antiphon and mode:

\whichantifon{advent}{i}

What I would like to do is pass the results of this choice to another macro which actually does the typesetting of the chant, using the two arguments from this choice:

\canticum{\whichantifon{advent}{i}}

In order to get a working example I put a simple \def like this one that does a minimum of typesetting:

\def\canticum#1, #2{%
    This is the #1, and Magnificat #2}%

The idea being that the simple comma which is part of the expansion of the \whichantifon will then be the separator for the two arguments for this \canticum, thinking this to be an elegant solution as otherwise I would have to have two very lengthly choice macros. However it doesn't work, or rather it only works partially.

If I have the following document with the above macros defined, I can get the output of the following:

\whichantifon{advent}{i}

Which gives this, so this part works very well:

First Sunday of Advent, Magnificat-4a

However if I try the simple \canticum as above :

\canticum{\whichantifon{advent}{i}}

I get the following error:

   ERROR: Paragraph ended before \canticum was complete.

Apparently 'A blank line occured in a command argument that shouldn't contain one'. However if I just copy/paste the output of the first macro to the \canticum it works just fine. I have looked all over SE for the \expandafter and other tricks but nothing works. I have even tried using string separators and other packages, but that ended up with even more complications and no solution.

I have always understood LaTeX to be simply a sort of macro expander or substitution language. However it seems not to substitute at certain times or in ways that are not at all intuitive. For instance, when does the argument to \def get expanded? before or after its own evaluation? It would seem to need to evaluate the arguments before the definition, but it doesn't seem to work in this way.

What I really want to do is have a function that returns two arguments to be used as the input for another function. This of course is not a very proper function so my approach is probably incorrect.

The real difficulty is that each Sunday has two pieces of information, the antiphon and the tone of the Magnificat, and these two pieces of information determine what gets typeset in the document. The contributors would ideally only have to provide one piece of information [which Sunday] while the latex would provide the rest (as the actual files and tones would already be in the project folder).

Any sort of help or links to resolve this difficulty, or even different approaches would be most welcome. If it would helpful I can post a link to the git repo as a 'work in progress'.

Thank you for at least reading this question!

  • 2
    exactly the opposite, the expansion of the outer macro happens first so \canticum{\whichantifon{advent}{i}} ignores the braces as \canticum isn't looking for a standard braced argument it reads ahead to find the , that ends its first argument and so gives an error that a , is not found. You can force expansion in other orders but whichantifon does not work by expansion so you can not just expand it prior to calling \canticum – David Carlisle Sep 12 '17 at 8:26
  • Here is the link to the public repository for those who might be interested in how the solution works: github.com/jsrjenkins/vesperale – Fr. John Jenkins Sep 12 '17 at 18:25
3

[please always provide a test file rather than just a fragment]

The easiest way is to pass the formatting command as an argument to your selector, I made it optional here

\newcommand\canticum[2]{%
    This is the #1, and Magnificat #2}%

\newcommand{\whichantifon}[3][\canticum]{%
   \IfEqCase{#2}{%
     {advent}{\IfEqCase{#3}{%
       {i}{#1{First Sunday of Advent}{Magnificat-4a}}
       {ii}{#1{Second Sunday of Advent}{Magnificat-6F}}
      }}% end advent cases
     {pentecost}{\IfEqCase{#3}{%
      {i}{#1{First Sunday after Pentecost}{Magnifcat-1d}}
      {ii}{#1{Second Sunday after Pentecost}{Magnifcat-3a}}
      }}% end pentecost cases
  }% end choose instruction
}%end command

so by default

\whichantifon{advent}{i}

will use \canticum but you can pass in any other two argument command instead

\newcommand\zzz[2]{\fbox{#1}---\fbox{#2}}
\whichantifon[\zzz]{advent}{i}
  • Brilliant solution! Thank you so much for this. I never thought of passing the command as an argument, which is exactly what needs to be done. A little like mapcar in lisp - very nice. Sorry about not including a full file, I will do this now. – Fr. John Jenkins Sep 12 '17 at 11:19
  • O just a note I noted that with three arguments you need a [3] in the \newcommand. See the Answer below. – Fr. John Jenkins Sep 12 '17 at 11:21
  • @jsrjenkins oops fixed, thanks. (If you had supplied a test file, I would have tested the answer code:-) – David Carlisle Sep 12 '17 at 11:25
1

With the brilliant solution by David Carlisle a full solution is here (apologies for not including a full version in the question):

\documentclass{article}
\usepackage{xstring}

\newcommand\canticum[2]{%
    This is the #1, and Magnificat tone is #2}%

\newcommand{\whichantifon}[3][\canticum]{%
   \IfEqCase{#2}{%
     {advent}{\IfEqCase{#3}{%
       {i}{#1{First Sunday of Advent}{4a}}
       {ii}{#1{Second Sunday of Advent}{6F}}
      }}% end advent cases
     {pentecost}{\IfEqCase{#3}{%
      {i}{#1{First Sunday after Pentecost}{1d}}
      {ii}{#1{Second Sunday after Pentecost}{3a}}
      }}% end pentecost cases
  }% end choose instruction
}%end command

\begin{document}

\whichantifon{advent}{i}

\whichantifon{pentecost}{ii}

\whichantifon{advent}{ii}

\end{document}

This gives the intended result:

This is the First Sunday of Advent, and Magnificat tone is 4a
This is the Second Sunday after Pentecost, and Magnificat tone is 3a
This is the Second Sunday of Advent, and Magnificat tone is 6F

Many thanks to David Carlisle for his elegant answer. Later when the project is ready to go public I'll include a link here.

1

We need to fully expand the \whichantifon{advent}{i} before \canticum is used. But \whichantifon isn't expandable because it is based on non-expandable \IfEqCase. So, we need to define fully expandable \eqcase first:

\def\eqcase#1#2{\eqcaseA{#1}#2\end{}}
\def\eqcaseA#1#2#3{\ifx\end#2\else
   \ifnum\pdfstrcmp{#1}{#2}=0 #3\eqcaseFIN\fi
   \eqcaseB{#1}\fi
}
\def\eqcaseB#1\fi{\fi\eqcaseA{#1}}
\def\eqcaseFIN#1\end#2{\fi\fi}

Now, we can define \whichantifon:

\def\whichantifon#1#2{%
   \eqcase{#1}{%
     {advent}{\eqcase{#2}{%
       {i}{First Sunday of Advent, Magnificat-4a}
       {ii}{Second Sunday of Advent, Magnificat-6F}
      }}% end advent cases
     {pentecost}{\eqcase{#2}{%
      {i}{First Sunday after Pentecost, Magnifcat-1d}
      {ii}{Second Sunday after Pentecost, Magnifcat-3a}
      }}% end pentecost cases
  }% end choose instruction
}%end command

We can define the \canticum macro (note that the second parameter is separated by period):

\def\canticum#1, #2.{This is the #1, and Magnificat #2}

And usage looks like this:

\edef\tmp{\whichantifon{advent}{i}}\expandafter\canticum\tmp.

The parameter is fully expanded in \tmp using \edef and then used. Note the period after \tmp because it is the separator of the second parameter.

  • Thank you very much for your answer - especially for the note on how some commands are 'non-expandable'. This seems to be the source of at least one of the problems. Which parts of TeX get expanded and which don't seems to be one of the hidden parts of TeX that can be rather confusing. – Fr. John Jenkins Sep 12 '17 at 12:44

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.