Take the 2-minute tour ×
TeX - LaTeX Stack Exchange is a question and answer site for users of TeX, LaTeX, ConTeXt, and related typesetting systems. It's 100% free, no registration required.

I'm designing a new LaTeX class, and trying to write a convenient helper command for declaring new 'variables' for use in the class.

Specifically, say I want to use a variable called \foo. I'd like an author to be able to write \foo{bar}, and then be able to use \@foo in the class file (which would itself expand to bar. This can be accomplished with the following code:

\let\@foo\relax
\def\foo#1{\def\@foo{#1}}

and the author can define it with \foo{bar}. I want to create a helper command that allows the variable declaration to be done with a command like \DeclareAuthorVariable, which I would use in the LaTeX class file to declare variables. For example, I would like to be able to write \DeclareAuthorVariable{foo} in the class file instead of the ugly two line mess above. I've tried a number of different approaches, but I'm having trouble figuring out how to do this, since the commands that I'm trying to replace themselves involve arguments. I'm wondering if anyone knows how to do this or if it isn't possible? Thanks!

(Also, apologies, I'm very new to LaTeX class design!)

share|improve this question

3 Answers 3

up vote 15 down vote accepted

I'd add also some functions. You can declare a variable to be mandatory or optional; for instance title might be mandatory, while subtitle only optional. I propose the syntax

\DeclareAuthorVariable*{title}   % mandatory
\DeclareAuthorVariable{subtitle} % optional

Here is the code. Change the ting prefix to what suits you best.

% Do the branching between * and normal version
\newcommand{\DeclareAuthorVariable}{%
  \@ifstar{\ting@DeclareAuthorVariable{\ting@mandatory@var}}
          {\ting@DeclareAuthorVariable{\ting@optional@var}}%
}

% The main command; the internal version of \foo is \ting@foo
% The macro \ting@foo is initialized to give an error or an info
% message when used, so if the user doesn't provide a value for a
% mandatory variable, we'll catch the issue
\newcommand{\ting@DeclareAuthorVariable}[2]{%
  \@namedef{ting@#2}{#1{#2}}%
  \@namedef{#2}##1{\@namedef{ting@#2}{##1}}%
}
% The error and info messages
\newcommand{\ting@mandatory@var}[1]{%
  \ClassError{ting}
    {Missing value for mandatory variable
     \expandafter\string\csname#1\endcsname}
    {You have to provide a value with
     \expandafter\string\csname#1\endcsname{...}}%
}
\newcommand{\ting@optional@var}[1]{%
  \ClassInfo{ting}
    {Missing value for optional variable
     \expandafter\string\csname#1\endcsname}%
}

%%% Define two variables
\DeclareAuthorVariable*{title}
\DeclareAuthorVariable{subtitle}

If you need to branch according to a variable having been given a value or not, you can modify \ting@DeclareAuthorVariable:

\newcommand{\ting@DeclareAuthorVariable}[2]{%
  \@namedef{ting@#2}{#1{#2}}%
  \@namedef{#2}##1{\@namedef{ting@#2}{##1}\@namedef{ting@#2@defined}{}}%
}

and add

\newcommand{\@ifauthorvariable}[3]{\@ifundefined{ting@#1@defined}{#3}{#2}}

so that you can say something like

\@ifauthorvariable{subtitle}
  {\vspace{3ex}\textsc{\ting@subtitle}\par\vspace{3ex}}
  {\vspace{1ex}---\par\vspace{1ex}}

(Here I assume that the title page will be set under \centering; the subtitle or, if missing, a dash would be printed.)

share|improve this answer
2  
Wow, thanks so much! This is not only an excellent answer in its own right, but provides great insight into the correct stylistic and robustness concerns in package design. –  Michael Tingley Jan 15 '13 at 14:12
    
One question though, why do you end the intermediate lines in your functions with %? –  Michael Tingley Jan 15 '13 at 14:21
    
@MichaelTingley Most of these % are irrelevant here; but it's a good habit to put them where a space might creep in. You don't need them between arguments to a macro, but only at the end. So no % is needed after \ClassInfo{ting} because TeX will be looking for the next argument to \ClassInfo, so skipping spaces; after the second argument to \ClassInfo it's good to have one. –  egreg Jan 15 '13 at 14:24
    
Any advice for how to check if one of these optional variables is defined? Thanks –  Michael Tingley Jan 16 '13 at 13:23
    
@MichaelTingley Are you meaning a check that \DefineAuthorVariable{foo} doesn't redefine an existing \foo macro? –  egreg Jan 16 '13 at 15:37
\makeatletter
\def\DeclareAuthorVariable#1{\@namedef{#1}##1{\@namedef{@#1}{##1}}}

\DeclareAuthorVariable{foo}

\show\foo

\foo{abc}

\show\@foo

\stop

Produces

> \foo=macro:
#1->\@namedef {@foo}{#1}.
l.7 \show\foo

? 
> \@foo=macro:
->abc.
l.11 \show\@foo

? 
 )
No pages of output.
share|improve this answer

You may want to study the KOMA-classes and their macro \newkomavar.

share|improve this answer
1  
\newkomavar is only available in the scrlttr2 class –  cgnieder Jul 19 '13 at 14:08

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.