% -------------------------------------------------------------------------- % the CNTFORMATS package % % A different way to read counters % % This package is part of the exsheets bundle % -------------------------------------------------------------------------- % Clemens Niederberger % Web: https://bitbucket.org/cgnieder/exsheets/ % E-Mail: contact@mychemistry.eu % -------------------------------------------------------------------------- % Copyright 2012 Clemens Niederberger % % This work may be distributed and/or modified under the % conditions of the LaTeX Project Public License, either version 1.3 % 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.3 or later is part of all distributions of LaTeX % version 2005/12/01 or later. % % This work has the LPPL maintenance status `maintained'. % % The Current Maintainer of this work is Clemens Niederberger. % -------------------------------------------------------------------------- % The cntformats package consists of the files % - cntformats.sty % -------------------------------------------------------------------------- % If you have any ideas, questions, suggestions or bugs to report, please % feel free to contact me. % -------------------------------------------------------------------------- \def\@cntfmts@date{2012/11/08} \def\@cntfmts@version{v0.4} \ProvidesPackage{cntformats}[\@cntfmts@date\space \@cntfmts@version\space A different way to read counters.] \RequirePackage{etoolbox} % -------------------------------------------------------------------------- % message handling \def\@cntfmts@error@message{% For details have a look at the `exsheets' manual.} \def\@cntfmts@create@message#1{% \ifstrequal{#1}{Error} {% \lowercase{\csdef{@cntfmts@#1}}##1{% \csuse{Package#1}{cntformats}{##1}{\@cntfmts@error@message}}% }{% \lowercase{\csdef{@cntfmts@#1}}##1{% \csuse{Package#1}{cntformats}{##1}}% }} \@cntfmts@create@message{Error} \@cntfmts@create@message{Warning} \@cntfmts@create@message{WarningNoLine} \@cntfmts@create@message{Info} \def\@cntfmts@err@already@defined#1{% \@cntfmts@error{The counter `#1' already exists!}} \def\@cntfmts@err@unknown@counter#1{% \@cntfmts@error{The counter `#1' is undefined!}} \def\@cntfmts@err@pattern@defined#1#2{% \@cntfmts@error{The pattern `#2' for module `#1' is already defined!}} \def\@cntfmts@err@pattern@undefined#1#2{% \@cntfmts@error{The pattern `#2' for module `#1' is undefined!}} % ---------------------------------------------------------------------------- % tokenlist analyzing and manipulating % if you happen to read this code and notice some obvious reasons why these % macros shoudn't be used like this, please send me your improved version % (seriously! But please explain why yours is better) \def\ifintl#1#2{% \def\@cntfmts@intl@tmpa##1#2{}% \expandafter\if\expandafter\relax\expandafter \detokenize\expandafter{\@cntfmts@intl@tmpa#1{}{}#2}\relax% \expandafter\@secondoftwo \else \expandafter\@firstoftwo \fi } \def\ifintlcs#1{% \expandafter\ifintl\expandafter{#1}} \long\def\replaceonceincs#1#2#3{% \ifintlcs#1{#2}% {\@cntfmts@replace@once@incs#1{#2}{#3}}{}% } \long\def\@cntfmts@replace@once@incs#1#2#3{% \def\@cntfmts@replo@tmpa##1#2##2\q@stop{% \def#1{##1#3##2}}% \expandafter\@cntfmts@replo@tmpa#1\q@stop } \long\def\replaceallin#1#2#3{% \def\@cntfmts@repla@tmpa{#1}% \replaceonceincs\@cntfmts@repla@tmpa{#2}{#3}% \ifintlcs\@cntfmts@repla@tmpa{#2}% {\expandafter\replaceallin\expandafter{\@cntfmts@repla@tmpa}{#2}{#3}}% {\expandonce\@cntfmts@repla@tmpa}% } \long\def\replaceallincs#1#2#3{% \replaceonceincs#1{#2}{#3}% \ifintlcs#1{#2}{\replaceallincs#1{#2}{#3}}{}% } % ---------------------------------------------------------------------------- % expansion tools % heavily inspired by expl3's \exp_args:N \long\def\@cntfmts@getnextbraced#1#2#3{#2\@cntfmts@firstofone{#3{#1}}} \long\def\@cntfmts@firstofone#1{#1} \long\def\@cntfmts@braced@unexpanded#1\@cntfmts@firstofone#2#3{% #1\@cntfmts@firstofone{#2{#3}}} \long\def\@cntfmts@braced@expandedonce#1\@cntfmts@firstofone#2#3{% \expandafter\@cntfmts@getnextbraced\expandafter{#3}{#1}{#2}} \long\def\@cntfmts@expand@first{% \@cntfmts@braced@expandedonce \@cntfmts@firstofone} \long\def\@cntfmts@expand@second{% \@cntfmts@braced@unexpanded \@cntfmts@braced@expandedonce \@cntfmts@firstofone} \long\def\@cntfmts@expand@third{% \@cntfmts@braced@unexpanded \@cntfmts@braced@unexpanded \@cntfmts@braced@expandedonce \@cntfmts@firstofone} % ---------------------------------------------------------------------------- % expandable commands with optional argument (and no mandatory) % this is probably not very robust. If you know what you're doing you're % probably able to define a better version yourself. If not, don't use it \long\def\@cntfmts@isopt@#1[#2\q@marker#3#{% \if\relax\detokenize{#1#2}\relax \expandafter\@firstoftwo \else \expandafter\@secondoftwo \fi} \long\def\@cntfmts@isopt#1#2#3{% \@cntfmts@isopt@#1\q@marker[\q@marker{#2#1}{#2[{#3}]{#1}}} \long\def\@cntfmts@defwopt#1[#2]#3{% \long\def#1##1{\@cntfmts@isopt{##1}{\csuse{\@cntfmts@strip@bs#1@opt}}{#2}}% \long\csdef{\@cntfmts@strip@bs#1@opt}[##1]{#3}} \def\@cntfmts@strip@bs{\expandafter\@gobble\string} % ---------------------------------------------------------------------------- % #1: module % #2: counter \def\@cntfmts@def@counter@read#1#2#3{% \@cntfmts@expand@second\csdef {@#1@read@#3@counter}% {\csname @#1@read@#2@counter\endcsname}} % create pattern for an existing counter: % #1: module % #2: counter % #3: id \newcommand*\@cntfmts@add@counter@pattern[3][cntfmts]{% \ifcsdef{the#2} {}{\@cntfmts@err@unknown@counter{#2}}% \ifcsdef{@#1@#2@counter} {\@cntfmts@err@pattern@defined{#1}{#2}} {\csdef{@#1@#2@counter}{}}% \listcsadd{@#1@counter@ids}{#3}% \@cntfmts@def@counter@read{#1}{#2}{#3}% } \newcommand*\@cntfmts@add@counter@pattern@nostar[3][cntfmts]{% \@cntfmts@add@counter@pattern[#1]{#2}{#3}% \@cntfmts@expand@third \@cntfmts@create@read@counter{#1}{#2}{\csname c@#2\endcsname}} \newrobustcmd*\AddCounterPattern{% \@ifstar {\@cntfmts@add@counter@pattern} {\@cntfmts@add@counter@pattern@nostar}} \@onlypreamble\AddCounterPattern % create pattern for a new counter % #1: counter % #2: id \newcommand*\@cntfmts@new@counter@pattern[3][cntfmts]{% \ifcsdef{the#2} {\@cntfmts@err@counter@defined{#2}}{}% \newcounter{#2}% \listcsadd{@#1@counter@ids}{#3}% \@cntfmts@def@counter@read{#1}{#2}{#3}% \csdef{@#1@#2@counter}{} } \newcommand*\@cntfmts@new@counter@pattern@nostar[3][cntfmts]{% \@cntfmts@new@counter@pattern[#1]{#2}{#3}% \@cntfmts@expand@third \@cntfmts@create@read@counter{#1}{#2}{\csname c@#2\endcsname}} \newrobustcmd*\NewCounterPattern{% \@ifstar {\@cntfmts@new@counter@pattern} {\@cntfmts@new@counter@pattern@nostar}} \@onlypreamble\NewCounterPattern % renew pattern: \newcommand*\@cntfmts@renew@counter@pattern[3][cntfmts]{% \ifcsdef{the#2} {}{\@cntfmts@err@unknown@counter{#2}}% \ifcsdef{@#1@#2@counter}{} {\@cntfmts@err@pattern@undefined{#1}{#2}}% \ifinlistcs{@#1@counter@ids}{#3} {}{\listcsadd{@#1@counter@ids}{#3}}% \@cntfmts@def@counter@read{#1}{#2}{#3}% } \newcommand*\@cntfmts@renew@counter@pattern@nostar[3][cntfmts]{% \@cntfmts@renew@counter@pattern[#1]{#2}{#3}% \@cntfmts@expand@third \@cntfmts@create@read@counter{#1}{#2}{\csname c@#2\endcsname}} \newrobustcmd\RenewCounterPattern{% \@ifstar {\@cntfmts@renew@counter@pattern} {\@cntfmts@renew@counter@pattern@nostar}} \@onlypreamble\RenewCounterPattern % ---------------------------------------------------------------------------- % assign a different internal command to than \c@ % can/must be used after a call from \AddCounterPattern* or % \NewCounterPattern* % #1: module % #2: counter % #3: internal command \def\@cntfmts@create@read@counter#1#2#3{% \expandafter\@cntfmts@defwopt\csname @#1@read@#2@counter\endcsname[]{% \ifblank{##1} {\@arabic{#3}} {\csuse{@cntfmts@counter@type@##1}{#3}}% }% } \newrobustcmd*\ReadCounterFrom[3][cntfmts]{% \@cntfmts@create@read@counter{#1}{#2}{#3}} % ---------------------------------------------------------------------------- % pattern formats % #1: key % #2: number presentation command like \@alph \def\@cntfmts@new@pattern@format#1#2{% \csdef{@cntfmts@counter@type@#1}{#2}} \newrobustcmd*\NewPatternFormat[2]{% \@cntfmts@new@pattern@format{#1}{#2}} \@onlypreamble\NewPatternFormat % ---------------------------------------------------------------------------- % interpret and print pattern: % #1: module % #2: list % #3: pattern \def\@cntfmts@read@counter@pattern#1#2#3{% \def\@cntfmts@parsed@pattern{#3\relax}% \forlistcsloop{\@cntfmts@replace@pattern{#1}}{#2}% } % #1: module % #2: pattern-key \def\@cntfmts@replace@pattern#1#2{% \replaceallincs\@cntfmts@parsed@pattern {#2}{{}\csuse{@#1@read@#2@counter}}} \newrobustcmd*\ReadCounterPattern[2][cntfmts]{% \@cntfmts@read@counter@pattern{#1}{@#1@counter@ids}{#2}\@cntfmts@parsed@pattern} \newrobustcmd*\ReadCounterPatternFrom[2][cntfmts]{% \@cntfmts@expand@third\@cntfmts@read@counter@pattern{#1}{@#1@counter@ids}{#2}% \@cntfmts@parsed@pattern} % #1: save pattern in % #2: save interpretation in % #3: pattern % #4: module \newcommand*\@cntfmts@save@counter@pattern[4]{% \@cntfmts@read@counter@pattern{#4}{@#4@counter@ids}{#3}% \let#2\@cntfmts@parsed@pattern \def#1{#3}% } \newcommand*\@cntfmts@esave@counter@pattern[4]{% \@cntfmts@read@counter@pattern{#4}{@#4@counter@ids}{#3}% \edef#2{\@cntfmts@parsed@pattern}% \def#1{#3}% } \newrobustcmd*\SaveCounterPattern[4][cntfmts]{% \@cntfmts@save@counter@pattern{#2}{#3}{#4}{#1}} \newrobustcmd*\SaveCounterPatternFrom[4][cntfmts]{% \@cntfmts@expand@third\@cntfmts@save@counter@pattern{#2}{#3}{#4}{#1}} \newrobustcmd*\eSaveCounterPattern[4][cntfmts]{% \@cntfmts@esave@counter@pattern{#2}{#3}{#4}{#1}} \newrobustcmd*\eSaveCounterPatternFrom[4][cntfmts]{% \@cntfmts@expand@third\@cntfmts@esave@counter@pattern{#2}{#3}{#4}{#1}} % ---------------------------------------------------------------------------- % predefined formats and pattern \NewPatternFormat{a}{\@alph} \NewPatternFormat{A}{\@Alph} \NewPatternFormat{1}{\@arabic} \NewPatternFormat{r}{\@roman} \NewPatternFormat{R}{\@Roman} \ifdef\theparagraph {\AddCounterPattern{paragraph}{pg}}{} \ifdef\thesubsubsection {\AddCounterPattern{subsubsection}{ssse}}{} \ifdef\thesubsection {\AddCounterPattern{subsection}{sse}}{} \ifdef\thesection {\AddCounterPattern{section}{se}}{} \ifdef\thechapter {\AddCounterPattern{chapter}{ch}}{} \endinput