summaryrefslogtreecommitdiff
path: root/macros/latex/contrib/locality
diff options
context:
space:
mode:
authorNorbert Preining <norbert@preining.info>2019-09-02 13:46:59 +0900
committerNorbert Preining <norbert@preining.info>2019-09-02 13:46:59 +0900
commite0c6872cf40896c7be36b11dcc744620f10adf1d (patch)
tree60335e10d2f4354b0674ec22d7b53f0f8abee672 /macros/latex/contrib/locality
Initial commit
Diffstat (limited to 'macros/latex/contrib/locality')
-rw-r--r--macros/latex/contrib/locality/README68
-rw-r--r--macros/latex/contrib/locality/changes.txt10
-rw-r--r--macros/latex/contrib/locality/locality.dtx634
-rw-r--r--macros/latex/contrib/locality/locality.ins52
-rw-r--r--macros/latex/contrib/locality/locality.pdfbin0 -> 186910 bytes
5 files changed, 764 insertions, 0 deletions
diff --git a/macros/latex/contrib/locality/README b/macros/latex/contrib/locality/README
new file mode 100644
index 0000000000..ffe43d8436
--- /dev/null
+++ b/macros/latex/contrib/locality/README
@@ -0,0 +1,68 @@
+LaTeX Package: Locality 2010/06/29 v0.1
+----------------------------------------
+Various macros for keeping things local
+
+Copyright (C) 2010
+by Jason Gross <JasonGross9+locality@gmail.com>
+
+Abstract:
+ This 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.
+
+CTAN: macros/latex/contrib/locality
+
+Recent changes:
+ [Release 0.2]
+ * Switched the order of tests in \manyaftergroup, eliminating an infinite loop.
+ * Added \DeclareNonlocal*s, \pushvalues, \popvalues, \pushvalue, \popvalue, and a few others.
+ * Fixed \DeclareNonlocal* to work with \aftergroup.
+ * Added requirement for etoolbox, so that patching takes place at the end of the preamble.
+ [Release 0.1]
+ * Initial release. Some macros untested.
+
+EOF
+
+
+Files:
+ * README - this file
+ * changes.txt - history of changes
+ * locality.ins - for installation to get .sty from .dtx
+ * locality.dtx - including sources and documentation
+ * locality.pdf - print-ready documentation
+
+Installation:
+[manual installation]
+ * To get locality.sty out of locality.dtx
+ $ latex locality.ins
+ * To build documentation
+ $ latex locality.dtx
+ * Put the derived files in the proper directories:
+ - tex/latex/locality/locality.sty
+ - doc/latex/locality/locality.pdf
+ - source/latex/locality/locality.dtx
+
+[TeXLive]
+ * Use 'tlmgr' command
+ $ tlmgr show locality -- to check the package info
+ $ sudo tlmgr update locality -- to update the package
+ * You can use 'TeX Live Utility' instead of 'tlmgr', if on MacOSX.
+
+[MikTeX]
+ * Use the MikTeX Update Wizard to update locality package.
+
+License:
+ This work 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.
+
+--
+Happy TeXing!
+Jason Gross
+
+EOF
diff --git a/macros/latex/contrib/locality/changes.txt b/macros/latex/contrib/locality/changes.txt
new file mode 100644
index 0000000000..fee40d7665
--- /dev/null
+++ b/macros/latex/contrib/locality/changes.txt
@@ -0,0 +1,10 @@
+2010/11/11 Release 0.2
+ * Switched the order of tests in \manyaftergroup, eliminating an infinite loop.
+ * Added \DeclareNonlocal*s, \pushvalues, \popvalues, \pushvalue, \popvalue, and a few others.
+ * Fixed \DeclareNonlocal* to work with \aftergroup.
+ * Added requirement for etoolbox, so that patching takes place at the end of the preamble.
+
+2010-06-29 Release 0.1
+ * Initial release. Some macros untested.
+
+EOF
diff --git a/macros/latex/contrib/locality/locality.dtx b/macros/latex/contrib/locality/locality.dtx
new file mode 100644
index 0000000000..f6fb404739
--- /dev/null
+++ b/macros/latex/contrib/locality/locality.dtx
@@ -0,0 +1,634 @@
+% \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/11/11 v0.2 Various macros for keeping things local]
+%<package>\RequirePackage{etoolbox}[2009/08/06]
+%
+%<*driver>
+\documentclass{ltxdoc}
+\usepackage{locality}
+\EnableCrossrefs
+\CodelineIndex
+\RecordChanges
+\begin{document}
+ \DocInput{locality.dtx}
+\end{document}
+%</driver>
+% \fi
+%
+% \CheckSum{573}
+%
+% \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.}
+% \changes{v0.2}{2010/11/11}{Switched the order of tests in \string
+% \manyaftergroup, eliminating an infinite loop. Added \string
+% \DeclareNonlocal*s\space, \string\pushvalues, \string\popvalues,
+% \string\pushvalue, \string\popvalue, and a few others. Fixed
+% \string\DeclareNonlocal*\space to work with \string\aftergroup.
+% Added requirement for etoolbox, so that patching takes place at
+% the end of the preamble.}
+%
+% \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{\DeclareNonlocalMacros}
+% \noindent Usage: |\DeclareNonlocalMacros|\marg{macro list} \par\noindent
+% \noindent Example: |\DeclareNonlocalMacros{\macroi,\macroii}| \par\noindent
+% Specification: \marg{macro list} Should be a comma-separated list of macros.
+% This command will run |\DeclareNonlocalMacro| on each argument.
+%
+%
+% \DescribeMacro{\DeclareNonlocalTheRegister}\DescribeMacro{\DeclareNonlocalCount}
+% \DescribeMacro{\DeclareNonlocalDimen}\DescribeMacro{\DeclareNonlocalSkip}
+% \DescribeMacro{\DeclareNonlocalMuskip}\DescribeMacro{\DeclareNonlocalToks}
+% \noindent Usage: |\DeclareNonlocalCount|\marg{count} \par\noindent
+% \phantom{Usage:} |\DeclareNonlocalDimen|\marg{dimen} \par\noindent
+% \phantom{Usage:} |\DeclareNonlocalSkip|\marg{skip} \par\noindent
+% \phantom{Usage:} |\DeclareNonlocalMuskip|\marg{muskip} \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
+%
+% Registers for \meta{count}s, \meta{dimen}s, \meta{skip}s, and \meta{muskips}s
+% can all be made nonlocal with |\DeclareNonlocalTheRegister|.
+%
+% 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{\DeclareNonlocalTheRegister}\DescribeMacro{\DeclareNonlocalCount}
+% \DescribeMacro{\DeclareNonlocalDimen}\DescribeMacro{\DeclareNonlocalSkip}
+% \DescribeMacro{\DeclareNonlocalMuskip}\DescribeMacro{\DeclareNonlocalToks}
+% \noindent Usage: |\DeclareNonlocalCounts|\marg{list of counts (comma separated)} \par\noindent
+% \phantom{Usage:} |\DeclareNonlocalDimens|\marg{list of dimens (comma separated)} \par\noindent
+% \phantom{Usage:} |\DeclareNonlocalSkips|\marg{list of skips (comma separated)} \par\noindent
+% \phantom{Usage:} |\DeclareNonlocalMuskips|\marg{list of muskips} \par\noindent
+% \phantom{Usage:} |\DeclareNonlocalTokses|\marg{list of toks (comma separated)} \par\noindent
+% Specification: Any changes to the value in \meta{register}s persist
+% after the end of the current group. \par\noindent
+%
+% \DescribeMacro{\pushvalue}\DescribeMacro{\popvalue}\noindent
+% Usage: |\pushvalue|\marg{macro} \par\noindent
+% \phantom{Usage:} |\popvalue|\marg{macro} \par
+% \noindent Specification: The argument \marg{macro} is backed up by
+% |\pushvalue|, and the most recently backed up value is restored by
+% |\popvalue|. The macro definitions are saved using a stack.
+%
+%
+% \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{\pushvalues}\DescribeMacro{\popvalues}\noindent
+% Usage: |\pushvalues|\marg{list of macros (comma separated)} \par\noindent
+% \phantom{Usage:} |\popvalues|\marg{list of macros (comma separated)} \par
+% \noindent Specification: Every macro in the passed argument is backed up by
+% |\pushvalues|, and the most recently backed up values are restored by
+% |\popvalues|. The macro definitions are saved using a stack.
+%
+%
+% \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}
+% We'll be messing with |\global|, so we better have a backup.
+\let\locality@tex@global=\global
+% \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{\if@nil#1 \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\locality@tex@begingroup=\begingroup
+\let\locality@tex@endgroup=\endgroup
+% \end{macrocode}
+% These macros are extended versions of the |\locallydefine| macro; they
+% redefine |\endgroup| to preserve definitions after the current group ends.
+%
+% Because |\aftergroup| would occur before definition restoration, we patch
+% |\aftergroup| so that it instead appends tokens to the end of |\endgroup|.
+% This doesn't fix all use cases, but it should fix a problem with the calc
+% package.
+% \begin{macrocode}
+\newcount\locality@global@aftergroup@count
+\locality@global@aftergroup@count=-1
+\newcommand\locality@patch@aftergroup{%
+ \def\aftergroup{%
+ \locality@tex@global\advance\locality@global@aftergroup@count by 1
+ \afterassignment\locality@aftergroup\locality@tex@global
+ \expandafter\let\csname locality@nextchar\space\the
+ \locality@global@aftergroup@count\endcsname=%
+ }%
+}
+\newcommand\locality@aftergroup{%
+ \expandafter\expandafter\expandafter\def
+ \expandafter\expandafter\expandafter\endgroup
+ \expandafter\expandafter\expandafter{\expandafter\endgroup
+ \csname locality@nextchar\space\the\locality@global@aftergroup@count
+ \endcsname}%
+}
+% \end{macrocode}
+%
+%
+% \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]{%
+ \locality@patch@aftergroup % first, patch |\aftergroup|
+ \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{macrocode}
+\newcommand\locality@declarenonlocals[2]{%
+ \@for\locality@declarenonlocals@name:=#2\do{%
+ \expandafter #1\expandafter{\locality@declarenonlocals@name}%
+ }%
+}
+% \end{macrocode}
+%
+% \begin{macro}{\DeclareNonlocalMacros}
+% \begin{macrocode}
+\newcommand{\DeclareNonlocalMacros}[1]{\locality@declarenonlocals{\DeclareNonlocalMacro}{#1}}
+% \end{macrocode}
+% \end{macro}
+%
+%
+% \begin{macro}{\DeclareNonlocalTheRegister}
+% \begin{macro}{\DeclareNonlocalCount}
+% \begin{macro}{\DeclareNonlocalDimen}
+% \begin{macro}{\DeclareNonlocalSkip}
+% \begin{macro}{\DeclareNonlocalMuskip}
+% This works the same way as as |\DeclareNonlocalMacro|, but uses |\the| instead of
+% |\def|.
+% \begin{macrocode}
+\newcommand{\DeclareNonlocalTheRegister}[1]{%
+ \locality@patch@aftergroup % first, patch |\aftergroup|
+ \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\DeclareNonlocalCount=\DeclareNonlocalTheRegister
+\let\DeclareNonlocalDimen=\DeclareNonlocalTheRegister
+\let\DeclareNonlocalSkip=\DeclareNonlocalTheRegister
+\let\DeclareNonlocalMuskip=\DeclareNonlocalTheRegister
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+%
+% \begin{macro}{\DeclareNonlocalTheRegisters}
+% \begin{macro}{\DeclareNonlocalCounts}
+% \begin{macro}{\DeclareNonlocalDimens}
+% \begin{macro}{\DeclareNonlocalSkips}
+% \begin{macro}{\DeclareNonlocalMuskips}
+% \begin{macrocode}
+\newcommand{\DeclareNonlocalTheRegisters}[1]{\locality@declarenonlocals{\DeclareNonlocalTheRegister}{#1}}
+\let\DeclareNonlocalCounts=\DeclareNonlocalTheRegisters
+\let\DeclareNonlocalDimens=\DeclareNonlocalTheRegisters
+\let\DeclareNonlocalSkips=\DeclareNonlocalTheRegisters
+\let\DeclareNonlocalMuskips=\DeclareNonlocalTheRegisters
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+% \end{macro}
+% \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]{%
+ \locality@patch@aftergroup % first, patch |\aftergroup|
+ \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}
+%
+% \begin{macro}{\DeclareNonlocalTokses}
+% \begin{macrocode}
+\newcommand{\DeclareNonlocalTokses}[1]{\locality@declarenonlocals{\DeclareNonlocalToks}{#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{\locality@tex@begingroup
+ \def\endgroup{\locality@tex@endgroup}% not \let, because
+ % that would break my |\aftergroup| patch
+ \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}{\pushvalues}
+% \begin{macro}{\popvalues}
+% \begin{macro}{\pushvalue}
+% \begin{macro}{\popvalue}
+% \begin{macrocode}
+\newcommand{\pushvalue}[1]{%
+ \@ifundefined{locality\space backup\space \string#1}{}{%
+ \expandafter\pushvalue\csname locality\space backup\space \string#1\endcsname%
+ }%
+ \expandafter\let\csname locality\space backup\space \string#1\endcsname=#1%
+}
+\newcommand{\pushvalues}[1]{%
+ \@for\locality@pushvalues@macroname:=#1\do{%
+ \expandafter\pushvalue\locality@pushvalues@macroname
+ }%
+}
+\newcommand{\popvalue}[1]{%
+ \@ifundefined{locality\space backup\space \string#1}{%
+ \let#1=\relax
+ }{%
+ \expandafter\let\expandafter#1\expandafter=\csname locality\space backup\space \string#1\endcsname
+ \expandafter\popvalue\csname locality\space backup\space \string#1\endcsname%
+ }%
+}
+\newcommand{\popvalues}[1]{%
+ \@for\locality@popvalues@macroname:=#1\do{%
+ \expandafter\popvalue\locality@popvalues@macroname
+ }%
+}
+% \end{macrocode}
+% \end{macro}
+% \end{macro}
+% \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{\global\gdef\xdef\@cons}}
+\newcommand{\unignoreglobal}{\popvalues{\global,\gdef,\xdef,\@cons}}
+\newcommand{\ignoreglobal}{%
+ \pushvalues{\global,\gdef,\xdef,\@cons}%
+ \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
+ }%
+ \locality@fix@for@amstext
+ \locality@fix@for@calc
+}
+% \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.
+%
+% We use |\AtEndPreamble| to ensure that we catch the other package loads.
+% \begin{macrocode}
+\AtEndPreamble{
+ \@ifpackageloaded{amstext}{
+ \newcommand{\locality@fix@for@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
+ }
+ }
+ }{
+ \let\locality@fix@for@amstext=\relax
+ }
+ \@ifpackageloaded{calc}{%
+ \def\locality@fix@for@calc{\expandafter\def\expandafter\begingroup\expandafter{\begingroup\DeclareNonlocalTheRegister{\calc@A}}}
+ }{
+ \let\locality@fix@for@calc=\relax
+ }
+}
+% \end{macrocode}
+% \end{macro}
+%
+%
+% \Finale
+\endinput
diff --git a/macros/latex/contrib/locality/locality.ins b/macros/latex/contrib/locality/locality.ins
new file mode 100644
index 0000000000..4944db3c3d
--- /dev/null
+++ b/macros/latex/contrib/locality/locality.ins
@@ -0,0 +1,52 @@
+%%
+%% Copyright (C) 2010 by Jason Gross
+%%
+%% 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.
+%%
+\input docstrip.tex
+\keepsilent
+\usedir{tex/latex/locality}
+
+\preamble
+
+This is a generated file.
+
+Copyright (C) 2010 by Jason Gross
+
+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.
+\endpreamble
+
+\generate{\file{locality.sty}{\from{locality.dtx}{package}}}
+
+\obeyspaces
+\Msg{****************************************************}
+\Msg{* *}
+\Msg{* To finish the installation you have to move the *}
+\Msg{* following file into a directory searched by TeX: *}
+\Msg{* *}
+\Msg{* locality.sty *}
+\Msg{* *}
+\Msg{* To produce the documentation run the file *}
+\Msg{* locality.dtx through LaTeX. *}
+\Msg{* *}
+\Msg{* Happy TeXing! *}
+\Msg{* *}
+\Msg{****************************************************}
+
+\endbatchfile \ No newline at end of file
diff --git a/macros/latex/contrib/locality/locality.pdf b/macros/latex/contrib/locality/locality.pdf
new file mode 100644
index 0000000000..21ac991b04
--- /dev/null
+++ b/macros/latex/contrib/locality/locality.pdf
Binary files differ