summaryrefslogtreecommitdiff
path: root/macros/latex/contrib/knowledge/knowledge-code.dtx
diff options
context:
space:
mode:
Diffstat (limited to 'macros/latex/contrib/knowledge/knowledge-code.dtx')
-rw-r--r--macros/latex/contrib/knowledge/knowledge-code.dtx3670
1 files changed, 3670 insertions, 0 deletions
diff --git a/macros/latex/contrib/knowledge/knowledge-code.dtx b/macros/latex/contrib/knowledge/knowledge-code.dtx
new file mode 100644
index 0000000000..22bb364790
--- /dev/null
+++ b/macros/latex/contrib/knowledge/knowledge-code.dtx
@@ -0,0 +1,3670 @@
+% \iffalse
+% !TEX encoding = UTF-8 Unicode
+% !TEX TS-program = pdflatex
+%
+%
+%
+% meta-comment
+%
+% Copyright (C) 2017-2019 by Thomas Colcombet
+% -----------------------------------
+%
+% 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.
+%
+% \fi
+%
+% \iffalse
+%<head>\usepackage{expl3}
+%<head>\ProvidesExplPackage{knowledge}{2019/02/16}{1.16}{}
+%<*driver>
+\def\knowledgecode{active}
+\input{knowledge.tex}
+%</driver>
+% \fi
+%
+% \CheckSum{0}
+%
+%
+% \changes{1.01}{2017/06/11}{Initial version} %
+% \changes{1.02}{2017/06/28}{bug fixes} %
+% \changes{1.03}{2017/07/27}{scoping,bug fixes} %
+% \changes{1.04}{2017/07/28}{minor changes,bug fixes} %
+% \changes{1.05}{2017/09/26}{minor changes,bug fixes} %
+% \changes{1.06}{2017/10/10}{bug correction} %
+% \changes{1.07}{2017/10/15}{minor improvements} %
+% \changes{1.08}{2017/10/17}{minor changes and reorganization of the files} %
+% \changes{1.09}{2017/10/31}{minor changes} %
+% \changes{1.10}{2018/02/17}{bug fixes} %
+% \changes{1.11}{2018/05/17}{bug fixes} %
+% \changes{1.12}{2018/07/26}{bug fixes} %
+% \changes{1.13}{2018/11/21}{bug fixes} %
+% \changes{1.14}{2018/11/22}{bug fix} %
+% \changes{1.15}{2019/01/23}{doc change} %
+% \changes{1.16}{2019/02/15}{correct anchor point locations} %
+% \GetFileInfo{knowledge.sty} %
+% \DoNotIndex{}
+%
+%
+%\let\ifcode\iffalse
+%
+%%%%%%%%%%
+%
+% \section{Implementation}
+% \label{section:code}
+%
+% \subsection{README.md}
+%
+%<*readme>
+% \begin{macrocode}
+This directory contains the package
+
+ name: knowledge
+ license: LaTeX Project Public License version 1.2 or above
+ version: v1.16
+ date: 2019/02/15
+ author: Thomas Colcombet
+ mail: thomas.colcombet@irif.fr
+ web: https://www.irif.fr/~colcombe/knowledge_en.html
+
+Purpose:
+ The knowledge package for LaTeX offers a systematic way to handle
+ notions/concepts/terms throughout a document. In combination with
+ hyperref, it is used for easily handling links inside a document (every
+ use of a concept is linked to its introduction), or outside the document
+ (for centralizing the url's in a separate part). It also helps building an
+ index, and deals with scoping of concepts as well as mathematics.
+ It is designed to--as much as possible--not interfere with the writing of
+ the document.
+
+Install:
+ It is sufficient to have the file knowledge.sty accessible by LaTeX.
+ It can be produced by `make knowledge.sty' if necessary.
+ The documentation is in the file knowledge.pdf.
+ A starting example can be found in knowledge-example.tex.
+
+Content of the file knowledge-sources.zip:
+ - README.md: this file generated while compiling knowledge.ins,
+ the content is in knowledge-code.dtx
+ - knowledge.sty: the package file (generated using knowledge.ins)
+ - knowledge.pdf: the user documentation (generated by compiling
+ knowledge.tex)
+ - knowledge.tex: the tex file producing the knowledge.pdf.
+ - makefile: the makefile. Use 'make all' to generate knowledge.sty
+ and knowledge.pdf. It can also: clean the directory, make zip
+ version of the sources, or ready for CTAN.
+ - knowledge.ins: is the file generating knowledge.sty and
+ README.md from knowledge-code.dtx (using docstrip).
+ - knowledge-code.dtx: most of the code. Can be compiled to
+ provided a longer documentation.
+ - knowledge-configuration.dtx: file containing part of the configuration.
+ - knowledge-utils.dtx: file containing several pieces of code not really
+ related specifically to knowledge
+ - knowledge-example.tex: an example file.
+
+% \end{macrocode}
+%</readme>
+% \subsection{Code preparation}
+%<*head>
+% \begin{macrocode}
+\RequirePackage{l3keys2e}
+\RequirePackage{etoolbox}
+\RequirePackage{xparse}
+\RequirePackage{etoolbox}
+\bool_if_exist:NTF\knowledge_package_loaded_bool
+ {\endinput}
+ {\bool_new:N\knowledge_package_loaded_bool
+ \bool_set_true:N\knowledge_package_loaded_bool}
+% \end{macrocode}
+% \begin{macrocode}
+% \end{macrocode}
+%</head>
+%\begin{center}
+% The content of \texttt{knowledge-utils.sty} is inserted here.\\
+%\end{center}
+%<*package>\\
+% Macros to skip pieces of code depending on some bool. This can certainly be done differently.
+% \begin{macrocode}
+\cs_new:Nn\knowledge_begin_module_if:n
+ {\bool_if:NF#1\knowledge_skip_module:}
+\cs_new:Npn\knowledge_skip_module:#1\knowledge_end_module:
+ {}
+\cs_new:Nn\knowledge_end_module:
+ {}
+% \end{macrocode}
+%
+%\AP One defines the code of \csintro{\klparse_ifnextchar:NTF}
+% which is a link to \cs{\@ifnextchar},
+% as well as the constant \csintro{\klparse_novalue_tl} which contains
+% the token list corresponding to a non-given optional argument
+% as used in the \kl(package){xparse} package.
+%
+% \begin{macrocode}
+\cs_set_eq:Nc\klparse_ifnextchar:NTF{@ifnextchar}
+% \end{macrocode}
+% \begin{macrocode}
+\tl_new:N\klparse_novalue_tl
+\NewDocumentCommand\klparse_setnovalue{o}
+ {\tl_set:Nn\klparse_novalue_tl{#1}}
+\klparse_setnovalue\relax
+% \end{macrocode}
+% \begin{macrocode}
+\cs_new:Npn\klparse_if_novalue:NTF
+ {\tl_if_eq:NNTF\klparse_novalue_tl}
+% \end{macrocode}
+% \begin{macrocode}
+\cs_generate_variant:Nn\tl_to_str:n{V}
+% \end{macrocode}
+%
+% \subsection{Messages of the package}
+%
+%\AP First, some generic messages that are produced using \csintro{\knowledge_info:n},
+% \csintro{\knowledge_warning:n} and \csintro{\knowledge_error:n}
+% as well as the argument expending versions.
+% These are mainly for development purposes.
+% \begin{macrocode}
+\cs_new:Nn\knowledge_info:n
+ {\msg_info:nnn{knowledge}{knowledge~info}{#1}}
+\cs_new:Nn\knowledge_warning:n
+ {\msg_warning:nnn{knowledge}{knowledge~warning}{#1}}
+\cs_new:Nn\knowledge_error:n
+ {\msg_error:nnn{knowledge}{knowledge~error}{#1}}
+% \end{macrocode}
+% The command \csintro{\knowledge_werror:Nn} takes a boolean as argument, and behaves like \cs{\knowledge_error:n} if it is true, and \cs{\knowledge_warning:n} otherwise.
+% \begin{macrocode}
+\cs_new:Npn\knowledge_werror:Nn#1
+ {\bool_if:NTF#1\knowledge_error:n\knowledge_warning:n}
+% \end{macrocode}
+% \begin{macrocode}
+\msg_new:nnnn{knowledge}{knowledge~info}{#1}{#2}
+\msg_new:nnnn{knowledge}{knowledge~warning}{#1}{#2}
+\msg_new:nnnn{knowledge}{knowledge~error}{#1}{#2}
+% \end{macrocode}
+% \begin{macrocode}
+\cs_generate_variant:Nn\knowledge_info:n{x}
+\cs_generate_variant:Nn\knowledge_warning:n{x}
+\cs_generate_variant:Nn\knowledge_error:n{x}
+% \end{macrocode}
+%\AP We provide now the `official' messages \csintro{knowledge~recursion}, \csintro{knowledge~unknown},
+% \csintro{knowledge~unknown~in~scope}, \csintro{knowledge~unknown~label}, \csintro{package~required} and \csintro{knowledge~exists}.
+% \begin{macrocode}
+\msg_new:nnn{ knowledge }{ knowledge~recursion }
+ { The~knowledges~are~probably~cyclic,~starting~from~'#1'~(namespace~'#2'),~
+ currently~at~'#3'.}
+% \end{macrocode}
+% \begin{macrocode}
+\msg_new:nnn{ knowledge }{ knowledge~unknown }
+ {The~knowledge~'#1'~could~not~be~found~in~scopes~<~#3~>~(namespace~'#2').}
+% \end{macrocode}
+% \begin{macrocode}
+\msg_new:nnn{ knowledge }{ knowledge~unknown~in~scope }
+ {The~knowledge~'#1'~could~not~be~found~in~scope~'#3'~(namespace~'#2').}
+% \end{macrocode}
+% \begin{macrocode}
+\msg_new:nnn{ knowledge }{ knowledge~unknown~label }
+ {The~label~'#2'~could~not~be~found~while~searching~for~'#1'.~Possibly~rerun~latex.}
+% \end{macrocode}
+% \begin{macrocode}
+\msg_new:nnn{ knowledge }{ package~required }
+ {In~order~to~use~directive~'#1',~please~load~package~or~use~option~'#2'.}
+% \end{macrocode}
+% \begin{macrocode}
+\msg_new:nnn{ knowledge }{ knowledge~exists }
+ { The~knowledge~'#1'~in~scope~'#2'~(namespace~'#3')~already~exists. }
+% \end{macrocode}
+%
+%\AP The messages when there is a problem with scoping are \csintro{area~exists}, \csintro{area~not~exist},
+% \csintro{empty~pop}, \csintro{no~pushing~here}, \csintro{no~popping},
+% \csintro{no~popping~here}, \csintro{unknown~label} and \csintro{area~not~in~context}.
+% \begin{macrocode}
+\msg_new:nnn{scope}{area~exists}{Area~'#1'~already~exists.}
+\msg_new:nnn{scope}{area~not~exist}{Area~'#1'~does~not~exist.}
+\msg_new:nnn{scope}{empty~pop}{Attempt~to~pop~an~empty~area~stack.}
+\msg_new:nnn{scope}{no~pushing~here}
+ {Not~allowed~to~open~'\scope_pushed_area_tl'~here.~
+ Current~stack~is~<\seq_use:Nn\scope_instances_stack_seq{::}>.}
+\msg_new:nnn{scope}{no~popping}{Not~allowed~to~close~'\scope_popped_area_tl'.}
+\msg_new:nnn{scope}{no~popping~here}
+ {Not~allowed~to~close~'\scope_popped_area_tl'~here~(at~'\scope_top_area_tl').}
+\msg_new:nnn{scope}{unknown~label}
+ {\tl_if_empty:nTF{#2}{}{\exp_not:n{#2}}:
+ ~Unknown~label~`#1'.~Possibly~rerun~latex.}
+\msg_new:nnn{scope}{area~not~in~context}
+ {\tl_if_empty:nTF{#2}{}{\exp_not:n{#2}}:
+ ~The~area~`#1'~can't~be~found~in~context.~Possibly~rerun~latex.}
+% \end{macrocode}
+%\AP We define new the final messages, that are thrown at the end of the compilation as a recap that some problems occured. These are: \csintro{recap~unknown~knowledge}, \csintro{recap~autoref~introduced~twice} and \csintro{recap~autoref~not~introduced}.
+% \begin{macrocode}
+\msg_new:nnn{knowledge}{recap~unknown~knowledge}
+ {Some~knowledge~are~not~defined.~See~the~'.diagnose'~file~for~more~information.}
+\msg_new:nnn{knowledge}{recap~autoref~introduced~twice}
+ {Some~knowledge~is~introduced~twice.~See~the~'.diagnose'~file~for~more~information.}
+\msg_new:nnn{knowledge}{recap~autoref~not~introduced}
+ {Some~knowledge~is~used~but~not~introduced.~See~the~'.diagnose'~file~for~more~information.}
+% \end{macrocode}
+%
+%
+% \subsection{Option and packages}
+%
+%
+% \subsubsection{Configuration option}
+%
+% The options exist in two forms, the one that usable during the loading of the package,
+% and the one that can be used in \cs{\knowledgeconfigure}, i.e., at some other locations in the document.
+% The configuration options can be used when loading the package, however, these are first
+% appended to the tl variable \csintro{\knowledge_configuration_pending_tl}, and executed at the end of the loading.
+% This is important, since automatic configuration needs, for instance, to know if the \kl{composition mode}, or the \kl{paper mode} is used right now, but one cannot expect the user to declare the options in this particular order.
+%
+% \ToImprove{I do not know why, but \cs{\ProcessKeysOptions} removes the spaces in the parameters.
+% So we have to do the same if we want to load options this way. This does not seem canonical.}
+%
+% We first provide a token list that stores the configurations (which are different from the options).
+% \begin{macrocode}
+\tl_clear_new:N\knowledge_configuration_pending_tl
+% \end{macrocode}
+%
+%
+% \paragraph{Configuration options}
+% We provide here the code that is used to create new options for \cs{\knowledgeconfigure}.
+% At the same time, it sets at package loading these options to be `posponed' (these will be executed)
+% when the package loading is completed.
+% \begin{macrocode}
+\newrobustcmd\knowledgeconfigure[1]{
+ \keys_set:nn{ knowledge~configuration~options }{#1}
+}
+% \end{macrocode}
+%
+% \begin{quote}
+% \csintro{\KnowledgeConfigureBooleanOption}[\cs{optional_bool}]\{option name\}\par
+% \csintro{\KnowledgeConfigureBooleanOptionTF}[\cs{optional_bool}]\{option name\}\par
+% ~~~~~~~~\{true code\}\{false code\}
+% \end{quote}
+% It takes an optional bool (of \kl(package){expl3}) and the name of the configuration option.
+% The option is defined both in \cs{knowledge~package~options},
+% and in \cs{knowledge~configuration~options}.
+% In the former case, the option is simply appended to \cs{\knowledge_configuration_pending_tl} for
+% being executed at the end of package loading.
+% \begin{macrocode}
+\NewDocumentCommand\KnowledgeConfigureBooleanOption{om}
+ {\KnowledgeConfigureBooleanOptionTF[#1]{#2}{}{}}
+\NewDocumentCommand\KnowledgeConfigureBooleanOptionTF{ommm}{
+ \tl_set:Nn\l_tmpa_tl{#2}
+ \tl_remove_all:Nn\l_tmpa_tl{~}
+ \IfNoValueTF{#1}
+ {\bool_new:c{knowledge_configuration_#2_bool}
+ \exp_args:NcnV\__knowledge_KnowledgeConfigureBooleanOption:Nnnnn
+ {knowledge_configuration_#2_bool}{#2}\l_tmpa_tl{#3}{#4}}
+ {\exp_args:NNnV\__knowledge_KnowledgeConfigureBooleanOption:Nnnnn
+ #1{#2}\l_tmpa_tl{#3}{#4}}
+ }
+\cs_new:Nn\__knowledge_KnowledgeConfigureBooleanOption:Nnnnn{
+ \keys_define:nn{ knowledge~package~options }{
+ #3 .choice:,
+ #3 / true .code:n = {\tl_put_right:Nn\knowledge_configuration_pending_tl{,#2=true}},
+ #3 / false .code:n = {\tl_put_right:Nn\knowledge_configuration_pending_tl{,#2=false}},
+ #3 .default:n = {true}
+ }
+ \keys_define:nn{ knowledge~configuration~options }{
+ #2 .choice:,
+ #2 / true .code:n = {\bool_if:NF#1{\bool_set_true:N#1#4}},
+ #2 / false .code:n = {\bool_if:NT#1{\bool_set_false:N#1#5}},
+ #2 .default:n = {true}
+}}
+% \end{macrocode}
+%\begin{quote}\tt
+% \csintro{\KnowledgeConfigureTrigger}\{option name\}\{code\}
+%\end{quote}
+% triggers the code when the corresponding configuration option is required.
+% \begin{macrocode}
+\NewDocumentCommand\KnowledgeConfigureTrigger{omm}{
+ \IfNoValueTF{#1}
+ {\tl_set:Nn\l_tmpa_tl{#2}
+ \tl_remove_all:Nn\l_tmpa_tl{~}
+ \exp_args:NNV\KnowledgeConfigureTrigger[\l_tmpa_tl]{#2}{#3}}
+ {\keys_define:nn { knowledge~configuration~options }
+ { #2 .code:n = {#3}, #2 .default:V = \klparse_novalue_tl }
+ \keys_define:nn { knowledge~package~options }
+ { #1 .code:n = {\tl_put_right:Nn\knowledge_configuration_pending_tl{,#2={##1}} }}
+ }
+}
+% \end{macrocode}
+%
+%
+%
+% \paragraph{Package loading options}
+%
+% \begin{quote}\tt
+% \csintro{\KnowledgePackageTrigger}\{package option\}\{code\}
+% \end{quote}
+% is similar to \cs{\KnowledgeConfigureTrigger} but only valid at package loading and not in \cs{\knowledgeconfigure}.
+% \begin{macrocode}
+\newrobustcmd\KnowledgePackageTrigger[2]
+ { \keys_define:nn{ knowledge~package~options }{ #1 .code:n = {#2} }
+ \keys_define:nn{ knowledge~configuration~options }{
+ #1 .code:n = {\knowledge_error:n
+ {The~configuration~directive~`#1'~can~only~be~used~at~package~loading.}}
+ }}
+% \end{macrocode}
+% \begin{quote}\tt
+% \csintro{\KnowledgePackageBooleanOption}[\cs{optional_bool}]\{optionname\}
+% \end{quote}
+% defines a Boolean package option, the value of which being stored in \cs{optional_bool}.
+% If no \cs{optional_bool} is given, then \cs{\knowledge_configuration_optioname_bool}
+% is chosen.
+% \begin{macrocode}
+\NewDocumentCommand\KnowledgePackageBooleanOption{om}{
+ \tl_set:Nn\l_tmpa_tl{#2}
+ \tl_remove_all:Nn\l_tmpa_tl{~}
+ \IfNoValueTF{#1}
+ {\bool_new:c{knowledge_configuration_#2_bool}
+ \exp_args:NcnV\knowledge_KnowledgePackageBooleanOption:Nnn
+ {knowledge_configuration_#2_bool}{#2}\l_tmpa_tl}
+ {\exp_args:NNnV\knowledge_KnowledgePackageBooleanOption:Nnn
+ #1{#2}\l_tmpa_tl}
+ }
+\cs_new:Nn\knowledge_KnowledgePackageBooleanOption:Nnn{
+ \keys_define:nn{ knowledge~package~options }{
+ #3 .choice:,
+ #3 / true .code:n = {\bool_set_true:N#1},
+ #3 / false .code:n = {\bool_set_false:N#1},
+ #3 .default:n = {true}
+ }
+ \keys_define:nn{ knowledge~configuration~options }{
+ #2 .code:n = {\knowledge_error:n
+ {The~configuration~directive~`#2'~can~only~be~used~at~package~loading.}}
+ }}
+% \end{macrocode}
+%
+%
+% \begin{macrocode}
+\cs_new:Nn\knowledge_option_bool_new:nN{
+ \keys_define:nn{ knowledge~package~options } {
+ #1 .choice: ,
+ #1 / true .code:n = { \bool_gset_true:N#2 },
+ #1 / false .code:n = { \bool_gset_false:N#2 },
+ #1 .default:n = {true}
+ }
+}
+\cs_new:Nn\knowledge_option_bool_new:n
+ {\bool_new:c{knowledge_option_#1_bool}
+ \exp_args:Nnc\knowledge_option_bool_new:nN{#1}{knowledge_option_#1_bool}}
+% \end{macrocode}
+%
+%
+% \subsubsection{List of options that have to be prepared}
+%
+% Code for a single feature. It takes the name of the trigger followed by the code.
+%
+% \begin{macrocode}
+\bool_new:N\knowledge_warningstrict_bool
+\bool_set_false:N\knowledge_warningstrict_bool
+\KnowledgeConfigureBooleanOption[\knowledge_warningstrict_bool]{strict}
+% \end{macrocode}
+% \begin{macrocode}
+\bool_new:N\knowledge_configuration_quotation_bool
+\KnowledgeConfigureBooleanOptionTF[\knowledge_configuration_quotation_bool]{quotation}{\klactivatequotation}{\kldeactivatequotation}
+\KnowledgeConfigureTrigger{protect~quotation}{\kl_protect_environment_quotation:n{#1}}
+% \end{macrocode}
+%
+% Activates or deactivates the line numbering in the "diagnose file".
+% \begin{macrocode}
+\bool_new:N\knowledge_configuration_diagnoseline_bool
+\bool_set_false:N\knowledge_configuration_diagnoseline_bool
+\KnowledgeConfigureBooleanOption[\knowledge_configuration_diagnoseline_bool]{diagnose~line}
+% \end{macrocode}
+%
+% \begin{macrocode}
+\bool_new:N\knowledge_configuration_visibleAP_bool
+\KnowledgeConfigureBooleanOption[\knowledge_configuration_visibleAP_bool]{visible~anchor~points}\KnowledgeConfigureBooleanOption[\knowledge_configuration_visibleAP_bool]{visible~AP}
+% \end{macrocode}
+%
+% \begin{macrocode}
+\bool_new:N\knowledge_hyperlinks_active_bool
+\bool_set_true:N\knowledge_hyperlinks_active_bool
+% \end{macrocode}
+%
+% Modes are stored in \csintro{\knowledge_option_mode_tl}.
+% \begin{macrocode}
+\tl_clear_new:N\knowledge_option_mode_tl
+\KnowledgePackageTrigger{ paper }{\tl_set:Nn\knowledge_option_mode_tl{paper}}
+\KnowledgePackageTrigger{ electronic }{\tl_set:Nn\knowledge_option_mode_tl{electronic}}
+\KnowledgePackageTrigger{ composition }{\tl_set:Nn\knowledge_option_mode_tl{composition}}
+% this one is for compatibility
+\KnowledgePackageTrigger{ final }{\tl_set:Nn\knowledge_option_mode_tl{final}}
+% \end{macrocode}
+%
+% \begin{macrocode}
+\KnowledgeConfigureTrigger{ fix~hyperref~twocolumn }
+ {\knowledgeFixHyperrefTwocolumn}
+\KnowledgeConfigureTrigger{ notion }
+ {\KnowledgeConfigureNotion{notion}}
+\KnowledgeConfigureTrigger{ protect~links }
+ {\kl_kl_nesting_incr:}
+\KnowledgeConfigureTrigger{ unprotect~links }
+ {\kl_kl_nesting_decr:}
+% \end{macrocode}
+%
+%
+%
+% \subsubsection{External package options}
+%
+%\csintro{\knowledge_xcolor_active_bool}, \csintro{\knowledge_xcolor_syntax_bool},
+%\csintro{\knowledge_hyperref_active_bool}, \csintro{\knowledge_hyperref_syntax_bool},
+%\csintro{\knowledge_makeidx_active_bool}, \csintro{\knowledge_makeidx_syntax_bool}
+%
+% First, one tests the package available.
+% \csintro{\package_if_loaded:nTF} tests if a package is loaded.
+% \csintro{\knowledge_option_aci_test_loaded:n} uses it for setting the default values of the booleans
+% \begin{compactitem}
+% \item \csintro{\knowledge_packagename_active_bool} that sets all the functionalities linked to the corresponding package to be active.
+% \item \csintro{\knowledge_packagename_syntax_bool} that states that the syntax is allowed.
+% \end{compactitem}
+% \begin{macrocode}
+\cs_new_eq:Nc\package_if_loaded:nTF{@ifpackageloaded}
+\cs_new:Nn\knowledge_option_aci_test_loaded:n{
+ \bool_new:c{knowledge_#1_active_bool}
+ \bool_new:c{knowledge_#1_syntax_bool}
+ \package_if_loaded:nTF{#1}
+ {\bool_set_true:c{knowledge_#1_active_bool}
+ \bool_set_true:c{knowledge_#1_syntax_bool}}
+ {\bool_set_false:c{knowledge_#1_active_bool}
+ \bool_set_false:c{knowledge_#1_syntax_bool}}
+}
+\knowledge_option_aci_test_loaded:n{hyperref}
+\knowledge_option_aci_test_loaded:n{xcolor}
+\knowledge_option_aci_test_loaded:n{makeidx}
+% \end{macrocode}
+%\begin{quote}\tt
+%\csintro{\knowledge_option_aci_define:n}\{package name\}
+%\end{quote}
+% defines the different possible ways to use the package.
+% \begin{macrocode}
+\cs_new:Nn\knowledge_option_aci_define:n{
+ \keys_define:nn{ knowledge~package~options } {
+ #1 .choice: ,
+ #1 / active .code:n = {
+ \bool_set_true:c{knowledge_#1_active_bool}
+ \bool_set_true:c{knowledge_#1_syntax_bool}},
+ #1 / compatibility .code:n = {
+ \bool_set_false:c{knowledge_#1_active_bool}
+ \bool_set_true:c{knowledge_#1_syntax_bool}},
+ #1 / inactive .code:n = {
+ \bool_set_false:c{knowledge_#1_active_bool}
+ \bool_set_false:c{knowledge_#1_syntax_bool}},
+ #1 .default:n = {active}
+ }}
+% \end{macrocode}
+% \begin{quote}\tt
+% \csintro{\knowledge_option_aci_autoload:nn}\{package name\}\{options for the package\}
+% \end{quote}
+% is called for each package after the options have been processed.
+% It loads the package if required, possibly with options.
+% \begin{macrocode}
+\cs_new:Nn\knowledge_option_aci_autoload:nnn{
+ \bool_if:cTF{knowledge_#1_active_bool}
+ {\package_if_loaded:nTF{#1}{}
+ {\RequirePackage[#2]{#1}{#3}}}
+ {}
+}
+\cs_new:Nn\knowledge_option_aci_autoload:nn
+ {\knowledge_option_aci_autoload:nnn{#1}{#2}{}}
+% \end{macrocode}
+%
+% \paragraph{The real options}
+%
+% \begin{macrocode}
+\knowledge_option_bool_new:n{scope}
+\knowledge_option_aci_define:n{hyperref}
+\knowledge_option_aci_define:n{xcolor}
+\knowledge_option_aci_define:n{makeidx}
+% \end{macrocode}
+%
+% \subsubsection{Executing the package options}
+%
+% \begin{macrocode}
+\ProcessKeysOptions{knowledge~package~options}
+% \end{macrocode}
+%
+% \subsubsection{Options post treatment for the "writing mode"}
+%
+% \begin{macrocode}
+
+\bool_new:N\knowledge_option_composition_bool
+\bool_set_false:N\knowledge_option_composition_bool
+\bool_new:N\knowledge_option_electronic_bool
+\bool_set_false:N\knowledge_option_electronic_bool
+\bool_new:N\knowledge_option_paper_bool
+\bool_set_false:N\knowledge_option_paper_bool
+% \end{macrocode}
+% Testing if the "writing mode" has been chosen by setting \cs{\knowledgepackagemode}.
+% \begin{macrocode}
+\tl_if_exist:NTF\knowledgepackagemode
+ {}
+ {\tl_new:N\knowledgepackagemode
+ \tl_set:Nn\knowledgepackagemode{}}
+% \end{macrocode}
+% \begin{macrocode}
+\tl_if_empty:NTF\knowledgepackagemode
+ {\tl_if_empty:NTF\knowledge_option_mode_tl
+ {\tl_set:Nn\knowledge_option_mode_tl{composition}}
+ {}}
+ {\tl_if_empty:NTF\knowledge_option_mode_tl
+ {\tl_set_eq:NN\knowledge_option_mode_tl\knowledgepackagemode}
+ {\knowledge_info:n{Knowledge~mode~overriden~by~user.}
+ \tl_set_eq:NN\knowledge_option_mode_tl\knowledgepackagemode
+ }}
+% \end{macrocode}
+%
+%
+% \begin{macrocode}
+\keys_define:nn{ knowledge~package~modes }{
+ paper .code:n = {
+ \bool_set_true:N\knowledge_option_paper_bool
+ \bool_set_false:N\knowledge_configuration_visibleAP_bool
+ },
+ electronic .code:n = {
+ \bool_set_true:N\knowledge_option_electronic_bool
+ \bool_set_false:N\knowledge_configuration_visibleAP_bool
+ },
+ composition .code:n = {
+ \bool_set_true:N\knowledge_option_composition_bool
+ \bool_set_true:N\knowledge_configuration_visibleAP_bool
+ },
+ final .code:n = { \knowledge_warning:x{Mode~`final`~is~deprecated,~
+ and~should~be~replaced~by~mode~`paper`.}
+ \tl_set:Nn\knowledge_option_mode_tl{paper}
+ \keys_set:nn{knowledge~package~modes}{paper}},
+ unknown .code:n =
+ {\knowledge_warning:x{Unknown~mode~`\l_keys_key_tl`.}
+ \tl_set:Nn\knowledge_option_mode_tl{ composition }
+ \keys_set:nV{ knowledge~package~modes }{ composition }}
+}
+\keys_set:nV{ knowledge~package~modes }\knowledge_option_mode_tl
+% \end{macrocode}
+%
+%
+% \subsubsection{Options post-treatment for the other packages}
+% \begin{macrocode}
+\knowledge_option_aci_autoload:nnn{ hyperref }{}{\hypersetup{hidelinks}}
+\knowledge_option_aci_autoload:nn{ xcolor }{}
+\knowledge_option_aci_autoload:nn{ makeidx }{}
+% \end{macrocode}
+%
+%
+%
+%
+% \subsection{Scope implementation}
+%
+% The two strings that are used as (hopefully) unique prefixes in the namespace.
+% \begin{macrocode}
+\tl_const:Nn\scope_tl{SC@PE}
+\tl_const:Nn\scopept_tl{SC@PE2}
+% \end{macrocode}
+% \csintro{\scope_instances_stack_seq} contains the stack of instances of areas.
+% \csintro{\scope_top_instance_tl} contains always the topmost instance of the stack.
+% \csintro{\scope_top_area_tl} contains the corresponding \kl{area}.
+% \begin{macrocode}
+\seq_new:N\scope_instances_stack_seq
+\tl_new:N\scope_top_instance_tl
+\tl_new:N\scope_top_area_tl
+% \end{macrocode}
+%
+%
+% \subsubsection{Data structures}
+%
+% Several `data structures' are used internally by the package.
+% \begin{description}
+% \item[\kl{areas}] are zones structuring valid documents. These are typically
+% `\texttt{document}', `\texttt{scope}', `\texttt{section}', `\texttt{subsection}', `\texttt{theorem}', `\texttt{itemize}', `\texttt{item}' and so on.
+% \item[\kl{categories}] are collections of \kl{areas} that share some common behaviours, for instance, the \kl{category} `\texttt{itemize-like}' will aggregate
+% `\texttt{itemize}', `\texttt{enumerate}' \kl{areas}. In particular an `\texttt{item}'
+% \kl{area} is required to have a parent that belongs to the \kl{category} `\texttt{itemize-like}'.
+% \item[\kl{instances}] are the realization of \kl{areas} in a document. Hence `section' is an \kl{area},
+% but each section of a document is an \kl{instance}.
+% \item[\kl{scopept instances}] stands for `phase two'. These are functions that are activated during
+% the second compilation. (and also, under implementation, in the preamble)
+% \item[\kl{knowledges}] are the central notion
+% \end{description}
+%
+% \paragraph{Areas}
+%
+% An \intro{area} is an environment unit such as `\texttt{theorem}', `\texttt{section}', and so on\dots{}
+% Special realization of these \kl{areas} are called `\kl{instances}'.
+% Hence, there is an \kl{area} named `\texttt{section}', and there are potentially
+% many \kl{instances} of this area in the document.
+% Part of the machinery is used for the allocation of \kl{instances}.
+% In some sense, this is a weak form of grammar describing how these can be used.
+% For instance, a subsection has to occur below a section, and opening a section immediately
+% closes the current subsection if it exists.
+%
+% To help the definition, the areas can be grouped into categories in order to share part of the code/definitions.
+% Each time an \kl{area} is defined, a corresponding \kl{category} with same name is also defined.
+%
+% An \kl{area} has some fields. The field X of \kl{area} A
+% can be found in the token of name |\scope_tl.area[A].X|.
+% \begin{compactdesc}
+% \item[\csintro{nesting_int}] is an int counting the nesting level of the area at the current moment.
+% \item[\csintro{count_int}] is an int counting the instances of the area opened so far. It is used (for the moment)
+% in order to uniquely name the instances. It is also used in some tests. It is incremented each time
+% a new \kl{instance} of this area is created.
+% \item[\csintro{name_tl}] is the text name of the \kl{area}.
+% \item[\csintro{pushcode_tl}] is code to be executed when an \kl{instance} of the \kl{area} is created.
+% \item[\csintro{popcode_tl}] is code to be executed just before an \kl{instance} of the \kl{area} is closed.
+% \item[\csintro{autoclose_bool}] is a boolean which, when set to true,
+% means that \kl{instances} of this area may be implicitly closed. This is the case for instance
+% for a `subsection', which can be implicitly closed when another `subsection' is started, or when
+% a `section' is started, or when the document finishes.
+% \item[\csintro{recursive_bool}] is a boolean describing whether such an environment can be opened inside itself.
+% This is more for making the error messages explicit.
+% \item[\csintro{multiple_bool}] is a boolean that tells whether several instances of this area can be defined
+% in the document. This is also mainly for making more explicit the error messages.
+% \item[\csintro{forces_tl}] is the name of an area that has to be opened if one wants to use this area.
+% It is opened if necessary.
+% \item[\csintro{acceptsknowledge_bool}] is a boolean telling whether a knowledge can be associated to an instance of this area.
+% \item[\csintro{labelizable_bool}] tells whether a label can point to such an environment.
+% \item[\csintro{attractsknowledge_bool}] is a boolean that tells whether this area
+% spontaneously catpures the \kl{knowledges} defined in its scope.
+% Hence, a section does not attract knowledges: the document does.
+% However, the user can force a knowledge to only be valid in a section since `section's accept knowledges.
+% \item[\csintro{mandatorybase_seq}] is a \texttt{seq} containing the list of categories that are allowed to
+% be the parent of this area. For instance, \cs{\item}
+% would have \texttt{itemize}, \texttt{compactdesc} and \texttt{enumerate}.
+% \end{compactdesc}
+%
+% \begin{macrocode}
+\tl_new:N\l_self_tl
+% \end{macrocode}
+% \begin{macrocode}
+\cs_new:Nn\scope_area_show:n{
+ \group_begin:
+ \scope_area_if_exist:nTF{#1}
+ { \tl_set:Nx\l_self_tl{\scope_tl.area[#1]}
+ \tl_show:x
+ {Area~name:~\use:c{\l_self_tl.name_tl},~
+ autoclose=\bool_if:cTF{\l_self_tl.autoclose_bool}TF,~
+ recursive=\bool_if:cTF{\l_self_tl.recursive_bool}TF,~
+ multiple=\bool_if:cTF{\l_self_tl.multiple_bool}TF,~
+ scope=\bool_if:cTF{\l_self_tl.scope_bool}TF,~
+ environment=\bool_if:cTF{\l_self_tl.environment_bool}TF,~
+ forces={\use:c{\l_self_tl.forces_tl}},~
+ accepts~knowledge=\bool_if:cTF{\l_self_tl.accepts_knowledge_bool}TF,~
+ attracts~knowledge=\bool_if:cTF{\l_self_tl.attracts_knowledge_bool}TF,~
+ accepts~labels=\bool_if:cTF{\l_self_tl.labelizable_bool}TF.
+ }
+ }
+ {\knowledge_error:n{Unknown~area~`#1'~in~`\noexpand\scope_area_show:n'.}}
+ \group_end:
+}
+% \end{macrocode}
+%
+%
+%
+% Areas are created empty by \cs{\scope_area_create:n}.
+% \begin{macrocode}
+\cs_new:Nn\scope_area_create:n
+ {\group_begin:
+ \tl_set:Nx\l_self_tl{\scope_tl.area[#1]}
+ %
+ \scope_category_add_area:nn{all}{#1}
+ %
+ \tl_new:c{\l_self_tl.name_tl}
+ \tl_gset:cn{\l_self_tl.name_tl}{#1}
+ \seq_new:c{\l_self_tl.category_seq}
+ \seq_gpush:cn{\l_self_tl.category_seq}{all}
+ \seq_gpush:cn{\l_self_tl.category_seq}{#1}
+ \bool_new:c{\l_self_tl.autoclose_bool}
+ \bool_gset_false:c{\l_self_tl.autoclose_bool}
+ \bool_new:c{\l_self_tl.environment_bool}
+ \bool_gset_true:c{\l_self_tl.environment_bool}
+ \bool_new:c{\l_self_tl.multiple_bool}
+ \bool_gset_true:c{\l_self_tl.multiple_bool}
+ \bool_new:c{\l_self_tl.attractsknowledge_bool}
+ \bool_gset_true:c{\l_self_tl.attractsknowledge_bool}
+ \bool_new:c{\l_self_tl.labelizable_bool}
+ \bool_gset_true:c{\l_self_tl.labelizable_bool}
+ \bool_new:c{\l_self_tl.scope_bool}
+ \bool_gset_false:c{\l_self_tl.scope_bool}
+ \bool_new:c{\l_self_tl.acceptsknowledge_bool}
+ \bool_gset_true:c{\l_self_tl.acceptsknowledge_bool}
+ \bool_new:c{\l_self_tl.recursive_bool}
+ \tl_gclear_new:c{\l_self_tl.pushcode_tl}
+ \tl_gclear_new:c{\l_self_tl.popcode_tl}
+ \tl_gclear_new:c{\l_self_tl.forces_tl}
+ \seq_new:c{\l_self_tl.mandatorybase_seq}
+ \int_new:c{\l_self_tl.count_int}
+ \int_gset:cn{\l_self_tl.count_int}{0}
+ \int_new:c{\l_self_tl.nesting_int}
+ \int_gset:cn{\l_self_tl.nesting_int}{0}
+ %
+ \scope_category_if_exist:nTF{#1}
+ {}{\scope_category_create:n{#1}
+ \seq_gpush:cn{\scope_tl.category[#1].areas_seq}{#1}}
+ \group_end:
+}
+% \end{macrocode}
+%
+%
+% \cs{\scope_area_if_exist:nTF}, \cs{\scope_area_if_in_scope:nTF}.
+% \begin{macrocode}
+\cs_new:Npn\scope_area_if_exist:nTF#1
+ {\tl_if_exist:cTF{\scope_tl.area[#1].name_tl}}
+% \end{macrocode}
+% \begin{macrocode}
+\cs_new:Npn\scope_if_triggers_area:nTF#1{
+ \scope_area_if_exist:nTF{#1}
+ {\bool_if:cTF{\scope_tl.area[#1].environment_bool}
+ \use_i:nn
+ \use_ii:nn}
+ \use_ii:nn
+}
+% \end{macrocode}
+% \begin{macrocode}
+\cs_new:Npn\scope_area_if_in_scope:nTF#1
+ {\int_compare:nNnTF
+ {\use:c{\scope_tl.area[#1].nesting_int}}>0}
+% \end{macrocode}
+%
+% \AP The commands \cs{\scope_area_set:nn}
+% introduces (if necessary) and changes the parameters of areas.
+% The first argument is a comma separated list of area names, and the second
+% argument is a comma separated list of key=val commands. The keys available by default are the following:
+%
+% \AP The base command for configuring a scope is \csintro{\ScopeConfigure}\{area~list\}\{directives\}.
+% \begin{macrocode}
+\newrobustcmd\ScopeConfigure[2]
+ {\scope_area_set:nn{#1}{#2}}
+% \end{macrocode}
+% \begin{macrocode}
+\cs_new:Nn\scope_area_set:nn
+ {\clist_map_inline:nn{#1}
+ {\scope_area_set_i:nn{##1}{#2}}}
+% \end{macrocode}
+% \begin{macrocode}
+\tl_new:N\scope_area_tl
+\cs_new:Nn\scope_area_set_i:nn {
+ \scope_area_if_exist:nTF{#1}
+ {}{
+ \scope_area_create:n{#1}}
+ \group_begin:
+ \tl_set:Nx\scope_area_tl{#1}
+ \tl_set:Nx\l_self_tl{\scope_tl.area[\scope_area_tl]}
+ \keys_set:nn{ scope~area~set }{#2}
+ \group_end:}
+% \end{macrocode}
+% \begin{macrocode}
+% \scope_area_tl contains the name of the area under definition
+\keys_define:nn{ scope~area~set } {
+ category .code:n =
+ {\clist_map_inline:nn{#1}
+ {\scope_category_ensure:n{##1}
+ \seq_gpush:cV
+ {\scope_tl.category[##1].areas_seq}\scope_area_tl
+ }},
+ autoclose .choice:,
+ autoclose / false .code:n =
+ {\bool_gset_false:c{\l_self_tl.autoclose_bool}},
+ autoclose / true .code:n =
+ {\bool_gset_true:c{\l_self_tl.autoclose_bool}},
+ parents .code:n =
+ {\seq_gset_from_clist:cn{\l_self_tl.mandatorybase_seq}{#1}},
+ push~code .code:n =
+ {\tl_gput_right:cn{\l_self_tl.pushcode_tl}{#1}},
+ pop~code .code:n =
+ {\tl_gput_right:cn{\l_self_tl.popcode_tl}{#1}},
+ occurrences .choice:,
+ occurrences / once .code:n =
+ {\bool_gset_false:c{\l_self_tl.multiple_bool}
+ \bool_gset_false:c{\l_self_tl.recursive_bool}},
+ occurrences / multiple .code:n = {
+ \bool_gset_true:c{\l_self_tl.multiple_bool}
+ \bool_gset_false:c{\l_self_tl.recursive_bool}},
+ occurrences / recursive .code:n = {
+ \bool_gset_true:c{\l_self_tl.multiple_bool}
+ \bool_gset_true:c{\l_self_tl.recursive_bool}},
+ scope .choice:,
+ scope / true .code:n = {
+ \bool_gset_true:c{\l_self_tl.scope_bool}},
+ scope / false .code:n = {
+ \bool_gset_false:c{\l_self_tl.scope_bool}},
+ environment .choice:,
+ environment / true .code:n = {
+ \bool_gset_true:c{\l_self_tl.environment_bool}},
+ environment / false .code:n = {
+ \bool_gset_false:c{\l_self_tl.environment_bool}},
+ environment .default:n = {true},
+ label .choice:,
+ label / none .code:n = {
+ \bool_gset_false:c{\l_self_tl.labelizable_bool}},
+ label / accepts .code:n = {
+ \bool_gset_true:c{\l_self_tl.labelizable_bool}},
+ knowledge .choice:,
+ knowledge / none .code:n = {
+ \bool_gset_false:c{\l_self_tl.acceptsknowledge_bool}
+ \bool_gset_false:c{\l_self_tl.attractsknowledge_bool}},
+ knowledge / accepts .code:n = {
+ \bool_gset_true:c{\l_self_tl.acceptsknowledge_bool}
+ \bool_gset_false:c{\l_self_tl.attractsknowledge_bool}},
+ knowledge / attracts .code:n = {
+ \bool_gset_true:c{\l_self_tl.acceptsknowledge_bool}
+ \bool_gset_true:c{\l_self_tl.attractsknowledge_bool}},
+ forces .code:n =
+ {\tl_gset:cn{\l_self_tl.forces_tl}{#1}}
+}
+% \end{macrocode}
+%
+% \paragraph{Categories}
+%
+%\begin{compactdesc}
+% \item[\csintro{\scope_category_if_exist:nTF}] tests if a \kl{category} does exist.
+% \item[\csintro{\scope_category_ensure:n}] guarantees that a \kl{category} exists, possibly creating it if necessary.
+% \item[\csintro{\scope_category_create:n}] creates a \kl{category}.
+% \item[\csintro{\scope_category_add_area:nn}] adds an \kl{area} to a \kl{category}.
+% \item[\csintro{\scope_category_use:n}] displays the \kl{category} as a comma separated list of \kl{area} names (expandable).
+% \item[\csintro{\scope_category_show:n}] shows the content of a \kl{category} on the console.
+% \end{compactdesc}
+% \iffalse
+% \begin{macrocode}
+\cs_new:Npn\scope_category_if_exist:nTF#1
+ {\tl_if_exist:cTF{\scope_tl.category[#1].name_tl}}
+% \end{macrocode}
+% \begin{macrocode}
+\cs_new:Nn\scope_category_ensure:n
+ {\scope_category_if_exist:nTF
+ {#1}{}{\scope_category_create:n{#1}}}
+% \end{macrocode}
+% \begin{macrocode}
+\cs_new:Nn\scope_category_create:n
+ {\tl_new:c{\scope_tl.category[#1].name_tl}
+ \tl_gset:cn{\scope_tl.category[#1].name_tl}{#1}
+ \seq_new:c{\scope_tl.category[#1].areas_seq}}
+% \end{macrocode}
+% \begin{macrocode}
+\cs_new:Nn\scope_category_add_area:nn
+ {\scope_category_ensure:n{#1}
+ \seq_gpush:cn{\scope_tl.category[#1].areas_seq}{#2}}
+% \end{macrocode}
+% \begin{macrocode}
+\cs_new:Nn\scope_category_use:n
+ {\seq_use:cn{\scope_tl.category[#1].areas_seq},}
+% \end{macrocode}
+% \begin{macrocode}
+\cs_new:Nn\scope_category_show:n
+ {\seq_show:c{\scope_tl.category[#1].areas_seq}}
+% \end{macrocode}
+%\fi
+%
+%\paragraph{Instances}
+%
+% We now turn to define the fields involved in an instance.
+% There are two series of objects. The ones defined in the first pass of compilation,
+% and used for maintaining the structure of the scopes, and the ones
+% that are used in the second pass, which gather information throughout the
+% whole file. The first one are prefixed by \texttt{scope},
+% the others by \texttt{kaux}.
+% \begin{compactdesc}
+% \item[\intro{instance.area}] is the name of the area it is an instance of.
+% \item[\intro{instance.parent}] is the name of the parent instance.
+% \end{compactdesc}
+% \begin{compactdesc}
+% \item[\csintro{\scope_instance_if_exist:nTF}]
+% \item[\csintro{\scopept_instance_if_exist:nTF}]
+% \item[\csintro{\scopept_label_if_exist:nTF}]
+% \end{compactdesc}
+%\iffalse
+% \begin{macrocode}
+\cs_new:Npn\scope_instance_if_exist:nTF#1
+ {\tl_if_exist:cTF{\scope_tl.instance[#1].area_tl}}
+% \end{macrocode}
+% \begin{macrocode}
+\cs_new:Npn\scopept_instance_if_exist:nTF#1
+ {\tl_if_exist:cTF{\scopept_tl.instance[#1].area_tl}}
+% \end{macrocode}
+% \begin{macrocode}
+\cs_new:Npn\scopept_label_if_exist:nTF#1
+ {\tl_if_exist:cTF{\scopept_tl.label[#1].instance_tl}}
+% \end{macrocode}
+%\fi
+%
+% \subsubsection{Pushing and popping}
+%
+% Introduces the macros \csintro{\scope_area_push:n} and \csintro{\scope_area_pop:n}.
+%
+% The token lists \csintro{\scope_popped_area_tl} and \csintro{\scope_pushed_area_tl}
+% contain the area that triggered the push / the pop. These lists are only meaningful in these macros.
+% \begin{macrocode}
+\tl_new:N\scope_pushed_area_tl
+\tl_new:N\scope_popped_area_tl
+% \end{macrocode}
+% \begin{macrocode}
+\cs_new:Nn\scope_area_pop:n {
+ \tl_gset:Nn\scope_popped_area_tl{#1}
+ \bool_if:cTF{\scope_tl.area[\scope_popped_area_tl].autoclose_bool}
+ {\msg_error:nn{scope}{no~popping}}
+ {\scope_area_pop_i:}}
+% \end{macrocode}
+% \begin{macrocode}
+\cs_new:Nn\scope_area_pop_i: {
+ \tl_if_eq:NNTF\scope_top_area_tl\scope_popped_area_tl
+ {\scope_internal_pop:}
+ {\bool_if:cTF{\scope_tl.area[\scope_top_area_tl].autoclose_bool}
+ {\scope_internal_pop:
+ \scope_area_pop_i:}
+ {\msg_error:nn{scope}{no~popping~here}}}}
+% \end{macrocode}
+% \begin{macrocode}
+\cs_new:Nn\scope_internal_pop: {
+ \use:c{\scope_tl.area[\scope_top_area_tl].popcode_tl}
+ \seq_gpop:NNTF\scope_instances_stack_seq\l_tmpa_tl
+ {\tl_gset_eq:NN\scope_top_instance_tl\l_tmpa_tl
+ \int_gdecr:c{\scope_tl.area[\scope_top_area_tl].nesting_int}
+ \exp_args:NV\knowledge_pop_visible_instances_to:n\scope_top_instance_tl
+ \seq_get:NN\scope_instances_stack_seq\l_tmpa_tl
+ \tl_gset_eq:NN\scope_top_instance_tl\l_tmpa_tl
+ \tl_gset:Nx\scope_top_area_tl
+ {\tl_use:c{\scope_tl.instance[\scope_top_instance_tl].area_tl}}}
+ {\msg_error:nnn{scope}{empty~pop}{}}
+ }
+% \end{macrocode}
+% \begin{macrocode}
+\cs_new:Nn\scope_area_push:n {
+ \tl_gset:Nn\scope_pushed_area_tl{#1}
+ \scope_area_push_i:n{#1}}
+% \end{macrocode}
+% \begin{macrocode}
+\cs_new:Nn\scope_area_push_i:n {
+ \tl_if_empty:cTF{\scope_tl.area[#1].forces_tl}
+ {}
+ {\exp_args:Nx\scope_area_if_in_scope:nTF
+ {\tl_use:c{\scope_tl.area[#1].forces_tl}}
+ {}
+ {\exp_args:Nx\scope_area_push_i:n
+ {\tl_use:c{\scope_tl.area[#1].forces_tl}}}}
+ \scope_area_push_ii:n{#1}
+}
+% \end{macrocode}
+% \begin{macrocode}
+\cs_new:Npn\scope_if_area_in_areaclist:nnTF#1
+ {\exp_args:NnV\clist_if_in:nnTF{#1}\scope_top_area_tl}
+
+\cs_new:Nn\scope_category_expand:n
+ {\clist_use:x{
+ \clist_map:nN{#1}{
+ \seq_use:c{\scope_tl.category[#1].areas_seq},}}}
+
+\cs_new:Nn\scope_categories_expand:n
+ {\clist_map_function:nN{#1}\scope_category_expand:n}
+
+\cs_new:Nn\scope_if_area_in_categoryclist:nnTF
+ {\group_begin:
+ \tl_set:Nx\l_tmpa_tl
+ {\clist_map_function:nN{#2}\scope_category_areas_use:n}
+ \bool_set_false:N\l_tmpa_bool
+ \clist_map_inline:nn{#2}
+ {\scope_category_areas_if_in:nnTF{##1}{#1}
+ {\bool_set_true:N\l_tmpa_bool\seq_map_break:}{}}
+ \bool_if:NTF\l_tmpa_bool
+ {\group_end:#3}
+ {\group_end:#4}
+ }
+
+
+\cs_new:Npn\scope_category_if_area_in:nnTF#1#2
+ {\exp_args:Nnx\seq_if_in:cnTF
+ {\scope_tl.category[#1].areas_seq}{#2}}
+
+\cs_new:Nn\scope_categoryseq_if_area_in:NnTF
+ { \seq_if_empty:NTF#1
+ {#3}
+ {\group_begin:
+ \bool_set_false:N\l_tmpa_bool
+ \seq_map_inline:Nn#1
+ {\seq_if_in:cnTF{\scope_tl.category[##1].areas_seq}{#2}
+ {\bool_set_true:N\l_tmpa_bool\seq_map_break:}{}}
+ \bool_if:NTF\l_tmpa_bool
+ {\group_end:#3}
+ {\group_end:#4}
+ }}
+
+\cs_new:Npn\scope_area_mandatorybase_if_area_in:nnTF#1
+ {\exp_args:Nc\scope_categoryseq_if_area_in:NnTF
+ {\scope_tl.area[#1].mandatorybase_seq}}
+
+\cs_new:Nn\scope_categoryseq_pop_to:N
+ {\exp_args:NNx\scope_categoryseq_if_area_in:NnTF#1{\scope_top_area_tl}
+ {}{\scope_auto_pop:\scope_categoryseq_pop_to:N#1}}
+
+\cs_new:Nn\scope_categoryseq_pop_to:n
+ {\group_begin:
+ \seq_set_from_clist:Nn\l_tmpa_seq{#1}
+ \scope_categoryseq_pop_to:N\l_tmpa_seq
+ \group_end:}
+
+\cs_new:Nn\scope_area_push_ii:n {
+ \seq_if_empty:cTF{\scope_tl.area[#1].mandatorybase_seq}
+ {\scope_internal_push:n{#1}}
+ {\exp_args:Nnx\use:n
+ {\scope_area_mandatorybase_if_area_in:nnTF{#1}}
+ {\scope_top_area_tl}
+ {\scope_internal_push:n{#1}}
+ {\scope_auto_pop:
+ \scope_area_push_ii:n{#1}}}
+ }
+% \end{macrocode}
+% \begin{macrocode}
+\cs_new:Nn\scope_internal_push:n {
+ \ScopeActivate
+ \tl_gset:Nn\scope_top_area_tl{#1}
+ \int_gincr:c{\scope_tl.area[\scope_top_area_tl].nesting_int}
+ \int_gincr:c{\scope_tl.area[\scope_top_area_tl].count_int}
+ % storing the previous top instance
+ \tl_set_eq:NN\l_tmpa_tl\scope_top_instance_tl
+ %naming the new instance
+ \bool_if:cTF{\scope_tl.area[\scope_top_area_tl].multiple_bool}
+ {\tl_gset:Nx\scope_top_instance_tl
+ {\scope_top_area_tl-\int_to_arabic:n{\int_use:c{\scope_tl.area[\scope_top_area_tl].count_int}}}}
+ {\tl_gset_eq:NN\scope_top_instance_tl\scope_top_area_tl}
+ %
+ \exp_args:Nx\knowledge_push_visible_instance:n{\scope_top_instance_tl}
+ \seq_gpush:Nx\scope_instances_stack_seq{\scope_top_instance_tl}
+ %
+ \tl_new:c
+ {\scope_tl.instance[\scope_top_instance_tl].area_tl}
+ \tl_gset:cx
+ {\scope_tl.instance[\scope_top_instance_tl].area_tl}
+ {\scope_top_area_tl}
+ \tl_new:c
+ {\scope_tl.instance[\scope_top_instance_tl].parent_tl}
+ \tl_gset:cx
+ {\scope_tl.instance[\scope_top_instance_tl].parent_tl}
+ {\l_tmpa_tl}
+ %
+ \seq_if_exist:cTF{\scopept_tl.instance[\l_tmpa_tl].context_seq}
+ {\seq_set_eq:Nc\l_tmpa_seq{\scopept_tl.instance[\l_tmpa_tl].context_seq}}
+ {\seq_clear_new:N\l_tmpa_seq}
+ \exp_args:NNx\seq_push:Nn
+ \l_tmpa_seq{\scope_top_instance_tl}
+ \seq_new:c
+ {\scopept_tl.instance[\scope_top_instance_tl].context_seq}
+ \seq_gset_eq:cN
+ {\scopept_tl.instance[\scope_top_instance_tl].context_seq}
+ \l_tmpa_seq
+ %
+ \KAuxWriteX
+ {\KAuxScopeNewInstance{\scope_top_area_tl}{\scope_top_instance_tl}{\l_tmpa_tl}}
+ %
+ \tl_use:c{\scope_tl.area[\scope_top_area_tl].pushcode_tl}
+}
+% \end{macrocode}
+% \begin{macrocode}
+\cs_new:Nn\scope_auto_pop: {
+ \bool_if:cTF{\scope_tl.area[\scope_top_area_tl].autoclose_bool}
+ {\scope_internal_pop:}
+ {\msg_error:nn{scope}{no~pushing~here}}
+ }
+% \end{macrocode}
+%
+%
+% \subsubsection{Inspecting}
+%
+% \csintro{\scope_get_attractive_instance:N} takes a \kl{token list variable},
+% and sets it to contain an
+% instance able to receive knowledges.
+% This is done by inspecting the scope stack until reaching an instance
+% that has \kl{instance.attractsknowledge_bool} set to true (by default, this is `base').
+%
+% Searching for instances.
+% \begin{macrocode}
+\cs_new:Nn\scope_get_attractive_instance:N
+{\tl_set:Nn#1{base}
+ \seq_map_inline:Nn\scope_instances_stack_seq
+ {\bool_if:cTF
+ {\scope_tl.area[\tl_use:c{\scope_tl.instance[##1].area_tl}].attractsknowledge_bool}
+ {\tl_set:Nn#1{##1}\seq_map_break:}{}}
+}
+% \end{macrocode}
+%
+% \begin{macrocode}
+\cs_new:Nn\scope_get_labelizable_instance:N
+{\tl_set:Nn#1{base}
+ \seq_map_inline:Nn\scope_instances_stack_seq
+ {\bool_if:cTF
+ {\scope_tl.area[\tl_use:c{\scope_tl.instance[##1].area_tl}].labelizable_bool}
+ {\tl_set:Nn#1{##1}\seq_map_break:}{}}
+}
+% \end{macrocode}
+%
+% The command \cs{\knowledge_scope_track_instance:Nn} tries to find a given instance in the current context,
+% and if it fails, it tries to find a label of this name that provides an instance.
+% \begin{macrocode}
+\cs_new:Nn\knowledge_scope_track_instance:Nn{
+ \scope_area_if_exist:nTF{#2}
+ {\knowledge_scope_track_instance_from_area:Nn#1{#2}}
+ {\knowledge_scope_track_instance_from_label:Nn#1{#2}}
+}
+\cs_new:Nn\knowledge_scope_track_instance_from_area:Nn{
+ \tl_set:Nn#1{}
+ \seq_map_inline:Nn\scope_instances_stack_seq
+ {\exp_args:Nxx\tl_if_eq:nnTF
+ {\csname \scope_tl.instance[##1].area_tl\endcsname}
+ {#2}
+ {\tl_set:Nn#1{##1}\seq_map_break:}
+ {}}
+ \tl_if_empty:NTF#1
+ {\msg_error:nnxx{scope}{area~not~in~context}{#2}{scope=}}
+ {}
+}
+\cs_new:Nn\knowledge_scope_track_instance_from_label:Nn{
+ \tl_set:Nn#1{}
+ \scopept_label_instance_if_exist:nTF{#2}
+ {\tl_set:Nx#1{\scopept_label_instance_use:n{#2}}}
+ {\msg_warning:nnnn{scope}{unknown~label}{#2}{scope=}}
+}
+% \end{macrocode}
+% \begin{macrocode}
+\bool_new:N\scopept_map_break_bool
+\cs_new:Nn\scopept_map_break:
+ {\bool_set_true:N\scopept_map_break_bool}
+
+\cs_new:Nn\scopept_map_instance_ancestors:nN
+ {\bool_set_false:N\scopept_map_break_bool
+ \scope_map_instance_ancestors_i:nN{#1}#2
+ }
+\cs_new:Nn\scopept_map_instance_ancestors_i:nN
+{ \tl_if_empty:nTF{#1}
+ {}
+ {\scopept_instance_if_exist:nTF{#1}{
+ #2{#1}
+ \bool_if:NTF\scopept_map_break_bool
+ {}
+ {\exp_args:Nx\scopept_map_instance_ancestors_i:nN
+ {\scopept_instance_parent_at:Nn\tl_use:N{#1}}#2}}
+ {}}}
+\cs_new:Nn\scopept_map_instances_seq_ancestors:NN
+ {\seq_map_inline:Nn#1
+ {\scopept_map_instance_ancestors_i:nN{##1}#2
+ \bool_if:NTF\scopept_map_break_bool:{\seq_map_break:}{}}
+}
+% \end{macrocode}
+%
+%
+% \subsubsection{Label overloading}
+%
+% In order to identify scopes, the standard \cs{\label} command is used.
+% This requires to overload it for it to write on the \kl{kaux file}.
+% Thus, the new \cs{\label} command executes the original code,
+% and furthermore writes in the \kl{kaux file} a \cs{\KAuxScopeLabel} command.
+% \iffalse
+% Note that in order to accelerate compilation, the label is both written on the "kaux file",
+% and directly in the memory. This
+% \fi
+% \begin{macrocode}
+\NewDocumentCommand\scopeLabel{m}
+ { \kl_hide_begin:
+ \scope_get_labelizable_instance:N\l_tmpb_tl
+ \KAuxWriteX*{\exp_not:n{\KAuxScopeLabel}{\exp_not:n{#1}}{\l_tmpb_tl}}
+ %\tl_new:cx{\scopept_tl.label[#1].instance_tl}{\l_tmpb_tl}
+ \kl_hide_end:
+ \cs_if_exist:NTF\LaTeXlabel\LaTeXlabel\use_none:n{#1}}
+% \end{macrocode}
+% \begin{macrocode}
+\let\label\scopeLabel
+\cs_new:Npn\knowledge_latex_label:n{
+ \cs_if_exist:NTF\LaTeXlabel\LaTeXlabel\label
+}
+% \end{macrocode}
+%
+%
+%\subsubsection{Processing the \kl{kaux file}}
+%
+% When reading the file, scope outputs commands that will be processed
+% at the next iteration. It shares the output files \kl{jobname.kaux} for that.
+% Commands that may be used in this process are defined here.
+% \begin{macrocode}
+\NewKAuxCommand\KAuxScopeNewInstance{mmm}
+ {Package~scope:~Declares~a~new~instance~of~a~scope.}
+\DeclareKAuxPhaseCommand\KAuxScopeNewInstance{init}
+ {\tl_new:cn{\scopept_tl.instance[#2].area_tl}{#1}
+ \tl_new:cn{\scopept_tl.instance[#2].parent_tl}{#3}}
+% \end{macrocode}
+% \begin{macrocode}
+\NewKAuxCommand\KAuxScopeLabel{mm}
+ {Package~scope:~Links~a~label~to~the~scope~of~its~definition.}
+\DeclareKAuxPhaseCommand\KAuxScopeLabel{init}
+ {\tl_if_exist:cTF{\scopept_tl.label[\tl_to_str:n{#1}].instance_tl}{}
+ {\tl_new:cn{\scopept_tl.label[\tl_to_str:n{#1}].instance_tl}{#2}}}
+% \end{macrocode}
+% \begin{macrocode}
+\cs_new:Npn\scopept_label_instance_if_exist:nTF#1
+ {\tl_if_exist:cTF{\scopept_tl.label[#1].instance_tl}}
+\cs_new:Nn\scopept_label_instance_use:n
+ {\tl_use:c{\scopept_tl.label[#1].instance_tl}}
+% \end{macrocode}
+%
+% \subsubsection{Commands}
+%
+% The command \cs{\knowledgeconfigureenvironment} declares a
+% standard "latex" environment to behave like the \kl(env){scope} environment
+% (while keeping its standard display).
+% \begin{macrocode}
+\newcommand\knowledgeconfigureenvironment\KnowledgeConfigureEnvironment
+\NewDocumentCommand\KnowledgeConfigureEnvironment{t?t!mm}
+ {\clist_map_inline:nn{#3}{
+ \IfBooleanTF{#2}
+ {\scope_area_environment_new:nn{##1}{#4}}
+ {\cs_if_exist:cT{##1}
+ {\cs_if_exist:cT{end##1}
+ {\scope_area_environment_new:nn{##1}{#4}
+ \use_none:n}}
+ {\IfBooleanF{#1}
+ {\knowledge_error:n{Unknown~environment~`##1'~in~\KnowledgeConfigureEnvironment.}}}
+ }}}
+\newcommand\scope_activate_environment[2][environment]{
+ \scope_area_environment_new:nn
+ {#2}{category=#1}}
+\cs_new:Nn\scope_area_environment_new:nn
+ {\scope_area_set:nn{#1}{
+ parents = all,
+ autoclose = false,
+ environment = true,
+ occurrences = recursive,
+ knowledge = attracts,
+ category = environment,
+ #2
+ }}
+% \end{macrocode}
+%
+%
+% \subsubsection{Activation of the \kl{scope option}}
+%
+% \begin{macrocode}
+\NewDocumentCommand\ScopeHackEnvironments{}
+ { \scope_area_push:n{document}
+ \kutils_secure_latex_command:N\begin
+ \global\let\SUPERbegin\begin
+ \global\def\begin##1
+ {\scope_if_triggers_area:nTF{##1}
+ {\scope_area_push:n{##1}}{}
+ \SUPERbegin{##1}}
+ \kutils_secure_latex_command:N\end
+ \global\let\SUPERend\end
+ \global\def\end##1
+ {\SUPERend{##1}
+ \scope_if_triggers_area:nTF{##1}
+ {\scope_area_pop:n{##1}}
+ {}}
+ \kutils_secure_latex_command:N\label
+ \let\label\scopeLabel
+}
+% \end{macrocode}
+%
+% This command will activate the scope package.
+% The idea is that this package, if activated too early, then
+% it may not yet have all its features usable. However, it
+% must be loaded before being used, e.g., by commands
+% like knowledge.
+% \begin{macrocode}
+\NewDocumentCommand\ScopeActivate{}{
+ \cs_gset_eq:NN\ScopeActivate\relax
+ \scope_internal_push:n{base}
+}
+\AtBeginDocument{\ScopeActivate}
+% \end{macrocode}
+%
+% \begin{macrocode}
+\AtBeginDocument{\ScopeHackEnvironments}
+\AtEndDocument{\scope_area_pop:n{document}}
+% \end{macrocode}
+%
+% \begin{macrocode}
+ \scope_area_set:nn{document,base,body} {
+ environment=false
+ }
+ \scope_area_set:nn{base}
+ {occurrences = once,
+ autoclose = false}
+ \scope_area_set:nn{document}
+ {autoclose = false,
+ occurrences = once,
+ parents = base}
+ \scope_area_set:nn{body}
+ {autoclose = true,
+ occurrences = once,
+ parents = document}
+ \scope_area_set:nn
+ {base,document}{knowledge=accepts}
+ \scope_area_set:nn
+ {base,document}{knowledge=attracts}
+ \scope_area_set:nn
+ {body}{knowledge=none}
+ %
+ \newenvironment{scope}
+ {\mode_if_preamble:TF{\ScopeActivate\scope_area_push:n{scope}}{}}
+ {\mode_if_preamble:TF{\scope_area_pop:n{scope}}{}}
+ \knowledgeconfigureenvironment{scope}{}
+% \end{macrocode}
+%
+% \subsubsection{Importing and exporting scopes}
+% \begin{macrocode}
+\scope_area_set:nn{knowledge~context~internal}
+{
+ occurrences = recursive,
+ autoclose = false,
+ parents= {base,all},
+ knowledge=attracts
+}
+\scope_area_set:nn{knowledge~import~internal}
+{
+ occurrences = recursive,
+ autoclose = false,
+ parents= {base,all},
+ knowledge = accepts
+}
+\NewDocumentEnvironment{knowledge~import}{m}
+ {\ScopeActivate\scope_area_push:n{knowledge~import~internal}
+ \clist_map_inline:nn{#1}{\knowledgeimport{##1}}}
+ {\scope_area_pop:n{knowledge~import~internal}}
+\NewDocumentEnvironment{knowledge~context}{m}
+ {\ScopeActivate\scope_area_push:n{knowledge~context~internal}
+ \scopeLabel{#1}}
+ {\scope_area_pop:n{knowledge~context~internal}}
+% \end{macrocode}
+% \subsection{Files}
+%
+%
+% \subsubsection{KAux file}
+%
+% Code to be executed before, at initialization and after the writing of the \kl{kaux file}.
+% \begin{macrocode}
+\KAuxBefore{\KAuxProcess{init}}
+\KAuxInit{}
+\KAuxAfter{\KnowledgeDiagnoseOutput}
+% \end{macrocode}
+%
+% \subsubsection{Diagnose file}
+%
+% \csintro{\knowledge_diagnose_lastline_tl} contains the text
+% of the last line that has been diagnosed. If it did not change, it will
+% not be output again.
+% \begin{macrocode}
+\iow_new:N\knowledge_diagnosefile_iow
+\cs_new:Nn\knowledge_diagnose:n
+ {\iow_now:Nn\knowledge_diagnosefile_iow{#1}}
+\cs_generate_variant:Nn\knowledge_diagnose:n{x,V}
+
+\tl_new:N\knowledge_diagnose_lastline_tl
+\cs_new:Nn\knowledge_diagnose_reset_line:
+ {\tl_gset:Nn\knowledge_diagnose_lastline_tl{...}}
+\knowledge_diagnose_reset_line:
+
+\cs_new:Nn\knowledge_diagnose_line:
+ {\bool_if:NT\knowledge_configuration_diagnoseline_bool
+ {\tl_set:Nx\l_tmpa_tl
+ {\c_percent_str\space\kauxCurrentFile : \kauxCurrentLine}
+ \tl_if_eq:NNTF\l_tmpa_tl\knowledge_diagnose_lastline_tl
+ {}
+ {\tl_gset_eq:NN\knowledge_diagnose_lastline_tl\l_tmpa_tl
+ \knowledge_diagnose:V\knowledge_diagnose_lastline_tl}}}
+
+\NewDocumentCommand\KnowledgeDiagnoseOutput{}{
+ \iow_open:Nn\knowledge_diagnosefile_iow{\c_sys_jobname_str.diagnose}
+ % compute first the list of warnings and important information
+ %
+ \knowledge_diagnose_reset_line:
+ \KAuxProcess{diagnose-digest}
+ %
+ \knowledge_diagnose:n{***********}
+ \knowledge_diagnose:n{*~Summary~*}
+ \knowledge_diagnose:n{***********}
+ \knowledge_diagnose:n{}
+ \knowledge_diagnose:x{\int_use:N\kl_digest_unknownknowledge_int\space undefined~knowledge(s).}
+ %\knowledge_diagnose:x{\int_use:N\kl_digest_unknownlabel_int\space label(s)~are~used~as~scopes~but~not~introduced.}
+ \knowledge_diagnose:x{\int_use:N\kl_digest_autoreftwiceintro_int\space autoreference(s)~are~introduced~twice.}
+ \knowledge_diagnose:x{\int_use:N\kl_digest_autorefnointro_int\space autoreference(s)~are~used~but~not~introduced.}
+ \knowledge_diagnose:n{}
+ \knowledge_diagnose:x{\int_use:N\kl_digest_autorefused_int\space autoreference(s)~are~properly~used.}
+ \knowledge_diagnose:x{\int_use:N\kl_digest_autorefunused_int\space autoreference(s)~are~defined~but~not~used.}
+ \knowledge_diagnose:n{}
+ \knowledge_diagnose:n{}
+ %
+ \int_compare:nNnT\kl_digest_unknownknowledge_int>0{
+ \knowledge_diagnose:n{************************}
+ \knowledge_diagnose:n{*~Undefined~knowledges~*}
+ \knowledge_diagnose:n{************************}
+ \knowledge_diagnose:n{}
+ %
+ \knowledge_diagnose_reset_line:
+ \KAuxProcess{diagnose-unknown-suggest}
+ %
+ \knowledge_diagnose:n{}
+ \knowledge_diagnose:n{}
+ %
+ \msg_warning:nn{knowledge}{recap~unknown~knowledge}
+ }
+ %
+ \int_compare:nNnT\kl_digest_autoreftwiceintro_int>0{
+ \knowledge_diagnose:n{****************************}
+ \knowledge_diagnose:n{*~autoref-introduced-twice~*}
+ \knowledge_diagnose:n{****************************}
+ \knowledge_diagnose:n{}
+ %
+ \knowledge_diagnose_reset_line:
+ \KAuxProcess{autoref-introduced-twice}
+ %
+ \knowledge_diagnose:n{}
+ \knowledge_diagnose:n{}
+ %
+ \msg_warning:nn{knowledge}{recap~autoref~introduced~twice}
+ }
+ %
+ \int_compare:nNnT\kl_digest_autorefnointro_int>0{
+ \knowledge_diagnose:n{******************************}
+ \knowledge_diagnose:n{*~Autoref~used~without~intro~*}
+ \knowledge_diagnose:n{******************************}
+ \knowledge_diagnose:n{}
+ %
+ \knowledge_diagnose_reset_line:
+ \KAuxProcess{autoref-not-introduced}
+ %
+ \knowledge_diagnose:n{}
+ \knowledge_diagnose:n{}
+ %
+ \msg_warning:nn{knowledge}{recap~autoref~not~introduced}
+ }
+ \int_compare:nNnT\kl_digest_autorefunused_int>0{
+ \knowledge_diagnose:n{***********************************}
+ \knowledge_diagnose:n{*~Autoref~introduced~but~not~used~*}
+ \knowledge_diagnose:n{***********************************}
+ \knowledge_diagnose:n{}
+ %
+ \knowledge_diagnose_reset_line:
+ \KAuxProcess{autoref-introduced-not-used}
+ %
+ \knowledge_diagnose:n{}
+ \knowledge_diagnose:n{}
+ %
+ }
+ %
+ \iffalse
+ \knowledge_diagnose:n{***********************}
+ \knowledge_diagnose:n{*~Exported~knowledges~*}
+ \knowledge_diagnose:n{***********************}
+ \knowledge_diagnose:n{}
+ \KAuxProcess{diagnose-export}
+ \knowledge_diagnose:n{}
+ \fi%
+ \iow_close:N\knowledge_diagnosefile_iow
+}
+% \end{macrocode}
+%
+%
+%
+%
+% \subsection{Accessing knowledges}
+%
+% We define now the basic macros that are used for accessing knowledges.
+% Each knowledge is identified by three parameters:
+% \begin{itemize}
+% \item the namespace name (no arobas in it), each different use of the "knowledge@@package" package can use a different namespace. For the moment, this is always `default'.
+% \item the \kl{instance} name (defining the scope, i.e. the region in which it is defined; no arobas in it), it is generated and dealt with by the \texttt{scope} package,
+% \item the \kl{knowledge} text itself.
+% \end{itemize}
+%
+% The variable \cs{\knowledge_namespace_tl}
+% stores the current namespace, i.e. the ones that is used by default.
+% It is sometimes temporarily modified.
+% \begin{macrocode}
+\tl_new:Nn\knowledge_default_namespace_tl {default}
+% \end{macrocode}
+% The macro
+% \begin{code}
+% \csintro{\knowledge_id:nnn}\{namespace\}\{instance\}\{knowledge key\}
+% \end{code}
+% takes these three arguments in
+% this order (namespace/instance/scope) and produces a unique string that can be used to access
+% (using \cs{\csname}, or \texttt{:c} in LaTeX3) the tuple.
+% \begin{macrocode}
+\makeatother
+\cell_new_type:nnn{knowledge}{nnnn}{KL@#2@#3@\tl_to_str:n{#4}_#1}
+\cell_new_type:nnn{knowledge}{nnn}{\knowledge_id:nnnn{}{#1}{#2}{#3}}
+\cs_generate_variant:Nn\knowledge_id:nnn{nnV,nVV,nVn,VVV}
+\cs_generate_variant:Nn\knowledge_at:Nnnn{NnnV}
+\cs_new:Npn\knowledge_at:c{\exp_args:Nc\knowledge_at:N}
+% \end{macrocode}
+%
+% For convenience, when the same knowledge has to be accessed many times, one uses
+% \begin{code}
+% \csintro{\knowledge_sets_to:nnn}\{namespace\}\{knowledge key\}\{scope\}
+% \end{code}
+% which is followed by the same three arguments.
+% It defines
+% \begin{code}
+% \csintro{\knowledge_at:N}\cs{\token}
+% \end{code} that executes \cs{\token} with as
+% first parameter the token pointing to the knowledge.
+% \begin{macrocode}
+\cs_new:Nn\knowledge_sets_to:nnn
+ {\cs_set:Nx\knowledge_at:N
+ {##1\exp_not:c{\knowledge_id:nnn{#1}{#2}{#3}}}}
+% \end{macrocode}
+% Finally, one creates a new kind of tuples, called \cs{ktuples}
+% for storing the \kl{knowledges}.
+% \begin{macrocode}
+\tuple_new:n{ktuple}
+% \end{macrocode}
+% Some more code for testing if a "knowledge" is defined:
+% \begin{code}
+% \csintro{\knowledge_knowledge_if_exist:nnnTF}\{namespace\}\{instance\}\{key\}\par
+% ~~~~~~~\{true code\}\{false code\}
+% \end{code}
+% \begin{macrocode}
+\cs_new:Npn\knowledge_knowledge_if_exist:nnnTF#1#2#3{
+ \exp_args:Nc\ktuple_if_exist:NTF{\knowledge_id:nnn{#1}{#2}{#3}}
+}
+\cs_generate_variant:Nn
+ \knowledge_knowledge_if_exist:nnnTF{VVVTF}
+% \end{macrocode}
+%
+%
+% \subsection{Knowledge code}
+%
+%
+% \subsubsection{Generalities}
+%
+% The \cs{\knowledge} command is dealt in several steps.
+% \begin{asparaitem}
+% \item In a first phase, the "directives" are parsed using the keys \csintro{knowledge~directives}.
+% During this phase, all the information concerning the target is fixed, as well as other pieces of informations
+% such as the real reference of the "autoref" directive. The result is gathered in a second comma separated
+% list of directives
+% \item Then, depdnging on the targetting information, the
+% \end{asparaitem}
+% Essentially, the \cs{\keys_define:nn}\verb|{ knowledgenow~directives }|(...)
+% commands used throughout the code are here to add new functionalities to it.
+%
+%
+% \subsubsection{Defining directives}
+%
+%
+% The commands used for introducing new directives.
+% The command
+% \begin{code}
+% \csintro{\NewKnowledgeParamBool}[*]\{name\}\cs{\token}
+% \end{code}
+% creates a new boolean directive of name `name'.
+% When the knowledge is executed, the value will be stored in the \cs{\token}.
+% By default, the directive is only usable in \kl{knowledgenow directives}.
+% If the optional star is used, then the \kl{directive} is usable in the \cs{\knowledge} command, and its value is propagated automatically. Hence, no-star means internal booleans used by the
+% system, and star means booleans accessible to the user.
+% \iffalse
+% \begin{macrocode}
+\NewDocumentCommand\NewKnowledgeParamBool{smm}{
+ \ktuple_new_bool_index:n{#2}
+ \bool_new:N#3
+ \use:c{ktuple_#2_expands_to:TF}
+ {\bool_set_true:N#3}{\bool_set_false:N#3}
+ %
+ \keys_define:nn { knowledgenow~directives }{
+ #2 .choice:,
+ #2 / false .code:n =
+ { \knowledge_at:c{ktuple_#2_gset_false:N}},
+ #2 / true .code:n =
+ { \knowledge_at:c{ktuple_#2_gset_true:N} },
+ #2 / default .code:n =
+ { \knowledge_at:c{ktuple_#2_gdel:N}},
+ #2 .default:n = {true}
+ }
+ \IfBooleanTF{#1}{\KnowledgeTransferBool{#2}}{}
+}
+\NewDocumentCommand\KnowledgeTransferBool{m}{
+ \clist_map_inline:nn{ #1 }{
+ \keys_define:nn { knowledge~directives }{
+ ##1 .choice:,
+ ##1 / false .code:n = { \knowledge_delay_directive:n{##1= false}},
+ ##1 / true .code:n = { \knowledge_delay_directive:n{##1= true}},
+ ##1 / default .code:n = { \knowledge_delay_directive:n{##1= default}},
+ ##1 .default:n = true
+ }}
+}
+% \end{macrocode}
+% \fi
+% \AP The command \cs{\NewKnowledgeParamTl} is similar to \cs{\NewKnowledgeParamBool},
+% but creates a directive that stores text.
+% \begin{code}
+% \csintro\NewKnowledgeParamTl*[\cs\token]\{name\}
+% \end{code}\noindent
+% \iffalse
+% \begin{macrocode}
+\NewDocumentCommand\NewKnowledgeParamTl{som}{
+ %\tl_show:n{#2}
+ \IfNoValueTF{#2}
+ { \tl_set:Nn\l_tmpa_tl{#3}
+ \tl_remove_all:Nn\l_tmpa_tl{~}
+ \use:x{
+ \exp_not:N\NewKnowledgeParamTl
+ \IfBooleanT{#1}{*}
+ [\exp_not:c{knowledge_kl_\l_tmpa_tl _tl}]
+ {#3}
+ }}
+ {\cs_if_exist:cTF{ktuple_#3_expands_to:n}
+ {}
+ {\ktuple_new_tl_index:n{#3}}
+ \tl_if_exist:NTF#2{}
+ {\tl_new:N#2}
+ \use:c{ktuple_#3_expands_to:n}
+ {\tl_set:Nn#2{##1}}
+ %
+ \keys_define:nn { knowledgenow~directives }{
+ #3 .code:n =
+ { \knowledge_at:c{ktuple_#3_gset:Nn}{##1} },
+ #3~X .code:n =
+ { \knowledge_at:c{ktuple_#3_gset:Nx}{##1} },
+ no~#3 .code:n =
+ { \knowledge_at:c{ktuple_#3_gdel:N} }}
+ \IfBooleanTF{#1}{\KnowledgeTransferTl{#3}}{}
+}}
+% \end{macrocode}
+% \begin{macrocode}
+\NewDocumentCommand\KnowledgeTransferTl{m}
+ {\keys_define:nn { knowledge~directives }
+ {#1 .code:n = {\knowledge_delay_directive:n{#1={##1}}}}}
+% \end{macrocode}
+% \fi
+% The command \cs{\NewKnowledgeParamCode} is similar to \cs{\NewKnowledgeParamBool},
+% but creates a directive that stores code. There is no optional star for code (never directly accessible to the user).
+% \begin{code}\AP
+% \csintro\NewKnowledgeParamCode\{name\}\cs{\token}
+% \end{code}\noindent
+% \begin{macrocode}
+\NewDocumentCommand\NewKnowledgeParamCode{mm}{
+ \ktuple_new_tl_index:n{#1}
+ \tl_new:N#2
+ \use:c{ktuple_#1_expands_to:n}
+ {\tl_set:Nn#2{##1}}
+ %
+ \keys_define:nn { knowledgenow~directives }{
+ #1 .code:n =
+ { \knowledge_at:c
+ {ktuple_#1_gset:Nn}{##1} },
+ #1+ .code:n =
+ { \knowledge_at:c
+ {ktuple_#1_gput_right:Nn}{##1} },
+ +#1 .code:n =
+ { \knowledge_at:c
+ {ktuple_#1_gput_left:Nn}{##1} }
+}}
+% \end{macrocode}
+%
+%\par
+% \AP The command \cs{\NewKnowledgeParamPackageError} takes a comma separated
+% list of directives as first argument, and a package name as second argument.
+% After that, when one of these \kl{directives} is used, an error suggesting to load the
+% corresponding package is thrown.
+% \begin{code}
+% \csintro\NewKnowledgeParamPackageError\{directive list\}\{package name\}
+% \end{code}\noindent
+% \begin{macrocode}
+\NewDocumentCommand\NewKnowledgeParamPackageError{mm}
+% \end{macrocode}
+% \ifcode
+% \begin{macrocode}
+{ \clist_map_inline:nn{#1}{
+ \keys_define:nn { knowledge~directives }{
+ ##1 .code:n = {
+ \msg_error:nnnn{ knowledge }{ package~required }{##1}{#2}}
+ }}}
+% \end{macrocode}
+%
+% \fi
+%
+%
+%
+% \subsubsection{Scope basics}
+%
+%
+% \kl{Knowledges} are attached to \kl{instances}, which identify
+% the region in which these have been defined and also where they can be used.
+% For instance, if the user mentions `\kl{scope=}section' when defining a knowledge,
+% this means that the knowledge will only be visible in this
+% area\footnote{Though it can be imported and become visible elsewhere using appropriate commands.}.
+% Technically, instances are not directly handled by the user, nor by the "knowledge@@package" package.
+%
+% In this part of the code, we provide a small number of commands for dealing with instances.
+% The real code that computes the current context of scope if later.
+%
+%
+% \begin{compactdesc}
+% \item[\csintro{\knowledge_current_instance_tl}] contains the current
+% instance to be used.
+% \item[\cs{\knowledge_visible_instances_seq}] contains the sequence
+% of instances that are visible right now.
+% \item[\csintro{\knowledge_scope_track_instance:Nn}\cs\tokenlist\{scope name\}]
+% sets \cs{\tokenlist} to the outermost instance of the scope name.
+% Typically, if the request is `\texttt{subsection}', the answer will be `\texttt{subsection-3.1}',
+% identifying the subsection currently in scope.
+% \end{compactdesc}
+% \begin{macrocode}
+\tl_new:N\knowledge_current_instance_tl
+\tl_gset:Nn\knowledge_current_instance_tl{base}
+% \end{macrocode}
+%
+% \AP The sequence \csintro{\knowledge_visible_instances_seq} contains the
+% "instances" that are visible right now. This are searched through when
+% a knowledge is used. The leftmost instance is the most important one (innermost scope).
+% Note that \cs{\knowledge_visible_instances_seq} may only be correct after one compilation.
+% \begin{compactdesc}
+% \item[\csintro{\knowledge_push_visible_instance:n}]
+% \item[\csintro{\knowledge_pop_visible_instance:}]
+% \item[\csintro{\knowledge_pop_visible_instances_to:n}]
+% \item[\csintro{\knowledge_show_visible_instances:}]
+% \end{compactdesc}
+%
+% \begin{macrocode}
+\seq_new:N\knowledge_visible_instances_seq
+\cs_new:Nn\knowledge_push_visible_instance:n
+ {\seq_gpush:Nn\knowledge_visible_instances_seq{#1}}
+\cs_new:Npn\knowledge_pop_visible_instance:
+ {\seq_gpop:NN\knowledge_visible_instances_seq\l_tmpa_tl}
+\cs_new:Nn\knowledge_pop_visible_instances_to:n
+ {\seq_gpop:NNTF\knowledge_visible_instances_seq\l_tmpa_tl
+ {\exp_args:NV\tl_if_eq:nnTF\l_tmpa_tl{#1}
+ {}
+ {\knowledge_pop_visible_instances_to:n{#1}}}
+ {\INTERNAL_ERROR_EMPTY_POP_VISIBLE}}
+\cs_new:Nn\knowledge_show_visible_instances:
+ {\tl_show:x
+ {Visible~instances~<\seq_use:Nn\knowledge_visible_instances_seq{,}>}}
+% \end{macrocode}
+% \begin{macrocode}
+\cs_new:Nn\knowledge_import_instance:n
+ {\seq_if_in:NnTF\knowledge_visible_instances_seq{#1}
+ {}{\knowledge_push_visible_instance:n{#1}}}
+% \end{macrocode}
+% \begin{macrocode}
+\NewDocumentCommand\knowledgeimport{m}
+ {\kl_hide_begin:
+ \scopept_label_instance_if_exist:nTF{#1}
+ {\exp_args:Nx\knowledge_import_instance:n{\scopept_label_instance_use:n{#1}}}
+ {\msg_warning:nnnn{scope}{unknown~label}{#1}{\knowledgeimport}}
+ \kl_hide_end:
+}
+% \end{macrocode}
+%
+%
+% \subsubsection{The knowledge targeting}
+%%
+% \begin{macrocode}
+\keys_define:nn { knowledge~directives } {
+ namespace .code:n = { \tl_set:Nn\knowledge_knowledge_namespace_tl{#1} },
+ append .choice:,
+ append / false .code:n = {\bool_set_false:N\knowledge_knowledge_append_bool},
+ append / true .code:n = {\bool_set_true:N\knowledge_knowledge_append_bool},
+ append .default:n = false,
+ clear .choice:,
+ clear / false .code:n = {\bool_set_false:N\knowledge_knowledge_clear_bool},
+ clear / true .code:n = {\bool_set_true:N\knowledge_knowledge_clear_bool},
+ clear .default:n = false,
+ export .choice:,
+ export / false .code:n = {\bool_set_false:N\knowledge_knowledge_export_bool},
+ export / true .code:n = {\bool_set_true:N\knowledge_knowledge_export_bool},
+ export .default:n = false,
+ instance .code:n =
+ { \tl_set:Nn\knowledge_knowledge_instance_tl{#1} },
+ scope .code:n =
+ { \knowledge_scope_track_instance:Nn\knowledge_knowledge_instance_tl{#1} },
+ synonym .code:n =
+ { \bool_set_true:N\knowledge_knowledge_is_synonym_bool
+ \exp_args:Nnx\keys_set:nn { knowledge~directives }
+ {link={\exp_not:o\knowledge_knowledge_synonym_tl},
+ link~instance={\exp_not:o\knowledge_knowledge_synonyminstance_tl},
+ instance={\exp_not:o\knowledge_knowledge_synonyminstance_tl}}}
+}
+% \end{macrocode}
+%
+%
+% The \csintro{\KAuxKnowledge} command is added to the \kl{kaux file} when
+% \cs{\knowledge} delays its definition to the next phase of compilation.
+% \begin{macrocode}
+\NewKAuxCommand\KAuxKnowledge{mmmm}
+ {Package~knowledge:~Declares~a~knowledge.~
+ Takes~the~{namespace}{instance}{knowledge}{directives}.}
+% \end{macrocode}
+% \begin{macrocode}
+\DeclareKAuxPhaseCommand\KAuxKnowledge{init}
+ {\knowledge_set_now:nnnn{#1}{#2}{#3}{#4}}
+% \end{macrocode}
+% \begin{macrocode}
+\newrobustcmd\KAuxExport[4]
+ {Package~knowledge:~undefined~so~far.}
+% \end{macrocode}
+%
+%\AP \csintro{\knowledge_set_now:nnnn}\cs{{}} takes the three parameters defining a knowledge and a list of \kl{knowledgenow directives}, checks that it was not existing before, and
+% then calls the \cs{\keys_set:nn}\{knowledgenow directives\} for defining it.
+% \begin{macrocode}
+\cs_new:Nn\knowledge_new_now:nnnn
+ {\knowledge_sets_to:nnn{#1}{#2}{#3}
+ \knowledge_at:N\ktuple_if_exist:NTF
+ {\bool_if:NTF\knowledge_knowledgestyle_bool
+ {\knowledge_at:N\ktuple_gclear:N}
+ {\bool_if:NF\knowledge_knowledge_append_bool
+ {\bool_if:NF\knowledge_knowledge_clear_bool
+ \knowledge_werror:Nn\knowledge_warningstrict_bool
+ {knowledge~'#3'~(namespace=#1,~scope=#2)~is~redefined.}}}
+ }
+ {\knowledge_at:N\ktuple_new:N}
+ \keys_set:nn { knowledgenow~directives } { #4 }
+}
+\cs_new:Nn\knowledge_set_now:nnnn
+ {\knowledge_sets_to:nnn{#1}{#2}{#3}
+ \knowledge_at:N\ktuple_if_exist:NTF
+ {\bool_if:NTF\knowledge_knowledgestyle_bool
+ {\knowledge_at:N\ktuple_gclear:N}
+ {}}
+ {\knowledge_at:N\ktuple_new:N}
+ \keys_set:nn { knowledgenow~directives } { #4 }
+}
+\cs_generate_variant:Nn\knowledge_new_now:nnnn{nnVn}
+\cs_generate_variant:Nn\knowledge_set_now:nnnn{nnVn}
+% \end{macrocode}
+%
+%
+%\AP We can now define the \cs{\knowledge} command itself.
+% It starts by writing the line number in the \kl{kaux file}
+% using \cs{\KAuxWriteLocation}, and then proceeds with \cs{\__knowledge_knowledge}.
+% \begin{macrocode}
+\NewDocumentCommand\knowledge{}
+ {\KAuxWriteLocation\__knowledge_knowledge}
+% \end{macrocode}
+% The command \csintro{\__knowledge_knowledge} is the center of the \cs{\knowledge}
+% command. It parses its arguments (in particular separating the synonyms using the "xparse@@package"), and executes \cs{\knowledge_knowledge_process:nn}
+% \begin{macrocode}
+\NewDocumentCommand\__knowledge_knowledge{t! t+ m >{\SplitList{|}}o m }
+{ \kl_hide_begin:
+ \group_begin:
+ %
+ \IfBooleanTF{#1}{%
+ \bool_set_false:N\knowledge_knowledge_append_bool
+ \bool_set_true:N\knowledge_knowledge_clear_bool
+ }%
+ \IfBooleanTF{#2}{%
+ \bool_set_true:N\knowledge_knowledge_append_bool
+ \bool_set_false:N\knowledge_knowledge_clear_bool
+ }%
+ %
+ \tl_set_eq:NN\knowledge_namespace_tl
+ \knowledge_default_namespace_tl
+ %
+ \bool_gset_false:N\knowledge_knowledge_is_synonym_bool
+ %
+ \use:x{
+ \exp_not:n{\knowledge_knowledge_process:nn{#3}}
+ {\exp_not:V\knowledge_knowledgedefault_tl,\exp_not:n{#5}}}
+ %
+ \bool_if:NF\knowledge_knowledge_is_synonym_bool
+ {\tl_gset:Nn\knowledge_knowledge_synonym_tl{#3}
+ \tl_gset_eq:NN\knowledge_knowledge_synonyminstance_tl
+ \knowledge_knowledge_instance_tl}
+ %
+ \IfNoValueTF{#4}{}{
+ \cs_set:Nn\l_tmpa_cs:n
+ {\exp_args:Nnx\knowledge_knowledge_process:nn{##1}{synonym}}
+ \ProcessList{#4}\l_tmpa_cs:n
+ }
+ %
+ \group_end:
+ \kl_hide_end:
+}
+% \end{macrocode}
+%
+%\AP The boolean \cs{\knowledge_knowledgestyle_bool}
+% is set to true in order \cs{\knowledge_knowledge_process:nn}
+% to know if it has been triggered by \cs{\knowledge}
+% or \cs{\knowledgestyle}.
+% \begin{macrocode}
+\NewDocumentCommand\knowledgestyle{ s m m }
+{ \kl_hide_begin:
+ \group_begin:
+ \tl_set:Nn\knowledge_namespace_tl{style}
+ %
+ \bool_set_true:N\knowledge_knowledgestyle_bool
+ \IfBooleanTF{#1}
+ {\bool_set_true:N\knowledge_knowledgestyle_override_bool}
+ {\bool_set_false:N\knowledge_knowledgestyle_override_bool}
+ %
+ \knowledge_knowledge_process:nn{#2}{#3}
+ \group_end:
+ \kl_hide_end:
+}
+% \end{macrocode}
+%
+%
+%
+%
+%
+%\AP The \cs{\knowledge_knowledge_process:nn} command is the internal
+% version of \cs{\knowledge}. It takes two parameters:
+% the key, and the comma separated list of directives.
+% \begin{macrocode}
+\bool_new:N\knowledge_knowledgestyle_bool
+\bool_new:N\knowledge_knowledgestyle_override_bool
+\bool_new:N\knowledge_knowledge_now_bool
+\bool_new:N\knowledge_knowledge_alsonow_bool
+\bool_new:N\knowledge_knowledge_is_synonym_bool
+\bool_new:N\knowledge_knowledge_autoref_bool
+\bool_new:N\knowledge_knowledge_clear_bool
+\bool_new:N\knowledge_knowledge_append_bool
+\tl_clear_new:N\knowledge_knowledge_synonym_tl
+\tl_clear_new:N\knowledge_knowledge_synonyminstance_tl
+\tl_clear_new:N\knowledge_knowledge_export_bool
+\tl_clear_new:N\knowledge_knowledge_key_tl
+\tl_clear_new:N\knowledge_knowledge_namespace_tl
+\tl_clear_new:N\knowledge_knowledge_instance_tl
+\tl_clear_new:N\knowledge_knowledge_directives_tl
+% \end{macrocode}
+% The macro \csintro{\knowledge_knowledge_process:nn}
+% is the heart of \cs{\knowledge} command.
+% \begin{macrocode}
+\cs_new:Nn\knowledge_knowledge_process:nn
+{ \bool_set_false:N\knowledge_knowledge_export_bool
+ \bool_set_false:N\knowledge_knowledge_autoref_bool
+ \bool_set_false:N\knowledge_knowledge_now_bool
+ \bool_set_false:N\knowledge_knowledge_alsonow_bool
+ %
+ \tl_set:Nn\knowledge_knowledge_key_tl{#1}
+ %
+ \tl_set_eq:NN\knowledge_knowledge_namespace_tl\knowledge_namespace_tl
+ \scope_get_attractive_instance:N\knowledge_knowledge_instance_tl
+ %
+ \tl_set:Nn\knowledge_knowledge_directives_tl{}
+ %
+ \keys_set:nn { knowledge~directives } { #2 }
+ %
+ \mode_if_preamble:TF
+ {\bool_set_true:N\knowledge_knowledge_now_bool}
+ {}
+ %
+ \bool_if:NT\knowledge_knowledge_clear_bool
+ {\tl_put_left:Nn\knowledge_knowledge_directives_tl{clear,}}
+ \bool_if:NT\knowledge_knowledge_append_bool
+ {\tl_put_left:Nn\knowledge_knowledge_directives_tl{force,}}
+ %
+ \bool_if:nTF{\knowledge_knowledge_now_bool}
+ {\use:x{
+ \exp_not:N\knowledge_new_now:nnnn
+ {\knowledge_knowledge_namespace_tl}
+ {\knowledge_knowledge_instance_tl}
+ {\exp_not:V\knowledge_knowledge_key_tl}
+ {\exp_not:V\knowledge_knowledge_directives_tl}}
+ }{}
+ \bool_if:nTF{\knowledge_knowledge_alsonow_bool}
+ {\use:x{
+ \exp_not:N\knowledge_set_now:nnnn
+ {\knowledge_knowledge_namespace_tl}
+ {\knowledge_knowledge_instance_tl}
+ {\exp_not:V\knowledge_knowledge_key_tl}
+ {\exp_not:V\knowledge_knowledge_directives_tl}}
+ }{}
+ \bool_if:NTF\knowledge_knowledge_now_bool
+ {}
+ { \KAuxWriteX*{
+ \exp_not:N\KAuxKnowledge
+ {\knowledge_knowledge_namespace_tl}
+ {\knowledge_knowledge_instance_tl}
+ {\exp_not:V\knowledge_knowledge_key_tl}
+ {\exp_not:V\knowledge_knowledge_directives_tl}}
+ }
+ \bool_if:NT\knowledge_knowledge_autoref_bool
+ {\KAuxWriteX*
+ {\exp_not:N\KAuxAutoref
+ {\knowledge_knowledge_namespace_tl}
+ {\knowledge_knowledge_instance_tl}
+ {\exp_not:V\knowledge_knowledge_key_tl}}
+ }
+ %
+ \bool_if:NT\knowledge_knowledge_export_bool
+ {\KAuxWriteX*{
+ \exp_not:N\KAuxExport
+ {\knowledge_knowledge_namespace_tl}
+ {\knowledge_knowledge_instance_tl}
+ {\exp_not:V\knowledge_knowledge_key_tl}
+ {\exp_not:V\knowledge_knowledge_directives_tl}}
+ }
+}
+% \end{macrocode}
+% \begin{macrocode}
+\cs_new:Nn\knowledge_delay_directive:n
+ {\tl_if_empty:NTF\knowledge_knowledge_directives_tl
+ {\tl_set:Nn\knowledge_knowledge_directives_tl{#1}}
+ {\tl_put_right:Nn\knowledge_knowledge_directives_tl{,#1}}}
+\cs_generate_variant:Nn\knowledge_delay_directive:n{x}
+% \end{macrocode}
+%
+%
+%
+% \subsubsection{The \cs{\knowledgedirective} command}
+%
+% \begin{macrocode}
+\NewDocumentCommand\knowledgedirective{mom}{
+ \kl_hide_begin:
+ \cs_new:cn
+ {knowledgedirective_#1:n}
+ {\keys_set:nn{ knowledge~directives }{#3}}
+ \keys_define:nn{ knowledge~directives }
+ {#1 .code:n = {\use:c{knowledgedirective_#1:n}{##1}}}
+ \IfNoValueF{#2}
+ {\keys_define:nn{ knowledge~directives }{#1 .default:n = {#2}}}
+ \kl_hide_end:
+}
+% \end{macrocode}
+%
+% \subsubsection{The \cs{\knowledgedefault} command}
+%
+% It uses internally the variable \csintro{\knowledge_knowledgedefault_tl}.
+% \begin{macrocode}
+\tl_new:N\knowledge_knowledgedefault_tl
+\NewDocumentCommand\knowledgedefault{sm}{
+ \kl_hide_begin:
+ \IfBooleanTF{#1}
+ {\tl_put_right:Nn\knowledge_knowledgedefault_tl{,#2}}
+ {\tl_set:Nn\knowledge_knowledgedefault_tl{#2}}
+ \kl_hide_end:
+}
+% \end{macrocode}
+%
+%
+% \subsubsection{Main \cs{\kl} code}
+%
+%
+% The \cs{\kl}, and its internal version \cs{\klTKS} are the central ones in the package. Indeed, all commands such as \cs{\intro}, \cs{\phantomintro}, \cs{\reintro} or the \kl{"...@...@..."} notation eventually end to a call to these functions.
+%\AP Essentially, \cs{\kl} parses its parameters, and then call its internal version \cs{\knowledge_klTKS:nnn}
+% with proper parameters: Text, Knowledge, Scope (the scope can be empty):
+%
+% \AP The macro \csintro{\knowledge_kl:w} is the part of \cs{\kl}-like commands that parses the arguments, and then calls \cs{\knowledge_klTKS:nnn} with proper arguments.
+% \begin{macrocode}
+\NewDocumentCommand\knowledge_kl:w{d() o d() m}{
+ \IfNoValueTF{#1}
+ {\IfNoValueTF{#3}
+ {\IfNoValueTF{#2}
+ {\knowledge_klTKS:nnn{#4}{#4}{}}
+ {\knowledge_klTKS:nnn{#4}{#2}{}}}
+ {\IfNoValueTF{#2}
+ {\knowledge_klTKS:nnn{#4}{#4}{#3}}
+ {\knowledge_klTKS:nnn{#4}{#2}{#3}}}}
+ {\IfNoValueTF{#2}
+ {\knowledge_klTKS:nnn{#4}{#4}{#1}}
+ {\knowledge_klTKS:nnn{#4}{#2}{#1}}}
+}
+% \end{macrocode}
+%
+% \AP The following macro, \csintro{\knowledge_klTKS:nnn} is an internal version of \cs{\kl}-like commands. it takes explicitely the text to be displayed,
+% followed by the \kl{knowledge name} to be used, and a \kl{label} pointing to the \kl[instance]{instance of scope}
+% in which the \kl{knowledge name} has to be searched for. This \kl{label} can be empty, and in this case, this means that
+% the stack of instances that are visible in the context of the call of the command should be inspected for searching for
+% the knowledge.
+% \AP The macro \csintro{\klTKS} is a version of \cs{\knowledge_klTKS:nnn}
+% that can be used without the "expl3@@package" syntax.
+% \begin{macrocode}
+\tl_clear_new:N\knowledge_kl_text_tl
+\tl_clear_new:N\knowledge_kl_base_key_tl
+\tl_clear_new:N\knowledge_kl_key_tl
+\tl_clear_new:N\knowledge_kl_autoref_tl
+\tl_clear_new:N\knowledge_kl_resourcetoken_tl
+\tl_clear_new:N\knowledge_kl_resourcearguments_tl
+\tl_clear_new:N\knowledge_kl_display_process_tl
+\tl_clear_new:N\knowledge_kl_display_sequence_tl
+\tl_new:N\knowledge_namespace_tl
+\tl_gnew:Nn\knowledge_display_code_tl{INTERNAL~ERROR~DISPLAY~CODE}
+% \end{macrocode}
+% \begin{macrocode}
+\NewDocumentCommand\klTKS{}{\knowledge_klTKS:nnn}
+% \end{macrocode}
+% \begin{macrocode}
+\cs_new:Nn\knowledge_klTKS:nnn{
+ \group_begin:
+ %
+ \tl_set:Nx\knowledge_kl_linkscope_tl{\tl_to_str:n{#3}}
+ \tl_set:Nn\knowledge_kl_instance_tl{}
+ \tl_set:Nn\knowledge_kl_text_tl{#1}
+ \tl_set:Nx\knowledge_kl_base_key_tl{\tl_to_str:n{#2}}
+ \tl_set_eq:NN\knowledge_kl_key_tl\knowledge_kl_base_key_tl
+ \int_set_eq:NN\knowledge_kl_recursion_int\knowledge_kl_max_recursion_int
+ %
+ \tl_if_exist:cTF
+ {knowledge_kl_\tl_to_str:V\knowledge_kl_modifiers_tl _init_tl}
+ {\use:c{knowledge_kl_\tl_to_str:V\knowledge_kl_modifiers_tl _init_tl}}
+ {\knowledge_error:x
+ {Unknown~variant~modifier~sequence~`\exp_not:V\knowledge_kl_modifiers_tl'.}}
+ %
+ \knowledge_kl_modifiers_reset:
+ %
+ \knowledge_kl_use_styles:x{\knowledge_kl_default_style_tl}
+ %
+ \knowledge_kl_find:
+ \group_end:
+ \knowledge_display_code_tl
+}
+% \end{macrocode}
+%
+% At this step, the code has launched \cs{\knowledge_kl_find:}
+% Internally, it counts using \cs{\knowledge_kl_recursion_int}
+% the number of indirections, and bounds
+% starting from the integer \cs{\knowledge_kl_max_recursion_int}
+% (40 by default).
+% \begin{macrocode}
+\int_const:Nn\knowledge_kl_max_recursion_int{40}
+\int_new:N\knowledge_kl_recursion_int
+% \end{macrocode}
+% \noindent
+% and then launches the search.
+%
+%
+%\AP The core of the \cs{\kl} command is \csintro{\knowledge_kl_find:}.
+% It uses the variables \cs{\knowledge_kl_recursion_int} for checking non-recursion.
+% It searches for the entry \cs{\knowledge_kl_key_tl}, either in searching in the \kl{stack of visible scope instances},
+% or following \cs{\knowledge_kl_linkscope_tl} if the label exists.
+% It first works on whether a scope label is given or not:
+% \begin{macrocode}
+\cs_set:Nn\knowledge_kl_find:{
+ \knowledge_kl_find_recursion_exceeded:TF
+ {\knowledge_kl_error_recursion:}
+ {\tl_if_empty:NTF\knowledge_kl_instance_tl
+ {\tl_if_empty:NTF\knowledge_kl_linkscope_tl
+ \knowledge_kl_find_withoutscope:
+ \knowledge_kl_find_withscope:}
+ \knowledge_kl_find_withinstance:}
+}
+% \end{macrocode}
+% \begin{macrocode}
+\cs_set:Npn\knowledge_kl_find_recursion_exceeded:TF{
+ \int_decr:N\knowledge_kl_recursion_int
+ \int_compare:nNnTF\knowledge_kl_recursion_int=0
+}
+% \end{macrocode}
+% In case a scope label is provided, then the label is tested for being known; if it is the case, it is followed, and the knowledge is looked for and executed.
+% \begin{macrocode}
+\cs_new:Nn\knowledge_kl_find_withinstance:{
+ \knowledge_knowledge_if_exist:VVVTF
+ \knowledge_kl_namespace_tl
+ \knowledge_kl_instance_tl
+ \knowledge_kl_key_tl
+ {\knowledge_kl_exec:nnV
+ \knowledge_kl_namespace_tl
+ \knowledge_kl_instance_tl
+ \knowledge_kl_key_tl}
+ { \knowledge_kl_error_unknown_in_scope_firsttime: }
+}
+\cs_new:Nn\knowledge_kl_find_withscope:{
+ \exp_args:NV
+ \scopept_label_instance_if_exist:nTF\knowledge_kl_linkscope_tl
+ { \tl_set:Nx\knowledge_kl_instance_tl
+ {\scopept_label_instance_use:n{\knowledge_kl_linkscope_tl}}
+ \knowledge_kl_find_withinstance: }
+ { \knowledge_kl_error_label_unknown: }
+}
+% \end{macrocode}
+% \begin{macrocode}
+\cs_new:Nn\knowledge_kl_find_withoutscope:{
+ \knowledge_kl_find_in_scope:VNTF
+ \knowledge_kl_key_tl
+ \knowledge_kl_instance_tl
+ {\knowledge_kl_exec:nnV
+ \knowledge_kl_namespace_tl
+ \knowledge_kl_instance_tl
+ \knowledge_kl_key_tl}
+ {\knowledge_kl_error_unknown_firsttime:}
+}
+% \end{macrocode}
+% We now code the macro \cs{\knowledge_kl_find_in_scope:nnNTF}, that
+% takes the \kl{namespace}, and the \kl{knowledge}, and answers the \kl{instance} (if it exists),
+% and sets the tl-token (third argument) to contain the scope in which it has been found.
+% \begin{macrocode}
+\cs_new:Npn\knowledge_kl_find_in_scope:nNTF{
+ \exp_args:NV\knowledge_kl_find_in_scope:nnNTF
+ \knowledge_kl_namespace_tl
+}
+% \end{macrocode}
+%
+% \begin{macrocode}
+\cs_new:Nn\knowledge_kl_find_in_scope:nnNTF{
+ \group_begin:
+ \tl_set:Nn\l_tmpa_tl{#1}
+ \tl_set:Nn\l_tmpb_tl{#2}
+ \bool_gset_false:N\g_tmpa_bool
+ \seq_map_function:NN
+ \knowledge_visible_instances_seq
+ \knowledge_kl_find_in_scope_test:n
+ \group_end:
+ \bool_if:NTF\g_tmpa_bool
+ {\tl_set_eq:NN#3\g_tmpa_tl #4}
+ {#5}
+}
+% \end{macrocode}
+% \begin{macrocode}
+\cs_new:Nn\knowledge_kl_find_in_scope_test:n{
+ \exp_args:Nc\ktuple_if_exist:NTF
+ {\knowledge_id:nnV{\l_tmpa_tl}{#1}\l_tmpb_tl}
+ {\bool_gset_true:N\g_tmpa_bool
+ \tl_gset:Nn\g_tmpa_tl{#1}
+ \seq_map_break:}{}}
+% \end{macrocode}
+% \begin{macrocode}
+\cs_generate_variant:Nn\knowledge_kl_find_in_scope:nnNTF{nVNTF}
+\cs_generate_variant:Nn\knowledge_kl_find_in_scope:nNTF{VNTF}
+% \end{macrocode}
+% \AP
+% When the \kl{knowledge} is found, it is eventually executed using
+% \begin{code}
+% \csintro{\knowledge_kl_exec:nnn}\{namespace\}\{instance\}\{key\}
+% \end{code} The argument is a control sequence pointing to the \kl{knowledge}. It is first executed
+% in order to set the variables.
+% Then, the token of the \kl{knowledge} is stored in the variable \cs{\knowledge_kl_resourcetoken_tl}.
+% Then, if a \kl{style} is given, it is executed. The next step is to update the \kl{knowledge}
+% which means essentially updating its internal counters of use.
+% \begin{macrocode}
+\cs_new:Nn\knowledge_kl_exec:nnn{
+ \tl_set:Nx\knowledge_kl_resourcearguments_tl
+ {{#1}{#2}{\exp_not:n{#3}}}
+ \exp_args:NNc\tl_set:Nn\knowledge_kl_resourcetoken_tl
+ {\knowledge_id:nnn{#1}{#2}{#3}}
+ \expandafter\ktuple_countuse_gincr:N\knowledge_kl_resourcetoken_tl
+ %
+ \tl_clear:N\knowledge_kl_link_tl
+ \tl_clear:N\knowledge_kl_linkscope_tl
+ \tl_clear:N\knowledge_kl_instance_tl
+ \tl_map_function:NN
+ \knowledge_kl_styledirectives_tl
+ \tl_clear:N
+ %
+ \knowledge_kl_resourcetoken_tl
+ %
+ \bool_if:NTF\kl_unknown_knowledge_bool
+ {\knowledge_kl_error_unknown:}
+ {\tl_map_function:NN
+ \knowledge_kl_styledirectives_tl
+ \knowledge_kl_use_styles:x
+ %
+ \tl_if_exist_ne:NTF\knowledge_kl_linkscope_tl{
+ \tl_if_exist_ne:NTF\knowledge_kl_link_tl{}{
+ \tl_set_eq:NN\knowledge_kl_link_tl
+ \knowledge_kl_key_tl
+ }}{}
+ %
+ \tl_if_exist_ne:NTF\knowledge_kl_link_tl
+ { \tl_set_eq:NN
+ \knowledge_kl_key_tl
+ \knowledge_kl_link_tl
+ \knowledge_kl_find:}
+ \knowledge_kl_compute_code:
+ }
+}
+\cs_generate_variant:Nn\knowledge_kl_exec:nnn{nnV}
+% \end{macrocode}
+% \begin{macrocode}
+\cs_new:Nn\knowledge_kl_use_styles:n
+ {\clist_map_function:nN{#1}\knowledge_kl_use_style:n}
+\cs_generate_variant:Nn\knowledge_kl_use_styles:n {x}
+% \end{macrocode}
+% \begin{macrocode}
+\cs_new:Nn\knowledge_kl_use_style:n{
+ \tl_if_empty:nTF{#1}{}
+ {\knowledge_kl_find_in_scope:nnNTF
+ {style}
+ {#1}
+ \l_tmpa_tl
+ {\use:c{\knowledge_id:nVn{style}\l_tmpa_tl{#1}}}
+ {\knowledge_error:n{Unknown~style~`#1'}}}
+}
+% \end{macrocode}
+%
+% \begin{macrocode}
+\cs_new:Nn\knowledge_usestyle:nn{
+ \group_begin:
+ \tl_set:Nn\knowledge_kl_forcedtext_tl{#2}
+ \knowledge_kl_use_styles:x{#1}
+ \knowledge_kl_compute_code:
+ \group_end:
+ \knowledge_display_code_tl
+}
+\NewDocumentCommand\knowledgeusestyle{mm}{\knowledge_usestyle:nn{#1}{#2}}
+% \end{macrocode}
+%
+%
+%
+%
+%
+%
+% \subsubsection{Error handling}
+%
+%
+%
+% \begin{macrocode}
+\NewKAuxCommand\KAuxErrorKnowledgeRecursive{mmmm}
+ {Package~'knowledge:~A~knowledge~has~recursive~definition.~
+ {namespace}{scope}{undefined~knowledge}{base~knowledge}}
+ {}
+\cs_new:Nn\knowledge_kl_error_recursion: {
+ \msg_error:nnxxx{ knowledge }{ knowledge~recursion }
+ {\exp_not:V\knowledge_kl_base_key_tl}
+ {\exp_not:V\knowledge_kl_namespace_tl}
+ {\exp_not:V\knowledge_kl_key_tl}
+ \knowledge_kl_error_display:n{ recursive~knowledge }
+}
+% \end{macrocode}
+% \begin{macrocode}
+\NewKAuxCommand\KAuxErrorKnowledgeUnknown{mmmmm}
+ {Package~'knowledge:~A~knowledge~is~not~defined.~
+ {namespace}{scope/empty}{undefined~knowledge}{base~knowledge}{command}}
+ {}
+\NewKAuxCommand\KAuxErrorLabelUnknown{m}
+ {Package~'knowledge:~A~label~is~not~defined.~
+ {label}}
+ {}
+% \end{macrocode}
+% \begin{macrocode}
+\DeclareKAuxPhaseCommand\KAuxErrorKnowledgeUnknown{diagnose-unknown-suggest}
+{ \knowledge_diagnose_line:
+ \tl_set_eq:Nc\l_tmpa_tl{knowledge_kl_\cs_to_str:N#5_suggestion_tl}
+ \tl_if_empty:nTF{#2}{}
+ {\tl_if_empty:NTF\l_tmpa_tl{}
+ {\tl_put_right:Nn\l_tmpa_tl{,}}
+ \tl_put_right:Nn\l_tmpa_tl{scope={#2}}}
+ \knowledge_diagnose:x
+ {\exp_not:n{\knowledge{#3}}{\exp_not:V\l_tmpa_tl}}
+}
+% \end{macrocode}
+% The code executed when an undefined knowledge is met. It
+% \begin{macrocode}
+\cs_new:Nn\knowledge_kl_error_unknown_firsttime:
+ {\bool_if:cTF{\knowledge_variant_var:n{unknownwarning_bool}}
+ {\IfKnowledgePaperModeF{
+ \msg_warning:nnxxx{ knowledge }{ knowledge~unknown }
+ {\exp_not:V\knowledge_kl_key_tl}
+ {\exp_not:V\knowledge_kl_namespace_tl}
+ {\seq_use:Nn\knowledge_visible_instances_seq{~|~}}}
+ }{}
+ \bool_if:cTF{\knowledge_variant_var:n{unknowndiagnose_bool}}
+ {\KAuxWriteX{
+ \KAuxErrorKnowledgeUnknown
+ {\knowledge_kl_namespace_tl}
+ {}
+ {\tl_to_str:V\knowledge_kl_key_tl}
+ {\tl_to_str:V\knowledge_kl_base_key_tl}
+ {\exp_not:V\knowledge_kl_command_tl}
+ }}{}
+ \use:x{\exp_not:N\knowledge_set_now:nnnn
+ {\knowledge_kl_namespace_tl}{base}
+ {\exp_not:V\knowledge_kl_key_tl}
+ {UnKnoWn~KNowLedGE}}
+ \tl_gset:Nx\knowledge_display_code_tl
+ {\exp_not:N\knowledge_usestyle:nn
+ {\use:c{\knowledge_variant_var:n{unknown_style_tl}}}
+ {\exp_not:V\knowledge_kl_text_tl}}
+}
+\cs_new:Nn\knowledge_kl_error_unknown:{
+ \tl_gset:Nx\knowledge_display_code_tl
+ {\exp_not:N\knowledge_usestyle:nn
+ {\use:c{\knowledge_variant_var:n{unknown_style_cont_tl}}}
+ {\exp_not:V\knowledge_kl_text_tl}}
+}
+% \end{macrocode}
+% \begin{macrocode}
+\cs_new:Nn\knowledge_kl_error_unknown_in_scope_firsttime:
+ {\bool_if:cTF{\knowledge_variant_var:n{unknownwarning_bool}}
+ {\IfKnowledgePaperModeF{
+ \msg_warning:nnxxx{ knowledge }{ knowledge~unknown~in~scope }
+ {\exp_not:V\knowledge_kl_key_tl}
+ {\exp_not:V\knowledge_kl_namespace_tl}
+ {\knowledge_kl_linkscope_tl}}}{}
+ \bool_if:cTF{\knowledge_variant_var:n{unknowndiagnose_bool}}
+ {\KAuxWriteX{
+ \KAuxErrorKnowledgeUnknown
+ {\knowledge_kl_namespace_tl}
+ {\knowledge_kl_linkscope_tl}
+ {\tl_to_str:V\knowledge_kl_key_tl}
+ {\tl_to_str:V\knowledge_kl_base_key_tl}
+ {\exp_not:V\knowledge_kl_command_tl}
+ }}{}
+ \use:x{\exp_not:N\knowledge_set_now:nnnn
+ {\knowledge_kl_namespace_tl}
+ {\knowledge_kl_linkscope_tl}
+ {\exp_not:V\knowledge_kl_key_tl}
+ {UnKnoWn~KNowLedGE}}
+ \tl_gset:Nx\knowledge_display_code_tl
+ {\exp_not:N\knowledge_usestyle:nn
+ {\use:c{\knowledge_variant_var:n{unknown_style_tl}}}
+ {\exp_not:V\knowledge_kl_text_tl}}
+}
+% \end{macrocode}
+% \begin{macrocode}
+\cs_new:Nn\knowledge_kl_error_label_unknown:{
+ \KAuxWriteX{
+ \KAuxErrorKnowledgeUnknown
+ {\knowledge_kl_namespace_tl}
+ {\knowledge_kl_linkscope_tl}
+ {\tl_to_str:V\knowledge_kl_key_tl}
+ {\tl_to_str:V\knowledge_kl_base_key_tl}
+ {\exp_not:V\knowledge_kl_command_tl}
+ }
+ %
+ \IfKnowledgePaperModeF{
+ \msg_warning:nnxx{ knowledge }{ knowledge~unknown~label }
+ {\exp_not:V\knowledge_kl_key_tl}
+ {\knowledge_kl_linkscope_tl}}
+ %
+ \tl_gset:Nx\knowledge_display_code_tl
+ {\exp_not:N\knowledge_usestyle:nn
+ {\use:c{\knowledge_variant_var:n{unknown_style_tl}}}
+ {\exp_not:V\knowledge_kl_text_tl}}
+}
+% \end{macrocode}
+% This is the code use by default when an error is met and the result has nevertheless to be displayed.
+% \ToImprove{this code is dependent on xcolor and shouldn't.}
+% \begin{macrocode}
+\cs_new:Nn\knowledge_kl_error_display:n
+ {\textcolor{orange}{\tl_to_str:V\knowledge_kl_text_tl}}
+% \end{macrocode}
+%
+% \subsubsection{Variant modifiers and \cs{\knowledgevariantmodifier}}
+%
+% When a \cs\kl-like command is met, its name is added to
+% \csintro{\knowledge_kl_modifiers_tl}.
+% Each time a new command is added using \csintro{\knowledge_kl_modifiers_add:N},
+% it is appended to \cs{\knowledge_kl_modifiers_tl}, and a reduction is applied
+% using \cs{\knowledge_kl_modifiers_reduce:}:
+% \begin{macrocode}
+\tl_clear_new:N\knowledge_kl_modifiers_tl
+\cs_new:Nn\knowledge_kl_modifiers_reset:
+ {\tl_gclear:N\knowledge_kl_modifiers_tl}
+\cs_new:Nn\knowledge_kl_modifiers_add:N
+ {\tl_gput_right:Nn\knowledge_kl_modifiers_tl{#1*}
+ \knowledge_kl_modifiers_reduce:}
+% \end{macrocode}
+%\AP This reduction is performed by \csintro{\knowledge_kl_modifiers_reduce:},
+% and configured using \cs{\knowledgevariantmodifier}.
+% \begin{macrocode}
+\NewDocumentCommand\knowledgevariantmodifier{mm}
+ {\tl_new:cn
+ {KLSV_\tl_to_str:n{#1*} _tl}
+ {#2*}}
+\cs_new:Nn\knowledge_kl_modifiers_reduce:
+ {\tl_if_exist:cTF
+ {KLSV_\tl_to_str:V\knowledge_kl_modifiers_tl _tl}
+ {\tl_gset_eq:Nc\knowledge_kl_modifiers_tl
+ {KLSV_\tl_to_str:V\knowledge_kl_modifiers_tl _tl}}
+ {}}
+% \end{macrocode}
+%
+% \begin{macrocode}
+% \end{macrocode}
+%
+% \begin{macrocode}
+% \end{macrocode}
+%
+% \subsubsection{Implementation of \cs{\knowledgenewvariant}}
+%
+% \begin{macrocode}
+\cs_new:Nn\knowledge_variant_var:n
+ {knowledge_kl_\expandafter\cs_to_str:N\knowledge_kl_command_tl _#1}
+% \end{macrocode}
+% \begin{macrocode}
+\NewDocumentCommand\knowledgenewvariant{mm}{
+ \exp_args:Nc\tl_new:Nn
+ {knowledge_kl_\cs_to_str:N#1_command_tl}
+ {#1}
+ %
+ %
+ \NewDocumentCommand#1{s}
+ {\knowledge_kl_modifiers_add:N#1
+ \IfBooleanF{##1}{\knowledge_kl:w}}
+ %
+ \tl_new_eq:cN
+ {knowledge_kl_\cs_to_str:N#1_namespace_tl}
+ \knowledge_default_namespace_tl
+ \tl_new:cx{knowledge_kl_\cs_to_str:N#1_suggestion_tl}{}
+ \bool_new_true:c{knowledge_kl_\cs_to_str:N#1_unknownwarning_bool}
+ \bool_new_true:c{knowledge_kl_\cs_to_str:N#1_unknowndiagnose_bool}
+ \tl_new:cn{knowledge_kl_\cs_to_str:N#1_default_style_tl}{}
+ \tl_new:cn{knowledge_kl_\cs_to_str:N#1_unknown_style_tl}{}
+ \tl_new:cn{knowledge_kl_\cs_to_str:N#1_unknown_style_cont_tl}{}
+ \tl_new:cx{knowledge_kl_\cs_to_str:N#1_autoknowledge_tl}{}
+ \tl_new:cx{knowledge_kl_\cs_to_str:N#1_styledirectives_tl}{}
+ %
+ \bool_if:NT\knowledge_hyperref_active_bool
+ {\exp_args:Nx\pdfstringdefDisableCommands
+ {\exp_not:N\def\exp_not:N#1
+ {\exp_not:N\knowledge_variant_arg_absorber:Nw
+ \exp_not:c{\cs_to_str:N#1_PDFstring}}}}
+ \exp_args:Nc\newcommand{\cs_to_str:N#1_PDFstring}[3]{##1}
+ %
+ \tl_new:cx{knowledge_kl_\tl_to_str:n{#1*} _init_tl}
+ {
+ \exp_not:n{\tl_set_eq:NN\knowledge_kl_command_tl}
+ \exp_not:c{knowledge_kl_\cs_to_str:N#1_command_tl}
+ \exp_not:n{\tl_set_eq:NN\knowledge_kl_namespace_tl}
+ \exp_not:c{knowledge_kl_\cs_to_str:N#1_namespace_tl}
+ \exp_not:n{\tl_set_eq:NN\knowledge_kl_default_style_tl}
+ \exp_not:c{knowledge_kl_\cs_to_str:N#1_default_style_tl}
+ \exp_not:n{\tl_set_eq:NN\knowledge_kl_unknown_style_tl}
+ \exp_not:c{knowledge_kl_\cs_to_str:N#1_unknown_style_tl}
+ \exp_not:n{\tl_set_eq:NN\knowledge_kl_unknown_style_cont_tl}
+ \exp_not:c{knowledge_kl_\cs_to_str:N#1_unknown_style_cont_tl}
+ \exp_not:n{\tl_set_eq:NN\knowledge_kl_styledirectives_tl}
+ \exp_not:c{knowledge_kl_\cs_to_str:N#1 _styledirectives_tl}
+ \exp_not:c{knowledge_kl_\cs_to_str:N#1 _autoknowledge_tl}
+ }
+ %
+ %\bool_if:NT\knowledge_hyperref_active_bool
+ % {\pdfstringdefDisableCommands{\let#1\knowledge_fake_kl:n}}
+ %
+ \knowledgesetvariant#1{#2}
+}
+\DeclareExpandableDocumentCommand\knowledge_variant_arg_absorber:Nw
+ {m d() o d() m}
+ {\IfNoValueTF{#2}
+ {#1{#5}{#2}{#3}}
+ {#1{#5}{#2}{#1}}}
+
+\tl_new:N\knowledge_variant_command_tl
+\tl_new:N\knowledge_variant_key_tl
+\NewDocumentCommand\knowledgesetvariant{mm}{
+ \tl_set:Nn\knowledge_variant_command_tl{#1}
+ \tl_set:Nx\knowledge_variant_key_tl{\cs_to_str:N#1}
+ %
+ \keys_set:nn{ knowledge~configure~variant }{#2}
+}
+% \end{macrocode}
+% \begin{macrocode}
+\keys_define:nn{ knowledge~configure~variant }{
+ namespace .code:n =
+ {\tl_set:cn{knowledge_kl_\knowledge_variant_key_tl _namespace_tl}{#1}},
+ %
+ unknown~warning .choices:nn = {true,false}
+ {\bool_set_text:cn{knowledge_kl_\knowledge_variant_key_tl _unknownwarning_bool}{#1}},
+ %
+ unknown~diagnose .choices:nn = {true,false}
+ {\bool_set_text:cn{knowledge_kl_\knowledge_variant_key_tl _unknowndiagnose_bool}{#1}},
+ %
+ default~style .code:n =
+ {\tl_set:cn{knowledge_kl_\knowledge_variant_key_tl _default_style_tl}{#1}},
+ unknown~style .code:n =
+ {\tl_set:cn{knowledge_kl_\knowledge_variant_key_tl _unknown_style_tl}{#1}},
+ unknown~style~cont .code:n =
+ {\tl_set:cn{knowledge_kl_\knowledge_variant_key_tl _unknown_style_cont_tl}{#1}},
+ %
+ auto~knowledge .code:n =
+ { \tl_set:cx{knowledge_kl_\knowledge_variant_key_tl _autoknowledge_tl}
+ {\exp_not:N\exp_args:NV
+ \exp_not:N\knowledge
+ {\exp_not:N\knowledge_kl_key_tl}
+ {namespace=\exp_not:N\knowledge_kl_namespace_tl,\exp_not:n{#1}}}},
+ %
+ style~directive .code:n = {
+ \tl_clear:c{knowledge_kl_\knowledge_variant_key_tl _styledirectives_tl}
+ \clist_map_inline:nn{#1}
+ {\use:x{\NewKnowledgeParamTl*
+ [\exp_not:c{knowledge_kl_##1_tl}]}
+ {##1}
+ \tl_put_right:cx{knowledge_kl_\knowledge_variant_key_tl _styledirectives_tl}
+ {\exp_not:c{knowledge_kl_##1_tl}}}
+ },
+ %
+ suggestion .code:n =
+ {\tl_set:cn{knowledge_kl_\knowledge_variant_key_tl _suggestion_tl}{#1}},
+ %
+ PDF~string .code:n =
+ {\exp_args:Nc\renewcommand{\knowledge_variant_key_tl _PDFstring}[3]{#1}}
+}
+% \end{macrocode}
+%
+%
+% \subsubsection{Variants of the \cs{\kl} macro}
+%
+%
+%
+% When defining a new use of \texttt{knowledge}, many macros have to be taken into account.
+% Some have to be defined explicitly. Some other have default behaviours.
+% \begin{asparaitem}
+% \itemAP \csintro{\knowledge_kl_display_preprocess_tl} is the code to be used first before displaying. It does nothing for \cs{\kl}, but is set to \cs{\knowledge_kl_target_preprocess_tl} for \cs{\intro}, which performs the \cs{\label} command fir the introduction.
+% \itemAP \csintro{\knowledge_kl_display_process_tl} is the code to be executed for displaying the \kl{knowledge}. This is not defined by default.
+% \itemAP \csintro{\knowledge_kl_error_unknown:} The fallback code to execute when the \kl{knowledge} is unknown.
+% By default, it displays a warning and put the name in orange.
+% \itemAP \csintro{\knowledge_kl_update:N} is a code to be executed to update the knowledge. By default, it increments the ktuple counter `\cs{countuse_int}'.
+% \itemAP \csintro{\knowledge_kl_namespace_tl} is the \kl{namespace} in which the \kl{knowledge} is to be searched. Not defined by default.
+% \itemAP \csintro{\knowledge_kl_linkscope_tl} is a label that points to an instance of a \kl{scope}. It can be empty, and in this case, this means that the search proceeds in the \kl{stack of visible scope instances}. By default it is empty.
+% \itemAP \csintro{\knowledge_kl_max_recursion_int} is the maximum number of recursion allowed when searching for a \kl{knowledge}. It is by default 40.
+% \end{asparaitem}
+%
+% The codes can uses internally the following variables, that are accessible for the user when defining new \cs\kl-like commands:
+% \begin{asparaitem}
+% \itemAP \csintro{\knowledge_kl_command_tl} the command that has triggered the search
+% \itemAP \csintro{\knowledge_kl_base_key_tl} contains the name of the knowledge for which the search has started,
+% \itemAP \csintro{\knowledge_kl_text_tl} contains the text to be displayed,
+% \itemAP \csintro{\knowledge_kl_key_tl} contains the name of the knowledge searched at a particular moment,
+% \itemAP \csintro{\knowledge_kl_recursion_int} counts the number of indirection in the current, starting from \cs{\knowledge_kl_max_recursion_int}, and going down,
+% \itemAP \csintro{\knowledge_kl_link_tl} contains the link to be followed.
+% \itemAP \cs{\knowledge_kl_resourcetoken_tl} contains a single token, which is the location of the knowledge.
+% \end{asparaitem}
+%
+% \begin{macrocode}
+\let\nointro\phantomintro
+% \end{macrocode}
+%
+% When the \cs{\intro} is used more than once, new labels are introduced (appending b,c,d\dots),
+% in order to point to these targets easily.
+% \begin{macrocode}
+\tl_new:Nn\knowledge_kl_target_preprocess_tl
+ {\tl_if_exist_ne:NTF\knowledge_kl_resourcetoken_tl
+ {\expandafter\ktuple_countintro_get_int:NN
+ \knowledge_kl_resourcetoken_tl\l_tmpa_int
+ \tl_set:Nx\l_tmpa_tl
+ {\int_compare:nNnTF\l_tmpa_int=1{}{\int_to_alph:n\l_tmpa_int}}}
+ {\tl_set:Nn\l_tmpa_tl{}}
+ \tl_if_exist_ne:NTF\knowledge_kl_autoref_tl
+ {\exp_args:Nx\knowledge_latex_label:n
+ {\expandafter\noexpand\knowledge_kl_autoref_tl\l_tmpa_tl}}
+ {}}
+% \end{macrocode}
+% \begin{macrocode}
+\tl_new:N\knowledge_kl_style_tl
+\tl_new:N\knowledge_kl_namespace_tl
+\tl_new:N\knowledge_kl_command_tl
+
+\cs_new:Nn\knowledge_kl_target_update:N
+ {\ktuple_countintro_gincr:N#1}
+\cs_gset:Nn\knowledge_kl_default_update:N
+ {\ktuple_countuse_gincr:N#1}
+% \end{macrocode}
+%
+%
+% \subsubsection{Code for mathematical variables (unstable)}
+%
+%
+%
+% \subsubsection{Display parameters}
+%
+%
+%\begin{compactdesc}
+%\item[\csintro{\kl_emphasize_bool}]
+%\item[\csintro{\kl_boldface_bool}]
+%\item[\csintro{\kl_underline_bool}]
+%\item[\csintro{\kl_typewriter_bool}]
+%\item[\csintro{\kl_fbox_bool}]
+%\item[\csintro{\kl_ensuremath_bool}]
+%\item[\csintro{\kl_ensuretext_bool}]
+%\item[\csintro{\kl_italic_bool}]
+%\item[\csintro{\kl_lowercase_bool}]
+%\item[\csintro{\kl_uppercase_bool}]
+%\item[\csintro{\knowledge_kl_forcedtext_tl}]
+%\item[\csreintro{\knowledge_kl_link_tl}]
+%\item[\csreintro{\knowledge_kl_linkscope_tl}]
+%\item[\csreintro{\knowledge_kl_display_process_tl}]
+%\item[\csintro{\knowledge_kl_default_invisible_display_process_tl}]
+%\end{compactdesc}
+%
+% \begin{macrocode}
+\NewKnowledgeParamBool*{fbox}\kl_fbox_bool
+\NewKnowledgeParamBool*{ensuremath}\kl_ensuremath_bool
+\NewKnowledgeParamBool*{ensuretext}\kl_ensuretext_bool
+\NewKnowledgeParamBool*{mathord}\kl_mathord_bool
+\NewKnowledgeParamBool*{mathop}\kl_mathop_bool
+\NewKnowledgeParamBool*{mathbin}\kl_mathbin_bool
+\NewKnowledgeParamBool*{mathrel}\kl_mathrel_bool
+\NewKnowledgeParamBool*{mathopen}\kl_mathopen_bool
+\NewKnowledgeParamBool*{mathclose}\kl_mathclose_bool
+\NewKnowledgeParamBool*{mathpunct}\kl_mathpunct_bool
+\NewKnowledgeParamBool*{emphasize}\kl_emphasize_bool
+\NewKnowledgeParamBool*{underline}\kl_underline_bool
+\NewKnowledgeParamBool*{typewriter}\kl_typewriter_bool
+\NewKnowledgeParamBool*{autoref~target}\kl_autoreftarget_bool
+\NewKnowledgeParamBool*{autoref~link}\kl_autoreflink_bool
+\NewKnowledgeParamBool*{invisible}\kl_invisible_bool
+\NewKnowledgeParamBool*{italic}\kl_italic_bool
+\NewKnowledgeParamBool*{smallcaps}\kl_smallcaps_bool
+\NewKnowledgeParamBool*{md}\kl_md_bool
+\NewKnowledgeParamBool*{up}\kl_up_bool
+\NewKnowledgeParamBool*{boldface}\kl_boldface_bool
+\NewKnowledgeParamBool*{detokenize}\kl_detokenize_bool
+\NewKnowledgeParamBool*{remove~space}\kl_removespace_bool
+\NewKnowledgeParamBool*{protect~link}\kl_protect_link_bool
+\NewKnowledgeParamBool*{lowercase}\kl_lowercase_bool
+\NewKnowledgeParamBool*{uppercase}\kl_uppercase_bool
+% \end{macrocode}
+%
+% \begin{macrocode}
+\NewKnowledgeParamTl*{link}
+\NewKnowledgeParamTl*{link~scope}
+\NewKnowledgeParamTl*[\knowledge_kl_instance_tl]{link~instance}
+\NewKnowledgeParamTl*[\knowledge_kl_forcedtext_tl]{text}
+\NewKnowledgeParamTl*{wrap}
+% \end{macrocode}
+%
+%
+% \begin{macrocode}
+
+\NewKnowledgeParamBool*{UnKnoWn~KNowLedGE}\kl_unknown_knowledge_bool
+\bool_gset_false:N\kl_unknown_knowledge_bool
+\ktuple_new_int_index:n{countuse}
+\ktuple_countuse_expands_to:n{}
+\ktuple_new_int_index:n{countintro}
+\ktuple_countintro_expands_to:n{}
+% \end{macrocode}
+%
+% The "directive" "now"
+% \begin{macrocode}
+\keys_define:nn{ knowledge~directives }{
+ now .code:n = { \bool_set_true:N\knowledge_knowledge_now_bool },
+ also~now .code:n = { \bool_set_true:N\knowledge_knowledge_alsonow_bool }
+}
+% \end{macrocode}
+%
+% The special directive \kl{autorefhere} is used for variables, where for which it is not necessary
+% to explicitely use a \cs{\knowledge} command.
+% \begin{macrocode}
+\int_new:N\knowledge_autoref_count
+
+\keys_define:nn{ knowledge~directives }{
+ autoref .code:n = {
+ \int_gincr:N\knowledge_autoref_count
+ \knowledge_delay_directive:x
+ {autoref = {autoref-\int_use:N\knowledge_autoref_count}}
+ \bool_set_true:N\knowledge_knowledge_autoref_bool},
+ autorefhere .code:n = {
+ \int_gincr:N\knowledge_autoref_count
+ \exp_args:Nx\label{autoref-\int_use:N\knowledge_autoref_count}
+ \knowledge_delay_directive:x
+ {autoref = {autoref-\int_use:N\knowledge_autoref_count}}}}
+
+\ktuple_new_tl_index:n{autoref}
+\use:c{ktuple_autoref_expands_to:n}
+ {\tl_set:Nn\knowledge_kl_autoref_tl{#1} }
+
+\keys_define:nn { knowledgenow~directives } {
+ autoref .code:n =
+ { \knowledge_at:c{ktuple_autoref_gset:Nn}{#1} }
+}
+% \end{macrocode}
+% \begin{macrocode}
+\int_new:N\kl_countuse_int
+\int_new:N\kl_countintro_int
+\NewKAuxCommand\KAuxAutoref{mmm}
+ {Package~knowledge:~Declares~an~autoref~knowledge.~
+ Arguments~{namespace}{instance}{knowledge}.}
+\NewKAuxCommand\KAuxAutorefTarget{mmm}
+ {Package~knowledge:~Declares~the~use~of~a~target~to~an~autoref~knowledge.~
+ Arguments~{namespace}{instance}{knowledge}.}
+\DeclareKAuxPhaseCommand\KAuxAutoref{init}{}
+
+\int_new:N\kl_digest_autorefused_int
+\int_new:N\kl_digest_autorefnointro_int
+\int_new:N\kl_digest_autoreftwiceintro_int
+\int_new:N\kl_digest_autorefunused_int
+\int_new:N\kl_digest_unknownknowledge_int
+\int_new:N\kl_digest_unknownlabel_int
+
+\DeclareKAuxPhaseCommand\KAuxErrorKnowledgeUnknown{diagnose-digest}
+ {\int_gincr:N\kl_digest_unknownknowledge_int}
+%\DeclareKAuxPhaseCommand\KAuxErrorLabelUnknown{diagnose-digest}
+% {\int_gincr:N\kl_digest_unknownlabel_int}
+
+\DeclareKAuxPhaseCommand\KAuxAutoref{diagnose-digest}
+ {\group_begin:
+ \knowledge_sets_to:nnn{#1}{#2}{#3}
+ \knowledge_at:N\ktuple_countuse_get_int:NN\kl_countuse_int
+ \knowledge_at:N\ktuple_countintro_get_int:NN\kl_countintro_int
+ \int_compare:nNnT\kl_countintro_int=1
+ {
+ \int_compare:nNnTF\kl_countuse_int=1
+ {\int_gincr:N\kl_digest_autorefunused_int}
+ {\int_gincr:N\kl_digest_autorefused_int}
+ }
+ \int_compare:nNnT\kl_countintro_int=0
+ {\int_compare:nNnF\kl_countuse_int=0
+ %{\int_gincr:N\kl_digest_autorefunused_int}
+ {\int_gincr:N\kl_digest_autorefnointro_int}}
+ \int_compare:nNnT\kl_countintro_int>1
+ {\int_gincr:N\kl_digest_autoreftwiceintro_int}
+ \group_end:}
+
+\DeclareKAuxPhaseCommand\KAuxAutoref{autoref-not-introduced}
+ {\group_begin:
+ \knowledge_sets_to:nnn{#1}{#2}{#3}
+ \knowledge_at:N\ktuple_countuse_get_int:NN\kl_countuse_int
+ \knowledge_at:N\ktuple_countintro_get_int:NN\kl_countintro_int
+ \int_compare:nNnT\kl_countuse_int>0
+ {\int_compare:nNnT\kl_countintro_int=0
+ {\knowledge_diagnose_line:
+ \knowledge_diagnose:n{\nointro{#1}{#2}{#3}}}}
+ \group_end:}
+\DeclareKAuxPhaseCommand\KAuxAutoref{autoref-introduced-not-used}
+ {\group_begin:
+ \knowledge_sets_to:nnn{#1}{#2}{#3}
+ \knowledge_at:N\ktuple_countuse_get_int:NN\kl_countuse_int
+ \knowledge_at:N\ktuple_countintro_get_int:NN\kl_countintro_int
+ \int_compare:nNnT\kl_countuse_int=1
+ {\int_compare:nNnT\kl_countintro_int=1
+ {\knowledge_diagnose_line:
+ \knowledge_diagnose:x{\kaux_current_location:\space
+ \exp_not:n{{#3}{#1}{#2}}}}}
+ \group_end:}
+\DeclareKAuxPhaseCommand\KAuxAutorefTarget{autoref-introduced-twice}
+ {\group_begin:
+ \knowledge_sets_to:nnn{#1}{#2}{#3}
+ \knowledge_at:N\ktuple_countuse_get_int:NN\kl_countuse_int
+ \knowledge_at:N\ktuple_countintro_get_int:NN\kl_countintro_int
+ \int_compare:nNnT\kl_countintro_int>1
+ {\knowledge_diagnose_line:
+ \knowledge_diagnose:x{\kaux_current_location:\space
+ \exp_not:n{{#3}{#1}{#2}}}}
+ \group_end:}
+% \end{macrocode}
+% \begin{macrocode}
+\NewKAuxCommand\KAuxUseKnowledge{mmm}
+ {Package~knowledge:~Identifies~the~use~of~some~knowledge.~
+ Arguments~{namespace}{instance}{knowledge}.}
+% \end{macrocode}
+%
+%
+%\subsubsection{Display code}
+%
+%
+%
+%
+% \begin{macrocode}
+\cs_new:Nn\knowledge_kl_display_generic:n
+ {\tl_gset:Nx\knowledge_display_code_tl
+ {\exp_not:n{#1}{\exp_not:V\knowledge_display_code_tl}}}
+\cs_new:Nn\knowledge_kl_display_generic_cond:Nn
+ {\bool_if:NTF#1
+ {\tl_gset:Nx\knowledge_display_code_tl
+ {\exp_not:n{#2}{\exp_not:V\knowledge_display_code_tl
+ }}}{}}
+\cs_generate_variant:Nn\knowledge_kl_display_generic:n{x}
+\cs_generate_variant:Nn\knowledge_kl_display_generic_cond:Nn{Nx}
+% \end{macrocode}
+% \begin{macrocode}
+\cs_new:Nn\knowledge_kl_compute_code:{
+ \tl_if_exist_ne:NTF\knowledge_kl_forcedtext_tl
+ {\tl_gset_eq:NN\knowledge_display_code_tl\knowledge_kl_forcedtext_tl}
+ {\tl_gset_eq:NN\knowledge_display_code_tl\knowledge_kl_text_tl}
+ \bool_if:NT\kl_detokenize_bool
+ {\tl_gset:Nx\knowledge_display_code_tl
+ {\tl_to_str:V\knowledge_display_code_tl}}
+ \bool_if:NT\kl_removespace_bool
+ {\tl_remove_all:Nn\knowledge_display_code_tl{~}}
+ \bool_if:NT\kl_lowercase_bool
+ {\tl_gset:Nx\knowledge_display_code_tl
+ {\exp_args:NV\tl_lower_case:n\knowledge_display_code_tl}}
+ \bool_if:NT\kl_uppercase_bool
+ {\tl_gset:Nx\knowledge_display_code_tl
+ {\exp_args:NV\tl_upper_case:n\knowledge_display_code_tl}}
+ %
+ \tl_if_empty:NTF\knowledge_kl_wrap_tl
+ {}
+ {\exp_args:NV\knowledge_kl_display_generic:n\knowledge_kl_wrap_tl}
+ %
+ \bool_if:NT\knowledge_xcolor_active_bool
+ \knowledge_kl_compute_code_xcolor:
+ \bool_if:NT\knowledge_hyperref_active_bool
+ \knowledge_kl_compute_code_hyperref:
+ %
+ \knowledge_kl_display_generic_cond:Nn\kl_underline_bool\kl_underline:n
+ \knowledge_kl_display_generic_cond:Nn\kl_md_bool\kl_md:n
+ \knowledge_kl_display_generic_cond:Nn\kl_boldface_bool\kl_bf:n
+ \knowledge_kl_display_generic_cond:Nn\kl_up_bool\kl_up:n
+ \knowledge_kl_display_generic_cond:Nn\kl_italic_bool\kl_it:n
+ \knowledge_kl_display_generic_cond:Nn\kl_smallcaps_bool\kl_smallcaps:n
+ \knowledge_kl_display_generic_cond:Nn\kl_typewriter_bool\kl_tt:n
+ % if math
+ \knowledge_kl_display_generic_cond:Nn\kl_mathop_bool\mathop
+ \knowledge_kl_display_generic_cond:Nn\kl_mathord_bool\mathord
+ \knowledge_kl_display_generic_cond:Nn\kl_mathbin_bool\mathbin
+ \knowledge_kl_display_generic_cond:Nn\kl_mathrel_bool\mathrel
+ \knowledge_kl_display_generic_cond:Nn\kl_mathclose_bool\mathclose
+ \knowledge_kl_display_generic_cond:Nn\kl_mathopen_bool\mathopen
+ \knowledge_kl_display_generic_cond:Nn\kl_mathpunct_bool\mathpunct
+ % if text
+ \knowledge_kl_display_generic_cond:Nn\kl_emphasize_bool\kl_em:n
+ \knowledge_kl_display_generic_cond:Nn\kl_fbox_bool\fbox
+ %
+ \knowledge_kl_display_generic_cond:Nn\kl_ensuremath_bool\ensuremath
+ \knowledge_kl_display_generic_cond:Nn\kl_ensuretext_bool\ensuretext
+ %
+ \bool_if:NT\knowledge_makeidx_active_bool
+ \knowledge_kl_compute_code_makeidx:
+ %
+ \bool_if:NT\kl_invisible_bool
+ {\tl_gclear:N\knowledge_display_code_tl}
+}
+\cs_new:Nn\knowledge_kl_compute_code_xcolor:{
+ \tl_if_empty:NF\knowledge_kl_color_tl
+ {\knowledge_kl_display_generic:x{\exp_not:N\textcolor{\knowledge_kl_color_tl}}}
+ \tl_if_empty:NF\knowledge_kl_colorbox_tl
+ {\knowledge_kl_display_generic:x{\exp_not:N\colorbox{\knowledge_kl_colorbox_tl}}}
+}
+\cs_new:Nn\knowledge_kl_compute_code_hyperref:{
+ \tl_if_exist_ne:NT\knowledge_kl_ref_tl
+ {\knowledge_kl_display_generic:x
+ {\exp_not:N\kl_hyperlink_silentref:nn
+ {\exp_not:V\knowledge_kl_ref_tl}}}
+ %
+ \knowledge_kl_compute_code_hyperreftarget:
+ %
+ \bool_if:NT\kl_autoreflink_bool
+ {\tl_if_exist_ne:NT\knowledge_kl_autoref_tl
+ {\knowledge_kl_display_generic:x
+ {\exp_not:N\kl_hyperlink_silentref:nn
+ {\exp_not:V\knowledge_kl_autoref_tl}}
+ }}
+ %
+ \tl_if_exist_ne:NT\knowledge_kl_url_tl
+ {\knowledge_kl_display_generic:x
+ {\exp_not:N\kl_hyperlink_url:nn
+ {\exp_not:V\knowledge_kl_url_tl}}}
+}
+\cs_new:Nn\knowledge_kl_compute_code_hyperreftarget:{
+ \bool_if:NT\kl_autoreftarget_bool
+ {\tl_if_exist_ne:NT\knowledge_kl_autoref_tl
+ {\expandafter\ktuple_countintro_get_int:NN
+ \knowledge_kl_resourcetoken_tl\l_tmpa_int
+ \tl_set:Nx\l_tmpa_tl
+ {\int_compare:nNnTF\l_tmpa_int=1
+ {} {\int_to_alph:n\l_tmpa_int}}
+ \exp_args:Nx\label{\exp_not:V\knowledge_kl_autoref_tl\l_tmpa_tl}}
+ \expandafter\ktuple_countintro_gincr:N
+ \knowledge_kl_resourcetoken_tl
+ \KAuxWriteX
+ {\exp_not:N\KAuxAutorefTarget
+ \exp_not:o\knowledge_kl_resourcearguments_tl}}
+}
+\cs_new:Nn\knowledge_kl_compute_code_makeidx:{
+ \tl_if_exist_ne:NTF\knowledge_kl_index_tl
+ {\exp_args:Nx\index
+ {\tl_if_exist_ne:NTF\knowledge_kl_index_parent_key_tl
+ {\exp_not:V\knowledge_kl_index_parent_key_tl!}{}
+ \tl_if_exist_ne:NTF\knowledge_kl_index_key_tl
+ {\exp_not:V\knowledge_kl_index_key_tl@}{}
+ \expandafter\tl_to_str:n\expandafter{\knowledge_kl_index_tl}
+ \tl_if_exist_ne:NTF\knowledge_kl_index_number_style_tl
+ {|\exp_not:V\knowledge_kl_index_number_style_tl}{}
+ }}{}
+}
+
+%\cs_new:Nn\knowledge_kl_default_display_code_fbox:n
+% {\bool_if:NTF\kl_fbox_bool{\exp_not:N\fbox{#1}}{#1}}
+% \end{macrocode}
+% \begin{macrocode}
+\cs_new:Npn\kl_up:n{\mode_if_math:TF\mathup\textup}
+\cs_new:Npn\kl_md:n{\mode_if_math:TF\mathmd\textmd}
+\cs_new:Npn\kl_sc:n{\mode_if_math:TF\mathsc\textsc}
+\cs_new:Npn\kl_it:n{\mode_if_math:TF\mathit\textit}
+\cs_new:Npn\mathscerror#1{\knowledge_error:n{`smallcaps'~only~allowed~in~math~mode.}}
+\cs_new:Npn\kl_smallcaps:n{\mode_if_math:TF\mathscerror\textsc}
+\cs_new:Npn\kl_tt:n{\mode_if_math:TF\mathtt\texttt}
+\cs_new:Npn\kl_bf:n{\mode_if_math:TF\mathbf\textbf}
+\cs_new:Npn\kl_underline:n{\mode_if_math:TF\use:n\underline}
+\cs_new:Npn\kl_em:n{\mode_if_math:TF\use:n\emph}
+% \end{macrocode}
+% \begin{macrocode}
+\cs_new:Nn\knowledge_kl_default_display_code_color:n{
+ \bool_if:NTF\knowledge_xcolor_active_bool
+ {\tl_if_exist_ne:NTF\knowledge_kl_color_tl
+ {\exp_not:N\textcolor{\knowledge_kl_color_tl}{#1}}{#1}}
+ {#1}}
+% \end{macrocode}
+% \begin{macrocode}
+\cs_new:Nn\knowledge_kl_default_display_code_colorbox:n{
+ \bool_if:NTF\knowledge_xcolor_active_bool
+ {\tl_if_exist_ne:NTF\knowledge_kl_colorbox_tl
+ {\exp_not:N\colorbox{\knowledge_kl_colorbox_tl}{#1}}{#1}}
+ {#1}}
+% \end{macrocode}
+% \begin{macrocode}
+\cs_new:Nn\knowledge_kl_default_code_nestingprotect:n{
+ \bool_if:NTF\kl_protect_link_bool
+ {\exp_not:N\kl_kl_nesting_incr:#1\exp_not:N\kl_kl_nesting_decr:}{#1}
+ }
+% \end{macrocode}
+% \begin{macrocode}
+\cs_new:Nn\knowledge_kl_default_code_wrap:n{
+ \tl_if_exist_ne:NTF\knowledge_kl_wrap_tl
+ {\exp_not:V\knowledge_kl_wrap_tl{#1}}{#1}}
+% \end{macrocode}
+% \begin{macrocode}
+\cs_new:Nn\knowledge_kl_default_display_code_text:{
+ \knowledge_kl_default_code_wrap:n{
+ \tl_if_exist_ne:NTF\knowledge_kl_forcedtext_tl
+ {\exp_not:V\knowledge_kl_forcedtext_tl}
+ {\exp_not:V\knowledge_kl_text_tl}
+ }
+}
+% \end{macrocode}
+%
+% \subsubsection{Other commands}
+%
+% \paragraph{\cs{\AP} and \cs{\itemAP}}
+% The code for the command \cs{\AP} is inspired from a
+% \href{http://tex.stackexchange.com/questions/123392/add-a-marker-to-the-left-of-the-text}{\underline{code}} of \kl{egreg} on \kl{stackexchange}.
+% \begin{macrocode}
+\NewDocumentCommand\AP{}
+ {\bool_if:NT\knowledge_hyperref_active_bool
+ {\strut\vadjust{\knowledge_AP_internal:}}}
+\NewDocumentCommand\itemAP{o}{
+ \IfNoValueTF{#1}
+ {\item\AP}
+ {\item[\knowledge_itemAP: #1]}}
+% \end{macrocode}
+% \begin{macrocode}
+\int_new:N\kl_hyperref_kl_nesting_count_int
+\bool_new:N\kl_hyperref_active_here_bool
+\bool_set_true:N\kl_hyperref_active_here_bool
+\cs_new:Npn\kl_if_hyperlinks_active_here:TF
+ {\bool_if:NTF\knowledge_hyperlinks_active_bool
+ {\bool_if:NTF\kl_hyperref_active_here_bool}
+ \use_ii:nn}
+\cs_new:Nn\kl_kl_nesting_incr:
+ {\int_gincr:N\kl_hyperref_kl_nesting_count_int
+ \bool_gset:Nn\kl_hyperref_active_here_bool
+ {\int_compare_p:nNn\kl_hyperref_kl_nesting_count_int=0}}
+\cs_new:Nn\kl_kl_nesting_decr:
+ {\int_gdecr:N\kl_hyperref_kl_nesting_count_int
+ \bool_gset:Nn\kl_hyperref_active_here_bool
+ {\int_compare_p:nNn\kl_hyperref_kl_nesting_count_int=0}}
+% \end{macrocode}
+% We make replicates of the commands of \kl(package){hyperref} that we want to sometimes deactivate.
+% \begin{macrocode}
+\cs_new:Npn\kl_hyperlink_ref:nn#1
+ {\kl_if_hyperlinks_active_here:TF{\hyperref[{#1}]}{\use:n}}
+\cs_new:Npn\kl_hyperlink_url:nn
+ {\kl_if_hyperlinks_active_here:TF\href\use_ii:nn}
+% \end{macrocode}
+% \begin{macrocode}
+\cs_new:Npn\kl_hyperlink_silentref:nn#1
+ {\kl_if_hyperref_exist:nTF{#1}
+ {\kl_hyperlink_ref:nn{#1}}
+ \use:n}
+\cs_new:Npn\kl_if_hyperref_exist:nTF#1
+ {\expandafter\ifx\csname r@#1\endcsname\relax
+ \expandafter\use_ii:nn\else
+ \expandafter\use_i:nn\fi}
+% \end{macrocode}
+% \begin{macrocode}
+\cs_new:Nn\knowledge_AP_internal:{%
+ \vbox to 0pt{
+ \noindent
+ \kern-\dp\strutbox
+ \smash{\llap{\knowledge_AP_mark:\kern0.3em}}
+ \vss}}
+\cs_new:Nn\knowledge_AP_mark:{%
+ \setlength\unitlength{1em}
+ \begin{picture}(0,0)
+ \put(0,1.2){
+ \bool_if:NT\knowledge_hyperref_active_bool
+ {\put(-0.05,-1.04){\phantomsection}}
+ \bool_if:NT\knowledge_configuration_visibleAP_bool
+ {\bool_if:NTF\knowledge_xcolor_active_bool
+ {\textcolor{red}}{\use:n}
+ {\line(0,-1){0.5}\line(1,0){0.5}}}}
+ \end{picture}{}}
+\cs_new:Nn\knowledge_itemAP:{
+ \hbox_overlap_left:n
+ {\knowledge_AP_mark:\hspace{1em}}
+ }
+% \end{macrocode}
+%
+% \subsection{Activate and deactivate the \kl{quotation notation}}
+%
+%
+% First, let us define an internal command that takes
+% knowledge,key,scope and is equivalent to \cs{\kl}.
+% \begin{macrocode}
+\tl_new:Nn\knowledge_variant_quote_modifier_tl{\kl*}
+\tl_new:Nn\knowledge_variant_doublequote_modifier_tl{\intro*}
+% \end{macrocode}
+%\knowledgeconfigure{quotation=false}
+% \begin{macrocode}
+\ExplSyntaxOff
+\def\makequotationactive
+ {\catcode`"13\relax}
+\def\makequotationletter
+ {\catcode`"12\relax}
+% \end{macrocode}
+% \begin{macrocode}
+\let\quotesymbol"
+% \end{macrocode}
+% \begin{macrocode}
+\ExplSyntaxOn
+\makequotationactive
+\edef\klactivequotationmark#1"{
+ \noexpand\tl_if_empty:nTF{#1}
+ {\noexpand\klactivedoublequotationmark}
+ {\noexpand\klquotation_parse_arobas_sep:Nw
+ \noexpand\klquotation_expand:nnn #1
+ @
+ @
+ @\noexpand\kl_end}
+}
+\edef\klactivedoublequotationmark#1""{
+ \noexpand\klquotation_parse_arobas_sep:Nw
+ \noexpand\kldoublequotation_expand:nnn #1
+ @
+ @
+ @\noexpand\kl_end
+}
+\cs_new:Npx\klquotation_parse_arobas_sep:Nw #1#2@#3@#4@#5\kl_end
+ {#1{#2}{#3}{#4}}
+
+\cs_set_eq:NN\tl_if_novalue:nTF\IfNoValueTF
+
+\cs_new:Npn\klquotation_expand:nnn
+ {\knowledge_variant_quote_modifier_tl
+ \klquotation_expand_base:nnn}
+\cs_new:Npn\kldoublequotation_expand:nnn
+ {\knowledge_variant_doublequote_modifier_tl
+ \klquotation_expand:nnn}
+% \end{macrocode}
+% \begin{macrocode}
+\cs_new:Nn\klquotation_expand_base:nnn{
+ \tl_if_empty:nTF{#2}
+ {\klTKS{#1}{#1}{#3}}
+ {\klTKS{#1}{#2}{#3}}
+}
+% \end{macrocode}
+% \begin{macrocode}
+\def\klactivatequotation
+ {\makequotationactive
+ \let"\klactivequotationmark}
+\def\kldeactivatequotation
+ {\makequotationletter}
+
+\kldeactivatequotation
+% \end{macrocode}
+%\knowledgeconfigure{quotation=true}
+%
+% We now provide the code that is used for easily activating and deactivating quotation.
+% \begin{macrocode}
+\cs_new:Nn\kl_protect_environment_quotation:n
+ {\clist_map_inline:nn{#1}
+ {\scope_area_set:nn{#1}
+ { push~code={\knowledgeconfigure{quotation=false}},
+ pop~code={\knowledgeconfigure{quotation=true}}}}
+ }
+% \end{macrocode}
+%
+
+% \subsection{Mathematics}
+%
+% \subsubsection{Capturing subscripts, superscripts and primes}
+% We know provide the core code for parsing subscripts, superscripts and primes.
+%
+% The central command is \csintro{\klparse_absorb_modifiers:}.
+% This command parses all the subscripts and so on occurring after,
+% and then launches \csintro{\klparse_absorb_modifiers_exec:}
+% (that is supposed to have been set with the proper code).
+% At the end, the token lists \csintro{\klparse_primes_tl}, \csintro{\klparse_subscript_tl}
+% and \csintro{\klparse_supscript_tl}
+% contain the texts that have been collected during the parsing.
+% If a subscript or a superscript is not present, then the corresponding token list
+% is set equal to be \cs{\klparse_novalue_tl}. This is not the case for primes:
+% if there are no primes, then the token list \cs{\klparse_primes_tl} is simply empty.
+% Parsing subscripts, superscripts and primes can be deactivated or activated by setting appropriately the
+% macros \cs{\klparse_if_load_primes:TF}
+% \cs{\klparse_if_load_subscript:TF} and \cs{\klparse_if_load_supscript:TF}.
+% \begin{macrocode}
+\cs_new:Nn\klparse_absorb_modifiers:
+ {\tl_set_eq:NN\klparse_primes_tl\c_empty_tl
+ \bool_if:NTF\klparse_load_primes_bool
+ \klparse_absorb_modifiers_pses:
+ \klparse_absorb_modifiers_ses:
+ }
+
+\cs_new:Nn\klparse_absorb_modifiers_pses:
+ {\klparse_ifnextchar:NTF'
+ {\tl_put_right:Nn\klparse_primes_tl'
+ \use_i:nn\klparse_absorb_modifiers_pses:}
+ \klparse_absorb_modifiers_ses:
+ }
+
+\cs_new:Nn\klparse_absorb_modifiers_ses:
+ {\bool_if:NTF\klparse_load_subscript_bool
+ {\klparse_absorb_subscript:Nn\klparse_subscript_tl\klparse_absorb_modifiers_es:}
+ {\tl_set_eq:NN\klparse_subscript_tl\klparse_novalue_tl
+ \klparse_absorb_modifiers_es:}
+ }
+
+\cs_new:Nn\klparse_absorb_modifiers_es:
+ {\bool_if:NTF\klparse_load_supscript_bool
+ {\tl_if_empty:NTF\klparse_primes_tl
+ {\klparse_absorb_supscript:Nn\klparse_supscript_tl
+ \klparse_absorb_modifiers_ts:}
+ {\tl_set_eq:NN\klparse_supscript_tl\klparse_novalue_tl
+ \klparse_absorb_modifiers_exec:}}
+ {\tl_set_eq:NN\klparse_supscript_tl\klparse_novalue_tl
+ \klparse_absorb_modifiers_exec:}
+ }
+
+\cs_new:Nn\klparse_absorb_modifiers_ts:
+ {\bool_if:NTF\klparse_load_subscript_bool{
+ \klparse_if_novalue:NTF\klparse_subscript_tl
+ {\klparse_absorb_subscript:Nn\klparse_subscript_tl\klparse_absorb_modifiers_exec:}
+ \klparse_absorb_modifiers_exec:}
+ {\klparse_absorb_modifiers_exec:}
+ }
+% \end{macrocode}
+%
+% The macros \csintro{\klparse_absorb_subscript:Nn} and \csintro{\klparse_absorb_supscript:Nn}.
+% These are weirdly defined because the catcode of underscore is changed.
+% \begin{macrocode}
+\ExplSyntaxOff
+\def\absorbsupscriptNn{\absorbopt ^}
+\def\absorbsubscriptNn{\absorbopt _}
+\ExplSyntaxOn
+\cs_set_eq:NN\klparse_absorb_supscript:Nn\absorbsupscriptNn
+\cs_set_eq:NN\klparse_absorb_subscript:Nn\absorbsubscriptNn
+
+\cs_new:Npn\absorbopt#1#2#3
+ {\klparse_ifnextchar:NTF #1
+ {\klparse_absorbopt_ii:NnNn #2 {#3}}
+ {\tl_set_eq:NN #2 \klparse_novalue_tl #3}}
+
+\cs_new:Nn\klparse_absorbopt_ii:NnNn
+ {\tl_set:Nn #1 {#4} #2 }
+% \end{macrocode}
+%
+% \begin{macrocode}
+\cs_set_eq:NN\klparse_if_load_subscript:TF\use_i:nn
+\cs_set_eq:NN\klparse_if_load_supscript:TF\use_i:nn
+\cs_set_eq:NN\klparse_if_load_primes:TF\use_i:nn
+% \end{macrocode}
+%
+%
+%
+% \subsection{Subpackages}
+%
+% \subsubsection{Generalities}
+%
+% \begin{macrocode}
+\cs_new:Nn\knowledge_directives_require_aci_package:nn
+ {\bool_if:cTF{knowledge_#2_syntax_bool}{}{
+ \NewKnowledgeParamPackageError{#1}{#2}}}
+% \end{macrocode}
+%
+%
+% \subsubsection{The \kl{xcolor option}}
+%
+% \begin{macrocode}
+\NewKnowledgeParamTl*{color}
+\NewKnowledgeParamTl*{colorbox}
+\knowledge_directives_require_aci_package:nn
+ {color,colorbox,cyclic~color}{xcolor}
+% \end{macrocode}
+%
+% \begin{macrocode}
+\tl_new:N\knowledge_cyclic_colors_tl
+\tl_new:N\knowledge_cyclic_color_tl
+% \end{macrocode}
+%
+% \begin{macrocode}
+\keys_define:nn{ knowledge~configuration~options }{
+ cyclic~colors .code:n = {\tl_gset:Nn\knowledge_cyclic_colors_tl{#1}}
+}
+\knowledgeconfigure{cyclic~colors =
+ {red,green,blue,cyan,magenta,yellow,gray,brown,lime,olive,orange,pink,purple,teal,violet}}
+% \end{macrocode}
+%
+% \begin{macrocode}
+\cs_new:Npn\__knowledge_cyclic_color_next:w#1,#2\__knowledge_cyclic_end
+ {\tl_gset:Nn\knowledge_cyclic_colors_tl{#2,{#1}}
+ \tl_gset:Nn\knowledge_cyclic_color_tl{#1}}
+\cs_new:Nn\knowledge_cycle_colors:
+ {\expandafter\__knowledge_cyclic_color_next:w\knowledge_cyclic_colors_tl\__knowledge_cyclic_end}
+
+\keys_define:nn{ knowledge~directives }{
+ cyclic~color .code:n = {
+ \knowledge_cycle_colors:
+ \knowledge_delay_directive:x
+ {color = {\knowledge_cyclic_color_tl}}}
+}
+% \end{macrocode}
+%
+% \subsubsection{The \kl{hyperref option}}
+%
+% \begin{macrocode}
+\NewKnowledgeParamTl*{url}
+\NewKnowledgeParamTl*{ref}
+
+\knowledge_directives_require_aci_package:nn
+ {url,ref,autoref}{hyperref}
+% \end{macrocode}
+% The commands \cs{\intro}, \cs{\kl} and \cs{\reintro} are made silent when
+% creating the pdf names of sections (for avoiding warnings of the "hyperref@@package").
+% \begin{macrocode}
+\bool_if:NT\knowledge_hyperref_active_bool{
+ \DeclareExpandableDocumentCommand\knowledge_fake_klTKS{mmm}{#1}
+ \pdfstringdefDisableCommands{%
+ \let\klTKS\knowledge_fake_klTKS
+ }
+}
+% \end{macrocode}
+%
+%
+% \subsubsection{The \kl{makeidx option}}
+%
+% \begin{macrocode}
+%\bool_if:NT\knowledge_makeidx_active_bool{
+% \makeindex
+%
+% \cs_gset:Npn\knowledge_kl_display_code_index:n
+% {\knowledge_kl_default_display_code_index:n}
+%
+% \cs_new:Npn\knowledge_kl_default_display_code_index:n
+% {\useless\tl_if_exist_ne:NT\knowledge_kl_index_tl
+% {\exp_not:N\index
+% {{\tl_if_exist_ne:NTF\knowledge_kl_index_parent_key_tl
+% {\exp_not:V\knowledge_kl_index_parent_key_tl!}{}
+% \tl_if_exist_ne:NTF\knowledge_kl_index_key_tl
+% {\exp_not:V\knowledge_kl_index_key_tl@}{}
+% \expandafter\tl_to_str:n\expandafter{\knowledge_kl_index_tl}
+% }}}}
+%}
+\def\knowledgeIntroIndexStyle#1{\textbf{#1}}
+\NewKnowledgeParamTl{index}
+\keys_define:nn { knowledge~directives }
+{ index .code:n = {
+ \tl_if_empty:nTF{#1}
+ {\knowledge_delay_directive:x{index={\exp_not:V\knowledge_knowledge_key_tl}}}
+ {\knowledge_delay_directive:n{index={#1}}}},
+ index .default:n = {}
+}
+
+\NewKnowledgeParamTl*[\knowledge_kl_index_number_style_tl]{index~style}
+\NewKnowledgeParamTl*[\knowledge_kl_index_parent_key_tl]{index~parent~key}
+\NewKnowledgeParamTl*[\knowledge_kl_index_key_tl]{index~key}
+% \end{macrocode}
+%
+% \subsection{Fixes}
+%
+% \subsubsection{Hyperref in twocolumn}
+%
+% A bug occurs when hyperref is used in twocolumn mode and a link spreads on the boundary between two pages. This causes a fatal error. Here is defined a workaround found at:
+%\url{http://tex.stackexchange.com/questions/249579/pdfendlink-ended-up-in-different-nesting-level-than-pdfstartlink-error-with}
+% for avoiding problems with hyperref links being split it is suficient to call
+% the macro \cs{\knowledgeFixHyperrefTwocolumn}
+% or \cs\knowledgeconfigure\texttt\{\kl{fix hyperref twocolumn}\texttt\}
+% \begin{macrocode}
+\ExplSyntaxOff\makeatletter
+\newcommand\knowledgeFixHyperrefTwocolumn{
+ \RequirePackage{etoolbox}
+ \newcount\c@additionalboxlevel
+ \setcounter{additionalboxlevel}{0}
+ \newcount\c@maxboxlevel
+ \setcounter{maxboxlevel}{1}
+ \patchcmd\@combinedblfloats{\box\@outputbox}{%
+ \stepcounter{additionalboxlevel}%
+ \box\@outputbox
+ }{}{\errmessage{\noexpand\@combinedblfloats could not be patched}}
+ %
+ \AtBeginShipout{%
+ \ifnum\value{additionalboxlevel}>\value{maxboxlevel}%
+ \typeout{Warning: maxboxlevel might be too small, increase to %
+ \the\value{additionalboxlevel}%
+ }%
+ \fi
+ \@whilenum\value{additionalboxlevel}<\value{maxboxlevel}\do{%
+ \typeout{* Additional boxing of page `\thepage'}%
+ \setbox\AtBeginShipoutBox=\hbox{\copy\AtBeginShipoutBox}%
+ \stepcounter{additionalboxlevel}%
+ }%
+ \setcounter{additionalboxlevel}{0}%
+ }
+}
+\ExplSyntaxOn
+\makeatother
+% \end{macrocode}
+%
+%
+%
+% \subsection{configuration}
+%
+% \subsubsection{Accessing the \kl{writing mode}}
+%
+% The paper can be compiled either in \kl{composition mode}, in \kl{paper mode}, or in \kl{electronic mode}.
+% But not both or none. In case of none, this is by default \kl{paper mode}. In case both are activated, this is \kl{paper mode}.
+% \begin{macrocode}
+\bool_if:NF\knowledge_option_composition_bool
+ {\bool_if:NF\knowledge_option_paper_bool}
+ {\bool_set_true:N\knowledge_option_composition_bool}
+\bool_if:NT\knowledge_option_composition_bool
+ {\bool_if:NT\knowledge_option_paper_bool}
+ {\bool_set_false:N\knowledge_option_composition_bool}
+
+
+\DeclareExpandableDocumentCommand\IfKnowledgeCompositionModeTF{}
+ {\bool_if:NTF\knowledge_option_composition_bool}
+\newif\ifKnowledgeCompositionMode
+\IfKnowledgeCompositionModeTF
+ \KnowledgeCompositionModetrue
+ \KnowledgeCompositionModefalse
+
+\DeclareExpandableDocumentCommand\IfKnowledgeElectronicModeTF{}
+ {\bool_if:NTF\knowledge_option_electronic_bool}
+\newif\ifKnowledgeElectronicMode
+\IfKnowledgeElectronicModeTF
+ \KnowledgeElectronicModetrue
+ \KnowledgeElectronicModefalse
+
+\DeclareExpandableDocumentCommand\IfKnowledgePaperModeTF{}
+ {\bool_if:NTF\knowledge_option_paper_bool}
+\DeclareExpandableDocumentCommand\IfKnowledgePaperModeF{}
+ {\IfKnowledgePaperModeTF{}}
+\newif\ifKnowledgePaperMode
+\IfKnowledgePaperModeTF
+ \KnowledgePaperModetrue
+ \KnowledgePaperModefalse
+
+\DeclareExpandableDocumentCommand\IfXcolorTF{}
+ {\bool_if:NTF\knowledge_xcolor_active_bool}
+\newif\ifXcolor
+\IfXcolorTF
+ \Xcolortrue
+ \Xcolorfalse
+% \end{macrocode}
+% When "xcolor@@package" is loaded, introduced indices are in red.
+% \begin{macrocode}
+\IfXcolorTF
+ {\def\knowledgeIntroIndexStyle#1{\textcolor{red}{#1}}}
+ {}
+% \end{macrocode}
+%
+%
+% \subsubsection{Variants of the \cs{\kl} macro}
+%
+% \begin{macrocode}
+\tl_new:Nn\knowledge_kl_default_style_tl{kl}
+\tl_new:Nn\knowledge_kl_unknown_style_tl{kl~unknown}
+\tl_new:Nn\knowledge_kl_unknown_style_cont_tl{kl~unknown~cont}
+\tl_new:Nn\knowledge_kl_styledirectives_tl{\knowledge_kl_style_tl}
+
+\ExplSyntaxOff
+\knowledgestyle{autoref link}{autoref link}
+\knowledgestyle{autoref target}{autoref target}
+\knowledgestyle{invisible}{invisible}
+
+\knowledgenewvariant\kl{
+ namespace= default,
+ default style= {kl,autoref link},
+ unknown style= kl unknown,
+ unknown style cont= kl unknown cont,
+ style directive={style}
+}
+\knowledgenewvariant\intro{
+ namespace= default,
+ default style= {intro,autoref target},
+ unknown style= intro unknown,
+ unknown style cont= intro unknown cont,
+ style directive= intro style
+}
+\knowledgenewvariant\phantomintro{
+ namespace=default,
+ default style={invisible,autoref target},
+ unknown style=invisible,
+ unknown style cont=invisible
+}
+\knowledgenewvariant\reintro{
+ namespace=default,
+ default style=intro,
+ unknown style=intro unknown,
+ unknown style cont=intro unknown cont,
+ style directive=intro style
+}
+\knowledgevariantmodifier{\intro*\kl}{\intro}
+\knowledgevariantmodifier{\reintro*\kl}{\reintro}
+
+\ExplSyntaxOn
+% \end{macrocode}
+%
+% \subsubsection{Basic configuration}
+%
+% \begin{macrocode}
+\tl_set_eq:NN\knowledge_kl_namespace_tl\knowledge_default_namespace_tl
+% \end{macrocode}
+%
+% \begin{macrocode}
+\newcommand\robustdisplay[1]
+ {\expandafter\use:n%\tl_trim_spaces:n
+ \expandafter{\tl_to_str:n{#1}}}
+\newcommand\robustdisplaybracket[1]
+ {[\robustdisplay{#1}]}
+
+\ExplSyntaxOff
+% in paper mode, nothing is displayed
+\IfKnowledgePaperModeTF{
+ \knowledgestyle{kl}{}
+ \knowledgestyle{kl unknown}{}
+ \knowledgestyle{kl unknown cont}{}
+ \knowledgestyle{intro}{emphasize,index style=knowledgeIntroIndexStyle}
+ \knowledgestyle{intro unknown}{emphasize}
+ \knowledgestyle{intro unknown cont}{emphasize}
+}{}
+
+\IfKnowledgeCompositionModeTF{
+ \IfXcolorTF{
+ \knowledgestyle{kl}{color={blue!70!black}}
+ \knowledgestyle{kl unknown}{color=orange}
+ \knowledgestyle{kl unknown cont}{color=brown}
+ \knowledgestyle{intro}{emphasize,color=blue,index style=knowledgeIntroIndexStyle}
+ \knowledgestyle{intro unknown}{emphasize,color=orange}
+ \knowledgestyle{intro unknown cont}{emphasize,color=brown}
+ }{
+ \knowledgestyle{kl}{}
+ \knowledgestyle{kl unknown}{underline}
+ \knowledgestyle{kl unknown cont}{underline}
+ \knowledgestyle{intro}{emphasize,index style=introindexstyle}
+ \knowledgestyle{intro unknown}{emphasize,underline}
+ \knowledgestyle{intro unknown cont}{emphasize,underline}
+ }
+}{}
+
+\IfKnowledgeElectronicModeTF{
+ \IfXcolorTF{
+ \knowledgestyle{kl}{color={blue!70!black}}
+ \knowledgestyle{kl unknown}{}
+ \knowledgestyle{kl unknown cont}{}
+ \knowledgestyle{intro}{emphasize,color=blue,index style=introindexstyle}
+ \knowledgestyle{intro unknown}{emphasize}
+ \knowledgestyle{intro unknown cont}{emphasize}
+ }{
+ \knowledgestyle{kl}{}
+ \knowledgestyle{kl unknown}{}
+ \knowledgestyle{kl unknown cont}{}
+ \knowledgestyle{intro}{emphasize,index style=introindexstyle}
+ \knowledgestyle{intro unknown}{emphasize}
+ \knowledgestyle{intro unknown cont}{emphasize}
+ }
+}{}
+
+\ExplSyntaxOn
+\let\nointro\phantomintro
+% \end{macrocode}
+%
+
+%
+% \subsubsection{The "notion" configurations}
+% \label{section:notion option}
+%
+%\paragraph{The configuration option `\kl{notion}'.}
+%
+%The macro \csintro{\KnowledgeConfigureNotion}
+% takes an optional color name (default is blue), and a text.
+% it creates the equivalent of notion of this name, including, configuration of the colors, introducing of styles, and so on.
+%
+% \begin{macrocode}
+\ExplSyntaxOff
+\newrobustcmd\KnowledgeConfigureNotion[2][blue]{
+% \end{macrocode}
+% This code, which is called using \cs{\KnowledgeConfigureNotion} or
+% the configuration option \kl{notion} can serve as a basis for other configuration.
+%\begin{code}[10cm]
+% \begin{macrocode}
+ \knowledgedirective{#2}{autoref,style=#2,intro style=intro #2}
+ \ifKnowledgePaperMode
+ % paper mode
+ \knowledgestyle{#2}{}
+ \knowledgestyle{intro #2}{emphasize}
+ \fi
+ \ifKnowledgeCompositionMode
+ \ifXcolor
+ % composition mode with colors
+ \knowledgestyle{#2}{color={#1!70!black}}
+ \knowledgestyle{intro #2}{emphasize,color={#1}}
+ \else
+ % composition mode, no colors (use underline)
+ \knowledgestyle{#2}{underline}
+ \knowledgestyle{intro #2}{emphasize, underline}
+ \fi
+ \fi
+ \ifKnowledgeElectronicMode
+ \ifXcolor
+ % electronic mode
+ \knowledgestyle{#2}{color={#1!70!black}}
+ \knowledgestyle{intro #2}{emphasize,color={#1}}
+ \else
+ % electronic mode, no colors (use underline)
+ \knowledgestyle{#2}{underline}
+ \knowledgestyle{intro #2}{emphasize, underline}
+ \fi
+ \fi
+% \end{macrocode}
+%\end{code}
+% End of the interesting code.
+% \begin{macrocode}
+}
+\ExplSyntaxOn
+% \end{macrocode}
+%
+% \subsection{Finalizing}
+%
+% At the end, the pending configurations have to be executed (this has to be done with the proper
+% catcode when for instance the \kl(option){quotation} notation is activated).
+%</package>
+%<*tail>
+% \begin{macrocode}
+\ExplSyntaxOn
+\exp_args:NNV\ExplSyntaxOff\knowledgeconfigure\knowledge_configuration_pending_tl
+% \end{macrocode}
+% \begin{macrocode}
+%\ScopeActivate
+% \end{macrocode}
+%</tail>
+%
+% \Finale
+%\endinput
+
+
+
+