How to write a class that accepts an optional key-value pair?
Here is a small example using scrbase:
\begin{filecontents}{preview.cls}
\ProvidesClass{preview}[2012/12/15 v 0.01 class for creating a tight PSTricks
diagram]
\RequirePackage{scrbase}
\DefineFamily{preview}
\DefineFamilyMember{preview}
\DefineFamilyKey{preview}{PreviewBorder}[0pt]{%
\if@atdocument% before or after \begin{document}?
\expandafter\@firstofone% after \begin{document} do it just now
\else
\expandafter\AtEndOfClass% \PreviewBorder first defined after loading
% preview package!
\fi{\setlength{\PreviewBorder}{#1}}%
}
\DeclareOption*{\PassOptionsToClass{\CurrentOption}{article}}
\FamilyProcessOptions{preview}
\LoadClass{article}
\RequirePackage{pstricks}
\RequirePackage[tightpage,active]{preview}
\PreviewEnvironment{pspicture}
\endinput
\end{filecontents}
\documentclass[PreviewBorder=12pt,twoside]{preview}
\begin{document}
\begin{pspicture}[showgrid=true](-2,-2)(2,2)
\end{pspicture}
And you may even change the value inside the document:
\FamilyOptions{preview}{PreviewBorder=5cm}
\begin{pspicture}[showgrid=true](-2,-2)(2,2)
\end{pspicture}
\end{document}
I've done so, because you may find a lot of information about using all the other packages, but seldom something about using scrbase
.
You need to differential between an initial value (set even if the key is never used) and a default value (used if the key is given with no value). In your example you seem to want an initial value rather than a default. There are several packages which can do what you want: I'd probably use kvoptions
for this relatively simple case.
\begin{filecontents}{preview.cls}
\ProvidesClass{preview}[2012/12/15 v 0.01 class for creating a tight PSTricks
diagram]
\RequirePackage{kvoptions}
\DeclareStringOption[0 pt]{PreviewBorder}
\ProcessKeyvalOptions*
\LoadClass{article}
\RequirePackage{pstricks}
\RequirePackage[tightpage,active]{preview}
\PreviewEnvironment{pspicture}
\AtEndOfClass{\setlength{\PreviewBorder}{\preview@PreviewBorder}}
%\AtEndOfClass{\showthe\PreviewBorder}
\end{filecontents}
\documentclass{preview}%default value 0pt does not work!
%\documentclass[PreviewBorder=0pt]{preview}% works as expected.
\begin{document}
\begin{pspicture}(-2,-2)(2,2)
\psframe[linecolor=red](-2,-2)(2,2)
\end{pspicture}
\end{document}
You'll see that I've only set the length once: there does not seem to be a need to set it otherwise.
I don't know where you are using your \PreviewBorder length, but here is what I would do.
\RequirePackage{xkeyval}
\newlength{\preview@border}
\setlength{\preview@border}{0pt}
\DeclareOptionX{PreviewBorder}[0pt]{\setlength{\preview@border}{#1}
\ProcessOptionsX
Use the length \preview@border in your code later.
Note that the default value is set in the \setlength
macro. The [0pt]
used in the option declaration is just the value to give if the user specifies the key with no value.
\usepackage{preview}
results in a border of 0pt.\usepackage[PreviewBorder]{preview}
results in a border of 0pt.\usepackage[PreviewBorder=10pt]{preview}
results in a border of 10pt.
Edit. Here is the working example. Thanks for the correction. The class:
\ProvidesClass{p}
\LoadClass{article}
\RequirePackage{xkeyval}
\newlength{\preview@border}
\setlength{\preview@border}{0pt}
\DeclareOptionX{PreviewBorder}[0pt]{\setlength{\preview@border}{#1}}
\ProcessOptionsX
\def\myborder{\the\preview@border}
now, use the class 'p' The LaTeX file:
\documentclass[PreviewBorder=10pt]{p}
\begin{document}
The border is \myborder
\end{document}