-1

A few moments ago I was struggling with the problem of doing calculations inside a tex file. I wanted a value to be given and the the \vspace function to take that value as its parameter after a few math. What I wanted to do was to obtain, for a given value x

\vspace{(x-1)0.6 cm}

I showed my broken code and it was fixed in following way

\documentclass[]{paper}
\usepackage{calc}

\makeatletter
\newcommand{\titlelines}[1]{\def\@TitleLines{#1}}
\titlelines{1}
\newlength{\mylength}
\setlength{\mylength}{(\@TitleLines cm-1cm)*\real{0.6}}
\makeatother


\title{text \\ \vspace*{\mylength} more text}

\begin{document}
\maketitle
\end{document}

When I compile this code it works perfectly. Now, however, I would like to put it inside a .cls file I'm working on for my supervisor. Inside the .cls file I have this piece of code, which also works perfectly

\title{
\begin{center}
\fontsize{\@TitleSize}{\@TitleSpacing}
\usefont{T1}{\@TitleFont}{b}{n}
\color{\@TitleColor}
\selectfont
\shadowtext{\begin{tabular}{c}\@TheTitle\end{tabular}}
\vspace*{0.6cm}
\\
\end{center}
\@Abs
}

\renewcommand{\title}[1]{\def\@TheTitle{#1}}

Here \@TitleStuff are just font customisations for the title. \@Abs is the abstract. The \vspace function inside \title{...} is the one I'm trying to deal with. When I insert the piece of code

\makeatletter
\newcommand{\titlelines}[1]{\def\@TitleLines{#1}}
\newlength{\mylength}
\setlength{\mylength}{(\@TitleLines cm-1cm)*\real{0.6}}
\makeatother

before the \title{} bit and then substitute \vspace*{0.6cm} for \vspace*{\mylength}, the .tex file compiled with this class gives me an error. It says \@TitleLines was not defined. Do you know what could be giving this error? I know its not practical do post the whole .cls file but if you have a guess on what is wrong I would thank you very much.

  • 1
    Omit \makeatletter and \makeatother when copying the code to the .cls file and try again… ;-) – GuM Dec 9 '16 at 2:12
  • The problem is that you don't have \titlelines{1} or something similar in your .cls file which defines \@TitleLines. If you don't use this before (re)calculating the length, your command will be undefined and, hence, the length setting fails. – siracusa Dec 9 '16 at 2:16
  • I omitted \makeletter and \makeatother and it did not work. @Siracusa... I don't understand. Isn't the line \newcommand{\titlelines}[1]{\def\@TitleLines{#1}} already defining \@TitleLines? When I write before everything \def\@TitleLines{0.6}, for example, it works but then the function \titlelines, which goes inside the .tex file, don't have any effect. – Gabu Dec 9 '16 at 2:29
  • For sure, \makeatletter and (especially) \makeatother do not belong there, and the .cls file cannot work if you include them. In the second place, you must execute \titlelines before using the value of \@TitleLines. – GuM Dec 9 '16 at 2:45
  • In the .txt file I call \titlelines before \title. In the .cls file \titlelines and \@TitleLines are connected through the definition of \titlelines: \newcommand{\titlelines}[1]{\def\@TitleLines{#1}}. Is this what you're talking about? – Gabu Dec 9 '16 at 2:55
1

Have a look, what the class code above does:

\newcommand{\titlelines}[1]{\def\@TitleLines{#1}}

\titlelines is defined. Each usage of \titlelines will (re)define \@TitleLines.

\newlength{\mylength}

New length \mylength is defined.

\setlength{\mylength}{(\@TitleLines cm-1cm)*\real{0.6}}

\@TitleLines is used to calculate and set the value of \mylength. But at this time, \titlelines have not been used, so \@TitleLines is still undefined. And that is also the main difference to the first code. There you have had

\titlelines{1}

before the calculation. This usage of \titlelines has defined \@TitleLines.

So, the problem with the class code above is, that \mylength is not (re)calculated just after defining \@TitleLines but just after defining \titlelines, before calling \titlelines and therefore without defined \@TitleLines. You can solve this by defining a default for \@TitleLines before the first usage and (re)calculating \mylength either just after each redefinition of \@TitleLines or before each usage of \@TitleLines. So you can either do:

\newcommand{\titlelines}[1]{\def\@TitleLines{#1}}
\newlength{\mylength}
\newcommand*{\@TitleLines}{1}
\newcommand*{\title}{%
  \setlength{\mylength}{(\@TitleLines cm-1cm)*\real{0.6}}%
  …
  \vspace{\mylength}%
  …
}

or

\newlength{\mylength}
\newcommand{\titlelines}[1]{%
  \def\@TitleLines{#1}%
  \setlength{\mylength}{(\@TitleLines cm-1cm)*\real{0.6}}%
}
\newcommand*{\@TitleLines}{1}

But I would suggest to simply eliminate the macro and replace the auxiliary length \mylength by length \@TitleLines:

\newlength{\@TitleLines}
\newcommand*{\titlelines}[1]{%
  \setlength{\@TitleLines}{0.6cm*(#1-1)}%
}

So you can again use \vspace{\@TitleLines} instead of \vspace{\mylength}. If you add \dimexpr to the calculation, you even don't need package calc:

\newlength{\@TitleLines}
\newcommand*{\titlelines}[1]{%
  \setlength{\@TitleLines}{\dimexpr 0.6cm*(#1-1)\relax}%
}

Alternatively you could still use a macro \@TitleLines and move the usage of \dimexpr to the usage of \vspace:

\newcommand*{\@TitleLines}{1}
\newcommand*{\titlelines}[1]{\renewcommand*{\@TitleLines}{#1}}
\newcommand*{\title}{%
   …
   \vspace{\dimexpr 0.6cm*(\@TitleLines-1)\relax}
   …
}

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.