% \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
% <package>\NeedsTeXFormat{LaTeX2e}[1999/12/01]
% <package>\ProvidesPackage{macroswap}
% <package>   [2013/08/21 v1.1 dtx macro swapper]
%
%<*driver>
\documentclass{ltxdoc}
\usepackage{macroswap}
\EnableCrossrefs
\CodelineIndex
\RecordChanges
\begin{document}
  \DocInput{macroswap.dtx}
\end{document}
%</driver>
% \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
