% \iffalse
% !TEX encoding = UTF-8 Unicode
% !TEX TS-program = pdflatex
%
%
%
%  meta-comment
%
% Copyright (C) 2017-2025 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}{2026/06/02}{1.34}{}
%<*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} %
% \changes{1.17}{2019/10/03}{improvements} %
% \changes{1.18}{2019/10/03}{bug fix/improvement} %
% \changes{1.19}{2019/11/19}{bug fix} %
% \changes{1.20}{2019/12/03}{bug fix} %
% \changes{1.21}{2020/01/26}{bug fix} %
% \changes{1.22}{2020/03/05}{improvements} %
% \changes{1.23}{2020/04/25}{minor change} %
% \changes{1.24}{2020/09/22}{silent option} %
% \changes{1.25}{2021/03/31}{bug correction} %
% \changes{1.26}{2021/12/20}{enhanced math+other functionalities+extra options} %
% \changes{1.27}{2022/01/12}{doc changes} %
% \changes{1.28}{2022/02/12}{imakeidx support} %
% \changes{1.29}{2024/03/10}{typographic bug corrected} %
% \changes{1.30}{2025/02/20}{bug correction} %
% \changes{1.31}{2025/05/09}{bug correction} %
% \changes{1.32}{2025/06/26}{new features} %
% \changes{1.33}{2026/04/02}{bug correction} %
% \changes{1.34}{2026/06/02}{bug correction} %
% \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.34
     date: 2026/06/02
     author: Thomas Colcombet
     mail: thomas.colcombet@irif.fr
     web: https://ctan.org/pkg/knowledge

### 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 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 using
   LaTeX to provide a longer documentation with code.
 - 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}
\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}
%
%    \begin{macrocode}
\tl_new:N\char_escape_tl
\tl_set:Nx\char_escape_tl
   {\expandafter\tl_head:n\expandafter{\string\escape}}
