# How can I define a command in the preamble with an optional argument for use in macros?

I'm trying to write tags to include document info which can be declared in the preamble then included in a title page using \@institution or \@module, similar to how LaTeX already includes \title{} to get \@title.

I need a command which has an optional "module number" and can be declared by \module[PH588]{Mathematical Techniques} in the preamble, to form tags like \@mod@no and \@mod@title (or similar) to be used in the title page as

{\Large \mod@no: \@mod@title \par}


and produce "PH588: Mathematical Techniques" in a large font.

I am new to this whole macro business and am only fully comfortable with basics like \newcommand. For other information I've used

\newcommand{\@dept}{}


to define each title element.

My attempts thus far (which have been fruitless) are along the lines of:

1)

\def\module[#1]#2{\gdef\@module[#1]{#2}}
\def\@module{}


2)

\def\module{\@ifnextchar[{\@module@wno}{\@module@wono}}
\newcommand{\@module}{}
\def\@module[#1]#2{#1: #2}
\def\@module#1{#1}


3)

\def\@module@no[#1]#2{#1}
\def\@module#1{#1}
\newcommand\@module@no[#1]#2{#1: #2}
\newcommand\@module#1{#1}


These are all between \makeatletter and \makeatother.

As you can see I have very little idea what I'm doing, so if you could provide a simple explanation of how each part of your code does what it's doing and why that would really help me out!

• Sorry, the question is unclear to me. Why fruitless? – user31729 May 9 '15 at 23:17
• You are thinking too complicated, step back a little. Looking at package or kernel code isn't necessary a sign for good coding. Simply do as in your very first snippet and add \renewcommand{\moduleno}{#1}, which is the optional argument. The mandatory argument is now #2. – Johannes_B May 9 '15 at 23:21
• Most probably, the \@module stuff should be 'renewcommand – user31729 May 9 '15 at 23:22
• If you think about adding a star feature somewhere, better familiarize yourself with package xparse, it will come in handy. And it might be handy here. – Johannes_B May 9 '15 at 23:23
• \newcommand\a[2][x]{#1-#2} will define \a so that \a{b} expands to x-b and \a[y]{b} to y-b. – Qrrbrbirlbel May 9 '15 at 23:25

Something with the hard way using \@ifnextchar and the easy way with xparse

\documentclass{article}

\usepackage{xcolor}
\usepackage{xparse}

\makeatletter

\providecommand{\@module@no}{}
\providecommand{\@module@title}{}

\newcommand{\module}{%
\@ifnextchar[{\module@@opt}{\module@@noopt}
}

\newcommand{\module@@opt}[2][no module number]{%
\renewcommand{\@module@no}{#1}%
\renewcommand{\@module@title}{#2}%
}

\newcommand{\module@@noopt}[1]{%
\module@@opt{#1}%
}

%\@onlypreamble{\module}

\NewDocumentCommand{\Module}{o+m}{%
\IfValueTF{#1}{%
\renewcommand{\@module@no}{#1}%
}{%
\renewcommand{\@module@no}{no module number}%
}%
\renewcommand{\@module@title}{#2}%
}

\newcommand{\printmoduleinfo}{%
{\large \textbf{\@module@no} \textsc{\@module@title}}%
}

\makeatother

\begin{document}

\module[The Fellowship of the Ring]{The Lord Of the Rings}

\printmoduleinfo

\module{The Lord Of the Rings}

\printmoduleinfo

\fbox{\textcolor{blue}{And now again with the xparse stuff}}

\Module[The two Towers]{The Lord Of the Rings}

\printmoduleinfo

\Module{The Lord Of the Rings}

\printmoduleinfo

\end{document}


• You should group that large – Johannes_B May 9 '15 at 23:30
• @Johannes_B: Principally yes, but it's only a demo command, since there is nothing else known – user31729 May 9 '15 at 23:32
• Sure, still, should be grouped. The fiont will else be large, or fett or whatever for the rest of the doc. Though not really necessarry for the example, it's a bit of best-practice. – Johannes_B May 9 '15 at 23:38
• @Johannes_B: And I don't care :-P – user31729 May 9 '15 at 23:39
• @ChristianHupfer you answered one of my questions the other day, too! I found the xparse part a little hard to follow but I'll look in to using that package for future endeavours. Thank you! – Harry Smith May 9 '15 at 23:46

The right solution is

0)

\def\module[#1]#2{\gdef\mod@no{#1}\gdef\mod@title{#2}}


This defines \module macro for the usage \module[num]{text}. This macro defines \mod@no as num and \mod@title as text. It means that you can use later \mod@no which expands to num and \mod@title which expands to text. This is exactly, what you need.

1)

\def\module[#1]#2{\gdef\@module[#1]{#2}}
\def\@module{}


After \module[num]{text} the macro \@module is defined with mandatory argument [num] (i.e. if you type something different from exactly \@module[num] then TeX will print an error). This very curious macro expands to the text. The setting \@module to empty macro via \def at line two is redundant.

2)

\def\module{\@ifnextchar[{\@module@wno}{\@module@wono}}
\newcommand{\@module}{}
\def\@module[#1]#2{#1: #2}
\def\@module#1{#1}


This is overcomplicated and bad. This defines \module as macro which looks to the next token. If it is [ then \@module@wno is executed else \@module@wono is executed. But these macros are not defined. Next, the \@module macro is defined as empty (the same as \def\@module{}). Next, this macro \@module is redefined as macro with one parameter in [...] and second in {}, The \@module[num]{text} expands to num: text. Finally, the \@module macro is redefined again, now with one parameter in {}, the \@module{text} expands to text. Why there are three definitions of the same macro? Only the last win. Why there are not defined the \@module@wno, \@module@wono macros?

3)

\newcommand{\module}[2][no module number]{%
\def\@module@no[#1]#2{#1}
\def\@module#1{#1}
\newcommand\@module@no[#1]#2{#1: #2}
\newcommand\@module#1{#1}



I tried to look at your code by TeX's eyes in order to show that all these codes are absurd. I recommend you to study how \def and macros in TeX behave. After such study, you will find out that the accepted solution is overcomplicated too.

• Did you notice, that I used \NewDocumentCommand as well to shorten the syntax? – user31729 May 10 '15 at 15:36
• It seems that your thorough and useful explanations will be just as thorough and useful if you leave only the facts, and delete the editorial references to things being bad and absurd. @HarrySmith clearly put genuine effort into the demonstrated solutions; what's the point of shaming him for mistakes? – LSpice May 11 '15 at 19:50
• @LSpice I don't shame him for mistakes because he know that there are mistakes (see the text: "As you can see I have very little idea what I'm doing, so if you could provide a simple explanation..."). I only provided the simple explanation as mentioned in the question. – wipet May 11 '15 at 20:23

It's very easy, with xparse, to define a command that prints what you want:

\usepackage{xparse}

\NewDocumentCommand{\module}{om}{%
{\Large\IfValueT{#1}{#1: }#2\par}%
}


The {#1: } part is printed if you call \module[PH588]{Mathematical Techniques}, but not with the call \module{Mathematical Techniques}

If you need the optional module number and the module title in other places, then you can follow the same pattern:

\usepackage{xparse}
\makeatletter
\newcommand{\@module@no}{} % initialize
\newcommand{\@module}{} % initialize

\NewDocumentCommand{\module}{om}{%
\IfValueTF{#1}
{% there is a module number
\renewcommand{\@module@no}{#1}%
}
{% there is no module number
\renewcommand{\@module@no}{}%
}%
\renewcommand{\@module}{#2}%
% print the module title
{\Large\IfValueT{#1}{#1: }#2\par}%
}
\makeatother


You'll be able to discriminate between the module number being currently available with an emptyness test such as

\if\relax\detokenize\expandafter{\@module@no}\relax
<code for no module number>%
\else
<code for available module number>%
\fi

• I suppose, it should read \IfValueTF in your first code snippet? – user31729 May 10 '15 at 16:20
• @ChristianHupfer No, why? If no optional argument is given, \IfValueT returns false and does nothing. – egreg May 10 '15 at 16:33
• Apparently I have missed that there is \IfValueT either – user31729 May 10 '15 at 16:45