summaryrefslogtreecommitdiff
path: root/Master/texmf-dist/source/latex/locality/locality.dtx
diff options
context:
space:
mode:
Diffstat (limited to 'Master/texmf-dist/source/latex/locality/locality.dtx')
-rw-r--r--Master/texmf-dist/source/latex/locality/locality.dtx446
1 files changed, 446 insertions, 0 deletions
diff --git a/Master/texmf-dist/source/latex/locality/locality.dtx b/Master/texmf-dist/source/latex/locality/locality.dtx
new file mode 100644
index 00000000000..c9f5abfa691
--- /dev/null
+++ b/Master/texmf-dist/source/latex/locality/locality.dtx
@@ -0,0 +1,446 @@
+% \iffalse meta-comment
+%
+% Copyright (C) 2010 by Jason Gross (JasonGross9+locality@gmail.com)
+%
+% This file may be distributed and/or modified under the
+% conditions of the LaTeX Project Public License, either
+% version 1.3c 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.3c or later is part of all distributions of
+% LaTeX version 2005/12/01 or later.
+%
+% \fi
+%
+%
+% \iffalse
+%<package>\NeedsTeXFormat{LaTeX2e}[1999/12/01]
+%<package>\ProvidesPackage{locality}
+%<package> [2010/06/29 v0.1 Various macros for keeping things local]
+%
+%<*driver>
+\documentclass{ltxdoc}
+\usepackage{locality}
+\EnableCrossrefs
+\CodelineIndex
+\RecordChanges
+\begin{document}
+ \DocInput{locality.dtx}
+\end{document}
+%</driver>
+% \fi
+%
+% \CheckSum{390}
+%
+% \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 \~}
+%
+% \changes{v0.1}{2010/06/15}{Initial version. Please note that some macros
+% have not yet been tested.}
+%
+% \GetFileInfo{locality.sty}
+%
+% \DoNotIndex{\#,\$,\%,\&,\@,\\,\{,\},\^,\_,\~,\ }
+% \DoNotIndex{}
+%
+% \title{The \textsf{locality} package\thanks{This document
+% corresponds to \textsf{locality}~\fileversion,
+% dated~\filedate.}}
+% \author{Jason Gross \\ \texttt{JasonGross9+locality@gmail.com}}
+%
+% \maketitle
+%
+% \section{Introduction}
+%
+% The \textsf{locality} package provides various macros to keep changes local
+% to the current group. This allows one to (re)define helper macros
+% without worrying about accidentally changing the functionality of another
+% package's or the user's definitions. Additionally, it allows recursive
+% macros to have some definitions persist between calls, and others be local.
+%
+% \section{Usage}
+% I give the usage and specification of every macro defined. I give bugs when
+% I know them (please email me if you find other bugs, or have fixes for the
+% bugs I list). I sometimes give extra description or justification.
+%
+% \DescribeMacro{\manyaftergroup}
+% \noindent Usage: |\manyaftergroup|\marg{tokens} \par\noindent
+% Specification: The \meta{tokens} get placed after the current group \par\noindent
+% Bugs: No braces are permitted, spaces are stripped
+%
+% I've often wanted to use \TeX's |\aftergroup| with a variable-length
+% argument. This macro allows this. It is expandable (may be used in
+% |\edef|), but it gobbles spaces.
+%
+% ToDo: Write a version of this macro that preserves spaces, allows braces.
+%
+% \DescribeMacro{\locallydefine}
+% \noindent Usage: |\locallydefine|\marg{macro}\marg{processing} \par\noindent
+% Specification: Execute \meta{processing} inside of a group, and make
+% the definition of |\macro| persist after the group ends. \par\noindent
+% Bugs: Changes via |\let| to an unexpandable macro yield an infinite recursive
+% loop.
+%
+% Normally, when you define a macro in a group, it's definition reverts after
+% the group ends, unless you use |\global|. If you use |\global|, then the
+% new definition replaces the current definition on all levels. This macro
+% provides something in between.
+%
+% \DescribeMacro{\DeclareNonlocalMacro}
+% \noindent Usage: |\DeclareNonlocalMacro|\marg{macro} \par\noindent
+% Specification: Any changes to the definition of |\macro| persist
+% after the end of the current group. \par\noindent
+% Bugs: Changes via |\let| to an unexpandable macro yield an infinite recursive
+% loop. Only works with |\begingroup| |\endgroup| (not with braces).
+%
+% This macro generalized |\locallydefine|.
+%
+%
+% \DescribeMacro{\DeclareNonlocalCount}\DescribeMacro{\DeclareNonlocalLength}\DescribeMacro{\DeclareNonlocalToks}
+% \noindent Usage: |\DeclareNonlocalCount|\marg{count} \par\noindent
+% \phantom{Usage:} |\DeclareNonlocalLength|\marg{length} \par\noindent
+% \phantom{Usage:} |\DeclareNonlocalToks|\marg{toks} \par\noindent
+% Specification: Any changes to the value in \meta{register} persist
+% after the end of the current group. \par\noindent
+% Bugs: Only works with |\begingroup| |\endgroup| (not with braces). Only
+% works if the argument is a single token.
+%
+% These do the same thing to registers (\meta{count}s, \meta{length}s, and
+% \meta{tok}s) that |\DeclareNonlocalMacro| does to macros.
+%
+%
+% \DescribeMacro{\savevalues}\DescribeMacro{\restorevalues}
+% \noindent Usage: |\savevalues|\marg{list of macros (no separator)} \par\noindent
+% \phantom{Usage:} |\restorevalues|\marg{list of macros (no separator)} \par\noindent
+% Specification: Every token in the passed argument is backed up by
+% |\savevalues|, and the most recently backed up values are restored by
+% |\restorevalues|.
+%
+%
+% \DescribeMacro{\makecommandslocal}
+% \noindent Usage: |\makecommandslocal|\marg{list of macros (no separator)}\marg{code} \par\noindent
+% Specification: Every token in the first argument is made local to \meta{code};
+% changes made to their definitions do not perist outside of \meta{code}.
+%
+% This macro is the natural opposite of |\DeclareNonlocalMacro|; it allows
+% some macros to behave as if \meta{code} was inside a group, while the rest
+% of the macros behave as if they were not.
+%
+%
+% \DescribeMacro{\ignoreglobal}\DescribeMacro{\obeyglobal}\DescribeMacro{\unignoreglobal}
+% \noindent Usage: |\ignoreglobal| \par\noindent
+% \noindent Usage: |\unignoreglobal| \par\noindent
+% \noindent Usage: |\obeyglobal| \par\noindent
+% Specification: The macro |\ignoreglobal| causes global changes, such as
+% |\edef|, |\xdef|, and those prefaced by |\global|, to be local. The macro
+% |\obeyglobal| causes these to be treated as global. The macro
+% |\unignoreglobal| undoes the changes made by the last |\ignoreglobal|. If
+% you call |\ignoreglobal| twice, then you must call |\unignoreglobal| twice to
+% allow global changes.
+%
+% \DescribeMacro{\makecounterslocal}
+% \noindent Usage: |\makecounterslocal| \par\noindent
+% Specification: The macro |\makecounterslocal| redefines the \LaTeX{}
+% \meta{counter} macros so that their changes are local, instead of global.
+% At the end of the group in which |\makecounterslocal| is called,
+% \meta{counter} macros revert to being global.
+%
+% \StopEventually{\PrintChanges\PrintIndex}
+%
+% \section{Implementation}
+% \subsection{Helper functions}
+% The following definitions are preliminary, to allow various tricks with |\def|.
+% \begin{macrocode}
+\def\@nil{\@nil\relax} % this way, I'll know if I've messed up; I'll get
+% a stack overflow error.
+\def\if@nil#1{\@if@nil#1\@@nil}
+\def\@if@nil#1#2\@@nil{\ifx\@nil#1}
+% \end{macrocode}
+%
+% \begin{macro}{\locality@global@non@collision@unique@count}
+% At various places, I want to have a macro associated with a certain name
+% which hasn't been used before. I use this count to number them. I use
+% a count, instead of a counter, so that I can control whether or not it's
+% global. The long name, with lots of |@|s, is to (hopefully) avoid
+% collisions.
+% \begin{macrocode}
+\newcount\locality@global@non@collision@unique@count
+\locality@global@non@collision@unique@count=0
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\manyaftergroup}
+%
+% The macro |\manyaftergroup| works by parsing it's argument one token at a
+% time, and applying |\aftergroup| to each argument. It checks for the end
+% with |\@nil|.
+% \begin{macrocode}
+\long\def\@manyaftergroup#1{\ifx#1\@nil \else \aftergroup#1
+\expandafter\@manyaftergroup\fi}
+\newcommand{\manyaftergroup}[1]{\@manyaftergroup#1\@nil}
+% \end{macrocode}
+% \end{macro}
+%
+%
+% \begin{macro}{\locallydefine}
+% Execute the second argument passed locally, and then preserve the definition
+% of the first argument passed.
+% \begin{macrocode}
+\newcommand{\locallydefine}[2]{{#2\expandafter}%
+ \expandafter\def\expandafter#1\expandafter{#1}}
+% \end{macrocode}
+%
+% \end{macro}
+%
+% The |\DeclareNonlocal| macros do some fancy stuff with |\begingroup| and
+% |\endgroup|, so the old definitions must be saved.
+% \begin{macrocode}
+\let\@old@begingroup=\begingroup
+\let\@old@endgroup=\endgroup
+% \end{macrocode}
+% These macros are extended versions of the |\locallydefine| macro; they
+% redefine |\endgroup| to preserve definitions after the current group ends.
+%
+% \begin{macro}{\DeclareNonlocalMacro}
+% This macro redefines |\endgroup| to do this for macro passed to it.
+%
+% First, back up |\endgroup| to a new macro.
+% \begin{macrocode}
+\newcommand{\DeclareNonlocalMacro}[1]{\expandafter\let
+ \csname endgroup \the\locality@local@group@non@local@macro@count
+ \endcsname=\endgroup
+% \end{macrocode}
+% Redefine |\endgroup| to, in order: revert it's definition, insert code to
+% update the definition of the passed macro outside of the group, and call
+% the (reverted) version of |\endgroup|.
+% \begin{macrocode}
+ \expandafter\def\expandafter\endgroup\expandafter{%
+ \expandafter\expandafter\expandafter\let\expandafter
+ \expandafter\expandafter\endgroup\expandafter\expandafter
+ \csname endgroup \the\locality@local@group@non@local@macro@count
+ \endcsname\expandafter\endgroup
+ \expandafter\def\expandafter#1\expandafter{#1}}%
+ \advance\locality@local@group@non@local@macro@count by 1
+}%
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\DeclareNonlocalCount}
+% \begin{macro}{\DeclareNonlocalLength}
+% This works the same way as as |\DeclareNonlocalMacro|, but uses |\the| instead of
+% |\def|.
+% \begin{macrocode}
+\newcommand{\DeclareNonlocalCount}[1]{\expandafter\let
+ \csname endgroup \the\locality@local@group@non@local@macro@count
+ \endcsname=\endgroup
+ \expandafter\def\expandafter\endgroup\expandafter{%
+ \expandafter\expandafter\expandafter\let
+ \expandafter\expandafter\expandafter\endgroup
+ \expandafter\expandafter
+ \csname endgroup \the\locality@local@group@non@local@macro@count
+ \endcsname\expandafter\endgroup
+ \expandafter#1\expandafter=\the#1 }% Note the space. This is to
+% prevent something like
+% |\newcount\tempc\begingroup \DeclareNonlocalCount\tempc \tempc=1\endgroup1|
+% from setting |\tempc| to 11.
+ \advance\locality@local@group@non@local@macro@count by 1
+}%
+\let\DeclareNonlocalLength=\DeclareNonlocalCount
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}{\DeclareNonlocalToks}
+% This works the same way as as |\DeclareNonlocalCount|, but puts braces around
+% the assigned value; |\toks0=1| fails, and should be |\toks0={1}|.
+% \begin{macrocode}
+\newcommand{\DeclareNonlocalToks}[1]{\expandafter\let
+ \csname endgroup \the\locality@local@group@non@local@macro@count
+ \endcsname=\endgroup
+ \expandafter\def\expandafter\endgroup\expandafter{%
+ \expandafter\expandafter\expandafter\let\expandafter\expandafter
+ \expandafter\endgroup\expandafter\expandafter
+ \csname endgroup \the\locality@local@group@non@local@macro@count'
+ \endcsname\expandafter\endgroup
+ \expandafter#1\expandafter=\expandafter{\the#1}}%
+ \advance\locality@local@group@non@local@macro@count by 1
+}%
+% \end{macrocode}
+% \end{macro}
+% I redefine |\begingroup| to reset the locality macros, so nesting works.
+% \begin{macrocode}
+\newcount\locality@local@group@non@local@macro@count % Hopefully, this
+% won't collide with anything. I hope putting this out here allows
+% proper nesting of groups
+\def\begingroup{\@old@begingroup
+ \let\endgroup=\@old@endgroup
+ \locality@local@group@non@local@macro@count=0
+}
+% \end{macrocode}
+%
+%
+%
+% \begin{macro}{\savevalues}
+% \begin{macro}{\restorevalues}
+% These macros parse their arguments token by token, renaming each |macro| to
+% |@\macro backup|, or vice versa.
+% \begin{macrocode}
+\def\@savevalues#1{\ifx#1\@nil \else \expandafter\let
+ \csname @\string#1\space backup\endcsname=#1
+ \expandafter\@savevalues\fi}
+\newcommand{\savevalues}[1]{\@savevalues#1\@nil}
+
+\def\@restorevalues#1{%
+\ifx
+ #1\@nil
+\else
+ \expandafter\let\expandafter#1\expandafter
+ =\csname @\string#1\space backup\endcsname
+ \expandafter
+ \let\csname @\string#1\space backup\endcsname
+ =\relax
+ \expandafter\@restorevalues
+\fi
+}
+\newcommand{\restorevalues}[1]{\@restorevalues#1\@nil}
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+%
+%
+% \begin{macro}{\makecommandslocal}
+% Save the macros, run the code, then restore the values.
+% \begin{macrocode}
+\newcommand{\makecommandslocal}[2]{\savevalues{#1}#2\restorevalues{#1}}
+% \end{macrocode}
+% \end{macro}
+%
+%
+% \begin{macro}{\makecounterslocal}
+% To make counters local without redefining them too badly (for example, this
+% should work with the |calc| package, as long as you load |calc| first),
+% we disable |\global|, and set |\gdef| and |\xdef| to |\def| and |\edef|
+% respectively.
+%
+% \begin{macro}{\ignoreglobal}
+% \begin{macro}{\obeyglobal}
+% \begin{macro}{\unignoreglobal}
+% We save the values of |\global|, |\gdef|, |\xdef|, globally, so
+% that multiple calls don't fail.
+%
+% We also save the value of |\@cons|, a special macro used in counters, which
+% uses |\xdef| to append something to a list. Since it must be redefined for
+% counters, I'll redefine it here to do without |\xdef| fails.
+%
+% For reference, the original definition of |\@cons|, from |latex.ltx|, is \\
+% |\def\@cons#1#2{\begingroup\let\@elt\relax\xdef#1{#1\@elt #2}\endgroup}|.
+% I try to make this forward-compatible, but if the definition of |\@cons|
+% changes too badly, this'll break.
+% \begin{macrocode}
+\savevalues{\global\gdef\xdef\@cons}
+{\def\begingroup{\begingroup\DeclareNonlocalMacro{##1}}%
+\expandafter\expandafter\expandafter}%
+\expandafter\expandafter\expandafter\def
+\expandafter\expandafter\expandafter\locality@cons
+\expandafter\expandafter\expandafter#%
+\expandafter\expandafter\expandafter1%
+\expandafter\expandafter\expandafter#%
+\expandafter\expandafter\expandafter2%
+\expandafter\expandafter\expandafter{\@cons{#1}{#2}}%
+\newcommand{\obeyglobal}{\restorevalues{\globabl\gdef\xdef\@cons}}
+\let\unignoreglobal=\obeyglobal
+\newcommand{\ignoreglobal}{%
+\let\global=\relax\let\gdef=\def\let\xdef=\edef
+\let\@cons=\locality@cons
+\expandafter\def\expandafter\unignoreglobal\expandafter{\expandafter
+\def\expandafter\unignoreglobal\expandafter{\unignoreglobal}%
+ \unignoreglobal}}
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+%
+% Now, the actual macro.
+%
+% We redefine |\stepcounter|, |\addtocounter|, |\refstepcounter|,
+% |\setcounter|, |\@addtoreset|, and |\@definecounter|.
+%
+% Since |\newcounter| does everything with |\@addtoreset| and
+% |\@definecounter|, it doesn't need and changes.
+% \begin{macrocode}
+\newcommand{\makecounterslocal}{% FIX, to make more robust
+ \expandafter\def\expandafter\stepcounter
+ \expandafter##\expandafter1\expandafter{%
+ \expandafter\ignoreglobal\stepcounter{##1}%
+ \unignoreglobal
+ }%
+ %
+ \expandafter\def\expandafter\refstepcounter
+ \expandafter##\expandafter1\expandafter{%
+ \expandafter\ignoreglobal\refstepcounter{##1}%
+ \unignoreglobal
+ }%
+ %
+ \expandafter\def\expandafter\setcounter
+ \expandafter##\expandafter1%
+ \expandafter##\expandafter2\expandafter{%
+ \expandafter\ignoreglobal\setcounter{##1}{##2}%
+ \unignoreglobal
+ }%
+ %
+ \expandafter\def\expandafter\addtocounter
+ \expandafter##\expandafter1%
+ \expandafter##\expandafter2\expandafter{%
+ \expandafter\ignoreglobal\addtocounter{##1}{##2}%
+ \unignoreglobal
+ }%
+ %
+ \expandafter\def\expandafter\@addtoreset
+ \expandafter##\expandafter1%
+ \expandafter##\expandafter2\expandafter{%
+ \expandafter\ignoreglobal\@addtoreset{##1}{##2}%
+ \unignoreglobal
+ }%
+ %
+ \expandafter\def\expandafter\@definecounter
+ \expandafter##\expandafter1\expandafter{%
+ \expandafter\ignoreglobal\@definecounter{##1}%
+ \unignoreglobal
+ }%
+% \end{macrocode}
+%
+% Following the example of the |calc| package, if the amstext package is loaded
+% we must add the |\iffirstchoice@| switch as well. We patch the commands this
+% way since it's good practice when we know how many arguments they take.
+% \begin{macrocode}
+ \@ifpackageloaded{amstext}{%
+ \expandafter\def\expandafter\stepcounter
+ \expandafter##\expandafter1\expandafter{%
+ \expandafter\iffirstchoice@\stepcounter{##1}\fi
+ }
+ \expandafter\def\expandafter\addtocounter
+ \expandafter##\expandafter1%
+ \expandafter##\expandafter2\expandafter{%
+ \expandafter\iffirstchoice@\addtocounter{##1}{##2}\fi
+ }
+ }{}
+}
+% \end{macrocode}
+% \end{macro}
+% \Finale
+\endinput