From 5d2b9323781e86126ca48a5d182002e28b387825 Mon Sep 17 00:00:00 2001 From: Karl Berry Date: Fri, 22 Aug 2014 00:17:27 +0000 Subject: assoccnt (21aug14) git-svn-id: svn://tug.org/texlive/trunk@35003 c570f23f-e606-0410-a88d-b1316a301751 --- Master/texmf-dist/tex/latex/assoccnt/assoccnt.sty | 200 ++++++++++++++++++---- 1 file changed, 165 insertions(+), 35 deletions(-) (limited to 'Master/texmf-dist/tex/latex/assoccnt/assoccnt.sty') diff --git a/Master/texmf-dist/tex/latex/assoccnt/assoccnt.sty b/Master/texmf-dist/tex/latex/assoccnt/assoccnt.sty index b6406ff56a4..08697e37332 100644 --- a/Master/texmf-dist/tex/latex/assoccnt/assoccnt.sty +++ b/Master/texmf-dist/tex/latex/assoccnt/assoccnt.sty @@ -1,26 +1,30 @@ \NeedsTeXFormat{LaTeX2e}% -\ProvidesPackage{assoccnt}[2014/08/13 v0.2 -- Associate counters stepping]% +\ProvidesPackage{assoccnt}[2014/08/21 v0.3 -- Associate counters stepping]% %%% %% License: LaTeX Project Public License %% Copyright (2014) Dr. Christian Hupfer %% Author: Christian Hupfer christian.hupfer@siebenfelsen.de %% -%% %%%% %%% Some options later on %%%% \RequirePackage{etoolbox}[2011/01/03 2.2]% +\RequirePackage{xkeyval}[2012/10/14 v2.6b]% + +\def\@@assoccnt@@keys{@@assoccnt@@keyfamily}% -\let\@@assoccnt@standardstepcounter\stepcounter% -\let\@@assoccnt@standardrefstepcounter\refstepcounter% +\newcounter{@@assoccnt@@internalcounter}% + +\let\@@assoccnt@@standardstepcounter\stepcounter% +\let\@@assoccnt@@standardrefstepcounter\refstepcounter% % Just for a quick suffix -\newcommand{\@@associatedcounterslistsuffix}{% +\newcommand{\@@assoccnt@@associatedcounterslistsuffix}{% AssociatedCountersList% }% @@ -29,62 +33,137 @@ AssociatedCountersList% %%% Internal macro to generate the name of the list of associated counters \newcommand{\@@assoccnt@@generatelistname}[1]{% % #1 Name of the driver counter -@#1\@@associatedcounterslistsuffix +@@#1@@\@@assoccnt@@associatedcounterslistsuffix }% +\newcommand{\@@assoccnt@@drivercounterlist}{% +@@assoccnt@@DriverCountersList% +}% -\newcommand{\@@assoccnt@@addassociatedcounter}[2]{% - \ifcsdef{#1}{% - \ifinlistcs{#2}{#1}{% - % Do nothing, since counter is already in the list - }{% - \listcsadd{#1}{#2}% +%% +%% Adds a driver counter to an internal administration list +\newcommand{\AddDriverCounter}[2][]{% +% #1 -> options +% #2 -> driver counter name + \setkeys{\@@assoccnt@@keys}{#1}% + \ifcsdef{\@@assoccnt@@drivercounterlist}{% + }{% + \csgdef{\@@assoccnt@@drivercounterlist}{}% + }% + \listcsgadd{\@@assoccnt@@drivercounterlist}{#2}% +}% + + +%% +%% Removes the complete list of driver counters +\newcommand{\ClearDriverCountersList}{% + \ifcsdef{\@@assoccnt@@drivercounterlist}% + {% + % Clear the possible driver counter entry in the list, the trailing associated counters list + % is cleared as well + \forlistcsloop{\ClearAssociatedCountersList}{\@@assoccnt@@drivercounterlist}% + }{% + % Nothing to be done + }% +}% + +\newcommand{\IsDriverCounter}[3]{% + \ifcsdef{\@@assoccnt@@drivercounterlist}{% + \ifinlistcs{#1}{\@@assoccnt@@drivercounterlist}{% True branch, it's in the list + #2% + }{% False branch, not in the list + #3% }% + }{% List does not exist at all --> expand false branch + #3% + }% +}% + +\newcommand{\@@assoccnt@@generateboundtocounterslist}[1]{% +#1@@boundtocounterslist% +}% + + +\newcommand{\@@assoccnt@@addassociatedcounter}[3][]{% + \ifcsdef{\@@assoccnt@@generateboundtocounterslist{#3}}{% + % The counter is already to some other counter, it should not be multiply associated! }{% - % Nothing in here + \csgdef{\@@assoccnt@@generateboundtocounterslist{#3}}{}% + \listcsgadd{\@@assoccnt@@generateboundtocounterslist{#3}}{#1} + \ifcsdef{#2}{% + \ifinlistcs{#3}{#2}{% + % Do nothing, since counter is already in the list, prevent multiple list insertion + }{% + \listcsgadd{#2}{#3}% + }% + }{% + % Nothing in here + }% }% }% +\newcommand{\AddAssociatedCounters}[3][]{% +% #1 --> options +% #2 --> driver counter +% #3 --> CSV list of counters, that should be stepped, if the driver counter is stepped +\setkeys{\@@assoccnt@@keys}{#1}% + \ifcsdef{\@@assoccnt@@generatelistname{#2}}{% + % % Nothing to be done --> List already exists + \forcsvlist{\@@assoccnt@@addassociatedcounter[#2]{\@@assoccnt@@generatelistname{#2}}}{#3}% + % Prevent accidental self - association + \RemoveAssociatedCounter{#2}{#2}% + }{% + \GenericError{}{Error: List for driver counter #2 does not exist -- Usage on line \the\inputlineno}{}{} + }% +}% % This command defines a list of counters, that should be stepped also if the driver counter % is `\stepcounter`ed. % A self - association is not possible, as this would lead to inconsistent counting -\newcommand{\DeclareAssociatedCounters}[2]{% -% #1 --> driver counter -% #2 --> CSV list of other counters, that should be stepped, if the driver counter is stepped - \ifcsdef{\@@assoccnt@@generatelistname{#1}}{% +\newcommand{\DeclareAssociatedCounters}[3][]{% +% #1 --> options +% #2 --> driver counter +% #3 --> CSV list of other counters, that should be stepped, if the driver counter is stepped +\setkeys{\@@assoccnt@@keys}{#1}% + \ifcsdef{\@@assoccnt@@generatelistname{#2}}{% % % Nothing to be done --> List already exists - \GenericWarning{}{Warning: List of associated counters for counter #1 already exists}% + \GenericWarning{}{Warning: List of associated counters for driver counter #2 already exists}% }{% - \csgdef{\@@assoccnt@@generatelistname{#1}}{}% Define some global list + \AddDriverCounter{#2}% + \csgdef{\@@assoccnt@@generatelistname{#2}}{}% Define some global list }% - % Now add the counter names from #2 to the list + % Now add the counter names from #3 to the list % Note: Currently, it is not checked whether a counter is already added! - \forcsvlist{\@@assoccnt@@addassociatedcounter{\@@assoccnt@@generatelistname{#1}}}{#2}% + \forcsvlist{\@@assoccnt@@addassociatedcounter[#2]{\@@assoccnt@@generatelistname{#2}}}{#3}% % Now remove an accidental self-association - \RemoveAssociatedCounter{#1}{#1}% + \RemoveAssociatedCounter{#2}{#2}% }% +%\@onlypreamble{\DeclareAssociatedCounters}% + + +%% + %%% A generic macro, that removes a list entry from the list by %%% defining a temporary list and omitting the -\newcommand{\@@assoccnt@removefromlist}[2]{% +\newcommand{\@@assoccnt@@removefromlist}[2]{% % #1 list name % #2 element to be removed \ifcsdef{#1}{% - \gdef\@@mytemplist{}% + \gdef\@@assoccnt@@mytemplist{}% \renewcommand*{\do}[1]{% \ifstrequal{##1}{#2}{ % Later one some success routine etc. ??? }{% - \listgadd{\@@mytemplist}{##1}% + \listgadd{\@@assoccnt@@mytemplist}{##1}% }% }% \dolistcsloop{#1}% - \csxdef{#1}{\@@mytemplist}% + \csxdef{#1}{\@@assoccnt@@mytemplist}% }{% % The list is not defined at all, can't remove something from something not existing... }% @@ -96,7 +175,7 @@ AssociatedCountersList% \newcommand{\RemoveAssociatedCounter}[2]{% % #1 arg: driver counter % #2 arg: counter name to be removed - \@@assoccnt@removefromlist{\@@assoccnt@@generatelistname{#1}}{#2}% + \@@assoccnt@@removefromlist{\@@assoccnt@@generatelistname{#1}}{#2}% }% %% Remove a CSV list of counters from the list of associated counters @@ -111,11 +190,12 @@ AssociatedCountersList% \newcommand{\ClearAssociatedCountersList}[1]{% % #1 arg: driver counter \csundef{\@@assoccnt@@generatelistname{#1}}% + \@@assoccnt@@removefromlist{\@@assoccnt@@drivercounterlist}{#1}% }% %% Test if a counter is an associated counter of driver counter -\newcommand{\IfIsAssociatedCounter}[4]{% +\newcommand{\IsAssociatedToCounter}[4]{% % #1 arg: driver counter % #2 arg: (possibly) associated counter % #3 arg: Code for execution on true branch @@ -132,22 +212,70 @@ AssociatedCountersList% }% +\newcommand{\IsAssociatedCounter}[3]{% + \ifcsdef{\@@assoccnt@@generateboundtocounterslist{#1}}{% true branch + \setcounter{@@assoccnt@@internalcounter}{0}% + \renewcommand*{\do}[1]{% + \@@assoccnt@@standardstepcounter{@@assoccnt@@internalcounter}% + }% + \dolistcsloop{\@@assoccnt@@generateboundtocounterslist{#1}}% + \ifnumgreater{\number\value{@@assoccnt@@internalcounter}}{0}{% + #2% + }{% + #3% + }% + }{% + #3% + }% End of \ifcsdef false branch +}% + + +\newcommand{\GetDriverCounter}[1]{% + \setcounter{@@assoccnt@@internalcounter}{0}% + \renewcommand*{\do}[1]{% + ##1% + \ifnumequal{\number\value{@@assoccnt@@internalcounter}}{1}{% + \listbreak}{% + \@@assoccnt@@standardstepcounter{@@assoccnt@@internalcounter}% + }% + }% + \dolistcsloop{\@@assoccnt@@generateboundtocounterslist{#1}}% +}% + +\newcommand{\@@assoccnt@@showassociatedcounterlist}[1]{% + \textcolor{red}{\textbf{#1{ }}}% +}% + +\newcommand{\@@assoccnt@@showdrivercounterlist}[1]{% + \textcolor{blue}{\textbf{#1}} + \ifcsdef{\@@assoccnt@@generatelistname{#1}}{% + \forlistcsloop{\@@assoccnt@@showassociatedcounterlist}{\@@assoccnt@@generatelistname{#1}}% + }{}% + \par% +}% + +\newcommand{\AssociationStatistics}[1][]{% + \forlistcsloop{\@@assoccnt@@showdrivercounterlist}{\@@assoccnt@@drivercounterlist}% +}% + + + %%% The stepcounter wrapper for the standard stepcounter command %%% This is just for convenience, if the command as to be improved/extended later on in future -\newcommand{\@@assoccnt@stepcounter}[1]{% - \@@assoccnt@standardstepcounter{#1}% +\newcommand{\@@assoccnt@@stepcounter}[1]{% + \@@assoccnt@@standardstepcounter{#1}% }% %%% Not needed so far \newcommand{\@@assoccnt@refstepcounter}[1]{% - \@@assoccnt@standardrefstepcounter{#1}% + \@@assoccnt@@standardrefstepcounter{#1}% }% %%%% Redefinition of the \stepcounter command \renewcommand{\stepcounter}[1]{% - \@@assoccnt@standardstepcounter{#1}% Traditional behaviour, since this is expected! + \@@assoccnt@@standardstepcounter{#1}% Traditional behaviour, since this is expected! \ifcsdef{\@@assoccnt@@generatelistname{#1}}{% Check first, whether the list exists at all, - \forlistcsloop{\@@assoccnt@stepcounter}{\@@assoccnt@@generatelistname{#1}}% March through the list + \forlistcsloop{\@@assoccnt@@stepcounter}{\@@assoccnt@@generatelistname{#1}}% March through the list }{% %No list -> do nothing at all }% @@ -155,13 +283,15 @@ AssociatedCountersList% + + %%%% Redefinition of the \stepcounter command \renewcommand{\refstepcounter}[1]{% - \@@assoccnt@standardstepcounter{#1}% Traditional behaviour, since this is expected! + \@@assoccnt@@standardstepcounter{#1}% Traditional behaviour, since this is expected! \protected@edef\@currentlabel% {\csname p@#1\endcsname\csname the#1\endcsname}% \ifcsdef{\@@assoccnt@@generatelistname{#1}}{% Check first, whether the list exists at all, - \forlistcsloop{\@@assoccnt@stepcounter}{\@@assoccnt@@generatelistname{#1}}% March through the list + \forlistcsloop{\@@assoccnt@@stepcounter}{\@@assoccnt@@generatelistname{#1}}% March through the list }{% %No list -> do nothing at all }% -- cgit v1.2.3