3

I want to simplify a cls file and hope you will give me some pointers.

How I arrived at this point

Years ago I found several thesis cls files from various places and adjusted them into a template our students could use. One of the templates used a style of coding that seems verbose to me now and I'm trying to adjust and simplify the class file without causing the authors to have to alter their preambles.

I cannot use xparse for this, the user interface has to stay the way it is.

What we have now works, it just seems cumbersome to me.

The author may insert up to 5 previous degrees in the title page. We have the author write in the preamble

\priorcreds{BA, 1999}{MA, 2004}{MS, 2004}{}{}

The empty {} are needed because the cls file is rigid. It requires input for 5 possible previous degrees. That's required because the cls file has this piece that converts each input into one of 5 variables

\def\@priorcreda{\@latex@warning{No prior credential information given}}
\def\priorcreds#1#2#3#4#5{
\renewcommand\@priorcreda{#1}
\newcommand\@priorcredb{#2}
\newcommand\@priorcredc{#3}
\newcommand\@priorcredd{#4}
\newcommand\@priorcrede{#5}
}

And then a new command that finds those named variables weaves them together

\newcommand\@priorcredsshow{
\begin{center}
\ifx\@priorcreda\@empty
\relax
\else
\vskip 0.25em
{\small \@priorcreda} \par
\fi% 
\ifx\@priorcredb\@empty
\relax
\else
\vskip 0.25em
{\small \@priorcredb} \par
\fi% 
\ifx\@priorcredc\@empty
\relax
\else
\vskip 0.25em
{\small \@priorcredc} \par
\fi% 
\ifx\@priorcredd\@empty
\relax
\else
\vskip 0.25em
{\small \@priorcredd} \par
\fi% 
\ifx\@priorcrede\@empty
\relax
\else
\vskip 0.25em
{\small \@priorcrede} \par
\fi% 
\end{center}
}

And then inside the \renewcommand{\maketitle} part, the priorcreds are pulled into the title page

{{\small \@priorcredsshow} \par}

This seems tedious that the users have to fill in the empty arguments {}
and editing the cls file is tedious with all of this cut and pasted code.

\@ifnextchar based alternative

I've looked around for alternatives and found one reasonable idea. This post Commands that may take a variable number of arguments demonstrating \@ifnextchar to handle user input piqued my curiosity. I made an mre that works where the \@ifnextchar magic is in the preamble and the macro call is in the document.

\documentclass{article}

\makeatletter
\newcommand{\showpriorcreds}[1]{%
 \vskip 0.24em%
{\begin{center}\small{}#1\par\end{center}}\checknextarg}
\newcommand{\checknextarg} {\@ifnextchar\bgroup{\gobblenextarg}{}}
\newcommand{\gobblenextarg}[1]{
\vskip 0.24em
{\begin{center}\small{}#1\par\end{center}}\@ifnextchar\bgroup{\gobblenextarg}{}}%


\begin{document}

Here's an example of showpriorcreds
\showpriorcreds{BA}{BS}{ABC}{PhD}

That was the previous example

\showpriorcreds{MD}{ABD}{DPHIL}{ACC}

\end{document}

The output is what I want. It is flexible so that if author puts in just 1 argument, or 5, it fills in the values. usage of \@ifnextchar

Can you help me make that into a cls file?

Now I wonder the following. Can I put a similar function into a cls file? I'm wading through guides and I'm not understanding some basic things. I want this to turn out so that in the PREAMBLE the user inserts

\priorcreds{MD}{ABD}{DPHIL}{ACC}

and then the cls file puts that information into a title page setup. This should work the way \@author or \@title are used in standard class files, the difference in this case is that the argument coming in is a series of values.

There are several pieces in this I don't understand, my minimal class file doesn't even give a reasonable document. I cannot understand how is the information from the user preamble {MD}{ABD}{DPHIL}{ACC} passed into the class structure, so that the \priorcredshow function can be used in the middle of a title page.

My second mre to use the cls file is

\documentclass{kuexample}

\makeatletter
\author{Paul J}
\title{Monstrously Awesome}
\priorcreds{BA}{BS}{ABC}{PhD}

\begin{document}

This is the document body
% it compiles if I put call in body of document
% but i never get title page
%%\priorcreds{BA}{BS}{ABC}{PhD}
\end{document}

And my small class file which is obviously wrong

% kuexample

%-------------------------- identification ---------------------
\NeedsTeXFormat{LaTeX2e}
\ProvidesClass{kuexample}[2018/03/29 kuexample]
%-------------------------- initial code -----------------------
\DeclareOption*{\PassOptionsToClass{\CurrentOption}{report}}
\ProcessOptions\relax
\LoadClass[letterpaper]{report}
% As an alternative to the above could use next line for twosided output
%\LoadClass[letterpaper,twoside,openright]{report}

\raggedbottom

%% PACKAGE REQUIREMENTS %%

%% Required to set margins
\RequirePackage{geometry}

%
% DECLARATIONS

%%priorcreds adaptation 20180328
\newcommand{\priorcreds}[1]{%
\vskip 0.24em%
{\begin{center}\small{}#1\par\end{center}}\checknextarg}
\newcommand{\checknextarg} {\@ifnextchar\bgroup{\gobblenextarg}{}}
\newcommand{\gobblenextarg}[1]{%
\vskip 0.24em%
{\begin{center}\small{}#1\par\end{center}}\@ifnextchar\bgroup{\gobblenextarg}{}}


\newcommand\@priorcredshow{
  \@priorcreds
}

% Define text area of page and margin offsets
%
\setlength{\topmargin}{0.0in}
\setlength{\oddsidemargin}{0.33in}
\setlength{\evensidemargin}{-0.08in}
\setlength{\textheight}{9.0in}
\setlength{\textwidth}{6.0in}

%
% Environments
%

% This macro defines an environment for front matter that is always 
% single column even in a double-column document.

\newenvironment{alwayssingle}{%
       \@restonecolfalse
       \if@twocolumn\@restonecoltrue\onecolumn
       \else\if@openright\cleardoublepage\else\clearpage\fi
       \fi}%
       {\if@restonecol\twocolumn
       \else\newpage\thispagestyle{empty}\fi}

%define title page layout
\renewcommand{\maketitle} {%
\begin{alwayssingle}
  \begin{singlespace} 
    \renewcommand{\footnotesize}{\small}
    \renewcommand{\footnoterule}{\relax}
    \thispagestyle{empty}
  \null\vfill
  \begin{center}
    {\Large {\bfseries {\@title}} \par}
  \vskip 1.5em%
    {{\Large \@author} \par}
  \vskip 0.5em%
     {\@priorcredshow}
\vfill

  \setcounter{footnote}{0}%
  \global\let\thanks\relax
  \global\let\maketitle\relax
  \global\let\@maketitle\relax
  \global\let\@author\@empty
  \global\let\@date\@empty
  \global\let\@title\@empty
  \global\let\title\relax
  \global\let\author\relax
  \global\let\date\relax
  \global\let\and\relax
\end{singlespace}
\end{alwayssingle}}
  • (1) Why can't you use xparse? Why should the need to keep the user interface stable stop you implementing it differently? (2) You are obviously changing the user interface, but want backwards compatibility. See (1). So, why can't you use xparse? – cfr Mar 30 '18 at 1:15
1

The interface is very awkward. What if the number of prior credentials is more than five?

However, you can do it with \@ifnextchar.

kuexample.cls

\NeedsTeXFormat{LaTeX2e}
\ProvidesClass{kuexample}[2018/03/29 kuexample]
%-------------------------- initial code -----------------------
\DeclareOption*{\PassOptionsToClass{\CurrentOption}{report}}
\ProcessOptions\relax
\LoadClass[letterpaper]{report}
% As an alternative to the above could use next line for twosided output
%\LoadClass[letterpaper,twoside,openright]{report}

\RequirePackage{setspace}

\raggedbottom

%% PACKAGE REQUIREMENTS %%

%% Required to set margins
\RequirePackage{geometry}

%
% DECLARATIONS

%%priorcreds adaptation 20180328
\def\@priorcreda{\@latex@warning{No prior credential information given}}
\def\@priorcreds@list{} % initialize
\def\priorcreds#{\@priorcreds} % the trailing # requires \priorcreds to be followed by {
\def\@priorcreds#1{\def\@priorcreda{{#1}}\@priorcreds@go}
\def\@priorcreds@go{\@ifnextchar\bgroup{\@priorcreds@add}{}}
\def\@priorcreds@add#1{%
  \ifx\@priorcreds@list\@empty
    \g@addto@macro\@priorcreds@list{{#1}}%
  \else
    \g@addto@macro\@priorcreds@list{,{#1}}%
  \fi
  \@priorcreds@go
}


\newcommand\@priorcredshow{%
  \par{\small
  \@priorcreda % this always exists
  \@for\next:=\@priorcreds@list\do{%
    \par\vspace{0.24em}%
    \next
  \par}}%
  \end{center}
}

% Define text area of page and margin offsets
%
\setlength{\topmargin}{0.0in}
\setlength{\oddsidemargin}{0.33in}
\setlength{\evensidemargin}{-0.08in}
\setlength{\textheight}{9.0in}
\setlength{\textwidth}{6.0in}

%
% Environments
%

% This macro defines an environment for front matter that is always 
% single column even in a double-column document.

\newenvironment{alwayssingle}{%
       \@restonecolfalse
       \if@twocolumn\@restonecoltrue\onecolumn
       \else\if@openright\cleardoublepage\else\clearpage\fi
       \fi}%
       {\if@restonecol\twocolumn
       \else\newpage\thispagestyle{empty}\fi}

%define title page layout
\renewcommand{\maketitle} {%
\begin{alwayssingle}
  \begin{singlespace} 
    \renewcommand{\footnotesize}{\small}
    \renewcommand{\footnoterule}{\relax}
    \thispagestyle{empty}
  \null\vfill
  \begin{center}
    {\Large {\bfseries {\@title}} \par}
  \vskip 1.5em
    {{\Large \@author} \par}
  \vskip 0.5em
     \@priorcredshow
\vfill

  \setcounter{footnote}{0}%
  \global\let\thanks\relax
  \global\let\maketitle\relax
  \global\let\@maketitle\relax
  \global\let\@author\@empty
  \global\let\@date\@empty
  \global\let\@title\@empty
  \global\let\title\relax
  \global\let\author\relax
  \global\let\date\relax
  \global\let\and\relax
\end{singlespace}
\end{alwayssingle}}

kuexample.tex

\documentclass{kuexample}

\begin{document}

\title{Test}
\author{Me}
\priorcreds{MD, 1920}{ABD, 2001}{DPHIL}{ACC}{X}{Y}{Z}{AAA}{BBB}

\maketitle

\end{document}

Output

enter image description here

Comment

A syntax such as

\priorcreds{{A}{B}{C}{D}}

or

\priorcreds{A|B|C|D}

would be more friendly.

  • Thanks. This helps me see where I was getting the cls file wrong. – pauljohn32 Mar 31 '18 at 16:16
3

You can use xparse. This need only affect how you implement the user interface: it need not break backwards-compatibility.

The problem with your current code is that using the command in the preamble tries to immediately typeset stuff, when the document hasn't yet begun. In addition, your class fails to load setspace (or otherwise define singlespace) and the definition of \maketitle fails to end the center environment.

Moreover, your document lacks \maketitle, so the title page is never typeset as you never ask LaTeX to typeset it.

Here's a version which enables the syntax you want, maintains backwards compatibility and compiles without error.

\begin{filecontents}{kuexample.cls}
\NeedsTeXFormat{LaTeX2e}
\ProvidesClass{kuexample}[2018/03/29 kuexample]
%-------------------------- initial code -----------------------
\DeclareOption*{\PassOptionsToClass{\CurrentOption}{report}}
\ProcessOptions\relax
\LoadClass[letterpaper]{report}
% As an alternative to the above could use next line for twosided output
%\LoadClass[letterpaper,twoside,openright]{report}

\raggedbottom

%% PACKAGE REQUIREMENTS %%

%% Required to set margins
\RequirePackage{geometry,setspace,xparse}

%
% DECLARATIONS

%%priorcreds adaptation 20180328
\newcommand\@showpriorcreds{}
\NewDocumentCommand\priorcreds {mgggg}{%
  \renewcommand\@showpriorcreds{%
    \gobblenextarg{#1}%
    \IfValueT{#2}{\gobblenextarg{#2}}%
    \IfValueT{#3}{\gobblenextarg{#3}}%
    \IfValueT{#4}{\gobblenextarg{#4}}%
    \IfValueT{#5}{\gobblenextarg{#5}}%
  }}
\newcommand{\gobblenextarg}[1]{%
  \vskip 0.24em%
  \begin{center}\small#1\par\end{center}%
}


% Define text area of page and margin offsets
%
\setlength{\topmargin}{0.0in}
\setlength{\oddsidemargin}{0.33in}
\setlength{\evensidemargin}{-0.08in}
\setlength{\textheight}{9.0in}
\setlength{\textwidth}{6.0in}

%
% Environments
%

% This macro defines an environment for front matter that is always 
% single column even in a double-column document.

\newenvironment{alwayssingle}{%
  \@restonecolfalse
  \if@twocolumn\@restonecoltrue\onecolumn
  \else\if@openright\cleardoublepage\else\clearpage\fi
  \fi
}{%
  \if@restonecol\twocolumn
  \else\newpage\thispagestyle{empty}\fi
}

%define title page layout
\renewcommand{\maketitle} {%
  \begin{alwayssingle}
    \begin{singlespace} 
      \renewcommand{\footnotesize}{\small}
      \renewcommand{\footnoterule}{\relax}
      \thispagestyle{empty}
      \null\vfill
      \begin{center}
        {\Large\bfseries\@title\par}
        \vskip 1.5em%
        {\Large\@author}\par
        \vskip 0.5em%
        \@showpriorcreds
        \vfill

        \setcounter{footnote}{0}%
        \global\let\thanks\relax
        \global\let\maketitle\relax
        \global\let\@maketitle\relax
        \global\let\@author\@empty
        \global\let\@date\@empty
        \global\let\@title\@empty
        \global\let\title\relax
        \global\let\author\relax
        \global\let\date\relax
        \global\let\and\relax
      \end{center}
    \end{singlespace}
  \end{alwayssingle}}
\endinput
\end{filecontents}
\documentclass{kuexample}

\makeatletter
\author{Paul J}
\title{Monstrously Awesome}
\priorcreds{BA}{BS}{ABC}{PhD}

\begin{document}
\maketitle

This is the document body

\end{document}

degree-laden Paul J tries for a fifth

  • +1 Thanks very much for answering. I stand corrected on xparse. The answer that @egreg suggested is a little more flexible, no upper limit on number of credentials. – pauljohn32 Mar 31 '18 at 16:16

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.