% \iffalse meta-comment % % Copyright (C) 2013 by Robert J Lee % % This file may be distributed and/or modified under the % conditions of the LaTeX Project Public License, either % version 1.2 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 % % and version 1.2 or later is part of all distributions of % LaTeX version 1999/12/01 or later. % % \fi % % \iffalse % \NeedsTeXFormat{LaTeX2e}[1999/12/01] % \ProvidesPackage{macroswap} % [2013/08/21 v1.1 dtx macro swapper] % %<*driver> \documentclass{ltxdoc} \usepackage{macroswap} \EnableCrossrefs \CodelineIndex \RecordChanges \begin{document} \DocInput{macroswap.dtx} \end{document} % % \fi % % \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 \~} % % \CheckSum{62} % % \changes{v1.0}{2013/08/18}{Initial version} % \changes{v1.1}{2013/08/20}{Correct month in version date, remove % (unstated) dependency on \texttt{etoolbox} package, support swapping % macros that expect parameters, improved error reporting (thanks to % Christian Tellechea, Ulrich Diez and Dan)} % % \GetFileInfo{macroswap.sty} % % \DoNotIndex{\let, \edef, \xdef, \relax, \newcommand} % \DoNotIndex{\csname, \endcsname} % % \title{The Macroswap Package\thanks{This document corresponds to \textsf{Macroswap}~\fileversion, dated \filedate.}} % \author{Robert J Lee \\ latex@rjlee.homelinux.org} % % \maketitle % % \begin{abstract} % % This package provides macros to allow the user to redefine a pair of % macros so that the token lists they expand to will be swapped. % % \end{abstract} % % \section{Introduction} % % This package was written to allaw a simple, readable syntax for % swapping the values within macros, used as program variables. % % % \section*{Usage} % % \DescribeMacro{\macroswap} % % The |\macroswap| macro allows you to temporarily swap two macro % definitions; for example: % % \begin{verbatim} % \newcommand{\myfirst}{1} % \newcommand{\myend}{2} % \begingroup % \macroswap{myfirst}{myend} % \myfirst\myend % prints ``21'' % \endgroup % \myfirst\myend % prints ``12'' (swapped defininions were local) % \end{verbatim} % % This local swap is often unwanted, and can use up TeX's stack memory. % So you may prefer the global version: % % \DescribeMacro{\gmacroswap} % % The |\gmacroswap| macro allows you to globally swap two macro % definitions; for example: % % \begin{verbatim} % \newcommand{\myfirst}{1} % \newcommand{\myend}{2} % \begingroup % \gmacroswap{myfirst}{myend} % \myfirst\myend % prints ``21'' % \endgroup % \myfirst\myend % prints ``21'' (swapped defininions are global) % \end{verbatim} % % \section*{Usage with arrayjobx} % % To globally swap two elements of an array declared with the |arrayjobx| % package, you need to arrange to swap the macros used by that % package. This is not part of the public interface and may change at % any time; unfortunately, it does not seem possible to do this with % only the public interface, especially if you do not want to expand % the tokens in the array. % % Assuming arrayjobx version~1.04~(labelled ``05/03/2010''), it is % only necessary to swap the values of the underlying macros using the % following syntax: % % \begin{verbatim} % \newarray{arr} % \readarray{arr}{A&C&B} % \gmacroswap{arr2\string~}{arr3\string~} % \arr(1)\par % prints ``A'' % \arr(2)\par % prints ``B'' % \arr(3)\par % prints ``C'' % \end{verbatim} % % % \section*{Implementation} %\StopEventually{\PrintChanges \pagebreak[4] \PrintIndex} % % \begin{macro}{\gmacroswap} % Given the name of two macros, swap their definitions. % Produces no output. % This version uses plain |\let| to produce a local assignment. % \begin{macrocode} \newcommand{\macroswap}[2]{% % \end{macrocode} % NB: there's no guarantee that |#1| or |#2| will be a single token. % % First verify that they expand to a single macro name: % \begin{macrocode} \expandafter\ifcsname#1\endcsname% \else% \PackageError{macrocode}{Two macro names are required for macroswap % (got ``#1'' and ``#2'')}{% Two macro names are required, but the first parameter does not % expand to a defined macro name. Macros have not been swapped.}% \fi% \expandafter\ifcsname#2\endcsname% \else% \PackageError{macrocode}{Two macro names are required for macroswap % (got ``#1'' and ``#2'')}{% Two macro names are required, but the second parameter does not % expand to a defined macro name. Macros have not been swapped.}% \fi% % \end{macrocode} % First we use a temporary variable, |macroswap@temp|, to hold the value of the first macro. % % |\expandafter| is used to evaluate the |\csname|\dots|\endcsname| % become the |\let|, as |\let| will only redefine its first parameter. % \begin{macrocode} \expandafter\let\expandafter\macroswap@temp\csname#1\endcsname% % \end{macrocode} % % Next, the same method is used to reassign each passed-in macro. % % \begin{macrocode} \expandafter\let\csname#1\expandafter\endcsname\csname#2\endcsname% \expandafter\let\csname#2\endcsname\macroswap@temp% % \end{macrocode} % Finally, we throw away our temporary macro: % \begin{macrocode} \let\macroswap@temp\relax% } % \end{macrocode} % \end{macro} % % \begin{macro}{\macroswap} % Given the name of two macros, swap their definitions. % Produces no output. % % This version is global; the only difference here is that |\global| % is used to modify |\let| to applied globally. % \begin{macrocode} \newcommand{\gmacroswap}[2]{% \expandafter\let\expandafter\macroswap@temp\csname#1\endcsname% % \end{macrocode} % NB: |\expandafter| is used before |\global| so that the |let| becomes global... % \begin{macrocode} \expandafter\global\expandafter\let\csname#1\expandafter\endcsname\csname#2\endcsname% \expandafter\global\expandafter\let\csname#2\endcsname\macroswap@temp% \let\macroswap@temp\relax% } % \end{macrocode} % \end{macro} % % That is all % \Finale \endinput