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