summaryrefslogtreecommitdiff
path: root/macros/latex/contrib/macroswap/macroswap.dtx
blob: 6853e77d4fb2aa4e1253d2ffbcab378b1e0e7c82 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
% \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