% \iffalse meta-comment % keycommand : an easy way to define commands with optional keys |v2.z 2009/08/26] % % This work may be distributed and/or modified under the % conditions of the LaTeX Project Public License, either % version 1.3 of this license or (at your option) any later % version. The latest version of this license is in % http://www.latex-project.org/lppl.txt % % This work consists of the main source file keycommand.dtx % and the derived files % keycommand.sty, keycommand.pdf, keycommand.ins, % keycommand-example.tex % % Unpacking: % (a) If keycommand.ins is present: % etex keycommand.ins % (b) Without keycommand.ins: % etex keycommand.dtx % (c) If you insist on using LaTeX % latex \let\install=y\input{keycommand.dtx} % (quote the arguments according to the demands of your shell) % % Documentation: % (pdf)latex keycommand.dtx % Copyright (C) 2009 by Florent Chervet %<*ignore> \begingroup \def\x{LaTeX2e}% \expandafter\endgroup \ifcase 0\ifx\install y1\fi\expandafter \ifx\csname processbatchFile\endcsname\relax\else1\fi \ifx\fmtname\x\else 1\fi\relax \else\csname fi\endcsname % %<*install> \input docstrip.tex \Msg{************************************************************************} \Msg{* Installation} \Msg{* Package: keycommand 2009/07/22 v1.0 an easy way to define commands with optional keys} \Msg{************************************************************************} \keepsilent \askforoverwritefalse \let\MetaPrefix\relax \preamble This is a generated file. keycommand : an easy way to define commands with optional keys [v2.z 2009/08/26] This work may be distributed and/or modified under the conditions of the LaTeX Project Public License, either version 1.3 of this license or (at your option) any later version. The latest version of this license is in http://www.latex-project.org/lppl.txt This work consists of the main source file keycommand.dtx and the derived files keycommand.sty, keycommand.pdf, keycommand.ins, keycommand-example.tex keycommand : an easy way to define commands with optional keys Copyright (C) 2009 by Florent Chervet \endpreamble \let\MetaPrefix\DoubleperCent \generate{% \file{keycommand.ins}{\from{keycommand.dtx}{install}}% \file{keycommand.sty}{\from{keycommand.dtx}{package}}% \file{keycommand-example.tex}{\from{keycommand.dtx}{example}}% } \obeyspaces \Msg{************************************************************************} \Msg{*} \Msg{* To finish the installation you have to move the following} \Msg{* file into a directory searched by TeX:} \Msg{*} \Msg{* keycommand.sty} \Msg{*} \Msg{* To produce the documentation run the file `keycommand.dtx'} \Msg{* through LaTeX.} \Msg{*} \Msg{* Happy TeXing!} \Msg{*} \Msg{************************************************************************} \endbatchfile % %<*ignore> \fi % %<*driver> \edef\thisfile{\jobname} \def\thisinfo{an easy way to define commands with optional keys.} \def\thisdate{2009/08/26} \def\thisversion{2.$\zeta$} \let\loadclass\LoadClass \def\LoadClass#1{\loadclass[abstracton]{scrartcl}\let\scrmaketitle\maketitle\AtEndOfClass{\let\maketitle\scrmaketitle}} \documentclass[a4paper,oneside]{ltxdoc} \usepackage[latin9]{inputenc} \usepackage[american]{babel} \usepackage{etex,holtxdoc,geometry,tocloft,fancyhdr,color,bbding,embedfile,framed,multirow,txfonts}\CodelineNumbered \lastlinefit999 \geometry{top=2cm,headheight=1cm,headsep=.3cm,bottom=1.4cm,footskip=.5cm,left=4cm,right=2cm} \hypersetup{% pdftitle={The keycommand package}, pdfsubject={An e-TeX package for more useful tools for LaTeX package writers}, pdfauthor={Florent CHERVET}, colorlinks,linkcolor=reflink, pdfstartview={FitH}, pdfkeywords={tex, e-tex, latex, package, keys, keycommand, newcommand, keyval, kvsetkeys, programming}, bookmarksopen=true,bookmarksopenlevel=2} \embedfile{\thisfile.dtx} \begin{document} \DocInput{\thisfile.dtx} \end{document} % % \fi % % \CheckSum{770} % % \CharacterTable % {Upper-case \A\B\C\D\E\F\G\H\I\J\K\L\M\N\O\P\Q\R\S\T\U\V\W\X\Y\Z % Lower-case \a\b\c\d\e\f\g\h\i\j\k\l\m\n\o\p\q\r\s\t\u\v\w\x\y\z % Digits \0\1\2\3\4\5\6\7\8\9 % Exclamation \! Double quote \" Hash (number) \# % Dollar \$ Percent \% Ampersand \& % Acute accent \' Left paren \( Right paren \) % Asterisk \* Plus \+ Comma \, % Minus \- Point \. Solidus \/ % Colon \: Semicolon \; Less than \< % Equals \= Greater than \> Question mark \? % Commercial at \@ Left bracket \[ Backslash \\ % Right bracket \] Circumflex \^ Underscore \_ % Grave accent \` Left brace \{ Vertical bar \| % Right brace \} Tilde \~} % % \DoNotIndex{\begin,\CodelineIndex,\CodelineNumbered,\def,\DisableCrossrefs} % \DoNotIndex{\DocInput,\documentclass,\EnableCrossrefs,\end,\GetFileInfo} % \DoNotIndex{\NeedsTeXFormat,\OnlyDescription,\RecordChanges,\usepackage} % \DoNotIndex{\ProvidesClass,\ProvidesPackage,\ProvidesFile,\RequirePackage} % \DoNotIndex{\filename,\fileversion,\filedate,\let} % \DoNotIndex{\@listctr,\@nameuse,\csname,\else,\endcsname,\expandafter} % \DoNotIndex{\gdef,\global,\if,\item,\newcommand,\nobibliography} % \DoNotIndex{\par,\providecommand,\relax,\renewcommand,\renewenvironment} % \DoNotIndex{\stepcounter,\usecounter,\nocite,\fi} % \DoNotIndex{\@fileswfalse,\@gobble,\@ifstar,\@unexpandable@protect} % \DoNotIndex{\AtBeginDocument,\AtEndDocument,\begingroup,\endgroup} % \DoNotIndex{\frenchspacing,\MessageBreak,\newif,\PackageWarningNoLine} % \DoNotIndex{\protect,\string,\xdef,\ifx,\texttt,\@biblabel,\bibitem} % \DoNotIndex{\z@,\wd,\wheremsg,\vrule,\voidb@x,\verb,\bibitem} % \DoNotIndex{\FrameCommand,\MakeFramed,\FrameRestore,\hskip,\hfil,\hfill,\hsize,\hspace,\hss,\hbox,\hb@xt@,\endMakeFramed,\escapechar} % \DoNotIndex{\do,\date,\if@tempswa,\@tempdima,\@tempboxa,\@tempswatrue,\@tempswafalse,\ifdefined,\ifhmode,\ifmmode,\cr} % \DoNotIndex{\box,\author,\advance,\multiply,\Command,\outer,\next,\leavevmode,\kern,\title,\toks@,\trcg@where,\tt} % \DoNotIndex{\the,\width,\star,\space,\section,\subsection,\textasteriskcentered,\textwidth} % \DoNotIndex{\",\:,\@empty,\@for,\@gtempa,\@latex@error,\@namedef,\@nameuse,\@tempa,\@testopt,\@width,\\,\m@ne,\makeatletter,\makeatother} % \DoNotIndex{\maketitle,\parindent,\setbox,\x,\kernel@ifnextchar} % \DoNotIndex{\KVS@CommaComma,\KVS@CommaSpace,\KVS@EqualsSpace,\KVS@Equals,\KVS@Global,\KVS@SpaceEquals,\KVS@SpaceComma,\KVS@Comma} % % \makeatletter % \MakeShortVerb{\+} % \catcode`\§\active\def§{\par\nobreak\vskip-\parskip} % \def\thispackage{\xpackage{\thisfile}} % \def\ThisPackage{\Xpackage{\thisfile}} % \def\Xpackage{\@dblarg\X@package} % \def\X@package[#1]#2{% % \xpackage{#2\footnote{\noindent\xpackage{#2}: \href{http://www.ctan.org/tex-archive/macros/latex/contrib/#1}{\nolinkurl{CTAN:macros/latex/contrib/#1}}}}} % % \parindent\z@\parskip.4\baselineskip\topsep\parskip\partopsep\z@ % \g@addto@macro\macro@font{\macrocodecolor\let\AltMacroFont\macro@font} % \def\smex{\leavevmode\hb@xt@2em{\hfil$\longrightarrow$\hfil}} % \def\csred#1{\textcolor{red}{\cs{#1}}} % \def\CSbf#1{\textbf{\CS{#1}}} % \def\csbf#1{\textbf{\cs{#1}}} % % \fancyhf{}\fancyhead[L]{The \thispackage\ package -- \thisinfo} % \fancyfoot[L]{\color[gray]{.35}\scriptsize\thispackage\quad[rev.\thisversion]\quad\copyright\oldstylenums{2009}\,\lower.3ex\hbox{\NibRight}\,Florent Chervet} % \fancyfoot[R]{\oldstylenums{\thepage} / \oldstylenums{\pageref{LastPage}}} % \pagestyle{fancy} % \fancypagestyle{plain}{% % \let\headrulewidth\z@ % \fancyhf{}% % \fancyfoot[R]{\oldstylenums{\thepage} / \oldstylenums{\pageref{LastPage}}}} % % \newcommand\macrocodecolor{\color{macrocode}}\definecolor{macrocode}{rgb}{0.18,0.00,0.45} % \newcommand\reflinkcolor{\color{reflink}}\definecolor{reflink}{rgb}{0.49,0.00,0.00} % % \makeatother % % \deffootnote{1em}{0pt}{\rlap{\textsuperscript{\thefootnotemark}}\kern1em} % \title{\mdseries The{\bfseries\ThisPackage}\kern.6em package} % \author{Florent Chervet {\footnotesize\xemail{florent.chervet@free.fr}}} % \date{\thisdate~--~version \thisversion} % \subtitle{\thisinfo} % % \maketitle % % \makeatletter\begingroup\let\@thefnmark\@empty\let\@makefntext\@firstofone % \footnotetext{\noindent % This documentation is produced with the +DocStrip+ utility. % \begin{tabbing} % \qquad\=\smex\=To get the documentation, \= run (thrice):\quad\= \texttt{pdflatex keycommand.dtx} \\ % \qquad\>\>To get the index, \> run:\>\texttt{makeindex -s gind.ist keycommand.idx} \\ % \>\smex\>To get the package, \> run:\> \texttt{etex keycommand.dtx} % \end{tabbing}§ % The \xext{dtx} file is embedded into this pdf file thank to \xpackage{embedfile} by H. Oberdiek.} % \endgroup\makeatother % % \deffootnote{1em}{0pt}{\rlap{\thefootnotemark.}\kern1em} % % \begin{abstract}\parindent0pt\noindent % % \xpackage{keycommand} provides an easy way to define commands or environments % with optional keys. It provides \cs{newkeycommand} and its relative % \cs{renewkeycommand}, \cs{newkeyenvironment}, \cs{renewkeyenvironment} % and \cs{providekeycommand}. % % Moreover it is possible to define key-commands using +\def+, +\edef+, +\gdef+ or +\xdef+ % via the +\keycmd+ prefix. % % This package requires and is based on the package \xpackage{kvsetkeys} by Heiko Oberdiek. % It is designed to work with \eTeX{} for the code uses the primives +\unexpanded+ and +\protected+. % % \end{abstract} % % \bigskip % \cftbeforesecskip=5pt plus2pt minus4pt % \tableofcontents % % \def\B#1{\texttt{[}\meta{#1}\texttt{]}} % % \section{Introduction} % % \subsection{User interface} % % With \xpackage{keycommand} it becomes very easy to define commands with optional keys. % Just say: % \begin{tabbing} % \qquad\=+\newkeycommand+\=+\CommandWithKeys[kOne=default,+...+][2]{%+\\ % \>\> definition with +\commandkey{kOne}+ etc. +#1+ and +#2}+ % \end{tabbing} % % As far as the keys are optional, it is not allowed to have another optional % parameter in a key-command. % % \goodbreak % \xpackage{keycommand} enables us to define key-environments as well, and provides: % \begin{center}\begin{tabular}{rll} % &+\newkeycommand+ & +\renewkeycommand+ \\ % &+\newkeyenvironment+ & +\renewkeyenvironment+ \\ % and:&+\providekeycommand+ % \end{tabular}\end{center} % % Moreover, if you need (or prefer) the syntax of +\def+ (or |\gdef|, |\edef|, |\xdef|) % you shall refer to the section \nameref{subsec:keycmd} (in \nameref{Implementation}). % % \begin{declcs}{newkeycommand}\,\M{control sequence}\,\B{key-value list}\,\B{number of args}\,\M{definition} % \end{declcs} % % \xpackage{keycommand} allow \LaTeX{} users to define commands with optional keys in a easy way. % Better is a small example than a long talking: let's define a command \cs{Rule} whose % +width+, +thickness+ and +raise+ can be specified as keys. % % With \xpackage{keycommand} we just have to say:§ % \begin{tabbing}\label{Rule} % \,\=+\new+\=+keycommand\Rule[raise=.4ex,width=1em,thick=.4pt][1]{%+\\ % \>\>+\rule[\commandkey{raise}]{\commandkey{width}}{\commandkey{thick}}+\\ % \>\>+#1%+\\ % \>\>+\rule[\commandkey{raise}]{\commandkey{width}}{\commandkey{thick}}}+ % \end{tabbing} % % which defines the keys +width+, +thick+ and +raise+ with their default values (if not specified): % +1em+, +.4pt+ and +.4ex+. Now \cs{Rule} can be used as follow: % \begin{tabbing} % \=1:\quad\=+\Rule[width=2em]{hello}+\hskip2cm\=\smex\,\=+width=2em,thick=.4pt,raise=.4ex+\\ % \>2:\>+\Rule[thick=1pt,width=2em]{hello}+\>\smex\>+width=2em,thick=1pt,raise=.4ex+\\ % \>3:\>+\Rule{hello}+\quad \>\smex\>+width=1em,thick=.4pt,raise=.4ex+\\ % \>4:\>+\Rule[thick=2pt,raise=1ex]{hello}+\>\smex\>+width=1em,thick=2pt,raise=1ex+\\ % \> \textit{et c\ae tera}. % \end{tabbing} % % They will produce: % \begin{tabbing} % \=1:\quad\=\rule[.4ex]{2em}{.4pt}hello\rule[.4ex]{2em}{.4pt}\\ % \>2:\> \rule[.4ex]{2em}{1pt}hello\rule[.4ex]{2em}{1pt}\\ % \>3:\> \rule[.4ex]{1em}{.4pt}hello\rule[.4ex]{1em}{.4pt}\\ % \>4:\> \rule[1ex]{1em}{2pt}hello\rule[1ex]{1em}{2pt} % \end{tabbing} % % \textsc{Nota bene:} it is also possible to give a key a default value which is the value of another key. % For example:§ % \quad |\newkeycommand\CmdKey[alpha=hello, beta=\commandkey{alpha}]{|...|}| % % When called as: |\CmdKey[alpha=world]|, the key |beta| will then have the same value: |world|. % % \begin{declcs}{newkeyenvironment}\,\M{envir name}\,\B{key-values pairs}\,\B{number of args}\,\M{begin}\,\M{end} % \end{declcs} % % In the same way, you may define environments with optional keys as follow:§ % \begin{tabbing} % \qquad\=+\newkeyenvironment+\=+{EnvirWithKeys}[kOne=+default value,...+][n]+\\ % \>\>+{+ commands at begin +EnvirWithKeys }+ \\ % \>\>+{+ commands at end +EnvirWithKeys }+ % \end{tabbing} % % Where $n$ is the number of mandatory other arguments (\emph{ie} without keys), if any. % % A example of a key-environment is left in the file: +keycommand-example.tex+. % % \subsection{Error messages} % % If you use the command +\Rule+ (defined in \ref{Rule}) with a key say: +height+ % that has not been declared at the definition of the key-command, you will get an % error message like this: % \begin{quote}\tt % There was no key ``height''§ % in the keycommand \string\Rule!§ % see the definition of the keycommand. % \end{quote} % % However, if you use +\commandkey{height}+ \textbf{in the definition} of +\Rule+ you % will not have any error message: +\commandkey{height}+ will just be expanded into +\relax+ % at +\Rule+ expansion time. % % \edef\restorespaceskip{\spaceskip\the\spaceskip \xspaceskip\the\xspaceskip} % \spaceskip=.1em plus.1fil \xspaceskip\spaceskip % To be honest, when you redefine a key-command using |\renewkeycommand| or % |\renewkeyenvironment| or |\keycmd\def| the keys defined before for the old command are undefined. % This way you have the expected error message in all cases. % \restorespaceskip % % \subsection{Test if a key is defined} % % When you define a key command you may let the default value of a key empty. Then, you may wish to % expand some commands only if the key has been given by the user (with a non empty value). This can % be achieved using the macro |\ifcommandkey|: % % \begin{declcs}{ifcommandkey}\,\M{key name}\,\M{commands if key is blank}\,\M{commands if key is NOT blank} % \end{declcs} % % % % \StopEventually{ % } % % \begin{center}\vskip6pt$\star$\hskip4em\lower12pt\hbox{$\star$}\hskip4em$\star$\vadjust{\vskip12pt}\end{center} % % \section{Implementation} \label{Implementation} % % \subsection{Identification} % % This package is intended to use with \LaTeX{} so we don't check if it is loaded twice. % % \begin{macrocode} %<*package> \NeedsTeXFormat{LaTeX2e}% LaTeX 2.09 can't be used (nor non-LaTeX) [2005/12/01]% LaTeX must be 2005/12/01 or younger (see kvsetkeys.dtx). \ProvidesPackage{keycommand} [2009/07/22 v2.e- an easy way to define commands with optional keys] % \end{macrocode} % % \subsection{Requirements} % % The package is based on \xpackage{kvsetkeys}. \xpackage{kvsetkeys} is more % reliable than \xpackage{keyval} as far as spaces and bracket (groups) are concerned. % Please refer to the \xpackage{kvsetkeys} documentation for more information. % % As long as we use \eTeX{} primitives in \xpackage{keycommand} we also load the % \xpackage{etex} package in order to get an error message if \eTeX{} is not running. % % \begin{macrocode} \RequirePackage{etex,kvsetkeys} % \end{macrocode} % % % \subsection{Syntactical enhancement} % % We will define a shortcut for +\expandafter\noexpand\csname+...+\endcsname+ all along this package. % \begin{macrocode} \edef\kcmd@AtEnd{\catcode34 \the\catcode34}% " \catcode34 4 % \end{macrocode} % % % \subsection{Defining keys} % % \begin{macro}{\kcmd@keydef} % To handle the case where the key-command was defined as +\global+, we have to % define keys globally too. Therefore, we can't use the +\define@key+ macro of % the \xpackage{keyval} package. % % \begin{macrocode} \def\kcmd@keydef#1#2#3#4#5{% #1=\global, #2=command, #3=family, #4=key, #5=def #1\expandafter\edef\csname kcmd@keys\string#2\endcsname{% \csname kcmd@keys\string#2\endcsname,#4}% #1\@namedef{KV@#3@#4@default\expandafter}\expandafter{% \csname KV@#3@#4\endcsname{#5}}% #1\@namedef{KV@#3@#4}##1} % \end{macrocode} % \end{macro} % % \begin{macro}{\kcmd@definekey} % In order to define keys, we will use the +\kv@parse+ macro (\xpackage{kvsetkeys}). % Therefore, the only requirement is to define the \emph{processor}. % % \begin{macrocode} \def\kcmd@definekey#1#2#3#4#5{% \begingroup\edef\@tempa{\endgroup \unexpanded{\kcmd@keydef{#1}{#2}{#3}{#4}{#5}}{\def \expandafter\noexpand\csname #3@#4\endcsname{####1}}% }\@tempa} % \end{macrocode} % \end{macro} % % \begin{macro}{\kcmd@undefinekeys} % Now in case we redefine a key-command, we would like the old keys (\emph{ie} the keys % associated to the old definition of the command) to be cleared, undefined. % That's the job of +\kcmd@undefinekeys+: % % \begin{macrocode} \def\kcmd@undefinekeys#1#2{% \@ifundefined{kcmd@keys\string#2} \relax {\expandafter\@for\expandafter\kcmp@temp \expandafter:\expandafter=\csname kcmd@keys\string#2\endcsname \do{#1\expandafter\let \csname KV@kcmd@\expandafter\@gobble\string #2@\kcmp@temp @default\endcsname \@undefined #1\expandafter\let \csname KV@kcmd@\expandafter\@gobble\string #2@\kcmp@temp\endcsname \@undefined}}% #1\@namedef{kcmd@keys\string#2}{\@gobble}} % \end{macrocode} % \end{macro} % % \clearpage % \subsection{The \csbf{keycmd} prefix} \label{subsec:keycmd} % % |\keycmd| acts just like a (expandable) prefix for |\def| or |\edef|: % % The syntax is:§ % \DeleteShortVerb{\|}\catcode`\|\active\let|\textbar % \def\tvs{\textcolor{green}{\textvisiblespace}} % \def\cblue{\color{blue}}\def\cred{\color{red}}% \begin{framed}\begin{centering}\begin{tabular}{clll} % & \multicolumn{2}{l}{\cs{keycmd}\textcolor{red}{\textasteriskcentered}\tvs} & \textcolor{red}{\textasteriskcentered} optional \\ % \cblue possibly & & (\csred{long}\tvs|\csred{global}\tvs|\csred{protected}\tvs|\csred{outer}\tvs) & optional (zero or more) \\ % \cblue in a macro & \multirow{-2}*{\cblue $\Biggl\lbrace$\qquad} & (\cs{def}|\cs{edef}|\cs{gdef}|\cs{xdef}) & required: see below \\ % & & \textit{control sequence} & required \\ % & & +[key=value pairs]+ & keys and default values \\ % & & \textcolor{red}{Parameter string} & optional \\ % & & \meta{Replacement text} & required % \end{tabular}\end{centering}\end{framed} % % Without the star form, +\long+ is assumed; but it can always be specified as +\long+ \textbf{after} % +\keycmd+. Example:§ % \qquad+\keycmd\gdef\CommandWithKeys[kOne=defOne,kTwo=defTwo]#1#2{+...+}+ % % \begin{macro}{\keycmd} % First we have to read the prefixes, if any: % \begin{macrocode} \DeclareRobustCommand\keycmd{\@star@or@long\kcmd@prefix} % \end{macrocode} % \end{macro} % % \begin{macro}{\kcmd@prefix} % This is the prefixes scanner: this macro reads the prefixes one after another (including the +\def+ word) % and stores them in +\kcmd@prfx+. We open a group for all declarations will % be local until the final definition of +\CommandWithKeys+. % % \begin{macrocode} \def\kcmd@prefix{\begingroup \let\kcmd@gbl\@empty \def\kcmd@prfx{\l@ngrel@x}% \futurelet\x\kcmd@@prefix} \def\kcmd@@prefix{% \let\kcmd@next@addto\kcmd@next@prefix \ifx\x\@sptoken \let\next\kcmd@space@prefix \else \let\next\kcmd@addto@prfx \ifx\x\long \else\ifx\x\outer \else\ifx\x\protected \else\ifx\x\global \def\kcmd@gbl{\global}% \else \def\kcmd@next@addto{\expandafter\key@cmd\noexpand}% \ifx\x\def \else\ifx\x\edef \else\ifx\x\gdef \def\kcmd@gbl{\global}% \else\ifx\x\xdef \def\kcmd@gbl{\global}% \else \let\kcmd@next@addto\kcmd@next@prefix \ifx\y\x\kcmd@error@prefix \else\let\y\x \fi \let\next\kcmd@expand@prefix \fi\fi\fi\fi \fi\fi\fi\fi \fi\next} \def\kcmd@next@prefix{\futurelet\x\kcmd@@prefix} \def\kcmd@expand@prefix{\expandafter\kcmd@next@prefix} \def\kcmd@addto@prfx#1{\let\y\@undefined \expandafter\def\expandafter\kcmd@prfx \expandafter{\kcmd@prfx#1}\kcmd@next@addto} \expandafter\def\expandafter\kcmd@space@prefix\space{\kcmd@next@prefix} \def\kcmd@error@prefix{\@latex@error{A \string\def\space (or \string\gdef\space or \string\edef\space or \string\xdef)\MessageBreak was expected after \string\keycmd\MessageBreak I found a \meaning\x!\MessageBreak see keycommand documentation for more information}\@ehd} % \end{macrocode} % \end{macro} % % \begin{macro}{\key@cmd, \@keycmd} % +\key@cmd+ will take the name of the command to be defined as its first argument % and checks if there are keys-values placed between brackets just after. Then, % +\@keycmd+ will check if the command is definable; if it is not, then the switch % +\@tempswa+ is set to false: the definition is processed nevertheless with a basic +\def+, % but the group (opened in +\kcmd@prefix+) is closed just after the assignment, canceling % everything out. % % \begin{macrocode} \def\key@cmd#1{\@testopt{\expandafter\@keycmd\noexpand#1}{}} \def\@keycmd#1[#2]{\@tempswafalse\expandafter \@rc@ifdefinable\noexpand#1{\@tempswatrue}% \if@tempswa \let#1=\relax \def\next{\kcmd@def#1{#2}}% \else \def\next{\afterassignment\endgroup \def\kcmd@notdefinable}% \fi\next} % \end{macrocode} % \end{macro} % % \begin{macro}{\kcmd@relaxify} % We temporarily assign the value +\relax+ to some commands in order to avoid % so many +\noexpand+ during the expanded definition of +\kcmd@def@+: % \begin{macrocode} \def\kcmd@relaxify{% \let\commandkey\relax \let\kvsetkeys\relax \let\kv@parse\relax \let\@testopt\relax \let\kv@set@family@handler\relax \let\kcmd@undefinekeys\relax \let\kcmd@keyerr\relax \let\kcmd@definekey\relax \def\"##1"{\expandafter\noexpand\csname ##1\endcsname}} % \end{macrocode} % \end{macro} % % \begin{macro}{\kcmd@def} % +\kcmd@def+ will define the keys and the command itself: % \begin{macrocode} \def\kcmd@def#1#2{% #1=\Command, #2=key-values \edef\kcmd@fam{kcmd@\expandafter\@gobble\string#1}% \kcmd@relaxify \edef\kcmd@def@##1{\endgroup \kv@set@family@handler{\kcmd@fam}{\kcmd@keyerr{#1}{####1}{####2}}% \kcmd@undefinekeys{\kcmd@gbl}{#1}% \kv@parse{##1}{\kcmd@definekey{\kcmd@gbl}{#1}{\kcmd@fam}}% \kcmd@gbl\protected\def#1{% entry point \def\commandkey########1{\noexpand\csname\kcmd@fam @########1\endcsname}% \def\"kcmd\string#1"########1[########2]{% \kvsetkeys{\kcmd@fam}{########1,########2}% \"\string #1"}% \@testopt{\"kcmd\string#1"{##1}}{}}% \let\commandkey\relax \expandafter\expandafter\expandafter \expandafter\expandafter\expandafter \expandafter\kcmd@prfx\"\string#1"% }\kcmd@def@{#2}} % \end{macrocode} % \end{macro} % % \begin{macro}{\kcmd@keyerr} % +\kcmd@keyerr+ is the default handler for key-commands. It is called % whenever the user wants to use a key that was not defined in the key-command: % % \begin{macrocode} \def\kcmd@keyerr#1#2#3{% \let\wheremsg\@empty \ifdefined\trcg@where\trcg@where{#1}\fi \@latex@error{There was no key "#2" \MessageBreak in the keycommand \string#1!\MessageBreak see the definition of the keycommand (or environment)\wheremsg}\@ehd} % \end{macrocode} % \end{macro} % % \subsection{new key-commands} % % \begin{macro}{\newkeycommand} % The +\expandafter+...+\noexpand+ trick is there in case the command to (re-)define % had been defined as +\outer+ before... % \begin{macrocode} \DeclareRobustCommand\newkeycommand{\@star@or@long {\expandafter\new@keycommand\noexpand}} \DeclareRobustCommand\renewkeycommand{\@star@or@long {\expandafter\renew@keycommand\noexpand}} \DeclareRobustCommand\providekeycommand{\@star@or@long {\expandafter\provide@keycommand\noexpand}} % \end{macrocode} % \end{macro} % % \begin{macrocode} \def\new@keycommand#1{\@testopt{\expandafter\@newkeycommand\noexpand#1}{}} \def\@newkeycommand#1[#2]{\begingroup \@tempswafalse\expandafter \@ifdefinable\noexpand#1{\@tempswatrue}% \if@tempswa \let#1=\relax \let\kcmd@gbl\@empty \def\kcmd@prfx##1{\unexpanded{\@testopt{\@argdef{##1}}0}}% \def\next{\kcmd@def#1{#2}}% \else \def\next{\afterassignment\endgroup \def\kcmd@notdefinable}% \fi\next} % \end{macrocode} % % \begin{macrocode} \def\renew@keycommand#1{\begingroup \escapechar\m@ne\edef\@gtempa{{\string#1}}% \expandafter\@ifundefined\@gtempa {\endgroup\@latex@error{\noexpand#1undefined}\@ehc} \endgroup \let\@ifdefinable\@rc@ifdefinable \expandafter\new@keycommand\noexpand#1} % \end{macrocode} % % \begin{macrocode} \def\provide@keycommand#1{\begingroup \escapechar\m@ne\edef\@gtempa{{\string#1}}% \expandafter\@ifundefined\@gtempa {\endgroup\new@keycommand#1} {\endgroup\let\kcmd@notdefinable\noexpand \renew@keycommand\kcmd@notdefinable}} % \end{macrocode} % % \subsection{new key-environments} % % \begin{macrocode} \DeclareRobustCommand\newkeyenvironment{\@star@or@long\new@keyenvironment} \DeclareRobustCommand\renewkeyenvironment{\@star@or@long\renew@keyenvironment} % \end{macrocode} % % \begin{macrocode} \def\new@keyenvironment#1{\@testopt{\@newkeyenva{#1}}{}} \def\@newkeyenva#1[#2]{% \kernel@ifnextchar [{\@newkeyenvb{#1}[{#2}]}{\@newkeyenv{#1}{[{#2}][0]}}} \def\@newkeyenvb#1[#2][#3]{\@newkeyenv{#1}{[{#2}][#3]}} \def\@newkeyenv#1#2#3#4{% \@ifundefined{#1}% {\expandafter\let\csname #1\expandafter\endcsname \csname end#1\endcsname}% \relax \expandafter\@newkeycommand \csname #1\endcsname#2{#3}% \l@ngrel@x\expandafter\def\csname end#1\endcsname{#4}} % \end{macrocode} % % \begin{macrocode} \def\renew@keyenvironment#1{% \@ifundefined{#1}% {\@latex@error{Environment #1 undefined}\@ehc }\relax \expandafter\let\csname#1\endcsname\relax \expandafter\let\csname\expandafter\string\csname #1\endcsname\endcsname\relax \expandafter\let\csname end#1\endcsname\relax \new@keyenvironment{#1}} % \end{macrocode} % \iffalse % % % \fi % % \subsection{Test if keys are blank} % % First we need some helper macros: % \begin{macrocode} \def\kcmd@afterelse#1\else#2\fi{\fi#1} \def\kcmd@afterfi#1\fi{\fi#1} % \end{macrocode} % % % \begin{macro}{\expandnext} % The following macros comes from the \Xpackage{etextools} package (by F. Chervet): % \begin{macrocode} \newcommand\kcmd@expandnext[2]{% \ifx#1\kcmd@expandnext \kcmd@afterelse\expandafter\expandafter\expandafter \expandafter\@kcmd@expandnext{#2}{\expandafter\expandafter\expandafter}% \else\kcmd@afterfi\expandafter#1\expandafter{#2}% \fi} \long\def\@kcmd@expandnext#1#2#3{% \ifx#1\kcmd@expandnext \expandafter\kcmd@afterelse\expandafter\expandafter\expandafter \expandafter\@kcmd@expandnext{#3}{\expandafter#2#2}% \else \expandafter\kcmd@afterfi#2#1#2{#3}% \fi} % \end{macrocode} % \end{macro} % % \begin{macro}{\kcmd@expandonce} % The following macro comes from the \Xpackage{etoolbox} package (by P. Lehmann): % \begin{macrocode} \def\kcmd@expandonce#1{\unexpanded\expandafter{#1}} % \end{macrocode} % \end{macro} % % \begin{macro}{\kcmd@ifblank} % The following macro comes from the \Xpackage[misc/url.sty]{url} package: % \begin{macrocode} \begingroup\catcode`\:=4\catcode`\&=4 \gdef\kcmd@ifblank#1{\kcmd@ifblank@#1&&\@secondoftwo\@firstoftwo:} \gdef\kcmd@ifblank@#1#2#4#5:{#4} \endgroup % \end{macrocode} % \end{macro} % % \begin{macro}{\ifcommandkey} % \begin{macrocode} \newcommand\ifcommandkey[3]{% \kcmd@expandnext\kcmd@expandnext\kcmd@expandnext\kcmd@expandnext\kcmd@expandnext \kcmd@expandnext\kcmd@expandnext\kcmd@expandnext\kcmd@expandnext\kcmd@expandnext \kcmd@expandnext\kcmd@expandnext\kcmd@expandnext\kcmd@ifblank{% \kcmd@expandnext\kcmd@expandnext\kcmd@expandonce{\commandkey{#1}}} {#3} {#2}} % \end{macrocode} % \end{macro} % % \begin{macrocode} \kcmd@AtEnd % % \end{macrocode} % % \section{Example} % % \begin{macrocode} %<*example> \ProvidesFile{keycommand-example} \documentclass{article} \usepackage[T1]{fontenc} \usepackage[latin1]{inputenc} \usepackage[american]{babel} \usepackage{keycommand} \usepackage{framed} % \makeatletter \parindent\z@ \newkeycommand\Rule[raise=.4ex,width=1em,thick=.4pt][1]{% \rule[\commandkey{raise}]{\commandkey{width}}{\commandkey{thick}}% #1% \rule[\commandkey{raise}]{\commandkey{width}}{\commandkey{thick}}} \newkeycommand\charleads[sep=1][2]{% \ifhmode\else\leavevmode\fi\setbox\@tempboxa\hbox{#2}\@tempdima=1.584\wd\@tempboxa% \cleaders\hb@xt@\commandkey{sep}\@tempdima{\hss\box\@tempboxa\hss}#1% \setbox\@tempboxa\box\voidb@x} \newcommand\charfill[1][]{\charleads[{#1}]{\hfill\kern\z@}} \newcommand\charfil[1][]{\charleads[{#1}]{\hfil\kern\z@}} % \newkeyenvironment{dblruled}[first=.4pt,second=.4pt,sep=1pt,left=\z@]{% \def\FrameCommand{% \vrule\@width\commandkey{first}% \hskip\commandkey{sep} \vrule\@width\commandkey{second}% \hspace{\commandkey{left}}}% \parindent\z@ \MakeFramed {\advance\hsize-\width \FrameRestore}} {\endMakeFramed} % \makeatother \begin{document} \title{This is {\tt keycommand-example.tex}} \author{Florent Chervet} \date{July 22, 2009} \maketitle \section{Example of a keycommand : \texttt{\string\Rule}} \begin{tabular*}\textwidth{rl} \verb+\Rule[width=2em]{hello}+:&\Rule[width=2em]{hello}\cr \verb+\Rule[thick=1pt,width=2em]{hello}+:&\Rule[thick=1pt,width=2em]{hello}\cr \verb+\Rule{hello}+:&\Rule{hello}\cr \verb+\Rule[thick=1pt,raise=1ex]{hello}+:&\Rule[thick=1pt,raise=1ex]{hello} \end{tabular*} \section{Example of a keycommand : \texttt{\string\charfill}} \begin{tabular*}\textwidth{rp{.4\textwidth}} \verb+\charfill{$\star$}+: & \charfill{$\star$}\cr \verb+\charfill[sep=2]{$\star$}+: & \charfill[sep=2]{$\star$} \\ \verb+\charfill[sep=.7]{\textasteriskcentered}+: & \charfill[sep=.7]{\textasteriskcentered} \end{tabular*} \section{Example of a keyenvironment : \texttt{dblruled}} \verb+\begin{dblruled}+\par \verb+ test for dblruled key-environment\par+\par \verb+ test for dblruled key-environment\par+\par \verb+ test for dblruled key-environment+\par \verb+\end{dblruled}+ \begin{dblruled} test for dblruled key-environment\par test for dblruled key-environment\par test for dblruled key-environment \end{dblruled} \verb+\begin{dblruled}[first=4pt,sep=2pt,second=.6pt,left=.2em]+\par \verb+ test for dblruled key-environment\par+\par \verb+ test for dblruled key-environment\par+\par \verb+ test for dblruled key-environment+\par \verb+\end{dblruled}+ \begin{dblruled}[first=4pt,sep=2pt,second=.6pt,left=.2em] test for dblruled key-environment\par test for dblruled key-environment\par test for dblruled key-environment \end{dblruled} \end{document} % % \end{macrocode} % % \begin{History} % % \begin{Version}{2009/08/26 v2.z} % \item % % \end{Version} % % \begin{Version}{2009/08/04 v2.e-} % \item % Fix catcode of double quote (") in case user command had a double quote in its name... % \item % Add History to the documentation file % \item % Modify the prefixes scanner (it is now the same as the one of \Xpackage{ltxnew}). % Modify the documentation (\KOMAScript\ classe) % \end{Version} % % \begin{Version}{2009/07/22 v1.0} % \item % First version. % \end{Version} % % \end{History} % % \begin{thebibliography}{9} % % \bibitem{kvsetkeys} % Heiko Oberdiek: % \textit{The \xpackage{kvsetkeys} package}; % 2007/09/29 v1.3; % \CTAN{macros/latex/contrib/oberdiek/kvsetkeys.dtx}. % % \bibitem{keyval} % David Carlisle: % \textit{The \xpackage{keyval} package}; % 1999/03/16 v1.13; % \CTAN{macros/latex/required/graphics/keyval.dtx}. % % \end{thebibliography} % % \PrintIndex % % \label{LastPage} % \Finale