%%
%% This is file `t-advice.tex',
%% generated with the docstrip utility.
%%
%% The original source files were:
%%
%% advice.dtx  (with options: `main,context')
%% 
%% 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
%% (<texmf>/doc/generic/advice/)FILES.
%D \module[
%D         file=t-advice.tex,
%D      version=1.1.1,
%D        title=Advice,
%D     subtitle=Extend commands and environments,
%D       author=Saso Zivanovic,
%D         date=2024-03-15,
%D    copyright=Saso Zivanovic,
%D      license=LPPL,
%D ]
\writestatus{loading}{ConTeXt User Module / advice}
\unprotect
\startmodule[advice]
\input miniltx
\input t-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}%
    \normalexpanded{\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={deactivate/.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={\normalunexpanded{##1}}}%
    },
    run conditions/.default=\AdviceRuntrue,
    bailout handler/.default=\relax,
    outer handler/.default=\AdviceCollector,
    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}},
  }%
}
\def\AdviceSetup#1#2#3{%
  \begingroup
  \def\AdviceName{#3}%
  \advice@def@AdviceCsname
  \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
    \expandafter\advice@setup@i\expandafter{\csname start#3\endcsname}%
      {#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{\AdviceCollector}%
  \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{%
  \normalexpanded{%
    \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
    \expandonce{\csname advice@o#1//\string#2\expandafter\endcsname\expandafter}%
  \else
    \normalunexpanded\expandafter{\expandafter#2\expandafter}%
  \fi
}
\begingroup
\catcode`\/=0
\catcode`\\=12
/gdef/advice@backslash@other{\}%
/endgroup
\def\AdviceCsnameGetOriginal#1#2{%
  \ifcsname advice@o#1//\advice@backslash@other#2\endcsname
    \expandonce{\csname advice@o#1//\advice@backslash@other#2\expandafter\endcsname
      \expandafter}%
  \else
    \expandonce{\csname#2\expandafter\endcsname\expandafter}%
  \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}%
  \advice@def@AdviceCsname
  \let\AdviceReplaced\AdviceName
  \def\AdviceOriginal{\AdviceGetOriginal{#1}{#2}}%
  \advice@init@I{#1}{#2}%
  \AdviceOuterHandler
}
\def\advice@def@AdviceCsname{%
  \begingroup
  \escapechar=-1
  \expandafter\expandafter\expandafter\endgroup
  \expandafter\expandafter\expandafter\def
  \expandafter\expandafter\expandafter\AdviceCsname
  \expandafter\expandafter\expandafter{\expandafter\string\AdviceName}%
}
\newif\ifAdviceRun
\def\advice@CollectArgumentsRaw{%
  \AdviceIfArgs{}{%
    \expandafter\GetDocumentCommandArgSpec\expandafter{\AdviceName}%
    \let\AdviceArgs\ArgumentSpecification
  }%
  \normalexpanded{%
    \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{%
  \normalexpanded{%
    \noexpand\advice@activate@cmd{#1}{\expandonce{\csname
        start%
        #2\endcsname}}%
  }%
}
\def\advice@deactivate@env#1#2{%
  \normalexpanded{%
    \noexpand\advice@deactivate@cmd{#1}{\expandonce{\csname
        start%
        #2\endcsname}}%
  }%
}
\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
}
  \long\def\advice@typeout#1{\directlua{texio.write_nl("\luaescapestring{#1}")}}
\def\advice@trace#1{\advice@typeout{[tracing advice] #1}}
\def\advice@trace@init@i#1#2{%
  \advice@trace{Advising \detokenize\expandafter{\string#2} (\detokenize{#1})}%
  \advice@trace{\space\space Original command meaning:
    \expandafter\expandafter\expandafter\meaning\advice@original@cs{#1}{#2}}%
  \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}}%
    \normalunexpanded{%
      \gdef\advice@collargs@return{0}%
      \appto\AdviceRawCollectorOptions{\advice@remember@collargs@return}%
    }%
    \expandonce\AdviceCollector
  }%
  \edef\advice@inner@handler@trace@do{%
    \noexpand\advice@trace{\space\space
      Executing inner handler:
      \detokenize\expandafter{\AdviceInnerHandler}}%
    \noexpand\advice@trace{\space\space\space\space
      Received arguments\noexpand\advice@inner@handler@trace@printcollargsreturn:
      \noexpand\detokenize\noexpand\expandafter{\normalunexpanded{\the\toks0}}}%
    \noexpand\advice@trace{\space\space\space\space
      Options:
      \detokenize\expandafter{\AdviceOptions}}%
    \expandonce{\AdviceInnerHandler}%
  }%
  \def\AdviceInnerHandler{\advice@inner@handler@trace}%
}
\def\advice@remember@collargs@return{%
  \global\let\advice@collargs@return\collargsReturn
}
\def\advice@inner@handler@trace{%
  \ifnum\advice@collargs@return=0
    \expandafter\advice@inner@handler@trace@i
  \else
    \expandafter\advice@inner@handler@trace@ii
  \fi
}
\def\advice@inner@handler@trace@i#1{%
  \toks0={#1}%
  \advice@inner@handler@trace@do{#1}%
}
\def\advice@inner@handler@trace@ii{%
  \expandafter\toks\expandafter0\expandafter{\the\collargsArgs}%
  \advice@inner@handler@trace@do
}
\def\advice@inner@handler@trace@printcollargsreturn{%
  \ifnum\advice@collargs@return=0
  \else
    \space(collargs return=%
    \ifcase\advice@collargs@return braced\or plain\or no\fi
    )%
  \fi
}
\stopmodule
\protect
\endinput
%%
%% End of file `t-advice.tex'.
