% \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 %\usepackage{expl3} %\ProvidesExplPackage{knowledge}{2019/11/19}{1.19}{} %<*driver> \def\knowledgecode{active} \input{knowledge.tex} % % \fi % % \CheckSum{0} % % % \changes{1.01}{2017/06/11}{Initial version} % % \changes{1.02}{2017/06/28}{bug fixes} % % \changes{1.03}{2017/07/27}{scoping,bug fixes} % % \changes{1.04}{2017/07/28}{minor changes,bug fixes} % % \changes{1.05}{2017/09/26}{minor changes,bug fixes} % % \changes{1.06}{2017/10/10}{bug correction} % % \changes{1.07}{2017/10/15}{minor improvements} % % \changes{1.08}{2017/10/17}{minor changes and reorganization of the files} % % \changes{1.09}{2017/10/31}{minor changes} % % \changes{1.10}{2018/02/17}{bug fixes} % % \changes{1.11}{2018/05/17}{bug fixes} % % \changes{1.12}{2018/07/26}{bug fixes} % % \changes{1.13}{2018/11/21}{bug fixes} % % \changes{1.14}{2018/11/22}{bug fix} % % \changes{1.15}{2019/01/23}{doc change} % % \changes{1.16}{2019/02/15}{correct anchor point locations} % % \changes{1.17}{2019/10/03}{improvements} % % \changes{1.18}{2019/10/03}{bug fix/improvement} % % \changes{1.19}{2019/11/19}{bug fix} % % \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.19 date: 2019/11/19 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} % % \subsection{Code preparation} %<*head> % \begin{macrocode} \RequirePackage{l3keys2e} \RequirePackage{etoolbox} \RequirePackage{xparse} \bool_if_exist:NTF\knowledge_package_loaded_bool {\endinput} {\bool_new:N\knowledge_package_loaded_bool \bool_set_true:N\knowledge_package_loaded_bool} % \end{macrocode} % \begin{macrocode} % \end{macrocode} % %\begin{center} % The content of \texttt{knowledge-utils.sty} is inserted here.\\ %\end{center} %<*package>\\ % Macros to skip pieces of code depending on some bool. This can certainly be done differently. % \begin{macrocode} \cs_new:Nn\knowledge_begin_module_if:n {\bool_if:NF#1\knowledge_skip_module:} \cs_new:Npn\knowledge_skip_module:#1\knowledge_end_module: {} \cs_new:Nn\knowledge_end_module: {} % \end{macrocode} % %\AP One defines the code of \csintro{\klparse_ifnextchar:NTF} % which is a link to \cs{\@ifnextchar}, % as well as the constant \csintro{\klparse_novalue_tl} which contains % the token list corresponding to a non-given optional argument % as used in the \kl(package){xparse} package. % % \begin{macrocode} \cs_set_eq:Nc\klparse_ifnextchar:NTF{@ifnextchar} % \end{macrocode} % \begin{macrocode} \tl_new:N\klparse_novalue_tl \NewDocumentCommand\klparse_setnovalue{o} {\tl_set:Nn\klparse_novalue_tl{#1}} \klparse_setnovalue\relax % \end{macrocode} % \begin{macrocode} \cs_new:Npn\klparse_if_novalue:NTF {\tl_if_eq:NNTF\klparse_novalue_tl} % \end{macrocode} % \begin{macrocode} \cs_generate_variant:Nn\tl_to_str:n{V} % \end{macrocode} % % \begin{macrocode} \tl_new:N\char_escape_tl \tl_set:Nx\char_escape_tl {\expandafter\tl_head:n\expandafter{\string\escape}} % \end{macrocode} % % \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} % \begin{macrocode} \msg_new:nnn{ knowledge }{ knowledgedirective~redifinition } { Directive~'#1'~already~exists~(\knowledgedirective~macro). } % \end{macrocode} % %\AP The messages when there is a problem with scoping are \csintro{area~exists}, \csintro{area~not~exist}, % \csintro{empty~pop}, \csintro{no~pushing~here}, \csintro{no~popping}, % \csintro{no~popping~here}, \csintro{unknown~label} and \csintro{area~not~in~context}. % \begin{macrocode} \msg_new:nnn{scope}{area~exists}{Area~'#1'~already~exists.} \msg_new:nnn{scope}{area~not~exist}{Area~'#1'~does~not~exist.} \msg_new:nnn{scope}{empty~pop}{Attempt~to~pop~an~empty~area~stack.} \msg_new:nnn{scope}{no~pushing~here} {Not~allowed~to~open~'\scope_pushed_area_tl'~here.~ Current~stack~is~<\seq_use:Nn\scope_instances_stack_seq{::}>.} \msg_new:nnn{scope}{no~popping}{Not~allowed~to~close~'\scope_popped_area_tl'.} \msg_new:nnn{scope}{no~popping~here} {Not~allowed~to~close~'\scope_popped_area_tl'~here~(at~'\scope_top_area_tl').} \msg_new:nnn{scope}{unknown~label} {\tl_if_empty:nTF{#2}{}{\exp_not:n{#2}}: ~Unknown~label~`#1'.~Possibly~rerun~latex.} \msg_new:nnn{scope}{area~not~in~context} {\tl_if_empty:nTF{#2}{}{\exp_not:n{#2}}: ~The~area~`#1'~can't~be~found~in~context.~Possibly~rerun~latex.} % \end{macrocode} %\AP We define new the final messages, that are thrown at the end of the compilation as a recap that some problems occured. These are: \csintro{recap~unknown~knowledge}, \csintro{recap~autoref~introduced~twice} and \csintro{recap~autoref~not~introduced}. % \begin{macrocode} \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_barsuggestion_bool \bool_gset_false:N\knowledge_configuration_barsuggestion_bool \KnowledgeConfigureBooleanOption[\knowledge_configuration_barsuggestion_bool]{bar~suggestion} % \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} \knowledgesetvariant\kl{suggestion=notion} \knowledgesetvariant\intro{suggestion=notion} \knowledgesetvariant\phantomintro{suggestion=notion} \knowledgesetvariant\reintro{suggestion=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[\intro{instances}] are the realization of \kl{areas} in a document. Hence `section' is an \kl{area}, % but each section of a document is an \kl{instance}. % \item[\intro{scopept instances}] stands for `phase two'. These are functions that are activated during % the second compilation. (and also, under implementation, in the preamble) % \item[\kl{knowledges}] are the central notion % \end{description} % % \paragraph{Areas} % % An \intro{area} is an environment unit such as `\texttt{theorem}', `\texttt{section}', and so on\dots{} % Special realization of these \kl{areas} are called `\kl{instances}'. % Hence, there is an \kl{area} named `\texttt{section}', and there are potentially % many \kl{instances} of this area in the document. % Part of the machinery is used for the allocation of \kl{instances}. % In some sense, this is a weak form of grammar describing how these can be used. % For instance, a subsection has to occur below a section, and opening a section immediately % closes the current subsection if it exists. % % To help the definition, the areas can be grouped into categories in order to share part of the code/definitions. % Each time an \kl{area} is defined, a corresponding \kl{category} with same name is also defined. % % An \kl{area} has some fields. The field X of \kl{area} A % can be found in the token of name |\scope_tl.area[A].X|. % \begin{compactdesc} % \item[\csintro{nesting_int}] is an int counting the nesting level of the area at the current moment. % \item[\csintro{count_int}] is an int counting the instances of the area opened so far. It is used (for the moment) % in order to uniquely name the instances. It is also used in some tests. It is incremented each time % a new \kl{instance} of this area is created. % \item[\csintro{name_tl}] is the text name of the \kl{area}. % \item[\csintro{pushcode_tl}] is code to be executed when an \kl{instance} of the \kl{area} is created. % \item[\csintro{popcode_tl}] is code to be executed just before an \kl{instance} of the \kl{area} is closed. % \item[\csintro{autoclose_bool}] is a boolean which, when set to true, % means that \kl{instances} of this area may be implicitly closed. This is the case for instance % for a `subsection', which can be implicitly closed when another `subsection' is started, or when % a `section' is started, or when the document finishes. % \item[\csintro{recursive_bool}] is a boolean describing whether such an environment can be opened inside itself. % This is more for making the error messages explicit. % \item[\csintro{multiple_bool}] is a boolean that tells whether several instances of this area can be defined % in the document. This is also mainly for making more explicit the error messages. % \item[\csintro{forces_tl}] is the name of an area that has to be opened if one wants to use this area. % It is opened if necessary. % \item[\csintro{acceptsknowledge_bool}] is a boolean telling whether a knowledge can be associated to an instance of this area. % \item[\csintro{labelizable_bool}] tells whether a label can point to such an environment. % \item[\csintro{attractsknowledge_bool}] is a boolean that tells whether this area % spontaneously catpures the \kl{knowledges} defined in its scope. % Hence, a section does not attract knowledges: the document does. % However, the user can force a knowledge to only be valid in a section since `section's accept knowledges. % \item[\csintro{mandatorybase_seq}] is a \texttt{seq} containing the list of categories that are allowed to % be the parent of this area. For instance, \cs{\item} % would have \texttt{itemize}, \texttt{compactdesc} and \texttt{enumerate}. % \end{compactdesc} % % \begin{macrocode} \tl_new:N\l_self_tl % \end{macrocode} % \begin{macrocode} \cs_new:Nn\scope_area_show:n{ \group_begin: \scope_area_if_exist:nTF{#1} { \tl_set:Nx\l_self_tl{\scope_tl.area[#1]} \tl_show:x {Area~name:~\use:c{\l_self_tl.name_tl},~ autoclose=\bool_if:cTF{\l_self_tl.autoclose_bool}TF,~ recursive=\bool_if:cTF{\l_self_tl.recursive_bool}TF,~ multiple=\bool_if:cTF{\l_self_tl.multiple_bool}TF,~ scope=\bool_if:cTF{\l_self_tl.scope_bool}TF,~ environment=\bool_if:cTF{\l_self_tl.environment_bool}TF,~ forces={\use:c{\l_self_tl.forces_tl}},~ accepts~knowledge=\bool_if:cTF{\l_self_tl.accepts_knowledge_bool}TF,~ attracts~knowledge=\bool_if:cTF{\l_self_tl.attracts_knowledge_bool}TF,~ accepts~labels=\bool_if:cTF{\l_self_tl.labelizable_bool}TF. } } {\knowledge_error:n{Unknown~area~`#1'~in~`\noexpand\scope_area_show:n'.}} \group_end: } % \end{macrocode} % % % % Areas are created empty by \cs{\scope_area_create:n}. % \begin{macrocode} \cs_new:Nn\scope_area_create:n {\group_begin: \tl_set:Nx\l_self_tl{\scope_tl.area[#1]} % \scope_category_add_area:nn{all}{#1} % \tl_new:c{\l_self_tl.name_tl} \tl_gset:cn{\l_self_tl.name_tl}{#1} \seq_new:c{\l_self_tl.category_seq} \seq_gpush:cn{\l_self_tl.category_seq}{all} \seq_gpush:cn{\l_self_tl.category_seq}{#1} \bool_new:c{\l_self_tl.autoclose_bool} \bool_gset_false:c{\l_self_tl.autoclose_bool} \bool_new:c{\l_self_tl.environment_bool} \bool_gset_true:c{\l_self_tl.environment_bool} \bool_new:c{\l_self_tl.multiple_bool} \bool_gset_true:c{\l_self_tl.multiple_bool} \bool_new:c{\l_self_tl.attractsknowledge_bool} \bool_gset_true:c{\l_self_tl.attractsknowledge_bool} \bool_new:c{\l_self_tl.labelizable_bool} \bool_gset_true:c{\l_self_tl.labelizable_bool} \bool_new:c{\l_self_tl.scope_bool} \bool_gset_false:c{\l_self_tl.scope_bool} \bool_new:c{\l_self_tl.acceptsknowledge_bool} \bool_gset_true:c{\l_self_tl.acceptsknowledge_bool} \bool_new:c{\l_self_tl.recursive_bool} \tl_gclear_new:c{\l_self_tl.pushcode_tl} \tl_gclear_new:c{\l_self_tl.popcode_tl} \tl_gclear_new:c{\l_self_tl.forces_tl} \seq_new:c{\l_self_tl.mandatorybase_seq} \int_new:c{\l_self_tl.count_int} \int_gset:cn{\l_self_tl.count_int}{0} \int_new:c{\l_self_tl.nesting_int} \int_gset:cn{\l_self_tl.nesting_int}{0} % \scope_category_if_exist:nTF{#1} {}{\scope_category_create:n{#1} \seq_gpush:cn{\scope_tl.category[#1].areas_seq}{#1}} \group_end: } % \end{macrocode} % % % \cs{\scope_area_if_exist:nTF}, \cs{\scope_area_if_in_scope:nTF}. % \begin{macrocode} \cs_new:Npn\scope_area_if_exist:nTF#1 {\tl_if_exist:cTF{\scope_tl.area[#1].name_tl}} % \end{macrocode} % \begin{macrocode} \cs_new:Npn\scope_if_triggers_area:nTF#1{ \scope_area_if_exist:nTF{#1} {\bool_if:cTF{\scope_tl.area[#1].environment_bool} \use_i:nn \use_ii:nn} \use_ii:nn } % \end{macrocode} % \begin{macrocode} \cs_new:Npn\scope_area_if_in_scope:nTF#1 {\int_compare:nNnTF {\use:c{\scope_tl.area[#1].nesting_int}}>0} % \end{macrocode} % % \AP The commands \cs{\scope_area_set:nn} % introduces (if necessary) and changes the parameters of areas. % The first argument is a comma separated list of area names, and the second % argument is a comma separated list of key=val commands. The keys available by default are the following: % % \AP The base command for configuring a scope is \csintro{\ScopeConfigure}\{area~list\}\{directives\}. % \begin{macrocode} \newrobustcmd\ScopeConfigure[2] {\scope_area_set:nn{#1}{#2}} % \end{macrocode} % \begin{macrocode} \cs_new:Nn\scope_area_set:nn {\clist_map_inline:nn{#1} {\scope_area_set_i:nn{##1}{#2}}} % \end{macrocode} % \begin{macrocode} \tl_new:N\scope_area_tl \cs_new:Nn\scope_area_set_i:nn { \scope_area_if_exist:nTF{#1} {}{ \scope_area_create:n{#1}} \group_begin: \tl_set:Nx\scope_area_tl{#1} \tl_set:Nx\l_self_tl{\scope_tl.area[\scope_area_tl]} \keys_set:nn{ scope~area~set }{#2} \group_end:} % \end{macrocode} % \begin{macrocode} % \scope_area_tl contains the name of the area under definition \keys_define:nn{ scope~area~set } { category .code:n = {\clist_map_inline:nn{#1} {\scope_category_ensure:n{##1} \seq_gpush:cV {\scope_tl.category[##1].areas_seq}\scope_area_tl }}, autoclose .choice:, autoclose / false .code:n = {\bool_gset_false:c{\l_self_tl.autoclose_bool}}, autoclose / true .code:n = {\bool_gset_true:c{\l_self_tl.autoclose_bool}}, parents .code:n = {\seq_gset_from_clist:cn{\l_self_tl.mandatorybase_seq}{#1}}, push~code .code:n = {\tl_gput_right:cn{\l_self_tl.pushcode_tl}{#1}}, pop~code .code:n = {\tl_gput_right:cn{\l_self_tl.popcode_tl}{#1}}, occurrences .choice:, occurrences / once .code:n = {\bool_gset_false:c{\l_self_tl.multiple_bool} \bool_gset_false:c{\l_self_tl.recursive_bool}}, occurrences / multiple .code:n = { \bool_gset_true:c{\l_self_tl.multiple_bool} \bool_gset_false:c{\l_self_tl.recursive_bool}}, occurrences / recursive .code:n = { \bool_gset_true:c{\l_self_tl.multiple_bool} \bool_gset_true:c{\l_self_tl.recursive_bool}}, scope .choice:, scope / true .code:n = { \bool_gset_true:c{\l_self_tl.scope_bool}}, scope / false .code:n = { \bool_gset_false:c{\l_self_tl.scope_bool}}, environment .choice:, environment / true .code:n = { \bool_gset_true:c{\l_self_tl.environment_bool}}, environment / false .code:n = { \bool_gset_false:c{\l_self_tl.environment_bool}}, environment .default:n = {true}, label .choice:, label / none .code:n = { \bool_gset_false:c{\l_self_tl.labelizable_bool}}, label / accepts .code:n = { \bool_gset_true:c{\l_self_tl.labelizable_bool}}, knowledge .choice:, knowledge / none .code:n = { \bool_gset_false:c{\l_self_tl.acceptsknowledge_bool} \bool_gset_false:c{\l_self_tl.attractsknowledge_bool}}, knowledge / accepts .code:n = { \bool_gset_true:c{\l_self_tl.acceptsknowledge_bool} \bool_gset_false:c{\l_self_tl.attractsknowledge_bool}}, knowledge / attracts .code:n = { \bool_gset_true:c{\l_self_tl.acceptsknowledge_bool} \bool_gset_true:c{\l_self_tl.attractsknowledge_bool}}, forces .code:n = {\tl_gset:cn{\l_self_tl.forces_tl}{#1}} } % \end{macrocode} % % \paragraph{Categories} % %\begin{compactdesc} % \item[\csintro{\scope_category_if_exist:nTF}] tests if a \kl{category} does exist. % \item[\csintro{\scope_category_ensure:n}] guarantees that a \kl{category} exists, possibly creating it if necessary. % \item[\csintro{\scope_category_create:n}] creates a \kl{category}. % \item[\csintro{\scope_category_add_area:nn}] adds an \kl{area} to a \kl{category}. % \item[\csintro{\scope_category_use:n}] displays the \kl{category} as a comma separated list of \kl{area} names (expandable). % \item[\csintro{\scope_category_show:n}] shows the content of a \kl{category} on the console. % \end{compactdesc} % \iffalse % \begin{macrocode} \cs_new:Npn\scope_category_if_exist:nTF#1 {\tl_if_exist:cTF{\scope_tl.category[#1].name_tl}} % \end{macrocode} % \begin{macrocode} \cs_new:Nn\scope_category_ensure:n {\scope_category_if_exist:nTF {#1}{}{\scope_category_create:n{#1}}} % \end{macrocode} % \begin{macrocode} \cs_new:Nn\scope_category_create:n {\tl_new:c{\scope_tl.category[#1].name_tl} \tl_gset:cn{\scope_tl.category[#1].name_tl}{#1} \seq_new:c{\scope_tl.category[#1].areas_seq}} % \end{macrocode} % \begin{macrocode} \cs_new:Nn\scope_category_add_area:nn {\scope_category_ensure:n{#1} \seq_gpush:cn{\scope_tl.category[#1].areas_seq}{#2}} % \end{macrocode} % \begin{macrocode} \cs_new:Nn\scope_category_use:n {\seq_use:cn{\scope_tl.category[#1].areas_seq},} % \end{macrocode} % \begin{macrocode} \cs_new:Nn\scope_category_show:n {\seq_show:c{\scope_tl.category[#1].areas_seq}} % \end{macrocode} %\fi % %\paragraph{Instances} % % We now turn to define the fields involved in an instance. % There are two series of objects. The ones defined in the first pass of compilation, % and used for maintaining the structure of the scopes, and the ones % that are used in the second pass, which gather information throughout the % whole file. The first one are prefixed by \texttt{scope}, % the others by \texttt{kaux}. % \begin{compactdesc} % \item[\intro{instance.area}] is the name of the area it is an instance of. % \item[\intro{instance.parent}] is the name of the parent instance. % \end{compactdesc} % \begin{compactdesc} % \item[\csintro{\scope_instance_if_exist:nTF}] % \item[\csintro{\scopept_instance_if_exist:nTF}] % \item[\csintro{\scopept_label_if_exist:nTF}] % \end{compactdesc} %\iffalse % \begin{macrocode} \cs_new:Npn\scope_instance_if_exist:nTF#1 {\tl_if_exist:cTF{\scope_tl.instance[#1].area_tl}} % \end{macrocode} % \begin{macrocode} \cs_new:Npn\scopept_instance_if_exist:nTF#1 {\tl_if_exist:cTF{\scopept_tl.instance[#1].area_tl}} % \end{macrocode} % \begin{macrocode} \cs_new:Npn\scopept_label_if_exist:nTF#1 {\tl_if_exist:cTF{\scopept_tl.label[#1].instance_tl}} % \end{macrocode} %\fi % % \subsubsection{Pushing and popping} % % Introduces the macros \csintro{\scope_area_push:n} and \csintro{\scope_area_pop:n}. % % The token lists \csintro{\scope_popped_area_tl} and \csintro{\scope_pushed_area_tl} % contain the area that triggered the push / the pop. These lists are only meaningful in these macros. % \begin{macrocode} \tl_new:N\scope_pushed_area_tl \tl_new:N\scope_popped_area_tl % \end{macrocode} % \begin{macrocode} \cs_new:Nn\scope_area_pop:n { \tl_gset:Nn\scope_popped_area_tl{#1} \bool_if:cTF{\scope_tl.area[\scope_popped_area_tl].autoclose_bool} {\msg_error:nn{scope}{no~popping}} {\scope_area_pop_i:}} % \end{macrocode} % \begin{macrocode} \cs_new:Nn\scope_area_pop_i: { \tl_if_eq:NNTF\scope_top_area_tl\scope_popped_area_tl {\scope_internal_pop:} {\bool_if:cTF{\scope_tl.area[\scope_top_area_tl].autoclose_bool} {\scope_internal_pop: \scope_area_pop_i:} {\msg_error:nn{scope}{no~popping~here}}}} % \end{macrocode} % \begin{macrocode} \cs_new:Nn\scope_internal_pop: { \use:c{\scope_tl.area[\scope_top_area_tl].popcode_tl} \seq_gpop:NNTF\scope_instances_stack_seq\l_tmpa_tl {\tl_gset_eq:NN\scope_top_instance_tl\l_tmpa_tl \int_gdecr:c{\scope_tl.area[\scope_top_area_tl].nesting_int} \knowledge_pop_visible_instances_to_mark: \seq_get:NN\scope_instances_stack_seq\l_tmpa_tl \tl_gset_eq:NN\scope_top_instance_tl\l_tmpa_tl \tl_gset:Nx\scope_top_area_tl {\tl_use:c{\scope_tl.instance[\scope_top_instance_tl].area_tl}}} {\msg_error:nnn{scope}{empty~pop}{}} } % \end{macrocode} % \begin{macrocode} \cs_new:Nn\scope_area_push:n { \tl_gset:Nn\scope_pushed_area_tl{#1} \scope_area_push_i:n{#1}} % \end{macrocode} % \begin{macrocode} \cs_new:Nn\scope_area_push_i:n { \tl_if_empty:cTF{\scope_tl.area[#1].forces_tl} {} {\exp_args:Nx\scope_area_if_in_scope:nTF {\tl_use:c{\scope_tl.area[#1].forces_tl}} {} {\exp_args:Nx\scope_area_push_i:n {\tl_use:c{\scope_tl.area[#1].forces_tl}}}} \scope_area_push_ii:n{#1} } % \end{macrocode} % \begin{macrocode} \cs_new:Npn\scope_if_area_in_areaclist:nnTF#1 {\exp_args:NnV\clist_if_in:nnTF{#1}\scope_top_area_tl} \cs_new:Nn\scope_category_expand:n {\clist_use:x{ \clist_map:nN{#1}{ \seq_use:c{\scope_tl.category[#1].areas_seq},}}} \cs_new:Nn\scope_categories_expand:n {\clist_map_function:nN{#1}\scope_category_expand:n} \cs_new:Nn\scope_if_area_in_categoryclist:nnTF {\group_begin: \tl_set:Nx\l_tmpa_tl {\clist_map_function:nN{#2}\scope_category_areas_use:n} \bool_set_false:N\l_tmpa_bool \clist_map_inline:nn{#2} {\scope_category_areas_if_in:nnTF{##1}{#1} {\bool_set_true:N\l_tmpa_bool\seq_map_break:}{}} \bool_if:NTF\l_tmpa_bool {\group_end:#3} {\group_end:#4} } \cs_new:Npn\scope_category_if_area_in:nnTF#1#2 {\exp_args:Nnx\seq_if_in:cnTF {\scope_tl.category[#1].areas_seq}{#2}} \cs_new:Nn\scope_categoryseq_if_area_in:NnTF { \seq_if_empty:NTF#1 {#3} {\group_begin: \bool_set_false:N\l_tmpa_bool \seq_map_inline:Nn#1 {\seq_if_in:cnTF{\scope_tl.category[##1].areas_seq}{#2} {\bool_set_true:N\l_tmpa_bool\seq_map_break:}{}} \bool_if:NTF\l_tmpa_bool {\group_end:#3} {\group_end:#4} }} \cs_new:Npn\scope_area_mandatorybase_if_area_in:nnTF#1 {\exp_args:Nc\scope_categoryseq_if_area_in:NnTF {\scope_tl.area[#1].mandatorybase_seq}} \cs_new:Nn\scope_categoryseq_pop_to:N {\exp_args:NNx\scope_categoryseq_if_area_in:NnTF#1{\scope_top_area_tl} {}{\scope_auto_pop:\scope_categoryseq_pop_to:N#1}} \cs_new:Nn\scope_categoryseq_pop_to:n {\group_begin: \seq_set_from_clist:Nn\l_tmpa_seq{#1} \scope_categoryseq_pop_to:N\l_tmpa_seq \group_end:} \cs_new:Nn\scope_area_push_ii:n { \seq_if_empty:cTF{\scope_tl.area[#1].mandatorybase_seq} {\scope_internal_push:n{#1}} {\exp_args:Nnx\use:n {\scope_area_mandatorybase_if_area_in:nnTF{#1}} {\scope_top_area_tl} {\scope_internal_push:n{#1}} {\scope_auto_pop: \scope_area_push_ii:n{#1}}} } % \end{macrocode} % \begin{macrocode} \cs_new:Nn\scope_internal_push:n { \ScopeActivate \tl_gset:Nn\scope_top_area_tl{#1} \int_gincr:c{\scope_tl.area[\scope_top_area_tl].nesting_int} \int_gincr:c{\scope_tl.area[\scope_top_area_tl].count_int} % storing the previous top instance \tl_set_eq:NN\l_tmpa_tl\scope_top_instance_tl %naming the new instance \bool_if:cTF{\scope_tl.area[\scope_top_area_tl].multiple_bool} {\tl_gset:Nx\scope_top_instance_tl {\scope_top_area_tl-\int_to_arabic:n{\int_use:c{\scope_tl.area[\scope_top_area_tl].count_int}}}} {\tl_gset_eq:NN\scope_top_instance_tl\scope_top_area_tl} % \knowledge_push_visible_instance_mark: \exp_args:Nx\knowledge_push_visible_instance:n{\scope_top_instance_tl} \seq_gpush:Nx\scope_instances_stack_seq{\scope_top_instance_tl} % \tl_new:c {\scope_tl.instance[\scope_top_instance_tl].area_tl} \tl_gset:cx {\scope_tl.instance[\scope_top_instance_tl].area_tl} {\scope_top_area_tl} \tl_new:c {\scope_tl.instance[\scope_top_instance_tl].parent_tl} \tl_gset:cx {\scope_tl.instance[\scope_top_instance_tl].parent_tl} {\l_tmpa_tl} % \seq_if_exist:cTF{\scopept_tl.instance[\l_tmpa_tl].context_seq} {\seq_set_eq:Nc\l_tmpa_seq{\scopept_tl.instance[\l_tmpa_tl].context_seq}} {\seq_clear_new:N\l_tmpa_seq} \exp_args:NNx\seq_push:Nn \l_tmpa_seq{\scope_top_instance_tl} \seq_new:c {\scopept_tl.instance[\scope_top_instance_tl].context_seq} \seq_gset_eq:cN {\scopept_tl.instance[\scope_top_instance_tl].context_seq} \l_tmpa_seq % \KAuxWriteX {\KAuxScopeNewInstance{\scope_top_area_tl}{\scope_top_instance_tl}{\l_tmpa_tl}} % \tl_use:c{\scope_tl.area[\scope_top_area_tl].pushcode_tl} } % \end{macrocode} % \begin{macrocode} \cs_new:Nn\scope_auto_pop: { \bool_if:cTF{\scope_tl.area[\scope_top_area_tl].autoclose_bool} {\scope_internal_pop:} {\msg_error:nn{scope}{no~pushing~here}} } % \end{macrocode} % % % \subsubsection{Inspecting} % % \csintro{\scope_get_attractive_instance:N} takes a \kl{token list variable}, % and sets it to contain an % instance able to receive knowledges. % This is done by inspecting the scope stack until reaching an instance % that has \kl{instance.attractsknowledge_bool} set to true (by default, this is `base'). % \begin{macrocode} \cs_new:Nn\scope_get_attractive_instance:N {\tl_set:Nn#1{base} \seq_map_inline:Nn\scope_instances_stack_seq {\bool_if:cTF {\scope_tl.area[\tl_use:c{\scope_tl.instance[##1].area_tl}].attractsknowledge_bool} {\tl_set:Nn#1{##1}\seq_map_break:}{}} } % \end{macrocode} % \csintro{\scope_get_labelizable_instance:N} takes a token list variable as input for holding the result. % It inspects the current stack of instances \cs{\scope_instances_stack_seq}, searching for an "instance" % of a "scope" which is labelizable, and returns it. The default is `base'. % \begin{macrocode} \cs_new:Nn\scope_get_labelizable_instance:N {\tl_set:Nn#1{base} \seq_map_inline:Nn\scope_instances_stack_seq {\bool_if:cTF {\scope_tl.area[\tl_use:c{\scope_tl.instance[##1].area_tl}].labelizable_bool} {\tl_set:Nn#1{##1}\seq_map_break:}{}} } % \end{macrocode} % The command \csintro{\knowledge_scope_track_instance:Nn} is the internal part od the "scope=" directive. % It takes as argument a token list variable for holding the result, and a text to be looked for. % If the text corresponds to a "scope" name (such as section, theorem, \dots), then it inspects the % content of the stacks for finding the target. % Otherwise, it uses it as a label. % and if it fails, it tries to find a label of this name that provides an instance. % \begin{macrocode} %\cs_new:Nn\knowledge_scope_track_instance:Nn{ % \tl_show:n{#1:#2} % \scope_area_if_exist:nTF{#2} % {\knowledge_scope_track_instance_from_area:Nn#1{#2}} % {\knowledge_scope_track_instance_from_scopetag:Nn#1{#2}} %} \cs_new:Nn\knowledge_scope_track_instance_from_area:Nn{ \tl_set:Nn#1{} \seq_map_inline:Nn\scope_instances_stack_seq {\exp_args:Nxx\tl_if_eq:nnTF {\csname \scope_tl.instance[##1].area_tl\endcsname} {#2} {\tl_set:Nn#1{##1}\seq_map_break:} {}} \tl_if_empty:NTF#1 {\msg_error:nnxx{scope}{area~not~in~context}{#2}{scope=}} {} } % \end{macrocode} % The command \cs{\knowledge_scope_track_scope:n} % is used to set the variable \cs{\knowledge_knowledge_instance_tl}. % If the argument is a scope name, then it is searched for in the context, and the corresponding "instance" is used. % Otherwise it is used as a "scopetag"; this "scopetag" being potentially % defined if necessary using \cs{\knowledge_scopetag_warn_if_unknown:n}. % \begin{macrocode} \cs_new:Nn\knowledge_scope_track_scope:n{ \scope_area_if_exist:nTF{#1} {\knowledge_scope_track_instance_from_area:Nn\knowledge_knowledge_instance_tl{#1}} {\tl_set:Nn\knowledge_knowledge_instance_tl{explicit-scope:#1} \knowledge_scopetag_warn_if_unknown:n{#1}} } % \end{macrocode} % \begin{macrocode} \bool_new:N\scopept_map_break_bool \cs_new:Nn\scopept_map_break: {\bool_set_true:N\scopept_map_break_bool} \cs_new:Nn\scopept_map_instance_ancestors:nN {\bool_set_false:N\scopept_map_break_bool \scope_map_instance_ancestors_i:nN{#1}#2 } \cs_new:Nn\scopept_map_instance_ancestors_i:nN { \tl_if_empty:nTF{#1} {} {\scopept_instance_if_exist:nTF{#1}{ #2{#1} \bool_if:NTF\scopept_map_break_bool {} {\exp_args:Nx\scopept_map_instance_ancestors_i:nN {\scopept_instance_parent_at:Nn\tl_use:N{#1}}#2}} {}}} \cs_new:Nn\scopept_map_instances_seq_ancestors:NN {\seq_map_inline:Nn#1 {\scopept_map_instance_ancestors_i:nN{##1}#2 \bool_if:NTF\scopept_map_break_bool:{\seq_map_break:}{}} } % \end{macrocode} % % % \subsubsection{Scope tags} % % A ""scopetag"" is a name that can be used to identify a family of "instances" that correspond to it. % It gets to have two variables attached to it: % \begin{description} % \itemAP[\cs{\knowledge_scopetag_tl}\texttt{{[TAG]}\_bool}] which tells whether it % has been officially declared (it is false if it has been used but not declared by a \cs{\knowledgescope} % or a \cs{\label} command). % \itemAP[\cs{\knowledge_scopetag_tl}\texttt{{[TAG]}\_seq}] is a sequence of % "instances" that are attached to it. It always contains (as soon as created) % \end{description} % % In order to identify scopes, the command~\cs{\knowledgescope} (or \cs{\label} which is overloaded for this purpose). % % \par\noindent\AP\csintro{\knowledge_scopetag_tl} is a unique string for identifying "scopetags". % \par\noindent\AP\csintro{\knowledge_scopetag_if_exist:nTF} tests the existence of a "scopetag". % \par\noindent\AP\csintro{\knowledge_scopetag_ensure:n} guarantees that the "scopetag" is defined (by default, the boolean is set to false). % \par\noindent\AP\csintro{\knowledge_scopetag_warn_if_unknown:n} writes \cs{\KAuxUndeclaredScopeTag} to the "kaux file" if the "scopetag" was never met before, then calls \cs{\knowledge_scopetag_ensure:n}. % \par\noindent\AP\csintro{\knowledge_scopetag_declares:n} creates the "scopetag" if necessary, and if it was not known before, declares and puts a \cs{\KAuxDeclaredScopeTag} command in the "kaux file". % \begin{macrocode} \tl_const:Nn\knowledge_scopetag_tl{ScpT@g} % \end{macrocode} % \begin{macrocode} \cs_new:Npn\knowledge_scopetag_if_exist:nTF#1 {\tl_if_exist:cTF{\knowledge_scopetag_tl[#1]_bool}} \cs_new:Nn\knowledge_scopetag_ensure:n{ \knowledge_scopetag_if_exist:nTF{#1}{} {\bool_new:c{\knowledge_scopetag_tl[#1]_bool} \bool_gset_false:c{\knowledge_scopetag_tl[#1]_bool} \seq_new:c{\knowledge_scopetag_tl[#1]_seq} \seq_gput_right:cn{\knowledge_scopetag_tl[#1]_seq}{explicit-scope:#1}}} % \end{macrocode} % \begin{macrocode} \cs_new:Nn\knowledge_scopetag_warn_if_unknown:n{ \knowledge_scopetag_if_exist:nTF{#1}{} {\KAuxWriteX*{\exp_not:N\KAuxUndeclaredScopeTag{#1}} \knowledge_scopetag_ensure:n{#1}} } % \end{macrocode} % \begin{macrocode} \cs_new:Nn\knowledge_scopetag_declares:n{ \knowledge_scopetag_ensure:n{#1} \bool_if:cTF{\knowledge_scopetag_tl[#1]_bool} {} {\KAuxWriteX*{\exp_not:N\KAuxDeclaredScopeTag{#1}} \bool_gset_true:c{\knowledge_scopetag_tl[#1]_bool}} } % \end{macrocode} % \AP The command \csintro{\knowledgescope} associates an "instance" to one or more "scopetags": % \begin{macrocode} \NewDocumentCommand\knowledgescope{ >{\SplitList{,}}m }{ \kl_hide_begin:\group_begin: \ProcessList{#1}\knowledge_knowledgescope_one:n \group_end:\kl_hide_end: } % \end{macrocode} % In the following code, now the name of the instance is expanded before being written to the "kaux file". % \begin{macrocode} \cs_new:Nn\knowledge_knowledgescope_one:n{ \knowledge_scopetag_declares:n{#1} \scope_get_labelizable_instance:N\l_tmpb_tl \KAuxWriteX*{\exp_not:n{\KAuxNewLinkScopetagInstance}%{\exp_not:n{#1}}% old version {#1}{\l_tmpb_tl}} } % \end{macrocode} % % \paragraph{Modified labels} % \AP The boolean \csintro{\knowledge_configuration_label_autoscope_bool} % activates or deactivates the automatic calling to \cs{knowlegescope} when \cs{\label} is used. % \begin{macrocode} \bool_new:N\knowledge_configuration_label_autoscope_bool \bool_gset_true:N\knowledge_configuration_label_autoscope_bool \KnowledgeConfigureBooleanOption[\knowledge_configuration_label_autoscope_bool]{patch~label} % \end{macrocode} % \noindent\AP\csintro{\scopeLabel} implicitly adds a call to \cs{\knowledgescope} (if \cs{\knowledge_configuration_label_autoscope_bool} is set to true), and then calls the original \cs{\label} code. % \begin{macrocode} \NewDocumentCommand\scopeLabel{m}{ \kl_hide_begin: \bool_if:NTF \knowledge_configuration_label_autoscope_bool \knowledge_knowledgescope_one:n \use_none:n {#1} \kl_hide_end: \cs_if_exist:NTF\LaTeXlabel\LaTeXlabel\use_none:n{#1} } \let\label\scopeLabel % \end{macrocode} % \AP In order to cicumvent this overloading, the normal \cs{\label} command % can be used using \csintro{\knowledge_latex_label:n}: % \begin{macrocode} \cs_new:Npn\knowledge_latex_label:n{ \cs_if_exist:NTF\LaTeXlabel\LaTeXlabel\label } % \end{macrocode} % \par\noindent\csintro{\knowledge_scopetag_warn_if_unknown:n} takes a "scopetag" as input. % If it does not exist, it defines, and sets its boolean to false. % \begin{macrocode} \NewKAuxCommand\KAuxUndeclaredScopeTag{m} {Package~scope:~States~that~a~labelname~is~used~in~a~knowledge~definition.} \DeclareKAuxPhaseCommand\KAuxUndeclaredScopeTag{init}{} \NewKAuxCommand\KAuxDeclaredScopeTag{m} {Package~scope:~States~that~a~labelname~has~been~declared.} \DeclareKAuxPhaseCommand\KAuxDeclaredScopeTag{init}{ \knowledge_scopetag_if_exist:nTF{#1}{} {\bool_new:c{\knowledge_scopetag_tl[#1]_bool}} \bool_gset_true:c{\knowledge_scopetag_tl[#1]_bool} } \NewKAuxCommand\KAuxNewLinkScopetagInstance{mm} {Package~scope:~Declares~that~a~label~is~declared~in~an~instance~of~a~scope.} \DeclareKAuxPhaseCommand\KAuxNewLinkScopetagInstance{init}{ \knowledge_scopetag_ensure:n{#1} \seq_gput_right:cn{\knowledge_scopetag_tl[#1]_seq}{#2} } % \end{macrocode} % % %\subsubsection{Processing the \kl{kaux file}} % % When reading the file, scope outputs commands that will be processed % at the next iteration. It shares the output files \kl{jobname.kaux} for that. % Commands that may be used in this process are defined here. % \begin{macrocode} \NewKAuxCommand\KAuxScopeNewInstance{mmm} {Package~scope:~Declares~a~new~instance~of~a~scope.} \DeclareKAuxPhaseCommand\KAuxScopeNewInstance{init} {\tl_new:cn{\scopept_tl.instance[#2].area_tl}{#1} \tl_new:cn{\scopept_tl.instance[#2].parent_tl}{#3}} % \end{macrocode} % \begin{macrocode} \NewKAuxCommand\KAuxScopeTag{mm} {Package~scope:~Links~a~scopetag~to~an~instance~of~a~scope.} \DeclareKAuxPhaseCommand\KAuxScopeTag{init} {\tl_if_exist:cTF{\scopept_tl.label[\tl_to_str:n{#1}].instance_tl}{} {\tl_new:cn{\scopept_tl.label[\tl_to_str:n{#1}].instance_tl}{#2}}} % \end{macrocode} % \begin{macrocode} \cs_new:Npn\scopept_label_instance_if_exist:nTF#1 {\tl_if_exist:cTF{\scopept_tl.label[#1].instance_tl}} \cs_new:Nn\scopept_label_instance_use:n {\tl_use:c{\scopept_tl.label[#1].instance_tl}} % \end{macrocode} % % \subsubsection{Commands} % % The command \cs{\knowledgeconfigureenvironment} declares a % standard "latex" environment to behave like the \kl(env){scope} environment % (while keeping its standard display). % \begin{macrocode} \newcommand\knowledgeconfigureenvironment\KnowledgeConfigureEnvironment \NewDocumentCommand\KnowledgeConfigureEnvironment{t?t!mm} {\clist_map_inline:nn{#3}{ \IfBooleanTF{#2} {\scope_area_environment_new:nn{##1}{#4}} {\cs_if_exist:cT{##1} {\cs_if_exist:cT{end##1} {\scope_area_environment_new:nn{##1}{#4} \use_none:n}} {\IfBooleanF{#1} {\knowledge_error:n{Unknown~environment~`##1'~in~\KnowledgeConfigureEnvironment.}}} }}} \newcommand\scope_activate_environment[2][environment]{ \scope_area_environment_new:nn {#2}{category=#1}} \cs_new:Nn\scope_area_environment_new:nn {\scope_area_set:nn{#1}{ parents = all, autoclose = false, environment = true, occurrences = recursive, knowledge = attracts, category = environment, #2 }} % \end{macrocode} % % % \subsubsection{Activation of the \kl{scope option}} % % \begin{macrocode} \NewDocumentCommand\ScopeHackEnvironments{} { \scope_area_push:n{document} \kutils_secure_latex_command:N\begin \global\let\SUPERbegin\begin \global\def\begin##1 {\scope_if_triggers_area:nTF{##1} {\scope_area_push:n{##1}}{} \SUPERbegin{##1}} \kutils_secure_latex_command:N\end \global\let\SUPERend\end \global\def\end##1 {\SUPERend{##1} \scope_if_triggers_area:nTF{##1} {\scope_area_pop:n{##1}} {}} \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} % \itemAP the namespace name (no arobas in it), each different use of the "knowledge@@package" package can use a different namespace. For the moment, this is always `default'. % \itemAP the \kl{instance} name (defining the scope, i.e. the region in which it is defined; no arobas in it). "Instances" are automatically generated, and the used should never has access to it. % \itemAP the \kl{knowledge} text itself. % \end{itemize} % % The variable \cs{\knowledge_namespace_tl} % stores the current namespace, i.e. the ones that is used by default. % It is sometimes temporarily modified. % \begin{macrocode} \tl_new:Nn\knowledge_default_namespace_tl {default} % \end{macrocode} % The macro % \begin{code} % \csintro{\knowledge_id:nnn}\{namespace\}\{instance\}\{knowledge key\} % \end{code} % takes these three arguments in % this order (namespace/instance/scope) and produces a unique string that can be used to access % (using \cs{\csname}, or \texttt{:c} in LaTeX3) the tuple. % \begin{macrocode} \makeatother \cell_new_type:nnn{knowledge}{nnnn}{KL@#2@#3@\tl_to_str:n{#4}_#1} \cell_new_type:nnn{knowledge}{nnn}{\knowledge_id:nnnn{}{#1}{#2}{#3}} \cs_generate_variant:Nn\knowledge_id:nnn{nnV,nVV,nVn,VVV} \cs_generate_variant:Nn\knowledge_at:Nnnn{NnnV} \cs_new:Npn\knowledge_at:c{\exp_args:Nc\knowledge_at:N} % \end{macrocode} % % For convenience, when the same knowledge has to be accessed many times, one uses % \begin{code} % \csintro{\knowledge_sets_to:nnn}\{namespace\}\{knowledge key\}\{scope\} % \end{code} % which is followed by the same three arguments. % It defines % \begin{code} % \csintro{\knowledge_at:N}\cs{\token} % \end{code} that executes \cs{\token} with as % first parameter the token pointing to the knowledge. % \begin{macrocode} \cs_new:Nn\knowledge_sets_to:nnn {\cs_set:Nx\knowledge_at:N {##1\exp_not:c{\knowledge_id:nnn{#1}{#2}{#3}}}} % \end{macrocode} % Finally, one creates a new kind of tuples, called \cs{ktuples} % for storing the \kl{knowledges}. % \begin{macrocode} \tuple_new:n{ktuple} % \end{macrocode} % Some more code for testing if a "knowledge" is defined: % \begin{code} % \csintro{\knowledge_knowledge_if_exist:nnnTF}\{namespace\}\{instance\}\{key\}\par % ~~~~~~~\{true code\}\{false code\} % \end{code} % \begin{macrocode} \cs_new:Npn\knowledge_knowledge_if_exist:nnnTF#1#2#3{ \exp_args:Nc\ktuple_if_exist:NTF{\knowledge_id:nnn{#1}{#2}{#3}} } \cs_generate_variant:Nn \knowledge_knowledge_if_exist:nnnTF{VVVTF,VnVTF} % \end{macrocode} % % % \subsection{Knowledge code} % % % \subsubsection{Generalities} % % The \cs{\knowledge} command is dealt in several steps. % \begin{asparaitem} % \item In a first phase, the "directives" are parsed using the keys \csintro{knowledge~directives}. % During this phase, all the information concerning the target is fixed, as well as other pieces of informations % such as the real reference of the "autoref" directive. The result is gathered in a second comma separated % list of directives % \item Then, depdnging on the targetting information, the % \end{asparaitem} % Essentially, the \cs{\keys_define:nn}\verb|{ knowledgenow~directives }|(...) % commands used throughout the code are here to add new functionalities to it. % % % \subsubsection{Defining directives} % % % The commands used for introducing new directives. % The command % \begin{code} % \csintro{\NewKnowledgeParamBool}[*]\{name\}\cs{\token} % \end{code} % creates a new boolean directive of name `name'. % When the knowledge is executed, the value will be stored in the \cs{\token}. % By default, the directive is only usable in \kl{knowledgenow directives}. % If the optional star is used, then the \kl{directive} is usable in the \cs{\knowledge} command, and its value is propagated automatically. Hence, no-star means internal booleans used by the % system, and star means booleans accessible to the user. % \iffalse % \begin{macrocode} \NewDocumentCommand\NewKnowledgeParamBool{smm}{ \ktuple_new_bool_index:n{#2} \bool_new:N#3 \use:c{ktuple_#2_expands_to:TF} {\bool_set_true:N#3}{\bool_set_false:N#3} % \keys_define:nn { knowledgenow~directives }{ #2 .choice:, #2 / false .code:n = { \knowledge_at:c{ktuple_#2_gset_false:N}}, #2 / true .code:n = { \knowledge_at:c{ktuple_#2_gset_true:N} }, #2 / default .code:n = { \knowledge_at:c{ktuple_#2_gdel:N}}, #2 .default:n = {true} } \IfBooleanTF{#1}{\KnowledgeTransferBool{#2}}{} } \NewDocumentCommand\KnowledgeTransferBool{m}{ \clist_map_inline:nn{ #1 }{ \keys_define:nn { knowledge~directives }{ ##1 .choice:, ##1 / false .code:n = { \knowledge_delay_directive:n{##1= false}}, ##1 / true .code:n = { \knowledge_delay_directive:n{##1= true}}, ##1 / default .code:n = { \knowledge_delay_directive:n{##1= default}}, ##1 .default:n = true }} } % \end{macrocode} % \fi % \AP The command \cs{\NewKnowledgeParamTl} is similar to \cs{\NewKnowledgeParamBool}, % but creates a directive that stores text. % \begin{code} % \csintro\NewKnowledgeParamTl*[\cs\token]\{name\} % \end{code}\noindent % \iffalse % \begin{macrocode} \NewDocumentCommand\NewKnowledgeParamTl{som}{ \IfNoValueTF{#2} { \tl_set:Nn\l_tmpa_tl{#3} \tl_remove_all:Nn\l_tmpa_tl{~} \use:x{ \exp_not:N\NewKnowledgeParamTl \IfBooleanT{#1}{*} [\exp_not:c{knowledge_kl_\l_tmpa_tl _tl}] {#3} }} {\cs_if_exist:cTF{ktuple_#3_expands_to:n} {} {\ktuple_new_tl_index:n{#3}} \tl_if_exist:NTF#2{} {\tl_new:N#2} \use:c{ktuple_#3_expands_to:n} {\tl_set:Nn#2{##1}} % \keys_define:nn { knowledgenow~directives }{ #3 .code:n = { \knowledge_at:c{ktuple_#3_gset:Nn}{##1} }, #3~X .code:n = { \knowledge_at:c{ktuple_#3_gset:Nx}{##1} }, no~#3 .code:n = { \knowledge_at:c{ktuple_#3_gdel:N} }} \IfBooleanTF{#1}{\KnowledgeTransferTl{#3}}{} }} % \end{macrocode} % \begin{macrocode} \NewDocumentCommand\KnowledgeTransferTl{m} {\keys_define:nn { knowledge~directives } {#1 .code:n = {\knowledge_delay_directive:n{#1={##1}}}}} % \end{macrocode} % \fi % The command \cs{\NewKnowledgeParamCode} is similar to \cs{\NewKnowledgeParamBool}, % but creates a directive that stores code. There is no optional star for code (never directly accessible to the user). % \begin{code}\AP % \csintro\NewKnowledgeParamCode\{name\}\cs{\token} % \end{code}\noindent % \begin{macrocode} \NewDocumentCommand\NewKnowledgeParamCode{mm}{ \ktuple_new_tl_index:n{#1} \tl_new:N#2 \use:c{ktuple_#1_expands_to:n} {\tl_set:Nn#2{##1}} % \keys_define:nn { knowledgenow~directives }{ #1 .code:n = { \knowledge_at:c {ktuple_#1_gset:Nn}{##1} }, #1+ .code:n = { \knowledge_at:c {ktuple_#1_gput_right:Nn}{##1} }, +#1 .code:n = { \knowledge_at:c {ktuple_#1_gput_left:Nn}{##1} } }} % \end{macrocode} % %\par % \AP The command \cs{\NewKnowledgeParamPackageError} takes a comma separated % list of directives as first argument, and a package name as second argument. % After that, when one of these \kl{directives} is used, an error suggesting to load the % corresponding package is thrown. % \begin{code} % \csintro\NewKnowledgeParamPackageError\{directive list\}\{package name\} % \end{code}\noindent % \begin{macrocode} \NewDocumentCommand\NewKnowledgeParamPackageError{mm} % \end{macrocode} % \ifcode % \begin{macrocode} { \clist_map_inline:nn{#1}{ \keys_define:nn { knowledge~directives }{ ##1 .code:n = { \msg_error:nnnn{ knowledge }{ package~required }{##1}{#2}} }}} % \end{macrocode} % % \fi % % % % \subsubsection{Scope basics} % % % \kl{Knowledges} are attached to \kl{instances}, which identify % the region in which these have been defined and also where they can be used. % For instance, if the user mentions `\kl{scope=}section' when defining a knowledge, % this means that the knowledge will only be visible in this % area\footnote{Though it can be imported and become visible elsewhere using appropriate commands.}. % Technically, instances are not directly handled by the user, nor by the "knowledge@@package" package. % % In this part of the code, we provide a small number of commands for dealing with instances. % The real code that computes the current context of scope if later. % % % \begin{compactdesc} % \item[\csintro{\knowledge_current_instance_tl}] contains the current % instance to be used. % \item[\cs{\knowledge_visible_instances_seq}] contains the sequence % of instances that are visible right now. % \item[\csintro{\knowledge_scope_track_instance:Nn}\cs\tokenlist\{scope name\}] % sets \cs{\tokenlist} to the innermost instance of the scope name. % Typically, if the request is `\texttt{subsection}', the answer will be `\texttt{subsection-3.1}', % identifying the subsection currently in scope. % \end{compactdesc} % \begin{macrocode} \tl_new:N\knowledge_current_instance_tl \tl_gset:Nn\knowledge_current_instance_tl{base} % \end{macrocode} % % \AP The sequence \csintro{\knowledge_visible_instances_seq} contains the % "instances" that are visible right now. This are searched through when % a knowledge is used. The leftmost instance is the most important one (innermost scope). % Note that \cs{\knowledge_visible_instances_seq} may only be correct after one compilation. % \begin{compactdesc} % \item[\csintro{\knowledge_push_visible_instance:n}] % \item[\csintro{\knowledge_push_visible_instance_mark:}] Inserts in \cs{\knowledge_visible_instances_seq} a special marker, % which is used when pushing a scope. % \item[\csintro{\knowledge_pop_visible_instances_to_mark:}] Pops everything till the special mark. % \item[\csintro{\knowledge_pop_visible_instances_to:n}] % \item[\csintro{\knowledge_show_visible_instances:}] % \end{compactdesc} % % \begin{macrocode} \seq_new:N\knowledge_visible_instances_seq % \end{macrocode} % Special marks are introduced for remembering till where to pop when a "scope" ends. % \begin{macrocode} \cs_new:Nn\knowledge_push_visible_instance:n {\seq_gpush:Nn\knowledge_visible_instances_seq{#1}} \cs_new:Nn\knowledge_push_visible_instance_mark: {\seq_gpush:Nn\knowledge_visible_instances_seq{|}} % \end{macrocode} % % \begin{macrocode} \cs_new:Nn\knowledge_pop_visible_instances_to_mark: {\seq_gpop:NNTF\knowledge_visible_instances_seq\l_tmpa_tl {\exp_args:NV\tl_if_eq:nnTF\l_tmpa_tl{|} {} {\knowledge_pop_visible_instances_to_mark:}} {\KNOWLEDGE_INTERNAL_ERROR:_stack_of_visible_instances_is_empty_while_popping}} % \end{macrocode} % \begin{macrocode} \cs_new:Nn\knowledge_show_visible_instances: {\tl_show:x {Visible~instances~<\seq_use:Nn\knowledge_visible_instances_seq{,}>}} % \end{macrocode} % \begin{macrocode} \NewDocumentCommand\knowledgeimport{ >{\SplitList{,}}m }{ \kl_hide_begin: \ProcessList{#1}\knowledge_knowledgeimport:n \kl_hide_end: } % \end{macrocode} % \begin{macrocode} \cs_set:Nn\knowledge_knowledgeimport:n{ \knowledge_scopetag_warn_if_unknown:n{#1} \knowledge_scopetag_ensure:n{#1} \exp_args:Nc\seq_map_function:NN {\knowledge_scopetag_tl[#1]_seq} \knowledge_push_visible_instance:n } % \end{macrocode} % % % \subsubsection{The knowledge targeting} % % We define now the "directives" that are used for choosing how the "knowledge" should be defined. % % \begin{macrocode} \keys_define:nn { knowledge~directives } { namespace .code:n = { \tl_set:Nn\knowledge_knowledge_namespace_tl{#1} }, append .choice:, append / false .code:n = {\bool_set_false:N\knowledge_knowledge_append_bool}, append / true .code:n = {\bool_set_true:N\knowledge_knowledge_append_bool}, append .default:n = false, clear .choice:, clear / false .code:n = {\bool_set_false:N\knowledge_knowledge_clear_bool}, clear / true .code:n = {\bool_set_true:N\knowledge_knowledge_clear_bool}, clear .default:n = false, export .choice:, export / false .code:n = {\bool_set_false:N\knowledge_knowledge_export_bool}, export / true .code:n = {\bool_set_true:N\knowledge_knowledge_export_bool}, export .default:n = false, % instance .code:n = % { \tl_set:Nn\knowledge_knowledge_instance_tl{#1} }, link~instance .code:n = { \tl_set:Nn\knowledge_knowledge_instance_tl{#1} }, scope .code:n = { \knowledge_scope_track_scope:n{#1} \tl_gput_right:Nn\knowledge_knowledge_immediate_synonym_directives_tl{,scope = {#1}}}, synonym .code:n = { \bool_set_true:N\knowledge_knowledge_is_synonym_bool \exp_args:Nnx\keys_set:nn { knowledge~directives } {link={\exp_not:o\knowledge_knowledge_synonymlink_tl}, link~instance={\exp_not:V\knowledge_knowledge_synonyminstance_tl}}}, } % \end{macrocode} % % % The \csintro{\KAuxKnowledge} command is added to the \kl{kaux file} when % \cs{\knowledge} delays its definition to the next phase of compilation. % \begin{macrocode} \NewKAuxCommand\KAuxKnowledge{mmmm} {Package~knowledge:~Declares~a~knowledge.~ Takes~the~{namespace}{instance}{knowledge}{directives}.} % \end{macrocode} % \begin{macrocode} \DeclareKAuxPhaseCommand\KAuxKnowledge{init} {\knowledge_set_now:nnnn{#1}{#2}{#3}{#4}} % \end{macrocode} % \begin{macrocode} \newrobustcmd\KAuxExport[4] {Package~knowledge:~undefined~so~far.} % \end{macrocode} % %\AP \csintro{\knowledge_set_now:nnnn}\cs{{}} takes the three parameters defining a knowledge and a list of \kl{knowledgenow directives}, checks that it was not existing before, and % then calls the \cs{\keys_set:nn}\{knowledgenow directives\} for defining it. % \begin{macrocode} \cs_new:Nn\knowledge_new_now:nnnn {\knowledge_sets_to:nnn{#1}{#2}{#3} \knowledge_at:N\ktuple_if_exist:NTF {\bool_if:NTF\knowledge_knowledgestyle_bool {\knowledge_at:N\ktuple_gclear:N} {\bool_if:NF\knowledge_knowledge_append_bool {\bool_if:NF\knowledge_knowledge_clear_bool \knowledge_werror:Nn\knowledge_warningstrict_bool {knowledge~'#3'~(namespace=#1,~scope=#2)~is~redefined.}}} } {\knowledge_at:N\ktuple_new:N} \keys_set:nn { knowledgenow~directives } { #4 } } % \end{macrocode} % \begin{macrocode} \cs_new:Nn\knowledge_set_now:nnnn {\knowledge_sets_to:nnn{#1}{#2}{#3} \knowledge_at:N\ktuple_if_exist:NTF {\bool_if:NTF\knowledge_knowledgestyle_bool {\knowledge_at:N\ktuple_gclear:N} {}} {\knowledge_at:N\ktuple_new:N} \keys_set:nn { knowledgenow~directives } { #4 } } % \end{macrocode} % \begin{macrocode} \cs_generate_variant:Nn\knowledge_new_now:nnnn{nnVn} \cs_generate_variant:Nn\knowledge_set_now:nnnn{nnVn} % \end{macrocode} % % %\AP We can now define the \cs{\knowledge} command itself. % It starts by writing the line number in the \kl{kaux file} % using \cs{\KAuxWriteLocation}, and then proceeds with \cs{\__knowledge_knowledge}. % \begin{macrocode} \NewDocumentCommand\knowledge{} {\KAuxWriteLocation\__knowledge_knowledge_init:w} % \end{macrocode} % The command \csintro{\__knowledge_knowledge} is the center of the \cs{\knowledge} % command. It parses its arguments (in particular separating the synonyms using the "xparse@@package"), and executes \cs{\knowledge_knowledge_process:nn} % \begin{macrocode} \NewDocumentCommand\__knowledge_knowledge_init:w{t! t+ m m}{ \kl_hide_begin: \group_begin: % \IfBooleanTF{#1}{% \bool_set_false:N\knowledge_knowledge_append_bool \bool_set_true:N\knowledge_knowledge_clear_bool }% \IfBooleanTF{#2}{% \bool_set_true:N\knowledge_knowledge_append_bool \bool_set_false:N\knowledge_knowledge_clear_bool }% % \tl_set_eq:NN\knowledge_namespace_tl \knowledge_default_namespace_tl % \tl_gset:Nn\knowledge_knowledge_immediate_synonym_directives_tl{synonym} % \bool_gset_false:N\knowledge_knowledge_is_synonym_bool % \tl_if_eq:nnTF{#4}{|} {\__knowledge_knowledge_cont_newsyntax:nw{#3}|} {\tl_if_eq:nnTF{#4}{[} {\__knowledge_knowledge_cont_classical:nw{#3}[} {\__knowledge_knowledge_cont_classical:nw{#3}{#4}}} } % \end{macrocode} % \begin{macrocode} \cs_new:Nn\__knowledge_knowledge_recallsynonym:n{ \bool_if:NF\knowledge_knowledge_is_synonym_bool {\tl_gset:Nn\knowledge_knowledge_synonymlink_tl{#1} \tl_gset_eq:NN\knowledge_knowledge_synonyminstance_tl \knowledge_knowledge_instance_tl} } % \end{macrocode} % \begin{macrocode} \cs_new:Nn\__knowledge_knowledge_end:{ \group_end: \kl_hide_end: } % \end{macrocode} % \begin{macrocode} \NewDocumentCommand\__knowledge_knowledge_cont_classical:nw{m >{\SplitList{|}}o m }{ \knowledge_knowledge_setparseat:NNn\l_tmpa_tl\l_tmpb_tl{#1} % \use:x{ \exp_not:N\knowledge_knowledge_process:nn {\exp_not:V\l_tmpa_tl} {\exp_not:V\knowledge_knowledgedefault_tl, \exp_not:n{#3}, \tl_if_empty:NTF\l_tmpb_tl{}{,scope={\exp_not:V\l_tmpb_tl}}}} % \exp_args:NV\__knowledge_knowledge_recallsynonym:n\l_tmpa_tl % \IfNoValueTF{#2}{}{ \cs_set:Nn\l_tmpa_cs:n {\exp_args:Nnx\knowledge_knowledge_process:nn{##1} {\exp_not:V\knowledge_knowledge_immediate_synonym_directives_tl}} \ProcessList{#2}\l_tmpa_cs:n } % \__knowledge_knowledge_end: } % \end{macrocode} % \begin{macrocode} \cs_new:Npn\knowledge_knowledge_newsyntax_firstline:n{} % \end{macrocode} % \begin{macrocode} \cs_new:Npn\knowledge_knowledge_newsyntax_nextlines:n{} % \end{macrocode} % \begin{macrocode} \cs_new:Npn\__knowledge_knowledge_cont_newsyntax:nw#1{ \cs_set:Nn\knowledge_knowledge_newsyntax_firstline:n {\knowledge{##1}{#1} \cs_set_eq:NN \knowledge_knowledge_newsyntax_exec_line:n \knowledge_knowledge_newsyntax_nextlines:n} \cs_set:Nn\knowledge_knowledge_newsyntax_nextlines:n {\exp_args:Nnx\knowledge{##1} {\exp_not:V\knowledge_knowledge_immediate_synonym_directives_tl}} \cs_set_eq:NN \knowledge_knowledge_newsyntax_exec_line:n \knowledge_knowledge_newsyntax_firstline:n \kl_newknowledge_parse:w } % \end{macrocode} % \begin{macrocode} \cs_new:Npn\kl_newknowledge_parse:w{ \peek_charcode_remove_ignore_spaces:NTF| {\kl_insert_klendline:w\knowledge_knowledge_newsyntax_exec_line:w} {\__knowledge_knowledge_end:} } % \end{macrocode} % \begin{macrocode} \cs_new:Npn\knowledge_knowledge_newsyntax_exec_line:w#1\kl_end_line:{ \knowledge_knowledge_newsyntax_exec_line:n{#1} \kl_newknowledge_parse:w } % \end{macrocode} % \begin{macrocode} \char_set_catcode_active:N\^^M \cs_gset:Npn\kl_insert_klendline:w{\group_begin:\catcode`\^^M=\active\kl_insert_klendline_:w} \cs_gset:Npn\kl_insert_klendline_:w#1^^M{\group_end:#1\kl_end_line:} \char_set_catcode_end_line:N\^^M % \end{macrocode} % \begin{macrocode} \cs_new:Nn\knowledge_knowledge_setparseat:NNn {\knowledge_knowledge_setparseat_:NNw#1#2#3@@\kl_end:} \cs_new:Npn\knowledge_knowledge_setparseat_:NNw#1#2#3@#4@#5\kl_end: {\tl_set:Nx#1{\tl_trim_spaces:n{#3}} \tl_set:Nx#2{\tl_trim_spaces:n{#4}}} % \end{macrocode} % %\AP The boolean \cs{\knowledge_knowledgestyle_bool} % is set to true in order \cs{\knowledge_knowledge_process:nn} % to know if it has been triggered by \cs{\knowledge} % or \cs{\knowledgestyle}. % \begin{macrocode} \NewDocumentCommand\knowledgestyle{ s m m } { \kl_hide_begin: \group_begin: \tl_set:Nn\knowledge_namespace_tl{style} % \bool_set_true:N\knowledge_knowledgestyle_bool \IfBooleanTF{#1} {\bool_set_true:N\knowledge_knowledgestyle_override_bool} {\bool_set_false:N\knowledge_knowledgestyle_override_bool} % \knowledge_knowledge_process:nn{#2}{#3} \group_end: \kl_hide_end: } % \end{macrocode} % % % % % %\AP The \cs{\knowledge_knowledge_process:nn} command is the internal % version of \cs{\knowledge}. It takes two parameters: % the key, and the comma separated list of directives. % It uses internally the following `variables': % \begin{asparadesc} % \itemAP[\csintro{\knowledge_knowledgestyle_bool}] is it a \cs{\knowledgestyle} macro? % \itemAP[\csintro{\knowledge_knowledgestyle_override_bool}] has it been required to override a previous "knowledge"? % \itemAP[\csintro{\knowledge_knowledge_now_bool}] set if in the preamble or by the directive "now". % \itemAP[\csintro{\knowledge_knowledge_alsonow_bool}] set by directive "also now". % \itemAP[\csintro{\knowledge_knowledge_is_synonym_bool}] set by the "synonym" directive. % \itemAP[\csintro{\knowledge_knowledge_autoref_bool}] set by the "autoref" directive % \itemAP[\csintro{\knowledge_knowledge_clear_bool}] % \itemAP[\csintro{\knowledge_knowledge_append_bool}] % \itemAP[\csintro{\knowledge_knowledge_export_bool}] % \itemAP[\csintro{\knowledge_knowledge_synonymlink_tl}] name of the "knowledge" to link to if a "synonym" directive is used. % \itemAP[\csintro{\knowledge_knowledge_synonyminstance_tl}] "instance" of the "knowledge" to link if a "synonym" directive is used. % \itemAP[\csintro{\knowledge_knowledge_immediate_synonym_directives_tl}] gathers the "directives" that have to be propagated to implicit synonyms. % \itemAP[\csintro{\knowledge_knowledge_key_tl}] the text for which the "knowledge" has to be defined. % \itemAP[\csintro{\knowledge_knowledge_namespace_tl}] the "namespace". % \itemAP[\csintro{\knowledge_knowledge_instance_tl}] % \itemAP[\csintro{\knowledge_knowledge_directives_tl}] gathers the "directives" that have to be executed for defining the "knowledge" (either to be executed now if \cs{\knowledge_knowledge_now_bool} is set, or to be propagated to the "kaux file" for execution during the next compilation phase) % \end{asparadesc} % \begin{macrocode} \bool_new:N\knowledge_knowledgestyle_bool \bool_new:N\knowledge_knowledgestyle_override_bool \bool_new:N\knowledge_knowledge_now_bool \bool_new:N\knowledge_knowledge_alsonow_bool \bool_new:N\knowledge_knowledge_is_synonym_bool \bool_new:N\knowledge_knowledge_autoref_bool \bool_new:N\knowledge_knowledge_clear_bool \bool_new:N\knowledge_knowledge_append_bool \tl_clear_new:N\knowledge_knowledge_synonymlink_tl \tl_clear_new:N\knowledge_knowledge_synonyminstance_tl \tl_clear_new:N\knowledge_knowledge_immediate_synonym_directives_tl \tl_clear_new:N\knowledge_knowledge_export_bool \tl_clear_new:N\knowledge_knowledge_key_tl \tl_clear_new:N\knowledge_knowledge_namespace_tl \tl_clear_new:N\knowledge_knowledge_instance_tl \tl_clear_new:N\knowledge_knowledge_directives_tl % \end{macrocode} % The macro \csintro{\knowledge_knowledge_process:nn} % is the heart of \cs{\knowledge} command. % \begin{macrocode} \cs_new:Nn\knowledge_knowledge_process:nn { \bool_set_false:N\knowledge_knowledge_export_bool \bool_set_false:N\knowledge_knowledge_autoref_bool \bool_set_false:N\knowledge_knowledge_now_bool \bool_set_false:N\knowledge_knowledge_alsonow_bool % \tl_set:Nn\knowledge_knowledge_key_tl{#1} % \tl_set_eq:NN\knowledge_knowledge_namespace_tl\knowledge_namespace_tl \scope_get_attractive_instance:N\knowledge_knowledge_instance_tl % \tl_set:Nn\knowledge_knowledge_directives_tl{} % \keys_set:nn { knowledge~directives } { #2 } % \mode_if_preamble:TF {\bool_set_true:N\knowledge_knowledge_now_bool} {} % \bool_if:NT\knowledge_knowledge_clear_bool {\tl_put_left:Nn\knowledge_knowledge_directives_tl{clear,}} \bool_if:NT\knowledge_knowledge_append_bool {\tl_put_left:Nn\knowledge_knowledge_directives_tl{force,}} % \bool_if:nTF{\knowledge_knowledge_now_bool} {\use:x{ \exp_not:N\knowledge_new_now:nnnn {\knowledge_knowledge_namespace_tl} {\knowledge_knowledge_instance_tl} {\exp_not:V\knowledge_knowledge_key_tl} {\exp_not:V\knowledge_knowledge_directives_tl}} }{} \bool_if:nTF{\knowledge_knowledge_alsonow_bool} {\use:x{ \exp_not:N\knowledge_set_now:nnnn {\knowledge_knowledge_namespace_tl} {\knowledge_knowledge_instance_tl} {\exp_not:V\knowledge_knowledge_key_tl} {\exp_not:V\knowledge_knowledge_directives_tl}} }{} \bool_if:NTF\knowledge_knowledge_now_bool {} { \KAuxWriteX*{ \exp_not:N\KAuxKnowledge {\knowledge_knowledge_namespace_tl} {\knowledge_knowledge_instance_tl} {\exp_not:V\knowledge_knowledge_key_tl} {\exp_not:V\knowledge_knowledge_directives_tl}} } \bool_if:NT\knowledge_knowledge_autoref_bool {\KAuxWriteX* {\exp_not:N\KAuxAutoref {\knowledge_knowledge_namespace_tl} {\knowledge_knowledge_instance_tl} {\exp_not:V\knowledge_knowledge_key_tl}} } % \bool_if:NT\knowledge_knowledge_export_bool {\KAuxWriteX*{ \exp_not:N\KAuxExport {\knowledge_knowledge_namespace_tl} {\knowledge_knowledge_instance_tl} {\exp_not:V\knowledge_knowledge_key_tl} {\exp_not:V\knowledge_knowledge_directives_tl}} } } % \end{macrocode} % \begin{macrocode} \cs_new:Nn\knowledge_delay_directive:n {\tl_if_empty:NTF\knowledge_knowledge_directives_tl {\tl_set:Nn\knowledge_knowledge_directives_tl{#1}} {\tl_put_right:Nn\knowledge_knowledge_directives_tl{,#1}}} \cs_generate_variant:Nn\knowledge_delay_directive:n{x} % \end{macrocode} % % % % \subsubsection{The \cs{\knowledgedirective} command} % % \begin{macrocode} \NewDocumentCommand\knowledgedirective{smom}{ \kl_hide_begin: \keys_if_exist:nnTF{ knowledge~directives }{ #2 } {\IfBooleanTF{#1} {\knowledgedirective:nnn{#2}{#3}{#4}} {\msg_error:nnn{ knowledge }{ knowledgedirective~redifinition }{#2}}} {\knowledgedirective:nnn{#2}{#3}{#4}} \kl_hide_end: } \cs_new:Nn\knowledgedirective:nnn{ \cs_set:cn {knowledgedirective_#1:n} {\keys_set:nn{ knowledge~directives }{#3}} \keys_define:nn{ knowledge~directives } {#1 .code:n = {\use:c{knowledgedirective_#1:n}{##1}}} \IfNoValueF{#2} {\keys_define:nn{ knowledge~directives }{#2 .default:n = {#2}}} } % \end{macrocode} % % \subsubsection{The \cs{\knowledgedefault} command} % % It uses internally the variable \csintro{\knowledge_knowledgedefault_tl}. % \begin{macrocode} \tl_new:N\knowledge_knowledgedefault_tl \NewDocumentCommand\knowledgedefault{sm}{ \kl_hide_begin: \IfBooleanTF{#1} {\tl_put_right:Nn\knowledge_knowledgedefault_tl{,#2}} {\tl_set:Nn\knowledge_knowledgedefault_tl{#2}} \kl_hide_end: } % \end{macrocode} % % % \subsubsection{Main \cs{\kl} code} % % % The \cs{\kl}, and its internal version \cs{\klTKS} are the central ones in the package. Indeed, all commands such as \cs{\intro}, \cs{\phantomintro}, \cs{\reintro} or the \kl{"...@...@..."} notation eventually end to a call to these functions. %\AP Essentially, \cs{\kl} parses its parameters, and then call its internal version \cs{\knowledge_klTKS:nnn} % with proper parameters: Text, Knowledge, Scope (the scope can be empty): % % \AP The macro \csintro{\knowledge_kl:w} is the part of \cs{\kl}-like commands that parses the arguments, and then calls \cs{\knowledge_klTKS:nnn} with proper arguments. % \begin{macrocode} \NewDocumentCommand\knowledge_kl:w{d() o d() m}{ \IfNoValueTF{#1} {\IfNoValueTF{#3} {\IfNoValueTF{#2} {\knowledge_klTKS:nnn{#4}{#4}{}} {\knowledge_klTKS:nnn{#4}{#2}{}}} {\IfNoValueTF{#2} {\knowledge_klTKS:nnn{#4}{#4}{#3}} {\knowledge_klTKS:nnn{#4}{#2}{#3}}}} {\IfNoValueTF{#2} {\knowledge_klTKS:nnn{#4}{#4}{#1}} {\knowledge_klTKS:nnn{#4}{#2}{#1}}} } % \end{macrocode} % % \AP The following macro, \csintro{\knowledge_klTKS:nnn} is an internal version of \cs{\kl}-like commands. it takes 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_new:Nn\knowledge_kl_find:{ \knowledge_kl_find_recursion_exceeded:TF \knowledge_kl_error_recursion: {\tl_if_empty:NTF\knowledge_kl_linkscope_tl \knowledge_kl_find_withoutscope: \knowledge_kl_find_withscopetag:} } % \end{macrocode} % \begin{macrocode} \cs_set:Npn\knowledge_kl_find_recursion_exceeded:TF{ \int_decr:N\knowledge_kl_recursion_int \int_compare:nNnTF\knowledge_kl_recursion_int=0 } % \end{macrocode} % In case a scope label is provided, then the label is tested for being known; if it is the case, it is followed, and the knowledge is looked for and executed. % \begin{macrocode} \cs_new:Nn\knowledge_kl_find_withinstance:{ \knowledge_knowledge_if_exist:VVVTF \knowledge_kl_namespace_tl \knowledge_kl_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: } } % \end{macrocode} % \csintro{\knowledge_kl_find_withscopetag:} searches for the knowledge, with a given scopetag % \begin{macrocode} \cs_new:Nn\knowledge_kl_find_withscopetag:{ \exp_args:NV\knowledge_scopetag_warn_if_unknown:n\knowledge_kl_linkscope_tl \tl_clear:N\l_tmpa_tl \exp_args:Nc\seq_map_function:NN {\knowledge_scopetag_tl[\knowledge_kl_linkscope_tl]_seq} \knowledge_kl_find_scopetag_tmpa:n \tl_if_empty:NTF\l_tmpa_tl {\knowledge_kl_error_unknown_in_scope_firsttime:} {\knowledge_kl_exec:VVV \knowledge_kl_namespace_tl \l_tmpa_tl \knowledge_kl_key_tl} } % \end{macrocode} % \csintro{\knowledge_kl_find_scopetag:Nn} takes a token list for the result, and % a scopetag as argument. If the tl is empty, and a knowledge using scopetag as instance is found, % then the scopetag is transfered to the token list. % \begin{macrocode} \cs_new:Nn\knowledge_kl_find_scopetag:Nn{ \tl_if_empty:NTF#1 {\knowledge_knowledge_if_exist:VnVTF \knowledge_kl_namespace_tl {#2}%instance \knowledge_kl_key_tl {\tl_set:Nn#1{#2}} {}} {} } \cs_new:Npn\knowledge_kl_find_scopetag_tmpa:n{ \knowledge_kl_find_scopetag:Nn\l_tmpa_tl } % \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} % \cs{\knowledge_kl_find_in_scope:nNTF} introduces the namespace as % first argument in a call to \cs{\knowledge_kl_find_in_scope:nnNTF} % \begin{macrocode} \cs_new:Npn\knowledge_kl_find_in_scope:nNTF{ \exp_args:NV\knowledge_kl_find_in_scope:nnNTF \knowledge_kl_namespace_tl } % \end{macrocode} % 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: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} % \cs{\knowledge_kl_find_in_scope_test:n} tests the existence of a "knowledge" % in the "scopetag" given as argument. For this it searches through all the instances associated to the % scopetag, and sets \cs{\g_tmpa_bool} when found. % One has to check that the visible instance is not the mark. % \begin{macrocode} \cs_new:Nn\knowledge_kl_find_in_scope_test:n{ \tl_if_eq:nnTF{#1}{|}{}{ \knowledge_kl_find_in_scope_test_:n{#1} \seq_if_exist:cTF{\knowledge_scopetag_tl[#1]_seq} {\exp_args:Nc\seq_map_function:NN {\knowledge_scopetag_tl[#1]_seq} \knowledge_kl_find_in_scope_test_:n }{}} } % \end{macrocode} % \begin{macrocode} \cs_new:Nn\knowledge_kl_find_in_scope_test_:n{ \exp_args:Nc\ktuple_if_exist:NTF {\knowledge_id:nnV{\l_tmpa_tl}{#1}\l_tmpb_tl} {\bool_gset_true:N\g_tmpa_bool \tl_gset:Nn\g_tmpa_tl{#1} \seq_map_break:}{} } % \end{macrocode} % \begin{macrocode} \cs_generate_variant:Nn\knowledge_kl_find_in_scope:nnNTF{nVNTF} \cs_generate_variant:Nn\knowledge_kl_find_in_scope:nNTF{VNTF} % \end{macrocode} % \AP % When the \kl{knowledge} is found, it is eventually executed using % \begin{code} % \csintro{\knowledge_kl_exec:nnn}\{namespace\}\{instance\}\{key\} % \end{code} The argument is a control sequence pointing to the \kl{knowledge}. It is first executed % in order to set the variables. % Then, the token of the \kl{knowledge} is stored in the variable \cs{\knowledge_kl_resourcetoken_tl}. % Then, if a \kl{style} is given, it is executed. The next step is to update the \kl{knowledge} % which means essentially updating its internal counters of use. % \begin{macrocode} \cs_new:Nn\knowledge_kl_exec:nnn{ \tl_set:Nx\knowledge_kl_resourcearguments_tl {{#1}{#2}{\exp_not:n{#3}}} \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,VVV} % \end{macrocode} % \begin{macrocode} \cs_new:Nn\knowledge_kl_use_styles:n {\clist_map_function:nN{#1}\knowledge_kl_use_style:n} \cs_generate_variant:Nn\knowledge_kl_use_styles:n {x} % \end{macrocode} % \begin{macrocode} \cs_new:Nn\knowledge_kl_use_style:n{ \tl_if_empty:nTF{#1}{} {\knowledge_kl_find_in_scope:nnNTF {style} {#1} \l_tmpa_tl {\use:c{\knowledge_id:nVn{style}\l_tmpa_tl{#1}}} {\knowledge_error:n{Unknown~style~`#1'}}} } % \end{macrocode} % % \begin{macrocode} \cs_new:Nn\knowledge_usestyle:nn{ \group_begin: \tl_set:Nn\knowledge_kl_forcedtext_tl{#2} \knowledge_kl_use_styles:x{#1} \knowledge_kl_compute_code: \group_end: \knowledge_display_code_tl } \NewDocumentCommand\knowledgeusestyle{mm}{\knowledge_usestyle:nn{#1}{#2}} % \end{macrocode} % % % % % % % \subsubsection{Error handling} % % % % \begin{macrocode} \NewKAuxCommand\KAuxErrorKnowledgeRecursive{mmmm} {Package~'knowledge:~A~knowledge~has~recursive~definition.~ {namespace}{scope}{undefined~knowledge}{base~knowledge}} {} \cs_new:Nn\knowledge_kl_error_recursion: { \msg_error:nnxxx{ knowledge }{ knowledge~recursion } {\exp_not:V\knowledge_kl_base_key_tl} {\exp_not:V\knowledge_kl_namespace_tl} {\exp_not:V\knowledge_kl_key_tl} \knowledge_kl_error_display:n{ recursive~knowledge } } % \end{macrocode} % \begin{macrocode} \NewKAuxCommand\KAuxErrorKnowledgeUnknown{mmmmm} {Package~'knowledge:~A~knowledge~is~not~defined.~ {namespace}{scope/empty}{undefined~knowledge}{base~knowledge}{command}} {} \NewKAuxCommand\KAuxErrorLabelUnknown{m} {Package~'knowledge:~A~label~is~not~defined.~ {label}} {} % \end{macrocode} % \begin{macrocode} \DeclareKAuxPhaseCommand\KAuxErrorKnowledgeUnknown{diagnose-unknown-suggest} { \knowledge_diagnose_line: \tl_set_eq:Nc\l_tmpa_tl{knowledge_kl_\cs_to_str:N#5_suggestion_tl} \tl_if_eq:nnTF{#1}{default} {} {\tl_if_empty:NTF\l_tmpa_tl{}{\tl_put_right:Nn\l_tmpa_tl{,} \tl_put_right:Nn\l_tmpa_tl{namespace={#1}}}} \bool_if:NTF\knowledge_configuration_barsuggestion_bool{ %\knowledge_diagnose:x{\char_escape_tl knowledge{\exp_not:V\l_tmpa_tl}} \tl_set:Nn\l_tmpa_tl{~~~|~~#3} \tl_if_empty:nTF{#2}{} {\tl_put_right:Nn\l_tmpa_tl{@#2}} \knowledge_diagnose:x{\exp_not:V\l_tmpa_tl} }{ \tl_if_empty:nTF{#2}{} {\tl_if_empty:NTF\l_tmpa_tl{}{\tl_put_right:Nn\l_tmpa_tl{,}} \tl_put_right:Nn\l_tmpa_tl{scope={#2}}} \knowledge_diagnose:x {\char_escape_tl knowledge\exp_not:n{{#3}}{\exp_not:V\l_tmpa_tl}} } } % \end{macrocode} % The code executed when an undefined knowledge is met. It % \begin{macrocode} \cs_new:Nn\knowledge_kl_error_unknown_firsttime: {\bool_if:cTF{\knowledge_variant_var:n{unknownwarning_bool}} {\IfKnowledgePaperModeF{ \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}{ \tl_if_exist:cTF{knowledge_kl_\cs_to_str:N#1_command_tl} {\knowledge_error:n{Variant~#1~already~exists~(in~\knowledgenewvariant).}} {\exp_args:Nc\tl_new:Nn {knowledge_kl_\cs_to_str:N#1_command_tl} {#1} % % \NewDocumentCommand#1{s} {\knowledge_kl_modifiers_add:N#1 \IfBooleanF{##1}{\knowledge_kl:w}} % \tl_new_eq:cN {knowledge_kl_\cs_to_str:N#1_namespace_tl} \knowledge_default_namespace_tl \tl_new:cx{knowledge_kl_\cs_to_str:N#1_suggestion_tl}{} \bool_new_true:c{knowledge_kl_\cs_to_str:N#1_unknownwarning_bool} \bool_new_true:c{knowledge_kl_\cs_to_str:N#1_unknowndiagnose_bool} \tl_new:cn{knowledge_kl_\cs_to_str:N#1_default_style_tl}{} \tl_new:cn{knowledge_kl_\cs_to_str:N#1_unknown_style_tl}{} \tl_new:cn{knowledge_kl_\cs_to_str:N#1_unknown_style_cont_tl}{} \tl_new:cx{knowledge_kl_\cs_to_str:N#1_autoknowledge_tl}{} \tl_new:cx{knowledge_kl_\cs_to_str:N#1_styledirectives_tl}{} % \bool_if:NT\knowledge_hyperref_active_bool {\exp_args:Nx\pdfstringdefDisableCommands {\exp_not:N\def\exp_not:N#1 {\exp_not:N\knowledge_variant_arg_absorber:Nw \exp_not:c{\cs_to_str:N#1_PDFstring}}}} \exp_args:Nc\newcommand{\cs_to_str:N#1_PDFstring}[3]{##1} % \tl_new:cx{knowledge_kl_\tl_to_str:n{#1*} _init_tl} { \exp_not:n{\tl_set_eq:NN\knowledge_kl_command_tl} \exp_not:c{knowledge_kl_\cs_to_str:N#1_command_tl} \exp_not:n{\tl_set_eq:NN\knowledge_kl_namespace_tl} \exp_not:c{knowledge_kl_\cs_to_str:N#1_namespace_tl} \exp_not:n{\tl_set_eq:NN\knowledge_kl_default_style_tl} \exp_not:c{knowledge_kl_\cs_to_str:N#1_default_style_tl} \exp_not:n{\tl_set_eq:NN\knowledge_kl_unknown_style_tl} \exp_not:c{knowledge_kl_\cs_to_str:N#1_unknown_style_tl} \exp_not:n{\tl_set_eq:NN\knowledge_kl_unknown_style_cont_tl} \exp_not:c{knowledge_kl_\cs_to_str:N#1_unknown_style_cont_tl} \exp_not:n{\tl_set_eq:NN\knowledge_kl_styledirectives_tl} \exp_not:c{knowledge_kl_\cs_to_str:N#1 _styledirectives_tl} \exp_not:c{knowledge_kl_\cs_to_str:N#1 _autoknowledge_tl} } % %\bool_if:NT\knowledge_hyperref_active_bool % {\pdfstringdefDisableCommands{\let#1\knowledge_fake_kl:n}} % } \knowledgesetvariant#1{#2} } \DeclareExpandableDocumentCommand\knowledge_variant_arg_absorber:Nw {m d() o d() m} {\IfNoValueTF{#2} {#1{#5}{#2}{#3}} {#1{#5}{#2}{#1}}} \tl_new:N\knowledge_variant_command_tl \tl_new:N\knowledge_variant_key_tl \NewDocumentCommand\knowledgesetvariant{mm}{ \tl_if_exist:cTF{knowledge_kl_\cs_to_str:N#1_command_tl} { \tl_set:Nn\knowledge_variant_command_tl{#1} \tl_set:Nx\knowledge_variant_key_tl{\cs_to_str:N#1} % \keys_set:nn{ knowledge~configure~variant }{#2} } {\knowledge_error:n{Variant~#1~does~not~exist~(in~\knowledgesetvariant).}} } % \end{macrocode} % \begin{macrocode} \keys_define:nn{ knowledge~configure~variant }{ namespace .code:n = {\tl_set:cn{knowledge_kl_\knowledge_variant_key_tl _namespace_tl}{#1}}, % unknown~warning .choices:nn = {true,false} {\bool_set_text:cn{knowledge_kl_\knowledge_variant_key_tl _unknownwarning_bool}{#1}}, % unknown~diagnose .choices:nn = {true,false} {\bool_set_text:cn{knowledge_kl_\knowledge_variant_key_tl _unknowndiagnose_bool}{#1}}, % default~style .code:n = {\tl_set:cn{knowledge_kl_\knowledge_variant_key_tl _default_style_tl}{#1}}, unknown~style .code:n = {\tl_set:cn{knowledge_kl_\knowledge_variant_key_tl _unknown_style_tl}{#1}}, unknown~style~cont .code:n = {\tl_set:cn{knowledge_kl_\knowledge_variant_key_tl _unknown_style_cont_tl}{#1}}, % auto~knowledge .code:n = { \tl_set:cx{knowledge_kl_\knowledge_variant_key_tl _autoknowledge_tl} {\exp_not:N\exp_args:NV \exp_not:N\knowledge {\exp_not:N\knowledge_kl_key_tl} {namespace=\exp_not:N\knowledge_kl_namespace_tl,\exp_not:n{#1}}}}, % style~directive .code:n = { \tl_clear:c{knowledge_kl_\knowledge_variant_key_tl _styledirectives_tl} \clist_map_inline:nn{#1} {\use:x{\NewKnowledgeParamTl* [\exp_not:c{knowledge_kl_##1_tl}]} {##1} \tl_put_right:cx{knowledge_kl_\knowledge_variant_key_tl _styledirectives_tl} {\exp_not:c{knowledge_kl_##1_tl}}} }, % suggestion .code:n = {\tl_set:cn{knowledge_kl_\knowledge_variant_key_tl _suggestion_tl}{#1}}, % PDF~string .code:n = {\exp_args:Nc\renewcommand{\knowledge_variant_key_tl _PDFstring}[3]{#1}} } % \end{macrocode} % % % \subsubsection{Variants of the \cs{\kl} macro} % % % % When defining a new use of \texttt{knowledge}, many macros have to be taken into account. % Some have to be defined explicitly. Some other have default behaviours. % \begin{asparaitem} % \itemAP \csintro{\knowledge_kl_display_preprocess_tl} is the code to be used first before displaying. It does nothing for \cs{\kl}, but is set to \cs{\knowledge_kl_target_preprocess_tl} for \cs{\intro}, which performs the \cs{\label} command fir the introduction. % \itemAP \csintro{\knowledge_kl_display_process_tl} is the code to be executed for displaying the \kl{knowledge}. This is not defined by default. % \itemAP \csintro{\knowledge_kl_error_unknown:} The fallback code to execute when the \kl{knowledge} is unknown. % By default, it displays a warning and put the name in orange. % \itemAP \csintro{\knowledge_kl_update:N} is a code to be executed to update the knowledge. By default, it increments the ktuple counter `\cs{countuse_int}'. % \itemAP \csintro{\knowledge_kl_namespace_tl} is the \kl{namespace} in which the \kl{knowledge} is to be searched. Not defined by default. % \itemAP \csintro{\knowledge_kl_linkscope_tl} is a label that points to an instance of a \kl{scope}. It can be empty, and in this case, this means that the search proceeds in the \kl{stack of visible scope instances}. By default it is empty. % \itemAP \csintro{\knowledge_kl_max_recursion_int} is the maximum number of recursion allowed when searching for a \kl{knowledge}. It is by default 40. % \end{asparaitem} % % The codes can uses internally the following variables, that are accessible for the user when defining new \cs\kl-like commands: % \begin{asparaitem} % \itemAP \csintro{\knowledge_kl_command_tl} the command that has triggered the search % \itemAP \csintro{\knowledge_kl_base_key_tl} contains the name of the knowledge for which the search has started, % \itemAP \csintro{\knowledge_kl_text_tl} contains the text to be displayed, % \itemAP \csintro{\knowledge_kl_key_tl} contains the name of the knowledge searched at a particular moment, % \itemAP \csintro{\knowledge_kl_recursion_int} counts the number of indirection in the current, starting from \cs{\knowledge_kl_max_recursion_int}, and going down, % \itemAP \csintro{\knowledge_kl_link_tl} contains the link to be followed. % \itemAP \cs{\knowledge_kl_resourcetoken_tl} contains a single token, which is the location of the knowledge. % \end{asparaitem} % % \begin{macrocode} \let\nointro\phantomintro % \end{macrocode} % % When the \cs{\intro} is used more than once, new labels are introduced (appending b,c,d\dots), % in order to point to these targets easily. % \begin{macrocode} \tl_new:Nn\knowledge_kl_target_preprocess_tl {\tl_if_exist_ne:NTF\knowledge_kl_resourcetoken_tl {\expandafter\ktuple_countintro_get_int:NN \knowledge_kl_resourcetoken_tl\l_tmpa_int \tl_set:Nx\l_tmpa_tl {\int_compare:nNnTF\l_tmpa_int=1{}{\int_to_alph:n\l_tmpa_int}}} {\tl_set:Nn\l_tmpa_tl{}} \tl_if_exist_ne:NTF\knowledge_kl_autoref_tl {\exp_args:Nx\knowledge_latex_label:n {\expandafter\noexpand\knowledge_kl_autoref_tl\l_tmpa_tl}} {}} % \end{macrocode} % \begin{macrocode} \tl_new:N\knowledge_kl_style_tl \tl_new:N\knowledge_kl_namespace_tl \tl_new:N\knowledge_kl_command_tl \cs_new:Nn\knowledge_kl_target_update:N {\ktuple_countintro_gincr:N#1} \cs_gset:Nn\knowledge_kl_default_update:N {\ktuple_countuse_gincr:N#1} % \end{macrocode} % % % \subsubsection{Code for mathematical variables (unstable)} % % % % \subsubsection{Display parameters} % % %\begin{compactdesc} %\item[\csintro{\kl_emphasize_bool}] %\item[\csintro{\kl_boldface_bool}] %\item[\csintro{\kl_underline_bool}] %\item[\csintro{\kl_typewriter_bool}] %\item[\csintro{\kl_fbox_bool}] %\item[\csintro{\kl_ensuremath_bool}] %\item[\csintro{\kl_ensuretext_bool}] %\item[\csintro{\kl_italic_bool}] %\item[\csintro{\kl_lowercase_bool}] %\item[\csintro{\kl_uppercase_bool}] %\item[\csintro{\knowledge_kl_forcedtext_tl}] %\item[\csreintro{\knowledge_kl_link_tl}] %\item[\csreintro{\knowledge_kl_linkscope_tl}] %\item[\csreintro{\knowledge_kl_display_process_tl}] %\item[\csintro{\knowledge_kl_default_invisible_display_process_tl}] %\end{compactdesc} % % \begin{macrocode} \NewKnowledgeParamBool*{fbox}\kl_fbox_bool \NewKnowledgeParamBool*{ensuremath}\kl_ensuremath_bool \NewKnowledgeParamBool*{ensuretext}\kl_ensuretext_bool \NewKnowledgeParamBool*{mathord}\kl_mathord_bool \NewKnowledgeParamBool*{mathop}\kl_mathop_bool \NewKnowledgeParamBool*{mathbin}\kl_mathbin_bool \NewKnowledgeParamBool*{mathrel}\kl_mathrel_bool \NewKnowledgeParamBool*{mathopen}\kl_mathopen_bool \NewKnowledgeParamBool*{mathclose}\kl_mathclose_bool \NewKnowledgeParamBool*{mathpunct}\kl_mathpunct_bool \NewKnowledgeParamBool*{emphasize}\kl_emphasize_bool \NewKnowledgeParamBool*{underline}\kl_underline_bool \NewKnowledgeParamBool*{typewriter}\kl_typewriter_bool \NewKnowledgeParamBool*{autoref~target}\kl_autoreftarget_bool \NewKnowledgeParamBool*{autoref~link}\kl_autoreflink_bool \NewKnowledgeParamBool*{invisible}\kl_invisible_bool \NewKnowledgeParamBool*{italic}\kl_italic_bool \NewKnowledgeParamBool*{smallcaps}\kl_smallcaps_bool \NewKnowledgeParamBool*{md}\kl_md_bool \NewKnowledgeParamBool*{up}\kl_up_bool \NewKnowledgeParamBool*{boldface}\kl_boldface_bool \NewKnowledgeParamBool*{detokenize}\kl_detokenize_bool \NewKnowledgeParamBool*{remove~space}\kl_removespace_bool \NewKnowledgeParamBool*{protect~link}\kl_protect_link_bool \NewKnowledgeParamBool*{lowercase}\kl_lowercase_bool \NewKnowledgeParamBool*{uppercase}\kl_uppercase_bool % \end{macrocode} % % \begin{macrocode} \NewKnowledgeParamTl*{link} \NewKnowledgeParamTl*[\knowledge_kl_linkscope_tl]{link~scope} \NewKnowledgeParamTl*[\knowledge_kl_instance_tl]{link~instance} \NewKnowledgeParamTl*[\knowledge_kl_forcedtext_tl]{text} \NewKnowledgeParamTl*{wrap} % \end{macrocode} % % % \begin{macrocode} \NewKnowledgeParamBool*{UnKnoWn~KNowLedGE}\kl_unknown_knowledge_bool \bool_set_false:N\kl_unknown_knowledge_bool \ktuple_new_int_index:n{countuse} \ktuple_countuse_expands_to:n{} \ktuple_new_int_index:n{countintro} \ktuple_countintro_expands_to:n{} % \end{macrocode} % % The "directive" "now" % \begin{macrocode} \keys_define:nn{ knowledge~directives }{ now .code:n = { \bool_set_true:N\knowledge_knowledge_now_bool }, also~now .code:n = { \bool_set_true:N\knowledge_knowledge_alsonow_bool } } % \end{macrocode} % % The special directive \kl{autorefhere} is used for variables, where for which it is not necessary % to explicitely use a \cs{\knowledge} command. % \begin{macrocode} \int_new:N\knowledge_autoref_count \keys_define:nn{ knowledge~directives }{ autoref .code:n = { \int_gincr:N\knowledge_autoref_count \knowledge_delay_directive:x {autoref = {autoref-\int_use:N\knowledge_autoref_count}} \bool_set_true:N\knowledge_knowledge_autoref_bool}, autorefhere .code:n = { \int_gincr:N\knowledge_autoref_count \exp_args:Nx\label{autoref-\int_use:N\knowledge_autoref_count} \knowledge_delay_directive:x {autoref = {autoref-\int_use:N\knowledge_autoref_count}}}} \ktuple_new_tl_index:n{autoref} \use:c{ktuple_autoref_expands_to:n} {\tl_set:Nn\knowledge_kl_autoref_tl{#1} } \keys_define:nn { knowledgenow~directives } { autoref .code:n = { \knowledge_at:c{ktuple_autoref_gset:Nn}{#1} } } % \end{macrocode} % \begin{macrocode} \int_new:N\kl_countuse_int \int_new:N\kl_countintro_int \NewKAuxCommand\KAuxAutoref{mmm} {Package~knowledge:~Declares~an~autoref~knowledge.~ Arguments~{namespace}{instance}{knowledge}.} \NewKAuxCommand\KAuxAutorefTarget{mmm} {Package~knowledge:~Declares~the~use~of~a~target~to~an~autoref~knowledge.~ Arguments~{namespace}{instance}{knowledge}.} \DeclareKAuxPhaseCommand\KAuxAutoref{init}{} \int_new:N\kl_digest_autorefused_int \int_new:N\kl_digest_autorefnointro_int \int_new:N\kl_digest_autoreftwiceintro_int \int_new:N\kl_digest_autorefunused_int \int_new:N\kl_digest_unknownknowledge_int \int_new:N\kl_digest_unknownlabel_int \DeclareKAuxPhaseCommand\KAuxErrorKnowledgeUnknown{diagnose-digest} {\int_gincr:N\kl_digest_unknownknowledge_int} %\DeclareKAuxPhaseCommand\KAuxErrorLabelUnknown{diagnose-digest} % {\int_gincr:N\kl_digest_unknownlabel_int} \DeclareKAuxPhaseCommand\KAuxAutoref{diagnose-digest} {\group_begin: \knowledge_sets_to:nnn{#1}{#2}{#3} \knowledge_at:N\ktuple_countuse_get_int:NN\kl_countuse_int \knowledge_at:N\ktuple_countintro_get_int:NN\kl_countintro_int \int_compare:nNnT\kl_countintro_int=1 { \int_compare:nNnTF\kl_countuse_int=1 {\int_gincr:N\kl_digest_autorefunused_int} {\int_gincr:N\kl_digest_autorefused_int} } \int_compare:nNnT\kl_countintro_int=0 {\int_compare:nNnF\kl_countuse_int=0 %{\int_gincr:N\kl_digest_autorefunused_int} {\int_gincr:N\kl_digest_autorefnointro_int}} \int_compare:nNnT\kl_countintro_int>1 {\int_gincr:N\kl_digest_autoreftwiceintro_int} \group_end:} \DeclareKAuxPhaseCommand\KAuxAutoref{autoref-not-introduced} {\group_begin: \knowledge_sets_to:nnn{#1}{#2}{#3} \knowledge_at:N\ktuple_countuse_get_int:NN\kl_countuse_int \knowledge_at:N\ktuple_countintro_get_int:NN\kl_countintro_int \int_compare:nNnT\kl_countuse_int>0 {\int_compare:nNnT\kl_countintro_int=0 {\knowledge_diagnose_line: \knowledge_diagnose:x{\char_escape_tl nointro{\exp_not:n{#1}}{\exp_not:n{#2}}{\exp_not:n{#3}}}}} \group_end:} \DeclareKAuxPhaseCommand\KAuxAutoref{autoref-introduced-not-used} {\group_begin: \knowledge_sets_to:nnn{#1}{#2}{#3} \knowledge_at:N\ktuple_countuse_get_int:NN\kl_countuse_int \knowledge_at:N\ktuple_countintro_get_int:NN\kl_countintro_int \int_compare:nNnT\kl_countuse_int=1 {\int_compare:nNnT\kl_countintro_int=1 {\knowledge_diagnose_line: \knowledge_diagnose:x{\kaux_current_location:\space \exp_not:n{{#3}{#1}{#2}}}}} \group_end:} \DeclareKAuxPhaseCommand\KAuxAutorefTarget{autoref-introduced-twice} {\group_begin: \knowledge_sets_to:nnn{#1}{#2}{#3} \knowledge_at:N\ktuple_countuse_get_int:NN\kl_countuse_int \knowledge_at:N\ktuple_countintro_get_int:NN\kl_countintro_int \int_compare:nNnT\kl_countintro_int>1 {\knowledge_diagnose_line: \knowledge_diagnose:x{\kaux_current_location:\space \exp_not:n{{#3}{#1}{#2}}}} \group_end:} % \end{macrocode} % \begin{macrocode} \NewKAuxCommand\KAuxUseKnowledge{mmm} {Package~knowledge:~Identifies~the~use~of~some~knowledge.~ Arguments~{namespace}{instance}{knowledge}.} % \end{macrocode} % % %\subsubsection{Display code} % % % % % \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\LaTeXlabel{\exp_not:V\knowledge_kl_autoref_tl\l_tmpa_tl}} \expandafter\ktuple_countintro_gincr:N \knowledge_kl_resourcetoken_tl \KAuxWriteX {\exp_not:N\KAuxAutorefTarget \exp_not:o\knowledge_kl_resourcearguments_tl}} } \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\use:n\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= {autoref link}, unknown style= kl unknown, unknown style cont= kl unknown cont, style directive= style } \knowledgenewvariant\intro{ namespace= default, default style= {autoref target}, unknown style= intro unknown, unknown style cont= intro unknown cont, style directive= intro style } \knowledgenewvariant\phantomintro{ namespace=default, default style={invisible,autoref target}, unknown style=invisible, unknown style cont=invisible } \knowledgenewvariant\reintro{ namespace=default, % default style=intro, unknown style=intro unknown, unknown style cont=intro unknown cont, style directive=intro style } \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). % %<*tail> % \begin{macrocode} \ExplSyntaxOn \exp_args:NNV\ExplSyntaxOff\knowledgeconfigure\knowledge_configuration_pending_tl % \end{macrocode} % \begin{macrocode} %\ScopeActivate % \end{macrocode} % % % \Finale %\endinput