%    \end{macrocode}
%
%    \begin{macrocode}
\cs_new:Nn\debug_vars:nn{
   \iow_term:n{---~{#1}}
   \tl_map_inline:nn{#2}
      {\iow_term:x{\space\space\exp_not:N##1=\space\tl_if_exist:NTF##1
           {{\exp_not:V##1}}
           {undefined}}}
}
%    \end{macrocode}
% \AP One also defines \csintro{\knowledge_invisible_begin:} and \csintro{\knowledge_invisible_end:}
% as shorthands for the standard \cs{\@bsphack} and \cs{\@esphack} macros.
%    \begin{macrocode}
\makeatletter
\cs_new_eq:NN\knowledge_invisible_begin:\@bsphack
\cs_new_eq:NN\knowledge_invisible_end:\@esphack
\makeatother
%    \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}
%
%    \begin{macrocode}
\cs_new:Npn\knowledge_warning:nn{
   \bool_if:NTF\knowledge_warningsilent_bool
      \use_none:nn
      \msg_warning:nn
}
\cs_new:Npn\knowledge_warning:nnn{
   \bool_if:NTF\knowledge_warningsilent_bool
      \use_none:nnn
      \msg_warning:nnn
}
\cs_new:Npn\knowledge_warning:nnnn{
   \bool_if:NTF\knowledge_warningsilent_bool
      \use_none:nnnn
      \msg_warning:nnnn
}
\cs_generate_variant:Nn\knowledge_warning:nnnn{nnxx}
\cs_new:Npn\knowledge_warning:nnnnn{
   \bool_if:NTF\knowledge_warningsilent_bool
      \use_none:nnnnn
      \msg_warning:nnnnn
}
\cs_generate_variant:Nn\knowledge_warning:nnnnn{nnxxx}
%    \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}
%    \begin{macrocode}
\msg_new:nnn{ knowledge }{ knowledgedirective~redifinition }
  { Directive~'#1'~already~exists~(\knowledgedirective~macro). }
%    \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}
\exp_args:Nnnx\msg_new:nnn{knowledge}{recap~unknown~knowledge}
  {Some~knowledge~are~not~defined.~See~the~'\c_sys_jobname_str.diagnose'~file~for~more~information.}
\exp_args:Nnnx\msg_new:nnn{knowledge}{recap~autoref~introduced~twice}
  {Some~knowledge~is~introduced~twice.~See~the~'\c_sys_jobname_str.diagnose'~file~for~more~information.}
\exp_args:Nnnx\msg_new:nnn{knowledge}{recap~autoref~not~introduced}
  {Some~knowledge~is~used~but~not~introduced.~See~the~'\c_sys_jobname_str.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}[parameter]\{option name\}\{code\}
%\end{quote}
% triggers the code when the corresponding configuration option is required.
% If no optional parameter is given, the trigger name is used instead (with spaces removed).
%    \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_warningsilent_bool
\bool_set_false:N\knowledge_warningsilent_bool
\KnowledgeConfigureBooleanOption[\knowledge_warningsilent_bool]{silent}
%    \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}
% Activates or deactivates the help in the "diagnose file".
%    \begin{macrocode}
\bool_new:N\knowledge_configuration_diagnosehelp_bool
\bool_set_true:N\knowledge_configuration_diagnosehelp_bool
\KnowledgeConfigureBooleanOption[\knowledge_configuration_diagnosehelp_bool]{diagnose~help}
%    \end{macrocode}
%
%    \begin{macrocode}
\bool_new:N\knowledge_configuration_diagnosebar_bool
\bool_gset_true:N\knowledge_configuration_diagnosebar_bool
\KnowledgeConfigureBooleanOption[\knowledge_configuration_diagnosebar_bool]{bar~suggestion}%backward compatibility
\KnowledgeConfigureBooleanOption[\knowledge_configuration_diagnosebar_bool]{diagnose~bar}
%    \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}
% Modes are stored in \csintro{\knowledge_option_mode_tl}.
%    \begin{macrocode}
\bool_new:N\knowledge_option_texpatch_bool
\bool_set_true:N\knowledge_option_texpatch_bool
\KnowledgePackageTrigger{ no patch }{\bool_set_false:N\knowledge_option_texpatch_bool}
%    \end{macrocode}
%    \begin{macrocode}
\tl_new:N\knowledge_option_knowledgeAP_command_tl
\tl_set:Nn\knowledge_option_knowledgeAP_command_tl{}
\tl_new:N\knowledge_option_complexityAP_command_tl
\tl_set:Nn\knowledge_option_complexityAP_command_tl{}
\KnowledgePackageTrigger{ knowledge AP }{
   \tl_if_single_token:nTF{#1}
     {\tl_set:Nn\knowledge_option_knowledgeAP_command_tl{#1}}
     {\knowledge_error:n{Package~option~'knowledge~AP'~must~be~followed~by~a~single~control~sequence.}}
}
\KnowledgePackageTrigger{ complexity AP }{
   \tl_if_single_token:nTF{#1}
     {\tl_set:Nn\knowledge_option_complexityAP_command_tl{#1}}
     {\knowledge_error:n{Package~option~'complexity~AP'~must~be~followed~by~a~single~control~sequence.}}
}
%    \end{macrocode}
%
%
%    \begin{macrocode}
\tl_new:N\knowledge_option_anchor_point_color_tl
\tl_set:Nn\knowledge_option_anchor_point_color_tl{red}
\KnowledgeConfigureTrigger{anchor~point~color}
  {\tl_set:Nn\knowledge_option_anchor_point_color_tl{#1}}
\KnowledgeConfigureTrigger{AP~color}
  {\tl_set:Nn\knowledge_option_anchor_point_color_tl{#1}}
\tl_new:N\knowledge_option_anchor_point_shift_tl
\tl_set:Nn\knowledge_option_anchor_point_shift_tl{(0,0)}
\KnowledgeConfigureTrigger{anchor~point~shift}
  {\tl_set:Nn\knowledge_option_anchor_point_shift_tl{(#1)}}
\KnowledgeConfigureTrigger{AP~shift}
  {\tl_set:Nn\knowledge_option_anchor_point_shift_tl{(#1)}}
  
\cs_new:Nn\knowledge_anchor_point_corner:n{\line(0,-1){#1}\line(1,0){#1}}
\cs_new:Nn\knowledge_anchor_point_cross:n{
	\put(0,0){\line(0,-1){#1}}\put(0,0){\line(0,1){#1}}\put(0,0){\line(-1,0){#1}}\put(0,0){\line(1,0){#1}}}
\tl_new:N\knowledge_option_anchor_point_shape_tl
\tl_set:Nn\knowledge_option_anchor_point_shape_tl{\knowledge_anchor_point_corner:n{0.2}}

\tl_const:Nn\knowledge_APshape_name_corner_tl{corner}
\tl_const:Nn\knowledge_APshape_name_tinycorner_tl{tiny~corner}
\tl_const:Nn\knowledge_APshape_name_smallcorner_tl{small~corner}
\tl_const:Nn\knowledge_APshape_name_largecorner_tl{large~corner}
\tl_const:Nn\knowledge_APshape_name_cross_tl{cross}
\tl_const:Nn\knowledge_APshape_name_tinycross_tl{tiny~cross}
\tl_const:Nn\knowledge_APshape_name_smallcross_tl{small~cross}
\tl_const:Nn\knowledge_APshape_name_largecross_tl{large~cross}

\KnowledgeConfigureTrigger{AP~shape}
  {\knowledge_set_anchor_point_shape:n{#1}}
\KnowledgeConfigureTrigger{anchor~point~shape}
  {\knowledge_set_anchor_point_shape:n{#1}}
\cs_new:Nn	\knowledge_set_anchor_point_shape:n{	
    \tl_set:Nn\l_tmpa_tl{#1}
    \tl_case:NnTF\l_tmpa_tl{
    	\knowledge_APshape_name_corner_tl
		{\tl_set:Nn\knowledge_option_anchor_point_shape_tl{\knowledge_anchor_point_corner:n{0.5}}}
    	\knowledge_APshape_name_tinycorner_tl 
		{\tl_set:Nn\knowledge_option_anchor_point_shape_tl{\knowledge_anchor_point_corner:n{0.1}}}
    	\knowledge_APshape_name_smallcorner_tl
		{\tl_set:Nn\knowledge_option_anchor_point_shape_tl{\knowledge_anchor_point_corner:n{0.2}}}
    	\knowledge_APshape_name_largecorner_tl 
		{\tl_set:Nn\knowledge_option_anchor_point_shape_tl{\knowledge_anchor_point_corner:n{0.8}}}
    	\knowledge_APshape_name_cross_tl
		{\tl_set:Nn\knowledge_option_anchor_point_shape_tl{\knowledge_anchor_point_cross:n{0.5}}}
    	\knowledge_APshape_name_tinycross_tl 
		{\tl_set:Nn\knowledge_option_anchor_point_shape_tl{\knowledge_anchor_point_cross:n{0.1}}}
    	\knowledge_APshape_name_smallcross_tl
		{\tl_set:Nn\knowledge_option_anchor_point_shape_tl{\knowledge_anchor_point_cross:n{0.2}}}
    	\knowledge_APshape_name_largecross_tl 
		{\tl_set:Nn\knowledge_option_anchor_point_shape_tl{\knowledge_anchor_point_cross:n{0.8}}}
    }{}{
    	\tl_set:Nn\knowledge_option_anchor_point_shape_tl{#1}
    }
  }
%    \end{macrocode}
%
%
%    \begin{macrocode}
\KnowledgeConfigureTrigger{ fix~hyperref~twocolumn }
  {\knowledgeFixHyperrefTwocolumn}
\KnowledgeConfigureTrigger{ notion }
  {
   \knowledge_directives_require_aci_package:nn{notion}{hyperref}
  \IfNoValueTF{#1}
      {
        \KnowledgeConfigureNotion[blue]{notion}
        \knowledgesetvariant\kl{suggestion=notion}
        \knowledgesetvariant\intro{suggestion=notion}
        \knowledgesetvariant\phantomintro{suggestion=notion}
        \knowledgesetvariant\reintro{suggestion=notion}  
      }
      {
        \KnowledgeConfigureNotion[blue]{#1}
      }
   }
\KnowledgeConfigureTrigger{ protect~links }
  {\kl_kl_nesting_incr:}
\KnowledgeConfigureTrigger{ unprotect~links }
  {\kl_kl_nesting_decr:}
%    \end{macrocode}
%
%
%
% \subsubsection{External package options}
%
%\csintro{\knowledge_cleveref_active_bool},
%\csintro{\knowledge_cleveref_syntax_bool},
%\csintro{\knowledge_hyperref_active_bool},
%\csintro{\knowledge_hyperref_syntax_bool},
%\csintro{\knowledge_makeidx_active_bool},
%\csintro{\knowledge_makeidx_syntax_bool},
%\csintro{\knowledge_imakeidx_active_bool}, 
%\csintro{\knowledge_imakeidx_syntax_bool}.
%\csintro{\knowledge_xcolor_active_bool},
% \csintro{\knowledge_xcolor_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}
\knowledge_option_aci_test_loaded:n{imakeidx}
\knowledge_option_aci_test_loaded:n{cleveref}
%    \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}
\knowledge_option_aci_define:n{imakeidx}
\knowledge_option_aci_define:n{cleveref}
%    \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 }{}{}
\knowledge_option_aci_autoload:nn{ xcolor }{}
\knowledge_option_aci_autoload:nn{ makeidx }{}
\knowledge_option_aci_autoload:nn{ imakeidx }{}
\knowledge_option_aci_autoload:nn{ cleveref }{}
%    \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[\intro{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[\intro{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}
     \knowledge_pop_visible_instances_to_mark:
     \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}
  %
  \knowledge_push_visible_instance_mark:
  \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').
%    \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}
% \csintro{\scope_get_labelizable_instance:N} takes a token list variable as input for holding the result.
% It inspects the current stack of instances \cs{\scope_instances_stack_seq}, searching for an "instance"
% of a "scope" which is labelizable, and returns it. The default is `base'.
%    \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 \csintro{\knowledge_scope_track_instance:Nn} is the internal part od the "scope=" directive.
% It takes as argument a token list variable for holding the result, and a text to be looked for.
% If the text corresponds to a "scope" name (such as section, theorem, \dots), then it inspects the
% content of the stacks for finding the target.
% Otherwise, it uses it as a label.
% 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{
%    \tl_show:n{#1:#2}
%    \scope_area_if_exist:nTF{#2}
%       {\knowledge_scope_track_instance_from_area:Nn#1{#2}}
%       {\knowledge_scope_track_instance_from_scopetag: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=}}
    {}
}
%    \end{macrocode}
% \AP The command \cs{\knowledge_scope_track_scope:n}
% is used to set the variable \cs{\knowledge_knowledge_instance_tl}.
% If the argument is a scope name, then it is searched for in the context, and the corresponding "instance" is used.
% Otherwise it is used as a "scopetag"; this "scopetag" being potentially
% defined if necessary using \cs{\knowledge_scopetag_warn_if_unknown:n}.
%    \begin{macrocode}
\cs_new:Nn\knowledge_scope_track_scope:n{
    \scope_area_if_exist:nTF{#1}
       {\knowledge_scope_track_instance_from_area:Nn\knowledge_knowledge_instance_tl{#1}}
       {\tl_set:Nn\knowledge_knowledge_instance_tl{explicit-scope:#1}
        \knowledge_scopetag_warn_if_unknown:n{#1}}
}
%    \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{Scope tags}
%
% \AP A ""scopetag"" is a name that can be used to identify a family of  "instances" that correspond to it.
% It gets to have two variables attached to it:
% \begin{description}
% \itemAP[\cs{\knowledge_scopetag_tl}\texttt{{[TAG]}\_bool}] which tells whether it
%    has been officially declared (it is false if it has been used but not declared by a \cs{\knowledgescope}
%    or a \cs{\label} command).
% \itemAP[\cs{\knowledge_scopetag_tl}\texttt{{[TAG]}\_seq}] is a sequence of
%    "instances" that are attached to it. It always contains (as soon as created) \textbf{explicit-scope:}\texttt{TAG}.
% \end{description}
%
% In order to identify scopes, the command~\cs{\knowledgescope} (or \cs{\label} which is overloaded for this purpose).
%
% \par\noindent\AP\csintro{\knowledge_scopetag_tl} is a unique string for identifying "scopetags".
% \par\noindent\AP\csintro{\knowledge_scopetag_if_exist:nTF} tests the existence of a "scopetag".
% \par\noindent\AP\csintro{\knowledge_scopetag_ensure:n} guarantees that the "scopetag" is defined (by default, the boolean is set to false).
% \par\noindent\AP\csintro{\knowledge_scopetag_warn_if_unknown:n} writes  \cs{\KAuxUndeclaredScopeTag} to the "kaux file" if the "scopetag" was never met before, then calls \cs{\knowledge_scopetag_ensure:n}.
% \par\noindent\AP\csintro{\knowledge_scopetag_declares:n} creates the "scopetag" if necessary, and if it was not known before, declares and puts a \cs{\KAuxDeclaredScopeTag} command in the "kaux file".
%    \begin{macrocode}
\tl_const:Nn\knowledge_scopetag_tl{ScpT@g}
%    \end{macrocode}
%    \begin{macrocode}
\cs_new:Npn\knowledge_scopetag_if_exist:nTF#1
   {\tl_if_exist:cTF{\knowledge_scopetag_tl[#1]_bool}}
\cs_new:Nn\knowledge_scopetag_ensure:n{
   \knowledge_scopetag_if_exist:nTF{#1}{}
      {\bool_new:c{\knowledge_scopetag_tl[#1]_bool}
       \bool_gset_false:c{\knowledge_scopetag_tl[#1]_bool}
       \seq_new:c{\knowledge_scopetag_tl[#1]_seq}
       \seq_gput_right:cn{\knowledge_scopetag_tl[#1]_seq}{explicit-scope:#1}}}
%    \end{macrocode}
%    \begin{macrocode}   
\cs_new:Nn\knowledge_scopetag_warn_if_unknown:n{
    \knowledge_scopetag_if_exist:nTF{#1}{}
      {\KAuxWriteX*{\exp_not:N\KAuxUndeclaredScopeTag{#1}}
       \knowledge_scopetag_ensure:n{#1}}
}
%    \end{macrocode}
%    \begin{macrocode}
\cs_new:Nn\knowledge_scopetag_declares:n{
    \knowledge_scopetag_ensure:n{#1}
    \bool_if:cTF{\knowledge_scopetag_tl[#1]_bool}
      {}
      {\bool_gset_true:c{\knowledge_scopetag_tl[#1]_bool}}
    \KAuxWriteX*{\exp_not:N\KAuxDeclaredScopeTag{#1}}
}
%    \end{macrocode}
% \AP The command \csintro{\knowledgescope} associates an "instance" to one or more "scopetags":
%    \begin{macrocode}
\NewDocumentCommand\knowledgescope{ >{\SplitList{,}}m }{
    \kl_hide_begin:\group_begin:
      \ProcessList{#1}\knowledge_knowledgescope_one:n
    \group_end:\kl_hide_end:
}
%    \end{macrocode}
% In the following code, now the name of the instance is expanded before being written to the "kaux file".
%    \begin{macrocode}
\cs_new:Nn\knowledge_knowledgescope_one:n{
    \knowledge_scopetag_declares:n{#1}
    \scope_get_labelizable_instance:N\l_tmpb_tl
    \KAuxWriteX*{\exp_not:N\KAuxNewLinkScopetagInstance{#1}{\l_tmpb_tl}}
}
%    \end{macrocode}
%
% \paragraph{Modified labels}
% \AP The boolean \csintro{\knowledge_configuration_label_autoscope_bool}
% activates or deactivates the automatic calling to \cs{knowlegescope} when \cs{\label} is used.
%    \begin{macrocode}
\bool_new:N\knowledge_configuration_label_autoscope_bool
\bool_gset_true:N\knowledge_configuration_label_autoscope_bool
\KnowledgeConfigureBooleanOption[\knowledge_configuration_label_autoscope_bool]{patch~label}
\KnowledgeConfigureBooleanOption[\knowledge_configuration_label_autoscope_bool]{label~scope}
%    \end{macrocode}
% One first changes the behavior of \cs\label\ in the preamble.
%    \begin{macrocode}
\global\let\knowledge_label_before_loading_package:n\label
\cs_gset:Npn\label{
   \mode_if_preamble:TF
       \knowledge_label_in_preamble:n
       \knowledge_label_before_loading_package:n
}
\cs_new:Npn\knowledge_label_in_preamble:n{
     \bool_if:NTF
         \knowledge_configuration_label_autoscope_bool
         \knowledge_knowledgescope_one:n
         \use_none:n
}
%    \end{macrocode}
% \AP In order to circumvent this overloading, the normal \cs{\label} command
% can be used using \csintro{\knowledge_latex_label:n}:
%    \begin{macrocode}
\cs_new:Npn\knowledge_latex_label:n{
  \cs_if_exist:NTF\LaTeXlabel\LaTeXlabel\label
}
%    \end{macrocode}
% \par\noindent\csintro{\knowledge_scopetag_warn_if_unknown:n} takes a "scopetag" as input.
% If it does not exist, it defines, and sets its boolean to false.
%    \begin{macrocode}
\NewKAuxCommand\KAuxUndeclaredScopeTag{m}
   {Package~scope:~States~that~a~labelname~is~used~in~a~knowledge~definition.}
\DeclareKAuxPhaseCommand\KAuxUndeclaredScopeTag{init}{}
\NewKAuxCommand\KAuxDeclaredScopeTag{m}
   {Package~scope:~States~that~a~labelname~has~been~declared.}
\DeclareKAuxPhaseCommand\KAuxDeclaredScopeTag{init}{
     \knowledge_scopetag_if_exist:nTF{#1}{}
       {\bool_new:c{\knowledge_scopetag_tl[#1]_bool}}
        \bool_gset_true:c{\knowledge_scopetag_tl[#1]_bool}
   }
\NewKAuxCommand\KAuxNewLinkScopetagInstance{mm}
   {Package~scope:~Declares~that~a~label~is~declared~in~an~instance~of~a~scope.}
\DeclareKAuxPhaseCommand\KAuxNewLinkScopetagInstance{init}{
    \knowledge_scopetag_ensure:n{#1}
    \seq_gput_right:cn{\knowledge_scopetag_tl[#1]_seq}{#2}
}
%    \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\KAuxScopeTag{mm}
  {Package~scope:~Links~a~scopetag~to~an~instance~of~a~scope.}
\DeclareKAuxPhaseCommand\KAuxScopeTag{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}}
       {}}
}
\AtBeginDocument{
  \kutils_secure_latex_command:N\label
   \RenewDocumentCommand\label{om}{\bool_if:NT
         \knowledge_configuration_label_autoscope_bool
        {\knowledge_knowledgescope_one:n{#2}}
     % if cleveref is loaded, label can use an optional type argument
     \IfNoValueTF{#1}{\LaTeXlabel{#2}}{\LaTeXlabel[{#1}]{#2}}}
}
%    \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}
    \knowledgescope{#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}.
% It tests before is the file was properly written during the last compilation using |\IfKAuxReadyTF|. 
%    \begin{macrocode}
\KAuxBefore{\IfKAuxReadyTF{\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{}
   %
   \bool_if:NTF\knowledge_configuration_diagnosehelp_bool
      {
        \knowledge_diagnose:n{********}
        \knowledge_diagnose:n{*~Help~*}
        \knowledge_diagnose:n{********}
        \knowledge_diagnose:n{}
        \knowledge_diagnose:x{\use:c{@backslashchar}\cs_to_str:N\knowledgeconfigure{diagnose~bar=false}~deactivate~`|'-notation~in~diagnose~file.}
        \knowledge_diagnose:x{\use:c{@backslashchar}\cs_to_str:N\knowledgeconfigure{diagnose~help=false}~deactivate~long~help~in~the~diagnose~file.}
        \knowledge_diagnose:x{\use:c{@backslashchar}\cs_to_str:N\knowledgeconfigure{diagnose~line=true}~add~line~numbers~to~diagnose~file.}
        \knowledge_diagnose:n{}
      }{
        \knowledge_diagnose:x{\use:c{@backslashchar}\cs_to_str:N\knowledgeconfigure{diagnose~help=true}~to~activate~help~in~the~diagnose~file.}
        \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:
     \bool_if:NT\knowledge_configuration_diagnosebar_bool
         {\knowledge_diagnose:x{\use:c{@backslashchar}knowledge{ignore}}}
     \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}
% \itemAP 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'.
% \itemAP the \kl{instance} name (defining the scope, i.e. the region in which it is defined; no arobas in it). "Instances" are automatically generated, and the used should never has access to it.
% \itemAP 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,VnVTF}
%    \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}{
  \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 innermost 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_push_visible_instance_mark:}] Inserts in \cs{\knowledge_visible_instances_seq} a special marker,
%   which is used when pushing a scope.
% \item[\csintro{\knowledge_pop_visible_instances_to_mark:}] Pops everything till the special mark.
% \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
%    \end{macrocode}
% Special marks are introduced for remembering till where to pop when a "scope" ends.
%    \begin{macrocode}
\cs_new:Nn\knowledge_push_visible_instance:n
  {\seq_gpush:Nn\knowledge_visible_instances_seq{#1}}
\cs_new:Nn\knowledge_push_visible_instance_mark:
  {\seq_gpush:Nn\knowledge_visible_instances_seq{|}}
%    \end{macrocode}
% 
%    \begin{macrocode}
\cs_new:Nn\knowledge_pop_visible_instances_to_mark:
  {\seq_gpop:NNTF\knowledge_visible_instances_seq\l_tmpa_tl
       {\exp_args:NV\tl_if_eq:nnTF\l_tmpa_tl{|}
            {}
            {\knowledge_pop_visible_instances_to_mark:}}
       {\KNOWLEDGE_INTERNAL_ERROR:_stack_of_visible_instances_is_empty_while_popping}}
%    \end{macrocode}
%    \begin{macrocode}
\cs_new:Nn\knowledge_show_visible_instances:
  {\tl_show:x
    {Visible~instances~<\seq_use:Nn\knowledge_visible_instances_seq{,}>}}
%    \end{macrocode}
%    \begin{macrocode}
\NewDocumentCommand\knowledgeimport{ >{\SplitList{,}}m }{
    \kl_hide_begin:
    \ProcessList{#1}\knowledge_knowledgeimport:n
    \kl_hide_end:
}
%    \end{macrocode}
%    \begin{macrocode}
\cs_set:Nn\knowledge_knowledgeimport:n{
   \knowledge_scopetag_warn_if_unknown:n{#1}
   \knowledge_scopetag_ensure:n{#1}
   \exp_args:Nc\seq_map_function:NN
       {\knowledge_scopetag_tl[#1]_seq}
       \knowledge_push_visible_instance:n
 }
%    \end{macrocode}
%
%
% \subsubsection{The  knowledge targeting}
%
% We define now the "directives" that are used for choosing how the "knowledge" should be defined.
%
%    \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,
  scope .code:n =
      { \knowledge_scope_track_scope:n{#1}
       \tl_gput_right:Nn\knowledge_knowledge_immediate_synonym_directives_tl{,scope = {#1}}},
  synonym .code:n =
     { \bool_set_true:N\knowledge_knowledge_is_synonym_bool
       \exp_args:Nnx\keys_set:nn { knowledge~directives }
          {link={\exp_not:V\knowledge_knowledge_synonymlink_tl},
           link~instance={\exp_not:V\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 }
}
%    \end{macrocode}
%    \begin{macrocode}
\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 }
}
%    \end{macrocode}
%    \begin{macrocode}
\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_init:w}
%    \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_init:w{t! t+ m 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
  %
  \tl_gset:Nn\knowledge_knowledge_immediate_synonym_directives_tl{synonym}
  %
  \bool_gset_false:N\knowledge_knowledge_is_synonym_bool
  %
  \tl_if_eq:nnTF{#4}{|}
     {\__knowledge_knowledge_cont_barnotation:nw{#3}|}
     {\tl_if_eq:nnTF{#4}{[}
          {\__knowledge_knowledge_cont_classical:nw{#3}[}
          {\__knowledge_knowledge_cont_classical:nw{#3}{#4}}}
}
%    \end{macrocode}
%    \begin{macrocode}
\cs_new:Nn\__knowledge_knowledge_recallsynonym:n{
    \bool_if:NF\knowledge_knowledge_is_synonym_bool
      {\tl_gset:Nn\knowledge_knowledge_synonymlink_tl{#1}
       \tl_gset_eq:NN\knowledge_knowledge_synonyminstance_tl
           \knowledge_knowledge_instance_tl}
}
%    \end{macrocode}
%    \begin{macrocode}
\cs_new:Nn\__knowledge_knowledge_end:{
  \group_end:
  \kl_hide_end:
}
%    \end{macrocode}
%    \begin{macrocode}
\NewDocumentCommand\__knowledge_knowledge_cont_classical:nw{m >{\SplitList{|}}o m }{
  %\iow_term:n{\__knowledge_knowledge_cont_classical~{#1}{#3}}
  \knowledge_knowledge_setparseat:NNn\l_tmpa_tl\l_tmpb_tl{#1}
  %
  \use:x{
    \exp_not:N\knowledge_knowledge_process:nn
      {\exp_not:V\l_tmpa_tl}
      {\exp_not:V\knowledge_knowledgedefault_tl,
      \exp_not:n{#3},
      \tl_if_empty:NTF\l_tmpb_tl{}{,scope={\exp_not:V\l_tmpb_tl}}}}
  %
  \exp_args:NV\__knowledge_knowledge_recallsynonym:n\l_tmpa_tl
  %\tl_show:N\l_tmpa_tl
  %\tl_show:N\knowledge_knowledge_instance_tl
  %\tl_show:N\knowledge_knowledge_immediate_synonym_directives_tl
  %
  \IfNoValueTF{#2}{}{
    \cs_set:Nn\l_tmpa_cs:n
      {\exp_args:Nnx\knowledge_knowledge_process:nn{##1}
          {\exp_not:V\knowledge_knowledge_immediate_synonym_directives_tl}}
    \ProcessList{#2}\l_tmpa_cs:n
    } 
  %
  \__knowledge_knowledge_end:
}
%    \end{macrocode}
% \AP The code for the "`\vbar'-notation".
% \csintro{\knowledge_knowledge_barnotation_firstline:n} and \csintro{\knowledge_knowledge_barnotation_nextlines:n}
% contain the code to be executed when the first line is read, then the following ones. This is defined during parsing.
% \csintro{\knowledge_knowledge_barnotation_exec_line:n} changes from one value to the other during the parsing.
%    \begin{macrocode}
\cs_new:Npn\knowledge_knowledge_barnotation_firstline:n{}
%    \end{macrocode}
%    \begin{macrocode}
\cs_new:Npn\knowledge_knowledge_barnotation_nextlines:n{}
%    \end{macrocode}
% \AP\csintro{\__knowledge_knowledge_cont_barnotation:nw} takes as first as argument the directives to be used for the
% defining the first "knowledge" (first argument in the "`\vbar'-notation"), and then it absorbs the content of the following line,
% from the first~`\vbar' to the line return.
%    \begin{macrocode}
\cs_new:Npn\__knowledge_knowledge_cont_barnotation:nw#1{
  \cs_set:Nn\knowledge_knowledge_barnotation_firstline:n{
      %\knowledge_knowledge_setparseat\g_tmpa_tl\g_tmpb_tl{#1}
      %\iow_term:n{\knowledge{##1}{#1}~(first)}
      \knowledge{##1}{#1}
      \cs_set_eq:NN
           \knowledge_knowledge_barnotation_exec_line:n
           \knowledge_knowledge_barnotation_nextlines:n}
    \cs_set:Nn\knowledge_knowledge_barnotation_nextlines:n
       {%\iow_term:n{\exp_not:n{\knowledge{##1}}{synonym}}
         \knowledge{##1}{synonym}}
    \cs_set_eq:NN
       \knowledge_knowledge_barnotation_exec_line:n
       \knowledge_knowledge_barnotation_firstline:n
    \kl_newknowledge_parse:w
}
%    \end{macrocode}
% \AP Now the core of the parsing works by calling \csintro{\kl_newknowledge_parse:w}.
% It tests the existence of a starting `\vbar', and in this case absorb the line
% using \cs{\knowledge_knowledge_barnotation_exec_line:w}
% and calls \cs{\knowledge_knowledge_barnotation_exec_line:n} to
% execute it. This operation is repeated
% until there are no more starting `\vbar', and in this case \cs{\__knowledge_knowledge_end:}
% is used.
%    \begin{macrocode}
\cs_new:Npn\kl_newknowledge_parse:w{
    \peek_charcode_remove_ignore_spaces:NTF|
        {\kl_insert_klendline:w\knowledge_knowledge_barnotation_exec_line:w}
        {\__knowledge_knowledge_end:}
}
%    \end{macrocode}
%    \begin{macrocode}
\cs_new:Npn\knowledge_knowledge_barnotation_exec_line:w#1\kl_end_line:{
    \knowledge_knowledge_barnotation_exec_line:n{#1}
    \kl_newknowledge_parse:w
}
%    \end{macrocode}
% The catcode modifications for parsing a single line in "`\vbar'-notation":
% \AP The macro \csintro{\kl_insert_klendline:w} replaces the next occurrence of 
% a line return by the control sequence \csintro{\kl_end_line:}.
% This temporarily changes the catcode. However, as soon as it is done, a normal command
% (meaning using the standard catcode regime) can then absorb the line.
%    \begin{macrocode}
\char_set_catcode_active:N\^^M
\cs_gset:Npn\kl_insert_klendline:w{\group_begin:\catcode`\^^M=\active\kl_insert_klendline_:w}
\cs_gset:Npn\kl_insert_klendline_:w#1^^M{\group_end:#1\kl_end_line:}
\char_set_catcode_end_line:N\^^M
%    \end{macrocode}
% \AP How to break a line from the  "`\vbar'-notation" in pieces.
% The \csintro{\knowledge_knowledge_setparseat:NNn}\ 
% takes two tl-variables and the line content.
% The result is that the part before the first `@' is put inside the first variable,
% and what is after and before the next `@' (possibly empty) in the second one.
%    \begin{macrocode}
\cs_new:Nn\knowledge_knowledge_setparseat:NNn
    {\knowledge_knowledge_setparseat_:NNw#1#2#3@@\kl_end:}
\cs_new:Npn\knowledge_knowledge_setparseat_:NNw#1#2#3@#4@#5\kl_end:
    {\tl_set:Nx#1{\tl_trim_spaces:n{#3}}
    \tl_set:Nx#2{\tl_trim_spaces:n{#4}}}
%    \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.
% It uses internally the following `variables':
% \begin{asparadesc}
% \itemAP[\csintro{\knowledge_knowledgestyle_bool}] is it a \cs{\knowledgestyle} macro?
% \itemAP[\csintro{\knowledge_knowledgestyle_override_bool}] has it been required to override a previous "knowledge"?
% \itemAP[\csintro{\knowledge_knowledge_now_bool}] set if in the preamble or by the directive "now".
% \itemAP[\csintro{\knowledge_knowledge_alsonow_bool}] set by directive "also now".
% \itemAP[\csintro{\knowledge_knowledge_is_synonym_bool}] set by the "synonym" directive.
% \itemAP[\csintro{\knowledge_knowledge_autoref_bool}] set by the "autoref" directive
% \itemAP[\csintro{\knowledge_knowledge_clear_bool}] 
% \itemAP[\csintro{\knowledge_knowledge_append_bool}]
% \itemAP[\csintro{\knowledge_knowledge_export_bool}]
% \itemAP[\csintro{\knowledge_knowledge_synonymlink_tl}] name of the "knowledge" to link to if a "synonym" directive is used.
% \itemAP[\csintro{\knowledge_knowledge_synonyminstance_tl}] "instance" of the "knowledge" to link if a "synonym" directive is used.
% \itemAP[\csintro{\knowledge_knowledge_immediate_synonym_directives_tl}] gathers the "directives" that have to be propagated to implicit synonyms.
% \itemAP[\csintro{\knowledge_knowledge_key_tl}] the text for which the "knowledge" has to be defined.
% \itemAP[\csintro{\knowledge_knowledge_namespace_tl}] the "namespace".
% \itemAP[\csintro{\knowledge_knowledge_instance_tl}]
% \itemAP[\csintro{\knowledge_knowledge_directives_tl}] gathers the "directives" that have to be executed for defining the "knowledge" (either to be executed now if \cs{\knowledge_knowledge_now_bool} is set, or to be propagated to the "kaux file" for execution during the next compilation phase)
% \end{asparadesc}
%    \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_synonymlink_tl
\tl_clear_new:N\knowledge_knowledge_synonyminstance_tl
\tl_clear_new:N\knowledge_knowledge_immediate_synonym_directives_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{smom}{
  \kl_hide_begin:
  \keys_if_exist:nnTF{ knowledge~directives }{ #2 }
    {\IfBooleanTF{#1}
       {\knowledgedirective:nnn{#2}{#3}{#4}}
       {\msg_error:nnn{ knowledge }{  knowledgedirective~redefinition }{#2}}}
    {\knowledgedirective:nnn{#2}{#3}{#4}}
  \kl_hide_end:
}
\cs_new:Nn\knowledgedirective:nnn{
   \cs_set: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}}}
}
%    \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 explicitly (1) the text to be displayed, 
% (2) the \kl{knowledge name} to be used for the search, and (3) 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{
  %\iow_term:n{\knowledge_klTKS:nnn{#1}{#2}{#3}}
  \group_begin:
    %
    \tl_set:Nx\knowledge_kl_linkscope_tl{\tl_to_str:n{#3}}
    \tl_set:Nn\knowledge_kl_linkinstance_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
    %\debug_vars:nn{klTKS:nnn}
    %    {\knowledge_kl_linkscope_tl\knowledge_kl_linkinstance_tl
    %     \knowledge_kl_text_tl\knowledge_kl_base_key_tl}
    %
    \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_new:Nn\knowledge_kl_find:{
  \knowledge_kl_find_recursion_exceeded:TF
     \knowledge_kl_error_recursion:
     {\tl_if_empty:NTF\knowledge_kl_linkscope_tl
        {\tl_if_empty:NTF\knowledge_kl_linkinstance_tl
            {\knowledge_kl_find_withoutscope:}
            {\knowledge_kl_find_withinstance:}}
        \knowledge_kl_find_withscopetag:}
}
%    \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_linkinstance_tl
      \knowledge_kl_key_tl
      {\knowledge_kl_exec:nnV
         \knowledge_kl_namespace_tl
         \knowledge_kl_linkinstance_tl
         \knowledge_kl_key_tl}
      { \knowledge_kl_error_unknown_in_scope_firsttime: }
}
%    \end{macrocode}
% \AP \csintro{\knowledge_kl_find_withscopetag:} searches for the knowledge, with a given "scopetag".
%    \begin{macrocode}
\cs_new:Nn\knowledge_kl_find_withscopetag:{
  %\debug_vars:nn{\knowledge_kl_find_withscopetag:}{\knowledge_kl_linkscope_tl}
  \exp_args:NV\knowledge_scopetag_warn_if_unknown:n\knowledge_kl_linkscope_tl
  \tl_clear:N\l_tmpa_tl
  \exp_args:Nc\seq_map_function:NN
        {\knowledge_scopetag_tl[\knowledge_kl_linkscope_tl]_seq}
        \knowledge_kl_find_scopetag_tmpa:n
   % tests whether the search was successful
   \tl_if_empty:NTF\l_tmpa_tl
      {\knowledge_kl_error_unknown_in_scope_firsttime:}
      {\knowledge_kl_exec:VVV
         \knowledge_kl_namespace_tl
         \l_tmpa_tl
         \knowledge_kl_key_tl}
}
%    \end{macrocode}
% \AP \csintro{\knowledge_kl_find_scopetag:Nn} takes a tl variable for the result, and
% a "scopetag" as argument. If the tl is empty, and a knowledge using "scopetag" as instance is found,
% then the "scopetag" is transferred to the token list.  \csintro{\knowledge_kl_find_scopetag_tmpa:n}
% uses as variable \cs{\l_tmpa_tl} 
%    \begin{macrocode}
\cs_new:Npn\knowledge_kl_find_scopetag_tmpa:n{
   \knowledge_kl_find_scopetag:Nn\l_tmpa_tl
}
\cs_new:Nn\knowledge_kl_find_scopetag:Nn{
  \tl_if_empty:NTF#1
    {\knowledge_knowledge_if_exist:VnVTF
        \knowledge_kl_namespace_tl
        {#2}%instance
        \knowledge_kl_key_tl
        {\tl_set:Nn#1{#2}}
        {}}
    {}
}
%    \end{macrocode}
%    \begin{macrocode}
\cs_new:Nn\knowledge_kl_find_withoutscope:{
  %\debug_vars:nn{\knowledge_kl_find_withoutscope:}
  %  {\knowledge_kl_key_tl\knowledge_kl_linkinstance_tl}
  %\exp_args:NVVV\knowledge_knowledge_if_exist:nnnTF
  %  \knowledge_kl_namespace_tl\knowledge_kl_linkinstance_tl\knowledge_kl_key_tl
  %   {\tl_show:n{found}}{\tl_show:n{not~found}}
  \knowledge_kl_find_in_scope:VNTF
      \knowledge_kl_key_tl
      \knowledge_kl_linkinstance_tl
      {\knowledge_kl_exec:VVV
          \knowledge_kl_namespace_tl
          \knowledge_kl_linkinstance_tl
          \knowledge_kl_key_tl}
      {\knowledge_kl_error_unknown_firsttime:}
}
%    \end{macrocode}
% \AP \csintro{\knowledge_kl_find_in_scope:nNTF} introduces the "namespace" as
% first argument in a call to \cs{\knowledge_kl_find_in_scope:nnNTF}
%    \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}
% \AP We now code the macro \csintro{\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:Nn\knowledge_kl_find_in_scope:nnNTF{
   \group_begin:
       %\tl_show:n{\knowledge_kl_find_in_scope:~#1/#2/#3}
       \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}
% \cs{\knowledge_kl_find_in_scope_test:n} tests the existence of a "knowledge" 
% in the "scopetag" given as argument. For this it searches through all the instances associated to the
% "scopetag", and sets \cs{\g_tmpa_bool} when found.
% One has to check that the visible instance is not the mark.
%    \begin{macrocode}
\cs_new:Nn\knowledge_kl_find_in_scope_test:n{
    \tl_if_eq:nnTF{#1}{|}{}{
    \knowledge_kl_find_in_scope_test_:n{#1}
    \seq_if_exist:cTF{\knowledge_scopetag_tl[#1]_seq}
       {\exp_args:Nc\seq_map_function:NN
          {\knowledge_scopetag_tl[#1]_seq}
          \knowledge_kl_find_in_scope_test_:n
       }{}}
}
%    \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}}}
  %\debug_vars:nn{\knowledge_kl_exec:nnn}{\knowledge_kl_resourcearguments_tl}
  \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_linkinstance_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,VVV}
%    \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_eq:nnTF{#1}{default}
     {}
     {\tl_if_empty:NTF\l_tmpa_tl{}{\tl_put_right:Nn\l_tmpa_tl{,}
      \tl_put_right:Nn\l_tmpa_tl{namespace={#1}}}}
      
   \bool_if:NTF\knowledge_configuration_diagnosebar_bool{
        %\knowledge_diagnose:x{\char_escape_tl knowledge{\exp_not:V\l_tmpa_tl}}
        \tl_set:Nn\l_tmpa_tl{~~~|~~#3}
        \tl_if_empty:nTF{#2}{}
          {\tl_put_right:Nn\l_tmpa_tl{@#2}}
        \knowledge_diagnose:x{\exp_not:V\l_tmpa_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
          {\char_escape_tl knowledge\exp_not:n{{#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{
     \knowledge_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{
     \knowledge_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{
     \knowledge_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}
%
% \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}{
  \tl_if_exist:cTF{knowledge_kl_\cs_to_str:N#1_command_tl}
    {\knowledge_error:n{Variant~#1~already~exists~(in~\knowledgenewvariant).}}
    {\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:n{\tl_set_eq:NN\knowledge_kl_display_process_tl}
            \exp_not:c{knowledge_kl_\cs_to_str:N#1 _display_process_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_if_exist:cTF{knowledge_kl_\cs_to_str:N#1_command_tl}
    {
      \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}
    }
    {\knowledge_error:n{Variant~#1~does~not~exist~(in~\knowledgesetvariant).}}
}
%    \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}},
   %
   display~code .code:n =
      {\tl_set:cn{knowledge_kl_\knowledge_variant_key_tl _display_process_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*[\knowledge_kl_linkscope_tl]{link~scope}
\NewKnowledgeParamTl*[\knowledge_kl_linkinstance_tl]{link~instance}
\NewKnowledgeParamTl*[\knowledge_kl_forcedtext_tl]{text}
\NewKnowledgeParamTl*{wrap}
%    \end{macrocode}
%
%
%    \begin{macrocode}

\NewKnowledgeParamBool*{UnKnoWn~KNowLedGE}\kl_unknown_knowledge_bool
\bool_set_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:x{\char_escape_tl nointro{\exp_not:n{#1}}{\exp_not:n{#2}}{\exp_not:n{#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}
%
%
%
%  \csintro{\knowledge_kl_display_generic:n} applies a code to the current displaycode, which is surrounded by braces.
%  \csintro{\knowledge_kl_display_generic_cond:Nn} does the same thing under condition
% of a boolean (see code of \cs{\knowledge_kl_default_compute_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}
% \AP \csintro{\knowledge_kl_compute_code:} tests whether a special display process is given, or otherwise
% defaults to the standard one.
%    \begin{macrocode}
\cs_new:Nn\knowledge_kl_compute_code:{
  \tl_if_exist_ne:NTF\knowledge_kl_display_process_tl
     \knowledge_kl_display_process_tl
     \knowledge_kl_default_compute_code:
}
%    \end{macrocode}
%    \begin{macrocode}
\cs_new:Nn\knowledge_kl_default_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:
     %
     \knowledge_kl_compute_code_hyperreftarget:
     %
     \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}
}
\def\ensuretext#1{\ensuremath{\text{#1}}}
%    \end{macrocode}
%    \begin{macrocode}
\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}}}   
}
%    \end{macrocode}
%    \begin{macrocode}
\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}}}
  %
  \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}}}
}
%    \end{macrocode}
%    \begin{macrocode}
\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\LaTeXlabel{\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}}
}
%    \end{macrocode}
%    \begin{macrocode}
\cs_new:Npn\kl_up:n{\mode_if_math:TF\use:n\textup}
\cs_new:Npn\kl_md:n{\mode_if_math:TF\use:n\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}
%
%
% \subsection{Displaying labels}
% Code for \cs{\kref}, \cs{\kpageref}, \cs{\kcref} and \cs{\kCref}.
% 
% \csintro{\knowledgedisplayref} is to be used when defining a variant. It takes a macro, and creates the display code
% which applies it to the label reference of the knowledge. See code of \cs{\kref}, \cs{\kcref}, \dots
%    \begin{macrocode}
\cs_new:Nn\knowledge_labelref_display_process:n{
  \tl_if_exist_ne:NTF\knowledge_kl_ref_tl
    {\tl_gset:Nx\knowledge_display_code_tl
       {\exp_not:n{#1}
         {\exp_not:V\knowledge_kl_ref_tl}}
  }{
  \bool_if:NTF\kl_autoreflink_bool
    {\tl_if_exist_ne:NT\knowledge_kl_autoref_tl
      {\tl_gset:Nx\knowledge_display_code_tl
         {\exp_not:n{#1}
             {\exp_not:V\knowledge_kl_autoref_tl}}
      }
  }{  \tl_gset:Nn\knowledge_display_code_tl{???}
   }
  }
}
\cs_set_eq:NN\knowledgedisplayref\knowledge_labelref_display_process:n
%    \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\knowledge_anchor_point_cs:{}
    {\bool_if:NT\knowledge_hyperref_active_bool
       {\strut\vadjust{\knowledge_AP_internal:}}}
\NewDocumentCommand\itemAP{o}{
  \IfNoValueTF{#1}
    {\item\knowledge_anchor_point_cs:}
    {\item[\knowledge_itemAP: #1]}}
\let\AP\knowledge_anchor_point_cs:
%    \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.1){\expandafter\put\knowledge_option_anchor_point_shift_tl{
              \bool_if:NT\knowledge_hyperref_active_bool
                 {\put(-0.05,-1.18){\phantomsection}}
              \bool_if:NT\knowledge_configuration_visibleAP_bool
                 {\bool_if:NTF\knowledge_xcolor_active_bool
                    {\textcolor{\knowledge_option_anchor_point_color_tl}}{\use:n}
                 {\knowledge_option_anchor_point_shape_tl}}}}
        \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}}
%
%
% We first define the mofifier sequences used for \cs{\kl*}, \cs{\intro*} and \cs{\hkl*},
% namely \csintro{\knowledge_variant_quote_modifier_tl},
% \csintro{\knowledge_variant_doublequote_modifier_tl} and \csintro{\knowledge_variant_highlight_quote_modifier_tl}:
%    \begin{macrocode}
\tl_new:Nn\knowledge_variant_quote_modifier_tl{\kl*}
\tl_new:Nn\knowledge_variant_doublequote_modifier_tl{\intro*}
\tl_new:Nn\knowledge_variant_highlight_quote_modifier_tl{\hkl*}
%    \end{macrocode}
% \knowledgeconfigure{quotation=false}
% \AP We now define the macros \csintro{\makequotationactive} and \csintro{\makequotationletter} that change the catcode ot quotes.
%    \begin{macrocode}
\ExplSyntaxOff
\def\makequotationactive
  {\catcode`"13\relax}
\def\makequotationletter
  {\catcode`"12\relax}
\let\quotesymbol"
\ExplSyntaxOn
%    \end{macrocode}
% \AP The macro  \csintro{\kl_parse_quote:w} is called when a quote is met and \kl(option){quotation} is active, and
% the macro  \csintro{\kl_parse_doublequote:w} is called when double quotes are met.
% \AP Both rely on \csintro{\klquotation_parse_arobas_sep:Nw} for splitting the arguments.
%  In the end, either \cs{\klquote_expand:nnn} or \cs{\kldoublequote_expand:nnn} are called (or an error is issued with \cs{\knowledge_error_doublequote_simplequote:n} if the double quotes are not properly closed):
%    \begin{macrocode}
\makequotationactive
\cs_new:Npn\kl_parse_quote:w#1"{
  \tl_if_empty:nTF{#1}
    \kl_parse_doublequote:w
    {\klquotation_parse_arobas_sep:Nw
     \kl_quote_expand:nnn #1 @@@\kl_end:}
}
%    \end{macrocode}
%    \begin{macrocode}
\cs_new:Npn\kl_parse_doublequote:w#1"#2"{
  \tl_if_empty:nTF{#2}
     {\klquotation_parse_arobas_sep:Nw
         \kl_doublequote_expand:nnn #1 @@@\kl_end:}
     {\knowledge_error_doublequote_simplequote:n{#1}}
}
%    \end{macrocode}
%    \begin{macrocode}
\cs_new:Npx\klquotation_parse_arobas_sep:Nw #1#2@#3@#4@#5\kl_end:
  {#1{#2}{#3}{#4}}
%    \end{macrocode}
% \AP Once the arguments collected \csintro{\kl_quote_expand:nnn} and \csintro{\kl_doublequote_expand:nnn} are called.
% \cs{\kl_quote_expand:nnn} checks first if the first character is a space (and then calling \cs{\_klquote_char_space:nnn}),
% then whether the first token \texttt{<tok>} triggers a special behaviour by looking at the macro \cs{\_klquote_char_<tok>:nnn}.
% If it is not the case, it defaults to \cs{\knowledge_variant_quote_modifier_tl}\cs{\klquote_expand_base:nnn}.
%    \begin{macrocode}
\cs_new:Npn\kl_quote_expand:nnn#1
  {\tl_if_head_is_space:nTF{#1@}
      {\_klquote_char_space:nnn}
      {\cs_if_exist_use:cTF{_klquote_char_\tl_to_str:n{\tl_head:n{#1@}}:nnn}
         {}
         {\knowledge_variant_quote_modifier_tl\kl_quote_expand_base:nnn}}
   {#1}
 }
 \cs_new:Npn\_klquote_char_space:nnn
   {\bool_if:NTF\knowledge_configuration_quotation_strict_bool
       {\knowledge_klquote_error_space:nnn}
       {\knowledge_variant_quote_modifier_tl\kl_quote_expand_base:nnn}
   }
%    \end{macrocode}
% \AP \cs{\kldoublequote_expand:nnn} use a similar logic.
%    \begin{macrocode}
\cs_new:Npn\kl_doublequote_expand:nnn#1
  {\tl_if_head_is_space:nTF{#1@}
     {\_kldoublequote_char_space:nnn}
      {\cs_if_exist_use:cTF{_kldoublequote_char_\tl_to_str:n{\tl_head:n{#1@}}:nnn}
         {}
         {\knowledge_variant_doublequote_modifier_tl\kl_quote_expand_base:nnn}}
   {#1}
 }
 \cs_new:Npn\_kldoublequote_char_space:nnn
   {\bool_if:NTF\knowledge_configuration_quotation_strict_bool
       {\knowledge_kldoublequote_error_space:nnn}
       {\knowledge_variant_doublequote_modifier_tl\kl_quote_expand_base:nnn}
   }
%    \end{macrocode}
% \AP The process converges toward \csintro{\kl_quote_expand_base:nnn} which
% produces the suitable \cs{\klKTS} command, possibly duplicating parameters if needed.
% The \csintro{\kl_quote_expand_base_gobble:nnn} does the same thing, but throws away the 
% first character of the first argument (to be used if a quote modifer symbol is used).
%    \begin{macrocode}
\cs_new:Npn\kl_quote_expand_base:nnn#1#2
    {\tl_if_empty:nTF{#2}{\klTKS{#1}{#1}}{\klTKS{#1}{#2}}}
\cs_new:Npn\kl_quote_expand_base_gobble:nnn#1
    {\exp_args:Nx\kl_quote_expand_base:nnn{\tl_tail:n{#1}}}
%    \end{macrocode}
% \AP Let us now define the code that captures syntax error in quotes.
% We first define the \kl(option){quotation strict} option, and link it to the
% boolean \csintro{\knowledge_configuration_quotation_strict_bool}:
%    \begin{macrocode}
\KnowledgeConfigureBooleanOption[\knowledge_configuration_quotation_strict_bool]
   {quotation~strict}
\bool_set_true:N\knowledge_configuration_quotation_strict_bool
%    \end{macrocode}
% \AP When a punctiation among ``\texttt{.,:;!?)}'' is seen after a quote,
% one calls the macro \cs{\knowledge_klquotation_punctuation:nnn}.
%    \begin{macrocode}
\cs_new:Nn\knowledge_new_quote_macro:NN
   {\cs_set:cpn{_klquote_char_\tl_to_str:n{#1}:nnn} {#2}}
\knowledge_new_quote_macro:NN . \knowledge_klquote_punctuation:nnn
\knowledge_new_quote_macro:NN , \knowledge_klquote_punctuation:nnn
\knowledge_new_quote_macro:NN : \knowledge_klquote_punctuation:nnn
\knowledge_new_quote_macro:NN ; \knowledge_klquote_punctuation:nnn
\knowledge_new_quote_macro:NN ! \knowledge_klquote_punctuation:nnn
\knowledge_new_quote_macro:NN ? \knowledge_klquote_punctuation:nnn
\knowledge_new_quote_macro:NN ) \knowledge_klquote_punctuation:nnn
\cs_new:Nn\knowledge_new_doublequote_macro:NN
   {\cs_set:cpn{_kldoublequote_char_#1:nnn} {#2}}
\knowledge_new_doublequote_macro:NN . \knowledge_kldoublequote_punctuation:nnn
\knowledge_new_doublequote_macro:NN , \knowledge_kldoublequote_punctuation:nnn
\knowledge_new_doublequote_macro:NN : \knowledge_kldoublequote_punctuation:nnn
\knowledge_new_doublequote_macro:NN ; \knowledge_kldoublequote_punctuation:nnn
\knowledge_new_doublequote_macro:NN ! \knowledge_kldoublequote_punctuation:nnn
\knowledge_new_doublequote_macro:NN ? \knowledge_kldoublequote_punctuation:nnn
\knowledge_new_doublequote_macro:NN ) \knowledge_kldoublequote_punctuation:nnn
%    \end{macrocode}
%    \begin{macrocode}
\NewDocumentCommand\knowledgequotemodifier{mm}
   {\cs_set:cpn{_klquote_char_{#1}:nnn}{#2\kl_quote_expand_base_gobble:nnn}}
\NewDocumentCommand\knowledgedoublequotemodifier{mm}
   {\cs_set:cpn{_kldoublequote_char_#1:nnn}{#2\kl_quote_expand_base_gobble:nnn}}
%    \end{macrocode}
% \AP And \csintro{\knowledge_klquotation_punctuation:nnn} either triggers an error
% if \kl(option){quotation strict} is activated, or defaults back to the unmodified behaviour.
%    \begin{macrocode}
\cs_new:Npn\knowledge_klquote_punctuation:nnn
  {\bool_if:NTF\knowledge_configuration_quotation_strict_bool
      \knowledge_klquote_error_punctuation:nnn
      {\knowledge_variant_quote_modifier_tl\kl_quote_expand_base:nnn}
   }
\cs_new:Npn\knowledge_kldoublequote_punctuation:nnn
  {\bool_if:NTF\knowledge_configuration_quotation_strict_bool
      \knowledge_kldoublequote_error_punctuation:nnn
      {\knowledge_variant_doublequote_modifier_tl\kl_quote_expand_base:nnn}
   }
%    \end{macrocode}
% \AP We now define all the error messages corresponding to quotations.
%    \begin{macrocode}
\cs_new:Nn\knowledge_error_doublequote_simplequote:n
  {\knowledge_error:x
    {Closing~double~quote~missing\iow_newline:\str_range:nnn{""#1"}{-35}{-1}~<-}}
\cs_new:Nn\knowledge_klquote_error_space:nnn
   {\knowledge_error:x
     {Forbidden~space~after~quote\iow_newline:->~\str_range:nnn{"#1}{1}{35}}}
\cs_new:Nn\knowledge_kldoublequote_error_space:nnn
   {\knowledge_error:x
     {Forbidden~space~after~double~quote\iow_newline:->~\str_range:nnn{""#1}{1}{35}}}
\cs_new:Nn\knowledge_klquote_error_punctuation:nnn
   {\knowledge_error:x
     {Forbidden~'\tl_head:n{#1}'~after~quote\iow_newline:->~\str_range:nnn{"#1}{1}{35}}}
\cs_new:Nn\knowledge_kldoublequote_error_punctuation:nnn
   {\knowledge_error:x
     {Forbidden~'\tl_head:n{#1}'~after~quote\iow_newline:->~\str_range:nnn{""#1}{1}{35}}}
%    \end{macrocode}
% Dealing with errors.
%    \begin{macrocode}
\knowledgequotemodifier{#}{\knowledge_variant_highlight_quote_modifier_tl}
%    \end{macrocode}
% \AP We finally define the macros \csintro{\klactivatequotation} and \csintro{\kldeactivatequotation}
% that activates and devates the quotes.
%    \begin{macrocode}
\def\klactivatequotation
  {\makequotationactive
   \let"\kl_parse_quote:w}
\def\kldeactivatequotation
  {\makequotationletter}
%    \end{macrocode}
%    \begin{macrocode}
\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}
%
%    \begin{macrocode}
\knowledgenewvariant\rekl{
  namespace= default,
  default~style= {autoref~link},
  unknown~style= kl~unknown,
  unknown~style~cont= kl~unknown~cont,
  style~directive= style
}
\knowledgevariantmodifier{\intro*\rekl}{\reintro}
\knowledgevariantmodifier{\rekl*\intro}{\reintro}
\knowledgevariantmodifier{\reintro*\rekl}{\reintro}
\knowledgevariantmodifier{\rekl*\reintro}{\reintro}
\knowledgevariantmodifier{\rekl*\kl}{\rekl}
\knowledgevariantmodifier{\kl*\rekl}{\rekl}
\knowledgevariantmodifier{\rekl*\rekl}{\rekl}
\knowledgevariantmodifier{\phantomintro*\rekl}{\phantomkl}
\knowledgevariantmodifier{\rekl*\phantomintro}{\phantomkl}
\knowledgevariantmodifier{\phantomintro*\kl}{\phantomintro}
\knowledgevariantmodifier{\phantomkl*\kl}{\phantomkl}

\knowledgedirective{automatic~in~command}{notion,also~now}
%    \end{macrocode}
%    \begin{macrocode}

\tl_gset:Nn\knowledge_inner_modifer_re_tl{\rekl*}

\int_new:N\knowledge_inner_modifier_count_int
\cs_new:Nn\knowledge_inner_command:
      {knowledge_cmdkl \int_to_arabic:n\knowledge_inner_modifier_count_int :n}

\NewDocumentCommand\withkl{mm}{
   \int_gincr:N\knowledge_inner_modifier_count_int
   \cs_gset:cpx
      {\knowledge_inner_command:}
        {\exp_not:N\cs_gset:Npn
               \exp_not:c{\knowledge_inner_command:}
               {\knowledge_inner_modifer_re_tl\knowledge_kl_modifiers_tl\exp_not:n{#1}}
         \knowledge_kl_modifiers_tl\exp_not:n{#1}}
   \knowledge_kl_modifiers_reset:
   #2
   \int_gdecr:N\knowledge_inner_modifier_count_int
}

\cs_new:Nn\knowledge_error_unexpected_cmdkl:{
   \knowledge_error:n{\cmdkl~is~only~allowed~inside~\withkl~or~in~macros~defined~using~\knowledgenewcommand-like~commands}
}
\newrobustcmd\cmdkl[1]{
   \int_compare:nNnTF\knowledge_inner_modifier_count_int=0
      \knowledge_error_unexpected_cmdkl:
      \use:c{\knowledge_inner_command:}{#1}
}

% 1: command to extend, 2:, 3,4,5,6: the newcommand arguments (token sequence, optional star, first optional parameter, second optional parameter, and body of the definition).
\NewDocumentCommand\knowledge_knowledgified_newcommand:NNwn{mmsoom}{
   \use:x{
      \exp_not:n{#1{#2}}
      \IfBooleanTF {#3} {*} {}
      \IfNoValueF{#4}{\exp_not:n{[{#4}]}}
      \IfNoValueF{#5}{\exp_not:n{[{#5}]}} }
   {\withkl{\kl[{#2}]}{#6}}   
   \knowledge{#2}{automatic~in~command}
}
\NewDocumentCommand\knowledge_knowledgified_NewDocumentCommand:NNnn{mmmm}{
   #1#2{#3}{\withkl{\kl[{#2}]}{#4}}
   \knowledge{#2}{automatic~in~command}
}
\NewDocumentCommand\KnowledgifyNewcommand{m}{
   \cs_if_exist:NTF#1{
      \exp_args:Nc\NewDocumentCommand{knowledge\cs_to_str:N#1}{}
         {\knowledge_knowledgified_newcommand:NNwn#1}
   }{
      \use:x{\exp_not:N\NewDocumentCommand
         \exp_not:c{knowledge\cs_to_str:N#1}
         {}
         {\exp_not:N\knowledge_error:n{
            The~command~\exp_not:N#1~should~be~defined~for~\exp_not:c
               {knowledge\cs_to_str:N#1}~to~be~usable.}}
         }
   }
}
\NewDocumentCommand\KnowledgifyNewDocumentCommand{m}{
   \cs_if_exist:NTF#1{
      \exp_args:Nc\NewDocumentCommand{Knowledge\cs_to_str:N#1}{}
         {\knowledge_knowledgified_NewDocumentCommand:NNnn#1}
   }{
      %\tl_show:n{Unknown~#1~in~\KnowledgifyNewDocumentCommand}
      \use:x{\exp_not:N\NewDocumentCommand
         \exp_not:c{knowledge\cs_to_str:N#1}
         {}
         {\exp_not:N\knowledge_error:n{
            The~command~\exp_not:N#1~should~be~defined~for~\exp_not:c
               {Knowledge\cs_to_str:N#1}~to~be~usable.}}
         }
   }
}
%    \end{macrocode}
%    Commands from LaTeX.
%    \begin{macrocode}
\KnowledgifyNewcommand\newcommand
\KnowledgifyNewcommand\renewcommand
\KnowledgifyNewcommand\newrobustcmd
\KnowledgifyNewcommand\renewrobustcmd
\KnowledgifyNewcommand\providerobustcmd
%    \end{macrocode}
%    Commands from "xparse@@package".
%    \begin{macrocode}
\KnowledgifyNewDocumentCommand\NewDocumentCommand
\KnowledgifyNewDocumentCommand\RenewDocumentCommand
\KnowledgifyNewDocumentCommand\ProvideDocumentCommand
\KnowledgifyNewDocumentCommand\DeclareDocumentCommand
%    \end{macrocode}
%    Commands from "mathcommand@@package" (
% \csintro\knowledgedeclarecommand,
% \csintro\knowledgenewmathcommand,
% \csintro\knowledgenewtextcommand,
% \csintro\knowledgerenewmathcommand,
% \csintro\knowledgerenewtextcommand,
% \csintro\knowledgedeclaremathcommand,
% \csintro\knowledgedeclaretextcommand,
% \csintro\KnowledgeNewDocumentMathCommand,
% \csintro\KnowledgeNewDocumentTextCommand,
% \csintro\KnowledgeRenewDocumentMathCommand,
% \csintro\KnowledgeRenewDocumentTextCommand,
% \csintro\KnowledgeProvideDocumentMathCommand,
% \csintro\KnowledgeProvideDocumentTextCommand,
% \csintro\KnowledgeDeclareDocumentMathCommand,
% \csintro\KnowledgeDeclareDocumentTextCommand,
% \csintro\knowledgenewcommandPIE,
% \csintro\knowledgerenewcommandPIE,
% \csintro\knowledgedeclarecommandPIE,
% \csintro\knowledgenewmathcommandPIE,
% \csintro\knowledgerenewmathcommandPIE,
% \csintro\knowledgedeclaremathcommandPIE,
% \csintro\KnowledgeNewDocumentCommandPIE,
% \csintro\KnowledgeRenewDocumentCommandPIE,
% \csintro\KnowledgeDeclareDocumentCommandPIE,
% \csintro\KnowledgeProvideDocumentCommandPIE,
% \csintro\KnowledgeNewDocumentMathCommandPIE,
% \csintro\KnowledgeRenewDocumentMathCommandPIE,
% \csintro\KnowledgeDeclareDocumentMathCommandPIE, and
% \csintro\KnowledgeProvideDocumentMathCommandPIE).
%    \begin{macrocode}
\KnowledgifyNewcommand\declarecommand
\KnowledgifyNewcommand\newmathcommand
\KnowledgifyNewcommand\newtextcommand
\KnowledgifyNewcommand\renewmathcommand
\KnowledgifyNewcommand\renewtextcommand
\KnowledgifyNewcommand\declaremathcommand
\KnowledgifyNewcommand\declaretextcommand
\KnowledgifyNewDocumentCommand\NewDocumentMathCommand
\KnowledgifyNewDocumentCommand\NewDocumentTextCommand
\KnowledgifyNewDocumentCommand\RenewDocumentMathCommand
\KnowledgifyNewDocumentCommand\RenewDocumentTextCommand
\KnowledgifyNewDocumentCommand\ProvideDocumentMathCommand
\KnowledgifyNewDocumentCommand\ProvideDocumentTextCommand
\KnowledgifyNewDocumentCommand\DeclareDocumentMathCommand
\KnowledgifyNewDocumentCommand\DeclareDocumentTextCommand
\KnowledgifyNewcommand\newcommandPIE
\KnowledgifyNewcommand\renewcommandPIE
\KnowledgifyNewcommand\declarecommandPIE
\KnowledgifyNewcommand\newmathcommandPIE
\KnowledgifyNewcommand\renewmathcommandPIE
\KnowledgifyNewcommand\declaremathcommandPIE
\KnowledgifyNewDocumentCommand\NewDocumentCommandPIE
\KnowledgifyNewDocumentCommand\RenewDocumentCommandPIE
\KnowledgifyNewDocumentCommand\DeclareDocumentCommandPIE
\KnowledgifyNewDocumentCommand\ProvideDocumentCommandPIE
\KnowledgifyNewDocumentCommand\NewDocumentMathCommandPIE
\KnowledgifyNewDocumentCommand\RenewDocumentMathCommandPIE
\KnowledgifyNewDocumentCommand\DeclareDocumentMathCommandPIE
\KnowledgifyNewDocumentCommand\ProvideDocumentMathCommandPIE
%    \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}{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} and \kl(option){imakeidx} options}
% Since "imakeidx@@package" extends the syntax of "makeidx@@package",
% internally, activating the package or the syntax for "imakeidx@@package"
% does the same thing for "makeidx@@package".
%    \begin{macrocode}
\bool_if:NT\knowledge_imakeidx_active_bool{\bool_set_true:N\knowledge_makeidx_active_bool}
\bool_if:NT\knowledge_imakeidx_syntax_bool{\bool_set_true:N\knowledge_makeidx_syntax_bool}
%    \end{macrocode}
% The index option has to variant, depending on whether the name of the index is used or not.
%    \begin{macrocode}
\cs_new:Npn \knowledge_index:nn #1 #2{
    \tl_if_empty:nTF {#1}
      {\index{#2}}
      {\index[{#1}]{#2}}
  }
\cs_generate_variant:Nn \knowledge_index:nn {xx}
%    \end{macrocode}
%    \begin{macrocode}
\cs_new:Nn\knowledge_kl_compute_code_makeidx:{
  \bool_if:NF\knowledge_kl_noindex_bool{
     \tl_if_exist_ne:NTF\knowledge_kl_index_tl
          {\knowledge_index:xx
              {\tl_if_exist_ne:NTF \knowledge_kl_index_name_tl
                  {\exp_not:V \knowledge_kl_index_name_tl}
                  {}
              }
              {\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@}
                  {}
                \exp_not:V\knowledge_kl_index_tl
                |
                \tl_if_exist_ne:NTF\knowledge_kl_index_modifier_tl
              	 {\exp_not:V\knowledge_kl_index_modifier_tl}
                  {}
                \tl_if_exist_ne:NTF\knowledge_kl_index_number_style_tl
              	 {\exp_not:V\knowledge_kl_index_number_style_tl}
                  {}
            }}{}
      }
}
%    \end{macrocode}
%    \begin{macrocode}
\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 = {}
}

\bool_if:NT\knowledge_makeidx_syntax_bool
{ \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}
  \NewKnowledgeParamBool*{no~index}\knowledge_kl_noindex_bool
  \NewKnowledgeParamTl*[\knowledge_kl_index_modifier_tl]{index~modifier}
}
\bool_if:NT\knowledge_imakeidx_syntax_bool { 
  \NewKnowledgeParamTl*[\knowledge_kl_index_name_tl]{index~name}
}
%    \end{macrocode}
% Activating error message is packages not loaded.
%    \begin{macrocode}
\knowledge_directives_require_aci_package:nn
   {index,index~key,index~parent~key,index~style,index~modifier}{makeidx}
\knowledge_directives_require_aci_package:nn
   {index~name}{imakeidx}
%    \end{macrocode}
%
%% \AP The "styles" ""debug index invisible@@style"", ""debug index from@@style"", 
% ""debug index to@@style"" are used to display index-related commands when the "configuration option" "debug index@@option" is set,
% and ""index unknown@@style"" is used similarly when an error is met (in combination with "kl unknown@@style").
% These styles wrap the knowledge in one of \csintro\knowledgeDisplayDebugIndex,
% \csintro\knowledgeDisplayDebugIndexFrom, \csintro\knowledgeDisplayDebugIndexTo, and \csintro\knowledgeDisplayIndexUnknown.
% Note that these "styles" and macros are not described in the main documentation, and a priori should not be referred to by the user.
%    \begin{macrocode}
\bool_if:NT\knowledge_makeidx_syntax_bool{
  \NewDocumentCommand\knowledgeDisplayDebugIndex{m}{(index:#1)}
  \NewDocumentCommand\knowledgeDisplayDebugIndexFrom{m}{(index:#1(}
  \NewDocumentCommand\knowledgeDisplayDebugIndexTo{m}{)index:#1)}
  \NewDocumentCommand\knowledgeDisplayIndexUnknown{m}{[index?:#1]}
  \knowledgestyle{debug~index}{wrap=\knowledgeDisplayDebugIndex}
  \knowledgestyle{debug~index~from}{wrap=\knowledgeDisplayDebugIndexFrom,index~modifier={(}}
  \knowledgestyle{debug~index~to}{wrap=\knowledgeDisplayDebugIndexTo,index~modifier={)}}
  \knowledgestyle{index~unknown}{no~index,wrap=\knowledgeDisplayIndexUnknown}
}
%    \end{macrocode}
% \AP The "styles" ""debug index visibility@@style"" and ""debug index unknown visibility@@style"" 
% are hooks for displaying or not the indexing commands. These are to be changed by the user using the "configuration directive" "debug index".
%    \begin{macrocode}
\bool_if:NT\knowledge_makeidx_syntax_bool{
  \knowledgestyle{debug~index~visibility}{invisible=true}
  \knowledgestyle{debug~index~unknown~visibility}{invisible=true}
  \KnowledgeConfigureBooleanOptionTF{debug~index}
    {\IfKnowledgeCompositionModeTF
       {\knowledgestyle{debug~index~visibility}{invisible=false}
         \knowledgestyle{debug~index~unknown~visibility}{invisible=false}}
       {}}
    {\knowledgestyle{debug~index~visibility}{invisible=true}
     \knowledgestyle{debug~index~unknown~visibility}{invisible=true}}
}
%    \end{macrocode}
%
% We define now the new variants \cs\kindex, \cs\kindexfrom, and \cs\kindexto, as well as the associated configuration.
% Essentially it amounts to change the variable \cs{\knowledge_kl_index_modifier_tl} that, if defined, modify the behaviour of indexing. 
%    \begin{macrocode}
\bool_if:NT\knowledge_makeidx_syntax_bool{
\knowledgenewvariant\kindex{
  namespace= default,
  default~style={composition,debug~index,debug~index~visibility},
  unknown~style={kl~unknown,index~unknown,debug~index~unknown~visibility},
  unknown~style~cont={kl~unknown~cont,index~unknown,debug~index~unknown~visibility},
  style~directive=kindex~style
}
\knowledgenewvariant\kindexfrom{
  namespace= default,
  default~style={composition,debug~index~from,debug~index~visibility},
  unknown~style={kl~unknown,index~unknown,debug~index~unknown~visibility},
  unknown~style~cont={kl~unknown~cont,index~unknown,debug~index~unknown~visibility},
  style~directive=kindex~style
}
\knowledgenewvariant\kindexto{
  namespace= default,
  default~style={composition,debug~index~to,debug~index~visibility},
  unknown~style={kl~unknown,index~unknown,debug~index~unknown~visibility},
  unknown~style~cont={kl~unknown~cont,index~unknown,debug~index~unknown~visibility},
  style~directive=kindex~style
}
\knowledgevariantmodifier{\kindex*\kl}{\kindex}
\knowledgevariantmodifier{\kindexfrom*\kl}{\kindexfrom}
\knowledgevariantmodifier{\kindexto*\kl}{\kindexto}
}
%    \end{macrocode}
%
%
%

%
% \subsubsection{The \kl{cleveref option}}
%
%    \begin{macrocode}
\bool_if:NTF\knowledge_cleveref_active_bool{
 \knowledgenewvariant\kcref{
  namespace=default,
  unknown~style={kl~unknown,ref~unknown},
  unknown~style~cont={kl~unknown~cont,ref~unknown},
  default~style=autoref~link,
  display~code={\knowledgedisplayref\cref}
 }
 \knowledgenewvariant\kCref{
  namespace=default,
  unknown~style={kl~unknown,ref~unknown},
  unknown~style~cont={kl~unknown~cont,ref~unknown},
  default~style=autoref~link,
  display~code={\knowledgedisplayref\Cref}
 }
 \knowledgenewvariant\kcpageref{
  namespace=default,
  unknown~style={kl~unknown,ref~unknown},
  unknown~style~cont={kl~unknown~cont,ref~unknown},
  default~style=autoref~link,
  display~code={\knowledgedisplayref\cpageref}
 }
 \knowledgenewvariant\kCpageref{
  namespace=default,
  unknown~style={kl~unknown,ref~unknown},
  unknown~style~cont={kl~unknown~cont,ref~unknown},
  default~style=autoref~link,
  display~code={\knowledgedisplayref\Cpageref}
 }
 \knowledgenewvariant\knamecref{
  namespace=default,
  unknown~style={kl~unknown,ref~unknown},
  unknown~style~cont={kl~unknown~cont,ref~unknown},
  default~style=autoref~link,
  display~code={\knowledgedisplayref\namecref}
 }
 \knowledgenewvariant\knameCref{
  namespace=default,
  unknown~style={kl~unknown,ref~unknown},
  unknown~style~cont={kl~unknown~cont,ref~unknown},
  default~style=autoref~link,
  display~code={\knowledgedisplayref\nameCref}
 }
 \knowledgenewvariant\knamecrefs{
  namespace=default,
  unknown~style={kl~unknown,ref~unknown},
  unknown~style~cont={kl~unknown~cont,ref~unknown},
  default~style=autoref~link,
  display~code={\knowledgedisplayref\namecrefs}
 }
 \knowledgenewvariant\knameCrefs{
  namespace=default,
  unknown~style={kl~unknown,ref~unknown},
  unknown~style~cont={kl~unknown~cont,ref~unknown},
  default~style=autoref~link,
  display~code={\knowledgedisplayref\nameCrefs}
 }
 \knowledgevariantmodifier{\kcref*\kl}{\kcref}
 \knowledgevariantmodifier{\kCref*\kl}{\kCref}
 \knowledgevariantmodifier{\kcpageref*\kl}{\kcpageref}
 \knowledgevariantmodifier{\kCpageref*\kl}{\kCpageref}
 \knowledgevariantmodifier{\knamecref*\kl}{\knamecref}
 \knowledgevariantmodifier{\knameCref*\kl}{\knameCref}
 \knowledgevariantmodifier{\knamecrefs*\kl}{\knamecrefs}
 \knowledgevariantmodifier{\knameCrefs*\kl}{\knameCrefs}
}{
  \cs_new:Nn\knowledge_cleveref_error:N{
     \newcommand#1{\knowledge_error:n{Use~package~'cleveref'~for~command~#1.}}
  }
  \knowledge_cleveref_error:N\kcref
  \knowledge_cleveref_error:N\kCref
  \knowledge_cleveref_error:N\kcpageref
  \knowledge_cleveref_error:N\kCpageref
  \knowledge_cleveref_error:N\knamecref
  \knowledge_cleveref_error:N\knameCref
  \knowledge_cleveref_error:N\knamecrefs
  \knowledge_cleveref_error:N\knameCrefs
}
%    \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{Patching}
%
% Since v1.22, the package corrects by default some behaviours that are annoying in other packages.
% This can be avoided using the trigger \kl{no patch} when you load the document.
%    \begin{macrocode}
\bool_if:NT\knowledge_option_texpatch_bool{
   \bool_if:NT\knowledge_hyperref_active_bool{
     \hypersetup{breaklinks}
     \hypersetup{hidelinks}
   }
}
%    \end{macrocode}
%
% \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_electronic_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}
\knowledgestyle{composition}{underline}
\knowledgenewvariant\kl{
  namespace= default,
  default style= {autoref link},
  unknown style= kl unknown,
  unknown style cont= kl unknown cont,
  style directive= style
}
\knowledgenewvariant\hkl{
  namespace= default,
  default style={autoref link},
  unknown style= kl unknown,
  unknown style cont= kl unknown cont,
  style directive= highlight style
}
\knowledgenewvariant\intro{
  namespace= default,
  default style= {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
}
\knowledgestyle{ref unknown}{text=??}
\knowledgenewvariant\kref{
  namespace=default,
  unknown style={kl unknown,ref unknown},
  unknown style cont={kl unknown cont,ref unknown},
  default style=autoref link,
  display code={\knowledgedisplayref\ref}
}
\knowledgenewvariant\kpageref{
   namespace=default,
    unknown style={kl unknown,ref unknown},
    unknown style cont={kl unknown cont,ref unknown},
    default style=autoref link,
   display code={\knowledgedisplayref\pageref}
}
\knowledgevariantmodifier{\hkl*\kl}{\hkl}
\knowledgevariantmodifier{\kref*\kl}{\kref}
\knowledgevariantmodifier{\kpageref*\kl}{\kpageref}
\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}]}
%    \end{macrocode}
% The ignore directive does nothing...
%    \begin{macrocode}
\knowledgedirective{ignore}{}
%    \end{macrocode}
%
%    \begin{macrocode}
\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{composition}{color=teal}
   }{
%    \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@@option" 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}
\NewDocumentCommand\KnowledgeConfigureNotion{ o m }{
%    \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}
  % \ltmpa_clist for the directive description
  \clist_set:Nn\l_tmpa_clist{}
  \clist_push:Nn\l_tmpa_clist{autoref}
  \clist_push:Nn\l_tmpa_clist{style=#2}
  \clist_push:Nn\l_tmpa_clist{intro~style=intro~#2}
  \clist_push:Nn\l_tmpa_clist{highlight~style=highlight~#2}
  \bool_if:NT\knowledge_makeidx_active_bool{
    \cs_set:cpn{#2KnowledgeIndexStyle}##1{##1}
    \cs_set:cpn{#2KnowledgeIndexIntroStyle}{\textbf}
    \clist_push:Nn\l_tmpa_clist{kindex~style=index~#2}
    \exp_args:Nnx\knowledgestyle{index~#2}{index~style=#2KnowledgeIndexStyle}
 }
  \exp_args:Nnx\knowledgedirective{#2}\l_tmpa_clist
  % \l_tmpa_clist for normal style
  % \l_tmpb_clist for intro style
  \clist_set:Nn\l_tmpa_clist{}
  \clist_set:Nn\l_tmpb_clist{}
  \ifKnowledgePaperMode
    % paper mode
    \clist_push:Nn\l_tmpb_clist{emphasize}
  \fi
  \ifKnowledgeCompositionMode
    \ifXcolor
      % composition mode with colors
      \clist_push:Nn\l_tmpb_clist{emphasize}
      \IfNoValueTF{#1}{}
         {\clist_push:Nn\l_tmpa_clist{color={#1!70!black}}
          \clist_push:Nn\l_tmpb_clist{color={#1}}}
    \else
      % composition mode, no colors (use underline)
      \clist_push:Nn\l_tmpa_clist{underline}
      \clist_push:Nn\l_tmpb_clist{emphasize}
      \clist_push:Nn\l_tmpb_clist{underline}
    \fi
  \fi
  \ifKnowledgeElectronicMode
    \ifXcolor
      % electronic mode 
      \clist_push:Nn\l_tmpb_clist{emphasize}
      \IfNoValueTF{#1}{}
         {\clist_push:Nn\l_tmpa_clist{color={#1!70!black}}
          \clist_push:Nn\l_tmpb_clist{color={#1}}}
      \clist_push:Nn\l_tmpb_clist{color={#1}}
    \else
      % electronic mode, no colors (use underline)
      \clist_push:Nn\l_tmpa_clist{underline}
      \clist_push:Nn\l_tmpb_clist{emphasize}
      \clist_push:Nn\l_tmpb_clist{underline}
   \fi
  \fi
  \bool_if:NT\knowledge_makeidx_active_bool{
  	\clist_push:Nn\l_tmpa_clist{index~style=#2KnowledgeIndexStyle}
  	\clist_push:Nn\l_tmpb_clist{index~style=#2KnowledgeIndexIntroStyle}
  }
  \exp_args:Nnx\knowledgestyle{#2}{\clist_use:Nn\l_tmpa_clist ,}
  \exp_args:Nnx\knowledgestyle{highlight~#2}{\clist_use:Nn\l_tmpa_clist ,}
  \exp_args:Nnx\knowledgestyle{intro~#2}{\clist_use:Nn\l_tmpb_clist ,}
%    \end{macrocode}
%\end{code}
% End of the interesting code.
%    \begin{macrocode}
}
%    \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




