diff options
author | Karl Berry <karl@freefriends.org> | 2023-10-11 20:25:00 +0000 |
---|---|---|
committer | Karl Berry <karl@freefriends.org> | 2023-10-11 20:25:00 +0000 |
commit | 12c5dc413d8aee3b5f9469df3ecc3f136f989631 (patch) | |
tree | 1feb79d30c1bca11f0d4780f4ed89c97f7d529e6 /Master/texmf-dist/tex/latex/advice | |
parent | 5ec656d8c6bbc8c9df68368cc5d0c375d40d081f (diff) |
advice (11oct23)
git-svn-id: svn://tug.org/texlive/trunk@68511 c570f23f-e606-0410-a88d-b1316a301751
Diffstat (limited to 'Master/texmf-dist/tex/latex/advice')
-rw-r--r-- | Master/texmf-dist/tex/latex/advice/advice.sty | 488 |
1 files changed, 488 insertions, 0 deletions
diff --git a/Master/texmf-dist/tex/latex/advice/advice.sty b/Master/texmf-dist/tex/latex/advice/advice.sty new file mode 100644 index 00000000000..c10d9e566ea --- /dev/null +++ b/Master/texmf-dist/tex/latex/advice/advice.sty @@ -0,0 +1,488 @@ +%% +%% This is file `advice.sty', +%% generated with the docstrip utility. +%% +%% The original source files were: +%% +%% advice.dtx (with options: `main,latex') +%% +%% This file is a part of Advice, a TeX package implementing a generic +%% framework for extending the functionality of selected commands and +%% environments, available at https://ctan.org/pkg/advice and +%% https://github.com/sasozivanovic/advice. +%% +%% Copyright (c) 2023- Saso Zivanovic <saso.zivanovic@guest.arnes.si> +%% (Sa\v{s}o \v{Z}ivanovi\'{c}) +%% +%% 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 +%% https://www.latex-project.org/lppl.txt and version 1.3c or later is part of +%% all distributions of LaTeX version 2008 or later. +%% +%% This work has the LPPL maintenance status `maintained'. +%% The Current Maintainer of this work is Saso Zivanovic. +%% +%% The files belonging to this work and covered by LPPL are listed in `FILES`. +\ProvidesPackage{advice}[2023/10/10 v1.0.0 Extend commands and environments] +\RequirePackage{collargs} +\pgfkeys{ + /handlers/.install advice/.code={% + \edef\auto@install@namespace{\pgfkeyscurrentpath}% + \def\advice@install@setupkey{advice}% + \def\advice@install@activation{immediate}% + \pgfqkeys{/advice/install}{#1}% + \expanded{\noexpand\advice@install + {\auto@install@namespace}% + {\advice@install@setupkey}% + {\advice@install@activation}% + }% + }, + /advice/install/.cd, + setup key/.store in=\advice@install@setupkey, + activation/.is choice, + activation/.append code=\def\advice@install@activation{#1}, + activation/immediate/.code={}, + activation/deferred/.code={}, +} +\def\advice@install#1#2#3{% + \pgfqkeys{#1}{% + #2/.code 2 args={% + \AdviceSetup{#1}{#2}{##1}{\pgfqkeys{#1/#2}{##2}}% + \pgfqkeys{#1}{try activate, activate={##1}}% + }, + #2'/.code 2 args={% + \AdviceSetup{#1}{#2}{##1}{\pgfqkeys{#1/#2}{##2}}% + }, + #2 csname/.style 2 args={ + #2/.expand once=\expandafter{\csname ##1\endcsname}{##2}, + }, + #2 csname'/.style 2 args={ + #2'/.expand once=\expandafter{\csname ##1\endcsname}{##2}, + }, + #2 key/.style 2 args={ + #2/.expand once=% + \expandafter{\csname pgfk@##1/.@cmd\endcsname}% + {collector=\advice@pgfkeys@collector,##2}, + }, + #2 key'/.style 2 args={ + #2'/.expand once=% + \expandafter{\csname pgfk@##1/.@cmd\endcsname}% + {collector=\advice@pgfkeys@collector,##2}, + }, + activation/.style={/advice/activation/##1={#1}}, + activation=#3, + activate deferred/.code={}, + activate csname/.style={activate/.expand once={\csname##1\endcsname}}, + deactivate csname/.style={activate/.expand once={\csname##1\endcsname}}, + activate key/.style={activate@key={#1/activate}{##1}}, + deactivate key/.style={activate@key={#1/deactivate}{##1}}, + activate@key/.code n args=2{% + \def\advice@temp{}% + \def\advice@do####1{% + \eappto\advice@temp{,\expandonce{\csname pgfk@####1/.@cmd\endcsname}}}% + \forcsvlist\advice@do{##2}% + \pgfkeysalso{##1/.expand once=\advice@temp}% + }, + #2/.cd, + run conditions/.store in=\AdviceRunConditions, + bailout handler/.store in=\AdviceBailoutHandler, + outer handler/.store in=\AdviceOuterHandler, + collector/.store in=\AdviceCollector, + collector options/.code={\appto\AdviceCollectorOptions{,##1}}, + clear collector options/.code={\def\AdviceCollectorOptions{}}, + raw collector options/.code={\appto\AdviceRawCollectorOptions{##1}}, + clear raw collector options/.code={\def\AdviceRawCollectorOptions{}}, + args/.store in=\AdviceArgs, + inner handler/.store in=\AdviceInnerHandler, + options/.code={\appto\AdviceOptions{,##1}}, + clear options/.code={\def\AdviceOptions{}}, + .unknown/.code={% + \eappto{\AdviceOptions}{,\pgfkeyscurrentname={\unexpanded{##1}}}% + }, + run conditions/.default=\AdviceRuntrue, + bailout handler/.default=\relax, + outer handler/.default=\advice@default@outer@handler, + collector/.default=\advice@CollectArgumentsRaw, + collector options/.value required, + raw collector options/.value required, + args/.default=\advice@noargs, + inner handler/.default=\advice@error@noinnerhandler, + options/.value required, + reset/.code={\csname\advice@setup@init@\AdviceType\endcsname}, + after setup/.code={\appto\AdviceAfterSetup{##1}}, + #1/#2=\begin{run conditions=\advice@begin@rc}, + }% +} +\def\AdviceSetup#1#2#3{% + \begingroup + \def\AdviceName{#3}% + \collargs@cs@cases{#3}{% + \def\AdviceType{command}% + \advice@setup@init@command + \advice@setup@i{#3}{#1}{#3}% + }{% + \advice@error@advice@notcs{#1/#2}{#3}% + }{% + \def\AdviceType{environment}% + \advice@setup@init@environment + \advice@setup@i{#3}% + {#1}{#3}% + }% +} +\def\advice@setup@i#1#2#3#4{% + \advice@setup@init@i{#2}{#1}% + \advice@setup@init@I{#2}{#1}% + \def\AdviceAfterSetup{}% + #4% + \advice@setup@save{#2}{#1}% +} +\def\advice@setup@init@common{% + \def\AdviceRunConditions{\AdviceRuntrue}% + \def\AdviceBailoutHandler{\relax}% + \def\AdviceOuterHandler{\advice@default@outer@handler}% + \def\AdviceCollector{\advice@CollectArgumentsRaw}% + \def\AdviceCollectorOptions{}% + \def\AdviceInnerHandler{\advice@error@noinnerhandler}% + \def\AdviceOptions{}% +} +\def\advice@setup@init@command{% + \advice@setup@init@common + \def\AdviceRawCollectorOptions{}% + \def\AdviceArgs{\advice@noargs}% +} +\def\advice@setup@init@environment{% + \advice@setup@init@common + \edef\AdviceRawCollectorOptions{% + \noexpand\collargsEnvironment{\AdviceName}% + \noexpand\collargsEndTagtrue + }% + \def\AdviceArgs{+b}% +} +\advice@setup@init@command +\def\advice@init@i#1#2{\csname advice@i#1//\string#2\endcsname} +\def\advice@init@I#1#2{\csname advice@I#1//\string#2\endcsname} +\let\advice@setup@init@i\advice@init@i +\let\advice@setup@init@I\advice@init@I +\def\advice@setup@save#1#2{% + \expanded{% + \endgroup + \noexpand\csdef{advice@i#1//\string#2}{% + \def\noexpand\AdviceRunConditions{\expandonce\AdviceRunConditions}% + \def\noexpand\AdviceBailoutHandler{\expandonce\AdviceBailoutHandler}% + }% + \noexpand\csdef{advice@I#1//\string#2}{% + \def\noexpand\AdviceOuterHandler{\expandonce\AdviceOuterHandler}% + \def\noexpand\AdviceCollector{\expandonce\AdviceCollector}% + \def\noexpand\AdviceRawCollectorOptions{\expandonce\AdviceRawCollectorOptions}% + \def\noexpand\AdviceCollectorOptions{\expandonce\AdviceCollectorOptions}% + \def\noexpand\AdviceArgs{\expandonce\AdviceArgs}% + \def\noexpand\AdviceInnerHandler{\expandonce\AdviceInnerHandler}% + \def\noexpand\AdviceOptions{\expandonce\AdviceOptions}% + }% + \expandonce{\AdviceAfterSetup}% + }% +} +\pgfkeys{ + /advice/activation/deferred/.style={ + #1/activate/.style={% + activate deferred/.append style={#1/activate={##1}}}, + #1/deactivate/.style={% + activate deferred/.append style={#1/deactivate={##1}}}, + #1/force activate/.style={% + activate deferred/.append style={#1/force activate={##1}}}, + #1/try activate/.style={% + activate deferred/.append style={#1/try activate={##1}}}, + }, + /advice/activation/immediate/.style={ + #1/activate/.code={% + \forcsvlist{\advice@activate{#1}}{##1}% + \advice@activate@forcefalse + \advice@activate@tryfalse + }, + #1/deactivate/.code={% + \forcsvlist{\advice@deactivate{#1}}{##1}% + \advice@activate@forcefalse + \advice@activate@tryfalse + }, + #1/force activate/.is if=advice@activate@force, + #1/try activate/.is if=advice@activate@try, + }, +} +\newif\ifadvice@activate@force +\newif\ifadvice@activate@try +\def\advice@original@csname#1#2{advice@o#1//\string#2} +\def\advice@original@cs#1#2{\csname advice@o#1//\string#2\endcsname} +\def\AdviceGetOriginal#1#2{% + \ifcsname advice@o#1//\string#2\endcsname + \csname advice@o#1//\string#2\expandafter\endcsname + \else + \expandafter#2% + \fi +} +\def\advice@activate#1#2{% + \collargs@cs@cases{#2}% + {\advice@activate@cmd{#1}{#2}}% + {\advice@error@activate@notcsorenv{}{#1}}% + {\advice@activate@env{#1}{#2}}% +} +\def\advice@deactivate#1#2{% + \collargs@cs@cases{#2}% + {\advice@deactivate@cmd{#1}{#2}}% + {\advice@error@activate@notcsorenv{de}{#1}}% + {\advice@deactivate@env{#1}{#2}}% +} +\def\advice@activate@cmd#1#2{% + \ifdef{#2}{% + \ifcsdef{\advice@original@csname{#1}{#2}}{% + \advice@if@our@definition{#1}{#2}{% + \advice@activate@error@activated{#1}{#2}{Command}{already}% + }{% + \ifadvice@activate@force + \advice@activate@cmd@do{#1}{#2}% + \else + \advice@activate@error@activated{#1}{#2}{Command}{already}% + \fi + }% + }{% + \advice@activate@cmd@do{#1}{#2}% + }% + }{% + \advice@activate@error@undefined{#1}{#2}{Command}{}% + }% +} +\def\advice@deactivate@cmd#1#2{% + \ifdef{#2}{% + \ifcsdef{\advice@original@csname{#1}{#2}}{% + \advice@if@our@definition{#1}{#2}{% + \advice@deactivate@cmd@do{#1}{#2}% + }{% + \advice@deactivate@error@changed{#1}{#2}% + }% + }{% + \advice@activate@error@activated{#1}{#2}{Command}{not yet}% + }% + }{% + \advice@activate@error@undefined{#1}{#2}{Command}{de}% + }% +} +\def\advice@if@our@definition#1#2{% + \protected\def\advice@temp{\advice@handle{#1}{#2}}% + \ifx#2\advice@temp + \expandafter\@firstoftwo + \else + \expandafter\@secondoftwo + \fi +} +\def\advice@activate@cmd@do#1#2{% + \cslet{\advice@original@csname{#1}{#2}}#2% + \protected\def#2{\advice@handle{#1}{#2}}% + \PackageInfo{advice (#1)}{Activated command "\string#2"}% +} +\def\advice@deactivate@cmd@do#1#2{% + \letcs#2{\advice@original@csname{#1}{#2}}% + \csundef{\advice@original@csname{#1}{#2}}% + \PackageInfo{advice (#1)}{Deactivated command "\string#2"}% +} +\def\advice@handle#1#2{% + \advice@init@i{#1}{#2}% + \AdviceRunfalse + \AdviceRunConditions + \advice@handle@rc{#1}{#2}% +} +\def\advice@handle@rc#1#2{% + \ifAdviceRun + \expandafter\advice@handle@outer + \else + \AdviceBailoutHandler + \expandafter\advice@original@cs + \fi + {#1}{#2}% +} +\def\advice@handle@outer#1#2{% + \def\AdviceNamespace{#1}% + \def\AdviceName{#2}% + \let\AdviceReplaced\AdviceName + \def\AdviceOriginal{\AdviceGetOriginal{#1}{#2}}% + \advice@init@I{#1}{#2}% + \AdviceOuterHandler +} +\newif\ifAdviceRun +\def\advice@default@outer@handler{% + \AdviceCollector +} +\def\advice@CollectArgumentsRaw{% + \AdviceIfArgs{}{% + \expandafter\GetDocumentCommandArgSpec\expandafter{\AdviceName}% + \let\AdviceArgs\ArgumentSpecification + }% + \expanded{% + \noexpand\CollectArgumentsRaw{% + \noexpand\collargsCaller{\expandonce\AdviceName}% + \expandonce\AdviceRawCollectorOptions + \ifdefempty\AdviceCollectorOptions{}{% + \noexpand\collargsSet{\expandonce\AdviceCollectorOptions}% + }% + }% + {\expandonce\AdviceArgs}% + {\expandonce\AdviceInnerHandler}% + }% +} +\def\advice@noargs@text{\advice@noargs} +\def\AdviceIfArgs{% + \ifx\AdviceArgs\advice@noargs@text + \expandafter\@secondoftwo + \else + \expandafter\@firstoftwo + \fi +} +\def\advice@pgfkeys@collector#1\pgfeov{% + \AdviceInnerHandler{#1}% +} +\def\advice@activate@env#1#2{% + \ifcsdef{\advice@original@csname{#1}{#2}}{% + \advice@activate@error@activated{#1}{#2}{Environment}{already}% + }{% + \csdef{\advice@original@csname{#1}{#2}}{}% + }% +} +\def\advice@deactivate@env#1#2{% + \ifcsdef{\advice@original@csname{#1}{#2}}{% + \csundef{\advice@original@csname{#1}{#2}}{}% + }{% + \advice@activate@error@activated{#1}{#2}{Environment}{not yet}% + }% +} +\def\advice@begin@rc#1\advice@handle@rc#2#3#4{% + \ifcsname\advice@original@csname{#2}{#4}\endcsname + \expandafter\advice@begin@env@rc + \else + \expandafter\advice@original@cs + \fi + {#2}{#3}{#4}% +} +\def\advice@begin@env@rc#1#2#3{% + \advice@init@i{#1}{#3}% + \AdviceRunConditions + \ifAdviceRun + \expandafter\advice@begin@env@outer + \else + \AdviceBailoutHandler + \expandafter\advice@original@cs + \fi + {#1}{#2}{#3}% +} +\def\advice@begin@env@outer#1#2#3{% + \def\AdviceNamespace{#1}% + \def\AdviceName{#3}% + \def\AdviceReplaced{#2{#3}}% + \def\AdviceOriginal{\AdviceGetOriginal{#1}{#2}{#3}}% + \advice@init@I{#1}{#3}% + \AdviceOuterHandler +} +\def\advice@activate@error@activated#1#2#3#4{% + \ifadvice@activate@try + \else + \PackageError{advice (#1)}{#3 "\string#2" is #4 activated}{}% + \fi +} +\def\advice@activate@error@undefined#1#2#3#4{% + \ifadvice@activate@try + \else + \PackageError{advice (#1)}{% + #3 "\string#2" you are trying to #4activate is not defined}{}% + \fi +} +\def\advice@deactivate@error@changed#1#2{% + \ifadvice@activate@try + \else + \PackageError{advice (#1)}{The definition of "\string#2" has changed since we + have activated it. Has somebody overridden our command?}{If you have tried + to deactivate so that you could immediately reactivate, you may want to try + "force activate".}% + \fi +} +\def\advice@error@advice@notcs#1#2{% + \PackageError{advice}{The first argument of key "#1" should be either a single + control sequence or an environment name, not "#2"}{}% +} +\def\advice@error@activate@notcsorenv#1#2{% + \PackageError{advice}{Each item in the value of key "#1activate" should be + either a control sequence or an environment name, not "#2".}{}% +} +\def\advice@error@storecs@notcs#1#2{% + \PackageError{advice}{The value of key "#1" should be a single control sequence, + not "\string#2"}{}% +} +\def\advice@error@noinnerhandler#1{% + \PackageError{advice (\AdviceNamespace)}{The inner handler for + "\expandafter\string\AdviceName" is not defined}{}% +} +\def\AdviceTracingOn{% + \let\advice@init@i\advice@trace@init@i + \let\advice@init@I\advice@trace@init@I +} +\def\AdviceTracingOff{% + \let\advice@init@i\advice@setup@init@i + \let\advice@init@I\advice@setup@init@I +} +\def\advice@trace#1{\immediate\write16{[tracing advice] #1}} +\def\advice@trace@init@i#1#2{% + \advice@trace{Advising \detokenize\expandafter{\string#2} (\detokenize{#1})}% + \advice@setup@init@i{#1}{#2}% + \edef\AdviceRunConditions{% + \expandonce\AdviceRunConditions + \noexpand\advice@trace{\space\space + Executing run conditions: + \detokenize\expandafter{\AdviceRunConditions} + --> + \noexpand\ifAdviceRun true\noexpand\else false\noexpand\fi + }% + }% + \edef\AdviceBailoutHandler{% + \noexpand\advice@trace{\space\space + Executing bailout handler: + \detokenize\expandafter{\AdviceBailoutHandler}}% + \expandonce\AdviceBailoutHandler + }% +} +\def\advice@trace@init@I#1#2{% + \advice@setup@init@I{#1}{#2}% + \edef\AdviceOuterHandler{% + \noexpand\advice@trace{\space\space + Executing outer handler: + \detokenize\expandafter{\AdviceOuterHandler}}% + \expandonce\AdviceOuterHandler + }% + \edef\AdviceCollector{% + \noexpand\advice@trace{\space\space + Executing collector: + \detokenize\expandafter{\AdviceCollector}}% + \noexpand\advice@trace{\space\space\space\space + argument specification: + \detokenize\expandafter{\AdviceArgs}}% + \noexpand\advice@trace{\space\space\space\space + options: + \detokenize\expandafter{\AdviceCollectorOptions}}% + \noexpand\advice@trace{\space\space\space\space + raw options: + \detokenize\expandafter{\AdviceRawCollectorOptions}}% + \expandonce\AdviceCollector + }% + \edef\advice@inner@handler@trace##1{% + \noexpand\advice@trace{\space\space + Executing inner handler: + \detokenize\expandafter{\AdviceInnerHandler}}% + \noexpand\advice@trace{\space\space\space\space + Received arguments: + \noexpand\detokenize{##1}}% + \noexpand\advice@trace{\space\space\space\space + options: + \detokenize\expandafter{\AdviceOptions}}% + \expandonce{\AdviceInnerHandler}{##1}% + }% + \def\AdviceInnerHandler{\advice@inner@handler@trace}% +} +\endinput +%% +%% End of file `advice.sty'. |