\begin{smodule}{Aux Macros} \begin{dangerbox} Keeping the implementation properly up-to-date is pretty much incompatible with the kinds of workflows systemically enforced in academia. Any of the following may be out of date. \end{dangerbox} \STEXexport{ \stex_sms_allow_escape:N \stexmacro \protected\def\stexmacro#1{ \stex_execute_in_module:x{\tl_set:cn{l_stex_stexmacro_\tl_to_str:n{#1}_path}{\l_stex_current_module_str?\tl_to_str:n{#1}}} \exp_args:NNx\symdecl*{\tl_to_str:n{#1}} \exp_args:Nx\notation{\tl_to_str:n{#1}}{\comp{\texttt{\textbackslash\detokenize{#1}}}} } \protected\def\stexvarmacro#1{ \tl_set:cx{l_stex_stexvarmacro_\tl_to_str:n{#1}_var}{\tl_to_str:n{#1}} \exp_args:Nnx\use:nn{\vardef}{ {\tl_to_str:n{varmacro_#1}}[name={\tl_to_str:n{#1}}]{ \noexpand\comp{\hbox{\noexpand\texttt{\noexpand\textbackslash\noexpand\detokenize{#1}}}} } } } \stex_sms_allow_escape:N \stexenv \protected\def\stexenv#1{ \stex_execute_in_module:x{\tl_set:cn{l_stex_stexenv_\tl_to_str:n{#1}_path}{\l_stex_current_module_str?\tl_to_str:n{#1}}} \exp_args:NNx\symdecl*{\tl_to_str:n{#1}} \exp_args:Nx\notation{\tl_to_str:n{#1}}{\noexpand\texttt{\noexpand\detokenize{#1}}} } \cs_set_nopar:Nn \_stexdoc_do_cs:nn { \tl_if_exist:cTF{l_stex_stexvarmacro_\tl_to_str:n{#1}_var}{ \exp_args:Nx \varref{\use:c{l_stex_stexvarmacro_\tl_to_str:n{#1}_var}}{#2} }{ \tl_if_exist:cTF{l_stex_stexmacro_\tl_to_str:n{#1}_path}{ \exp_args:Nx \symref{\use:c{l_stex_stexmacro_\tl_to_str:n{#1}_path}}{#2} }{#2} } } \RenewDocumentCommand\cmd { O{} m } { \_stexdoc_do_cs:nn{#2}{\__codedoc_cmd:no {#1} { \token_to_str:N #2 }} } \RenewDocumentCommand \cs { O{} m } { \_stexdoc_do_cs:nn{#2}{\__codedoc_cmd:no {#1} { \c_backslash_str #2 }} } \RenewDocumentCommand \tn { O{} m } { \_stexdoc_do_cs:nn{#2}{ \@@_cmd:no { module = TeX , replace = false , #1 } { \c_backslash_str #2 } }} \protected\def\env#1{ \tl_if_exist:cTF{l_stex_stexenv_\tl_to_str:n{#1}_path}{ \exp_args:Nx \symref{\use:c{l_stex_stexenv_\tl_to_str:n{#1}_path}}{\texttt{\tl_to_str:n{#1}}} }{\texttt{\tl_to_str:n{#1}}} } \cs_set_protected:Nn \_stexdoc_dcs: { \peek_charcode:NTF [ { \_stexdoc_dcs:w }{ \exp_args:NNe \use:nn \_stexdoc_dcs:w {[\seq_item:Nn \_stexdoc_sfunction_seq 1]} } } \cs_set_protected:Npn \_stexdoc_dcs:w [#1] { \exp_args:Ne \definiendum{\tl_to_str:n{#1}}{\exp_args:Nne \__codedoc_cmd:nn {} { \c_backslash_str \tl_to_str:n{ #1 } }} \xspace } \ProvideDocumentEnvironment {sfunction}{m O{} +v}{ \seq_set_split:Nnn \_stexdoc_sfunction_seq , {#1} \seq_map_inline:Nn \_stexdoc_sfunction_seq { \stex_pseudogroup_with:nn{\stex_smsmode_do:}{\def\stex_smsmode_do:{}\stexmacro{##1}} } \cs_set_eq:NN \dcs \_stexdoc_dcs: \ifstexhtml \def\box_move_up:nn##1##2{\tex_raise:D\__box_dim_eval:n{0pt}##2} \renewenvironment{syntax}{\noindent}{\par} \fi \begin{sparagraph}[style=symdoc,for={#1}] \__codedoc_function:nnw{#2}{#3} }{ \stex_if_smsmode:F{\__codedoc_function_end:} \end{sparagraph} } \stex_sms_allow_env:n{sfunction} \ProvideDocumentEnvironment { svariable } { m +v } { \seq_set_split:Nnn \_stexdoc_sfunction_seq , {#1} \seq_map_inline:Nn \_stexdoc_sfunction_seq { \stex_pseudogroup_with:nn{\stex_smsmode_do:}{\def\stex_smsmode_do:{}\stexmacro{##1}} } \cs_set_eq:NN \dcs \_stexdoc_dcs: \ifstexhtml \def\box_move_up:nn##1##2{\tex_raise:D\__box_dim_eval:n{0pt}##2} \renewenvironment{syntax}{\noindent}{\par} \fi \begin{sparagraph}[style=symdoc,for={#1}] \bool_if:NTF \l__codedoc_in_implementation_bool { \__codedoc_macro:nnw { var , } {#2} } { \__codedoc_function:nnw {} {#2} } } { \bool_if:NTF \l__codedoc_in_implementation_bool { \__codedoc_macro_end: } { \__codedoc_function_end: } \end{sparagraph} } \stex_sms_allow_env:n{svariable} \ProvideDocumentEnvironment {senv} {m} { \def\denv{\exp_args:Ne\definiendum{\tl_to_str:n{#1}}{\texttt{\tl_to_str:n{#1}}}} \stex_pseudogroup_with:nn{\stex_smsmode_do:}{\def\stex_smsmode_do:{}\stexenv{#1}} \begin{sparagraph}[style=symdoc,for={#1}] \exp_args:Ne\DescribeEnv{\tl_to_str:n{#1}} }{ \end{sparagraph}\par\smallskip } \stex_sms_allow_env:n{senv} } \CodedocExplain %^^A\CodedocExplainEXP %^^A\CodedocExplainREXP %^^A\CodedocExplainTF \begin{sfunction}{stex_debug:nn}{\stex_debug:nn} \begin{syntax} \dcs \marg{prefix} \marg{msg} \end{syntax} Logs the debug message \marg{msg} under the prefix \marg{prefix}. A message is shown if its prefix is in a list of prefixes given either via the package option |debug=|\meta{prefixes} or the environment variable |STEX_DEBUG=|\meta{prefixes}, where the latter overrides the former. \end{sfunction} \begin{sfunction}{_stex_do_deprecation:n}{\_stex_do_deprecation:n} TODO \dcs \end{sfunction} \begin{sfragment}{Documents} \begin{svariable}{l_stex_docheader_sect}{\l_stex_docheader_sect} integer register keeping track of the current sectioning level: \begin{itemize} \item[0] part \item[1] chapter \item[2] section \item[3] subsection \item[4] subsubsection \item[5] paragraph \item[$>5$] subparagraph \end{itemize} \cs{setsectionlevel} sets \cs{l_stex_docheader_sect} to the corresponding integer value. \end{svariable} \begin{sfunction}{stex_ref_new_doc_target:n}{\stex_ref_new_doc_target:n} internal variant of \cs{sreflabel}. If the argument is empty, the label is determined to be |REF|\meta{counter} and \meta{counter} is increased. \end{sfunction} \begin{sfunction}{stex_ref_new_symbol:n}{\stex_ref_new_symbol:n} registers a new link target for the symbol with the given full uri (as string), using the |url-base|-field of the current archive's manifest file to link the symbol to \meta{url-base}|/symbol?|\meta{uri}. \end{sfunction} \begin{sfunction}{stex_ref_new_sym_target:n}{\stex_ref_new_sym_target:n} sets a new label for the symbol with the given full uri (as string). If called in sms-mode, defers to \cs{stex_ref_new_symbol:n}, if not already registered. Otherwise, sets a \cs{label} for the symbol. \end{sfunction} \begin{sfunction}{stex_ref_new_sym_target:nn}{\stex_ref_new_sym_target:nn} \begin{syntax}\dcs\marg{symbol}\marg{target} \end{syntax} redirects links for \meta{symbol} to the one for the symbol \meta{target}. Useful for e.g. symbols elaborated from structural features. Note that this acts as a \emph{default}, in that previous or subsequent calls of \cs{stex_ref_new_sym_target:n}\marg{symbol} are prioritized. Requires that either \cs{stex_ref_new_sym_target:n}\marg{target} or \cs{stex_ref_new_sym_target:nn}\marg{target}\marg{other-target} have been called previously. \end{sfunction} \end{sfragment} \begin{sfragment}{Modules} \stexmacro{stex_module_add_symbol:nnnnnnN} \stexmacro{stex_add_module_notation:nnnnn} \stexmacro{stex_module_add_morphism:nnn} The contents of a module with full URI \meta{uri} are represented as four macros: \begin{itemize} \item |\c_stex_module_|\meta{uri}|_code|: code to be executed every time the module is \emph{activated}; e.g. the contents of \cs{STEXexport}, defines semantic macros and macros for notations, activates dependency modules, etc. \item |\c_stex_module_|\meta{uri}|_morphisms_prop|: property list containing all module dependencies of this module (see \cs{stex_module_add_morphism:nnn}). \item |\c_stex_module_|\meta{uri}|symbols_prop|: property list containing all declarations in this module (see \cs{stex_module_add_symbol:nnnnnnN}). \item |\c_stex_module_|\meta{uri}|_notations_prop|: property list containing all notations introduced in this module (see \cs{stex_add_module_notation:nnnnn}). \end{itemize} \begin{svariable}{l_stex_current_module_str}{\l_stex_current_module_str} contains the full URI of the current module. \end{svariable} \begin{svariable}{l_stex_all_modules_seq}{\l_stex_all_modules_seq} contains the full URIs of all modules currently in scope. \end{svariable} \stexvarmacro{l_stex_key_sig_str} \begin{sfunction}{stex_module_setup:n}{\stex_module_setup:n} \begin{syntax} \dcs\marg{name} \end{syntax} Computes the full URI of a new module with name \meta{name} in the current namespace, initializes the four macros above and sets \cs{l_stex_current_module_str} accordingly. Also takes care of correct naming for nested modules, activates the meta theory and loads the signature module if |sig=| was provided (according to \cs{l_stex_key_sig_str}). \end{sfunction} \stexmacro{stex_persist:n} \begin{sfunction}{stex_close_module:}{\stex_close_module:} closes the current module; checks whether we are currently in sms mode, and if so, calls \cs{stex_persist:n} to write the module contents to the sms-file. \end{sfunction} \begin{sfunction}{stex_every_module:n}{\stex_every_module:n} \begin{syntax}\dcs\marg{code}\end{syntax} executes \meta{code} every time a new module is opened. \end{sfunction} \begin{sfunction}{stex_if_in_module:}[pTF]{\stex_if_in_module:} tests whether we are currently in a module. \end{sfunction} \begin{sfunction}{stex_if_module_exists:n}[pTF]{\stex_if_module_exists:n} tests whether a module with the given full URI exists, in the sense of \emph{has been parsed at some point in the current document}. \end{sfunction} \begin{sfunction}{stex_activate_module:n}{\stex_activate_module:n,\stex_activate_module:o,\stex_activate_module:x} activates the module with the given full URI \emph{if and only if} it has not already been activated in the current scope. \end{sfunction} \stexmacro{stex_metagroup_do_in:nn} \begin{sfunction}{stex_execute_in_module:n}{\stex_execute_in_module:n,\stex_execute_in_module:x} executes the provided code, adds it to the current module activation code, and makes sure the macros defined in it are valid in the current module \TeX\ group level. \end{sfunction} This macro is a combination of the following two macros: \begin{sfunction}{stex_do_up_to_module:n}{\stex_do_up_to_module:n,\stex_do_up_to_module:x} executes the provided code such that all definitions in it are valid in the current module regardless of \TeX\ group level (using \cs{stex_metagroup_do_in:nn}). \end{sfunction} \begin{sfunction}{stex_module_add_code:n}{\stex_module_add_code:n,\stex_module_add_code:x} adds the provided code to the module's |\c_stex_module_|\meta{uri}|_code|-macro. \end{sfunction} \end{sfragment} \begin{sfragment}{Symbols} A symbol in \stex is represented as a tuple of several components: \stexvarmacro{id} \stexvarmacro{invokation_macro} \stexmacro{_stex_invoke_symbol:nnnnnnnN} \begin{sfunction}{stex_module_add_symbol:nnnnnnnN}{\stex_module_add_symbol:nnnnnnnN} \begin{arguments} \item \meta{id}: An \emph{identifier} (possibly empty) that determines its semantic macro name, or e.g. in \env{mathstructure} its accessor-identifier (if empty, the name is used for that), \item \meta{name} a unique \emph{name}, which in combination with the containing module determines its URI as \meta{module-URI}|?|\meta{name}, \item \meta{arity} a numeric string in the range |0..9|, \item \meta{args} a list of argument specifiers of the form \meta{i}\meta{mode}|{|\meta{argname}|}| (the length of \meta{args} must be $3\cdot$\meta{arity}), \item \meta{definiens} (or empty), \item \meta{type} (or empty), \item \meta{return code} (or empty), and \item \meta{\cs{invokation_macro}}. \end{arguments} the arguments are stored in the property list \cs{c_stex_module_}\meta{\cs{l_stex_current_module}}|_symbols_prop| under key \meta{name}. If the identifier \meta{id} is non-empty, the macro \cs{id} is defined as |{|\cs{_stex_invoke_symbol:nnnnnnnN}|}| with the arguments described there. \begin{texnote} \cs{invokation_macro} must be \cs{protected}. \end{texnote} \end{sfunction} \begin{sfunction}{stex_iterate_symbols:n,stex_iterate_break:,stex_iterate_break:n}{\stex_iterate_symbols:n,\stex_iterate_break:,\stex_iterate_break:n} \begin{syntax}\dcs\marg{code}\end{syntax} iterates over all symbols currently in scope and calls \meta{code} for all of them with arguments \marg{module}\marg{name}\marg{arity}\meta{args}\marg{definiens} \marg{type}\marg{return code}\marg{\cs{invokation_macro}}. Iteration can be stopped prematurely with \dcs[stex_iterate_break:] and can stop and return code with \dcs[stex_iterate_break:n]. \end{sfunction} \begin{sfunction}{stex_iterate_symbols:nn}{\stex_iterate_symbols:nn} \begin{syntax}\dcs\marg{csl}\marg{code}\end{syntax} iterates over all symbols in the provided \meta{csl} of full module URIs. \meta{code} receives the same arguments as \cs{stex_iterate_symbols:n}, but iteration can not be stopped early. \end{sfunction} \begin{sfunction}{ stex_get_symbol:n, l_stex_get_symbol_mod_str, l_stex_get_symbol_name_str, l_stex_get_symbol_arity_int, l_stex_get_symbol_args_tl, l_stex_get_symbol_def_tl, l_stex_get_symbol_type_tl, l_stex_get_symbol_return_tl, l_stex_get_symbol_invoke_cs }{\stex_get_symbol:n, \l_stex_get_symbol_mod_str, \l_stex_get_symbol_name_str, \l_stex_get_symbol_arity_int, \l_stex_get_symbol_args_tl, \l_stex_get_symbol_def_tl, \l_stex_get_symbol_type_tl, \l_stex_get_symbol_return_tl, \l_stex_get_symbol_invoke_cs } \dcs attemps to find a symbol with the given name or id that is currently in scope. A name may be prefixed with a module name/path separated by |?|. Throws an error if no such symbol is found; otherwise, sets the listed |\l_stex_get_symbol_...|-macros to the components of the found symbol. \end{sfunction} \begin{sfunction}{stex_if_check_terms:}[pTF]{\stex_if_check_terms:} whether to typeset declaration components (notations, types, definientia etc.) in a throwaway box. Is true iff the backend is |pdflatex| and either the |STEX_CHECKTERMS| environment variable or |checkterms| package option is set. \end{sfunction} \begin{sfunction}{stex_check_term:n}{\stex_check_term:n} typesets the argument in a throwaway box in math mode iff \cs{stex_if_check_terms:} is true. Is deactivated in sms-mode. \end{sfunction} \begin{sfunction}{ stex_symdecl_do:, l_stex_key_name_str, l_stex_key_args_str, l_stex_key_argnames_clist, l_stex_assoc_args_count, l_stex_argnames_seq }{\stex_symdecl_do:, \l_stex_key_name_str, \l_stex_key_args_str, \l_stex_key_argnames_clist, \l_stex_assoc_args_count, \l_stex_argnames_seq } \dcs processes the shared (mandatory and optional) arguments of e.g. \cs{symdecl}, \cs{symdef}, \cs{vardef} etc. Requires the following macros to be set \begin{itemize} \item \dcs[l_stex_key_name_str]: the name of the symbol, \item \dcs[l_stex_key_args_str]: the |args|-string (e.g. |3| or |ai|) \item \dcs[l_stex_key_argnames_clist]: a list of \emph{names} for the arguments, the length of which should be $\leq$ the arity of the symbol \end{itemize} and will generate the following macros: \begin{itemize} \item \cs{l_stex_get_symbol_arity_int}: the arity of the symbol, \item \dcs[l_stex_key_args_str]: the args string as a definite sequence of argument-mode characters, whose length is the arity of the symbol; e.g. |3| is turned into |iii|, \item \dcs[l_stex_assoc_args_count]: the number of sequence arguments (i.e. |a| or |B| mode), \item \dcs[l_stex_argnames_seq]: the full sequence of argument names; those not provided by \cs{l_stex_key_argnames_clist} are set to be |$j|\iffalse$\fi, where |j| is the index of the argument, \item \cs{l_stex_get_symbol_args_tl}: a token list of triples |jm{|\meta{argname}|}|, where |j| is the index and |m| the respective argument mode character (i.e. |i|, |a|, |b| or |B|). \end{itemize} \end{sfunction} \begin{sfunction}{_stex_symdecl_check_terms:, l_stex_key_type_tl,l_stex_key_def_tl}{\_stex_symdecl_check_terms:} calls \cs{stex_check_term:n} for the type and definiens stored in \cs{l_stex_key_type_tl} and \cs{l_stex_key_def_tl} \end{sfunction} \stexmacro{stex_invoke_symbol:} \begin{sfunction}{stex_symdecl_top:n,l_stex_macroname_str}{\stex_symdecl_top:n} \begin{syntax}\dcs\marg{maybename}\end{syntax} checks whether \cs{l_stex_key_name_str} is empty, and if so, sets it to be \meta{maybename}. Then calls \cs{stex_symdecl_do:} and \cs{_stex_symdecl_check_terms:}, writes the components to the HTML (if applicable) and adds the symbol to the current module with invokation macro \cs{stex_invoke_symbol:} and id/macroname \cs{l_stex_macroname_str}. \end{sfunction}\bigskip Variables work very similar to symbols, except that their declarations are local to the current \TeX-group rather than the current module, and they are not exported in modules. \begin{svariable}{l_stex_variables_prop}{\l_stex_variables_prop} stores all variables currently in scope as a property list with key \meta{name} and value \marg{id}\marg{name}\marg{arity}\meta{args}\marg{definiens} \marg{type}\marg{return code}\marg{\cs{invokation_macro}}. The invokation macro for ``normal'' variables declared with \cs{vardef} is \cs{stex_invoke_symbol:}. \end{svariable} \begin{sfunction}{_stex_vardecl_notation_macro:}{\_stex_vardecl_notation_macro:} generates the notation macro for a variable, based on the values of the |\l_stex_key|-macros und \cs{l_stex_notation_macrocode_cs}. \end{sfunction} \begin{sfunction}{stex_get_var:n}{\stex_get_var:n} like \cs{stex_get_symbol:n}, but attempts to retrieve a variables and throws an error if none is found. \end{sfunction} \begin{sfunction}{stex_get_symbol_or_var:n}{\stex_get_symbol_or_var:n} like \cs{stex_get_symbol:n}, but first attempts to find a \emph{variable}, and if none is found, defers to \cs{stex_get_symbol:n}. \end{sfunction} \end{sfragment} \begin{sfragment}{Notations} \stexmacro{stex_set_notation_macro:nnnnn} \begin{sfunction}{stex_module_add_notation:nnnnn}{\stex_module_add_notation:nnnnn, \stex_module_add_notation:eoexo} \begin{syntax}\dcs \marg{symboluri}\marg{id}\marg{arity}\meta{code}\meta{op code} \end{syntax} stores the arguments in the property list \cs{c_stex_module_}\meta{\cs{l_stex_current_module}}|_notations_prop| under key \meta{symboluri}|!|\meta{id} and calls \cs{stex_set_notation_macro:nnnnn}. \end{sfunction} \begin{sfunction}{stex_set_notation_macro:nnnnn}{\stex_set_notation_macro:nnnnn,\stex_set_notation_macro:eoexo} \begin{syntax}\dcs \marg{symboluri}\marg{id}\marg{arity}\meta{code}\meta{op code} \end{syntax} Declares the following macros: An active notation for a symbol with uri \meta{symboluri} and id \meta{id} is represented as a macro \cs{l_stex_notation_}\meta{symboluri}|_|\meta{id}|_cs|, that takes \meta{arity} many argument and expands to \meta{code}, and (if nonempty) an \emph{operator} notation as a macro \cs{l_stex_notation_}\meta{symboluri}|_op_|\meta{id}|_cs| that expands to \meta{op code}. The default notation is represented as the \emph{empty} id. If the correponding macros \cs{l_stex_notation_}\meta{symboluri}|__cs|, and \cs{l_stex_notation_}\meta{symboluri}|_op__cs| do not yet exist, they are now defined as \meta{id}. \end{sfunction} \begin{sfunction}{stex_iterate_notations:nn}{\stex_iterate_notations:nn} \begin{syntax}\dcs\marg{csl}\marg{code}\end{syntax} iterates over all notations in the provided \meta{csl} of full module URIs and calls \meta{code} on each of them with arguments \marg{symboluri}\marg{id}\marg{arity}\meta{code}\meta{op code}. \end{sfunction} \begin{sfunction}{ stex_notation_parse_and_then:nw, l_stex_key_prec_str, l_stex_key_variant_str, l_stex_notation_macrocode_cs }{\stex_notation_parse_and_then:nw, \l_stex_key_prec_str, \l_stex_key_variant_str, \l_stex_notation_macrocode_cs } \begin{syntax}\dcs\marg{code}\meta{notations} \end{syntax} parses a notation (which may consist of multiple braced components, depending on the argument modes) and subsequently calls \meta{code}. Requires the following macros to be set: \begin{itemize} \item \cs{l_stex_get_symbol_arity_int}, \item \cs{l_stex_get_symbol_args_tl}, \item \dcs[l_stex_key_prec_str]: The precedence string as provided by a user in the optional |precs|-argument, \item \dcs[l_stex_key_variant_str]: the id of the notation variant. \end{itemize} Stores the final notation in the macro \dcs[l_stex_notation_macrocode_cs] taking \cs{l_stex_get_symbol_arity_int} many arguments. \end{sfunction}\bigskip Some thing to consider when we generate a notation macro: \begin{itemize} \item The notation macro generated by the \cs{notation}-command should contain the variant identifier and the precedences, as these are intrinsic parts of the notation. \item It should \emph{not} contain the symbol itself however, so that notations can be copied between symbols. \item Notations as provided by users will largely adhere to the standard \LaTeX\ category code scheme, and \item notations need to be ``persistable'' in |.deps|-files. \end{itemize} We therefore want to augment the simple code provided by a user by various ``annotations'' that contain the relevant information (such as precedences) and to mark the argument positions for semantic extractions, but we should adhere to the default \LaTeX\ category code scheme in doing so. \begin{sfunction}{ STEXInternalTermMathArgiii, STEXInternalTermMathOMSOrOMViii, STEXInternalTermMathAssocArgiiiii, STEXInternalAssocArgMarkerI, STEXInternalAssocArgMarkerII, STEXInternalTermMathOMAiii, STEXInternalTermMathOMBiii, STEXInternalSymbolAfterInvokationTL }{ \STEXInternalTermMathArgiii, \STEXInternalTermMathAssocArgiiiii, \STEXInternalAssocArgMarkerI, \STEXInternalAssocArgMarkerII, \STEXInternalTermMathOMSOrOMViii, \STEXInternalTermMathOMAiii, \STEXInternalTermMathOMBiii, \STEXInternalSymbolAfterInvokationTL } In \openmath/\OMDoc, there are (for our purposes) three kinds of expressions that an application of a semantic macro -- and hence a notation macro -- can represent, each of which corresponds to a macro taking care of the semantic annotations: \begin{itemize} \item |OMS/OMV|: a simple symbol (arity 0) (\dcs[STEXInternalTermMathOMSOrOMViii]) \item |OMA|: an application of a symbol to argument (arity $>0$, \dcs[STEXInternalTermMathOMAiii]) \item |OMB|: a binding application of a symbol that binds/declares one or more variables (argument string contains |b| or |B|, \dcs[STEXInternalTermMathOMBiii]). \end{itemize} The arguments are marked with \dcs[STEXInternalTermMathArgiii] (|i| or |b|) or \dcs[STEXInternalTermMathAssocArgiiiii] (|a| or |B|). Finally, the notation is closed with \dcs[STEXInternalSymbolAfterInvokationTL]. How this works is best explained by example. \end{sfunction} \begin{sexample} Assume we have a symbol and notation: \begin{stexcode} \symdecl{somesymbol}[args=iai] \notation{somesymbol}[prec=10;20x30x40,variant=foo] {First: #1; Second: #2; Third: #3; End} {(#1 -- ##1 split ##2 -- #3)} \end{stexcode} Since the symbol corresponds to an |OMA|, the whole notation is wrapped in \cs{STEXInternalTermMathOMAiii}, taking as arguments the variant identifier (|foo|), the operator precedence (|10|) and the body of the notation. The second argument in the notation, being associative, is wrapped in a \cs{STEXInternalTermMathAssocArgiiiii}, taking as arguments the argument number (|2|), the precedence (|30|), the \TeX\ parameter token (|#2|) the notation body (|(#1 -- ##1 split ##2 -- #3)|), and finally the argument mode (|a|). Additionally, the markers |##1| and |##2| are replaced by \cs{STEXInternalAssocArgMarkerI} and \cs{STEXInternalAssocArgMarkerII}, respectively. Subsequently, the non-sequence parameter tokens are wrapped in \cs{STEXInternalTermMathArgiii} with arguments |mj| (where |m| is the mode und |j| the index), the precedence (|20| or |40| respectively), and the parameter token. Finally, a \cs{STEXInternalSymbolAfterInvokationTL} is inserted. The final expansion of \cs{l_stex_notation_macrocode_cs} is thus: \begin{stexcode} \STEXInternalTermMathOMAiii{foo}{10}{ First: \STEXInternalTermMathArgiii{i1}{20}{#1}; Second: \STEXInternalTermMathAssocArgiiiii{2}{30}{#2}{ (\STEXInternalTermMathArgiii{i1}{20}{##1} -- \STEXInternalAssocArgMarkerI split \STEXInternalAssocArgMarkerII -- \STEXInternalTermMathArgiii{i3}{40}{##3}) }{a}; Third: \STEXInternalTermMathArgiii {i3}{40}{#3}; End }\STEXInternalSymbolAfterInvokationTL \end{stexcode} \end{sexample} \begin{sfunction}{stex_notation_top:nnw}{\stex_notation_top:nnw} \begin{syntax}\dcs\marg{symboluri}\marg{code}\end{syntax} calls \cs{stex_notation_parse_and_then:nw}\marg{code} and, adds the notation for the symbol with URI \meta{symboluri} to the current module and exports it to the HTML (if applicable). \end{sfunction} \end{sfragment} \begin{sfragment}{Structural Features} \begin{sfunction}{stex_structural_feature_module:nn, stex_structural_feature_module_end:, g_stex_last_feature_str }{\stex_structural_feature_module:nn, \stex_structural_feature_module_end:, \g_stex_last_feature_str } \begin{syntax}\dcs\marg{name}\marg{typeid}\end{syntax} opens a new module-like structural feature of type \meta{typeid} with name \meta{name}, which needs to be closed with \dcs[stex_structural_feature_module_end:]. Its body behaves like a nested module with name \meta{modulename}|/|\meta{name}, the full URI of which is stored in \dcs[g_stex_last_feature_str] for subsequent elaboration. \end{sfunction} \begin{sfunction}{ stex_structural_feature_morphism:nnnnn, stex_structural_feature_morphism_end:, l_stex_current_domain_str, l_stex_feature_name_str, l_stex_morphism_symbols_prop, l_stex_morphism_renames_prop, l_stex_morphism_morphisms_seq }{ \stex_structural_feature_morphism:nnnnn, \stex_structural_feature_morphism_end:, \l_stex_current_domain_str, \l_stex_feature_name_str, \l_stex_morphism_symbols_prop, \l_stex_morphism_renames_prop, \l_stex_morphism_morphisms_seq } \begin{syntax}\dcs\marg{moprhismname}\marg{typeid}\marg{archive}\marg{domain}\marg{annotations}\end{syntax} opens a new morphism-like structural feature of type \meta{typeid} with name \meta{morphismname} and the module |[|\meta{archive}|]|\marg{domain} as domain, which needs to be closed with \dcs[stex_structural_feature_morphism_end:]. Deactivates \cs{symdecl}, \cs{textsymdecl}, \cs{symdef}, \cs{notation} and \env{smodule}, and activates \cs{assign}, \cs{assignMorphism} and \cs{renamedecl}. Defines the following macros: \begin{itemize} \item \dcs[l_stex_feature_name_str]|=|\marg{name}. \item \dcs[l_stex_current_domain_str]|=| the full uri of \meta{domain}. \item \dcs[l_stex_morphism_symbols_prop]: This property list is initialized as follows: For every symbol transitively included in \meta{domain} with data \meta{module}, \meta{name}, \meta{id}, \meta{arity}, \meta{args}, \meta{definiens}, \meta{type}, and \meta{return code}, the property list contains an entry with key |[|\meta{module}|]/[|\meta{name}|]| and value \marg{id}\marg{arity}\marg{args}\marg{definiens} \marg{type}\marg{return code}. \item \dcs[l_stex_morphism_renames_prop]: An initially empty property list. \item \dcs[l_stex_morphism_morphisms_seq]: TODO \end{itemize} At \dcs[stex_structural_feature_morphism_end:], the elaboration is computed from the above data thusly: For every entry in \dcs[l_stex_morphism_symbols_prop], a new symbol is created with the values \meta{arity}, \meta{args}, \meta{definiens}, \meta{type} and \meta{return code} from that property list, and either: \begin{itemize} \item if \dcs[l_stex_morphism_renames_prop] does \emph{not} contain an entry with key \meta{module}|?|\meta{name}, then the elaborated name is \meta{morphismname}|/|\meta{name} and its \meta{id} is empty (no semantic macro is generated), or \item if \dcs[l_stex_morphism_renames_prop] contains an entry with key \meta{module}|?|\meta{name}, then its value needs to be of the form \marg{id}\marg{name}, which are used for the elaborated symbol. \end{itemize} All notations of the symbols transitively included in the domain are copied over to their elaborations. \end{sfunction} \end{sfragment} \begin{sfragment}{Imports and Morphisms} \begin{sfunction}{stex_module_add_morphism:nnnn}{\stex_module_add_morphism:nnnn, \stex_module_add_morphism:nonn, \stex_module_add_morphism:ooox} adds a new module morphism (i.e. inheritance, possibly with modification) to the current module \begin{arguments} \item The name of the morphism (may be empty for e.g. \cs{importmodule}, but may be named for e.g. \env{copymodule}), \item the URI of the module being ``imported'', \item the ``type'' of the morphism (e.g. |import| or |copymodule|), \item a list of assignments as pairs |{|\meta{source}|}{|\meta{target}|}| that signify that the symbol with full URI \meta{source} is being mapped or elaborated to the new symbol with name \meta{target} in the current module. May be empty for e.g. \cs{importmodule}. \end{arguments} The provided arguments are stored in |\c_stex_module_|\meta{uri}|_morphisms_prop| with key |#1| (if non-empty) or |[#2]| (if |#1| is empty) and value |{#1}{#2}{#3}{#4}| \end{sfunction}\bigskip Import-like statements in \sTeX are usually given as pairs |[|\meta{archive}|]{|\meta{path}|?|\meta{module}|}|, which be relative to the current archive and/or file path. For persistence and sms-mode, these pairs first need to be resolved into an \emph{absolute} specification: \begin{sfunction}{ stex_import_module_uri:nn, l_stex_import_archive_str, l_stex_import_name_str, l_stex_import_uri_str, l_stex_import_path_str }{ \stex_import_module_uri:nn, \l_stex_import_archive_str, \l_stex_import_name_str, \l_stex_import_uri_str, \l_stex_import_path_str } \begin{syntax}\dcs\marg{archive}\marg{pathstring}\end{syntax} (where \meta{archive} may be empty) resolves the given arguments into: \begin{itemize} \item \dcs[l_stex_import_archive_str] the given archive id (in which case \cs{stex_require_archive:n} is called), or the id of the current archive (if existent and \meta{archive} empty), or empty, \item \dcs[l_stex_import_uri_str] if an archive id is given, or we currently are in an archive, its corresponding namespace; otherwise |{file:}|, \item \dcs[l_stex_import_path_str] the path of the URI relative to the given (or current) archive, or (if not existent) the absolute path of \meta{pathstring} (without a module name) resolved relative to the current file's parent directory, and \item \dcs[l_stex_import_name_str] the name of the module. \end{itemize} If \meta{pathstring} does not contain the character |?|, the whole pathstring is assumed to be the name of the module and the path is empty (or the current file's parent directory, depending on the above). \end{sfunction} \begin{sfunction}{stex_import_require_module:nnn}{\stex_import_require_module:nnn} takes as arguments values \cs{l_stex_import_archive_str}, \cs{l_stex_import_path_str} and \cs{l_stex_import_name_str} as computed by \cs{stex_import_module_uri:nn} and (optionally loads and) activates the corresponding module (or throws an error if it does not exist). \end{sfunction}\bigskip Most complex morphisms (\env{copymodule} et al) are implemented as structural features using \cs{stex_structural_feature_morphism:nnnn}. \begin{sfunction}{stex_get_in_morphism:n, l_stex_get_symbol_macro_str}{\stex_get_in_morphism:n, \l_stex_get_symbol_macro_str} finds a symbol with the provided name or id in the domain of the current morphism. Sets the same macros as \cs{stex_get_symbol:n}, and additionaly \dcs[l_stex_get_symbol_macro_str] to the \meta{id} of the symbol. Throws an error if no such symbol is found. \end{sfunction} \end{sfragment} \begin{sfragment}{Expressions and Semantic Macros} \begin{sfunction}{_stex_invoke_symbol:nnnnnnnN, l_stex_current_symbol_str, l_stex_current_arity_str, l_stex_current_args_tl, l_stex_current_return_tl, l_stex_current_type_tl }{\_stex_invoke_symbol:nnnnnnnN \l_stex_current_symbol_str, \l_stex_current_arity_str, \l_stex_current_args_tl, \l_stex_current_return_tl, \l_stex_current_type_tl } \begin{syntax}\dcs \marg{module}\marg{name}\marg{arity}\marg{args}\marg{definiens} \marg{type} \marg{return code} \marg{\cs{invokation_macro}} \end{syntax} is how a semantic macro is/should be defined. \dcs first checks whether semantic macros are currently allowed, and throws an error if not. Otherwise, it sets the \cs{comp}-controlled highlighting to \cs{compemph@uri}, initializes \cs{STEXInternalSymbolAfterInvokationTL}, defines the following macros for all of its arguments, and subsequently calls the \cs{invokation_macro}: \begin{itemize} \item \dcs[l_stex_current_symbol_str]|={|\meta{module}|?|\meta{name}|}| \item \dcs[l_stex_current_arity_str]|=|\marg{arity} \item \dcs[l_stex_current_args_tl]|=|\marg{args} \item \dcs[l_stex_current_type_tl]|=|\marg{type} \item \dcs[l_stex_current_return_tl]|=|\marg{return code} \end{itemize} The simplest example for an \cs{invokation_macro} is \cs{stex_invoke_symbol:}. \end{sfunction} \begin{sfunction}{_stex_invoke_variable:nnnnnnN}{\_stex_invoke_variable:nnnnnnN} analogous to \cs{_stex_invoke_symbol:nnnnnnnN}, but for variables; sets the \cs{comp}-controlled highlighting to \cs{varemph@uri}. \end{sfunction} \begin{sfunction}{stex_invoke_symbol:}{\stex_invoke_symbol:} branches based on the mode and following characters: \begin{itemize} \item If math, check next character: \begin{itemize} \item[!] operator; defer to operator notation \item[else] defer to notation and check the value of \cs{l_stex_current_return_tl}=\meta{return}. \begin{itemize} \item If \meta{return} is empty, call the notation macro, \item otherwise, call \meta{return}|{|\cs{stex_invoke_symbol}|!}|. \end{itemize} \end{itemize} \item If text: \end{itemize} \end{sfunction} \begin{sfunction}{stex_invoke_sequence_range:, stex_invoke_sequence_in: }{ \stex_invoke_sequence_range:, \stex_invoke_sequence_in: } TODO \end{sfunction} \end{sfragment} \begin{sfragment}{Optional (Key-Value) Argument Handling} \LaTeX3 is surprisingly weak when it comes to handling optional (key-val) arguments in such a manner that \emph{only} the freshly set macros are defined, and to modularly build up sets of argument keys. The following macros attempt to fix that: \begin{sfunction}{stex_keys_define:nnnn,stex_keys_set:nn}{\stex_keys_define:nnnn,\stex_keys_set:nn} \begin{syntax} \dcs\marg{id}\marg{setup code} \marg{keyval setup code}\marg{parents} \end{syntax} Defines a set of keys and their allowed values with identifier |stex/|\meta{id}, that inherits from the sets with identifiers in \meta{parents}. \dcs[stex_keys_set:nn]\marg{id}\marg{CSL} first executes \meta{setup code} (e.g. to empty the macros holding the values) and then sets the keys in set \meta{id} with the values provided in \meta{CSL}. \end{sfunction} \stexvarmacro{l_stex_key_id_str} \begin{sfunction}{_stex_do_id:}{\_stex_do_id:} should be called whenever a macro or environment has a label id, i.e. calls \cs{stex_keys_set:nn}|{id}{...}|, after the title has been typeset. Sets a \cs{label} by calling \cs{stex_ref_new_doc_target:n}\marg{id}. \end{sfunction} \begin{sexample} If we define a set of keys with: \stexvarmacro{l_stex_key_archive_str} \stexvarmacro{l_stex_key_file_str} \begin{stexcode}[gobble=6] |\cs{stex_keys_define:nnnn}|{archive file}{ \str_clear:N |\cs{l_stex_key_archive_str}| \str_clear:N |\cs{l_stex_key_file_str}| }{ archive .str_set_x:N = |\cs{l_stex_key_archive_str}| , file .str_set_x:N = |\cs{l_stex_key_file_str}| }{id} \end{stexcode} then calling \cs{stex_keys_set:nn}|{archive file}{id=foo,file=bar}| sets \cs{l_stex_key_file_str}|={bar}|, assures that \cs{l_stex_key_archive_str} is empty, and executes the code associated with |id|, i.e. it sets \cs{l_stex_key_id_str}|={foo}|. \end{sexample} \end{sfragment} \begin{sfragment}{Stylable Commands and Environments} \stexmacro{stex_style_apply:} \begin{sfunction}{stex_new_stylable_cmd:nnnn,l_stex_key_style_clist}{\stex_new_stylable_cmd:nnnn} \begin{syntax} \dcs\marg{name}\marg{arity}\marg{code} \marg{default} \end{syntax} Creates a new macro \cs{}\meta{name} with expansion \meta{code} taking \meta{arity} many arguments, that is customizable in presentation by a user by calling \cs{stexstyle}\meta{name}. On calling \cs{stex_style_apply:} executes the presentation code provided by a user. \meta{code} should: \begin{itemize} \item Call \cs{stex_keys_set:nn}|{style}{...}| (or a keyset inheriting from |style|), \item set macros with prefix |\this...| that a user might want to use for presentation (e.g. \cs{thistitle}), \item call \cs{stex_style_apply:} at some point. \end{itemize} \end{sfunction} \begin{sfunction}{stex_new_stylable_env:nnnnnnn}{\stex_new_stylable_env:nnnnnnn} \begin{syntax} \dcs\marg{name}\marg{arity}\marg{begincode} \marg{endcode}\marg{default begin}\marg{default end}\marg{prefix} \end{syntax} Like \cs{stex_new_stylable_cmd:nnnn}, but defines a new environment |{|\meta{prefix}\meta{name}|}| stylable via \cs{stexstyle}\meta{name}. Should call \cs{stex_style_apply:} twice; once in the \meta{begincode} and once in \meta{endcode}. \end{sfunction} \begin{sfunction}{stex_style_apply:}{\stex_style_apply:} Sets \cs{thisstyle} to be the head of the CSL \cs{l_stex_key_style_clist} and checks whether a style for the current stylable macro/environment has been defined; if not, executes the code for the default style. \end{sfunction} \begin{sexample} \cs{importmodule} is defined something like the following: \begin{stexcode}[gobble=6] |\cs{stex_new_stylable_cmd:nnnn}|{importmodule}{O{} m}{ ... \def|\cs{thismoduleuri}|{...} \def|\cs{thismodulename}|{...} |\cs{stex_style_apply:}| ... }{} \end{stexcode} A user can then customize the output generated by \cs{importmodule} (by default none) via \cs{stexstyleimportmodule}|{...|\cs{thismodulename}|...}|. \end{sexample} \begin{sexample} \env{smodule} does something like \begin{stexcode}[gobble=6] |\cs{stex_new_stylable_env:nnnnnnn}|{module}{O{} m}{ ... \def|\cs{thismoduleuri}|{...} \def|\cs{thismodulename}|{...} |\cs{stex_style_apply:}| ... }{ ... |\cs{stex_style_apply:}| ... }{}{}{s} \end{stexcode} which defines the environment name to be \env{smodule} and generates \cs{stexstylemodule}. \end{sexample} \end{sfragment} \begin{sfragment}{Math Archives} Math archives are represented as \LaTeX3 property lists, the keys/values of which correspond to the entries in the archive's manifest file. The most important fields are \begin{itemize} \item |id|, \item |narr| the document namespace, \item |ns| the content namespace, and \item |docurl| the document URL base. \end{itemize} \stexvarmacro{target} \begin{sfunction}{stex_resolve_path_pair:Nnn}{\stex_resolve_path_pair:Nnn,\stex_resolve_path_pair:Nxx} \begin{syntax}\dcs\marg{\cs{target}}\marg{archive-id}\marg{pathstring} \end{syntax} computes the absolute file path of \meta{pathstring} relative to the |source|-folder of \meta{archive-id} (if non-empty), or the current archive (if existent) or the parent working directory (otherwise), and stores the result in \cs{target}. \end{sfunction} \begin{svariable}{l_stex_current_archive_prop}{\l_stex_current_archive_prop} \dcs always points to the current math archive or is \cs{undefined}, if the current file is not part of a math archive. \end{svariable} \begin{svariable}{c_stex_main_archive_prop}{\c_stex_main_archive_prop} \dcs represents the math archive in which the main file resides (if existent). \end{svariable} \begin{sfunction}{stex_require_archive:n}{\stex_require_archive:n,\stex_require_archive:o} \begin{syntax}\dcs\marg{id} \end{syntax} looks for a math archive \meta{id} in the MathHub directory, parses its manifest file, creates the corresponding property list |\c_stex_mathhub_|\meta{id}|_manifest_prop|, and throws a fatal error if the archive is not found. If the archive has been found and parsed before, does nothing, so it is cheap and safe to call repeatedly for the same id. \end{sfunction} \begin{sfunction}{stex_set_current_archive:n}{\stex_set_current_archive:n} \begin{syntax}\dcs\marg{id} \end{syntax} Calls \cs{stex_require_archive:n}\marg{id} and sets \cs{l_stex_current_archive_prop}. \end{sfunction} \begin{sfunction}{stex_in_archive:nn}{\stex_in_archive:nn} \begin{syntax}\dcs\marg{opt-id}\marg{code} \end{syntax} Executes \meta{code} in the context of math archive \meta{opt-id} (using \cs{stex_require_archive:n}), i.e. iff \meta{opt-id} is non-empty, changes the current archive to the one with id \meta{opt-id}, call \meta{code} with \meta{opt-id} as argument (in |#1|) and changes it back afterwards. If \meta{opt-id} is empty, \meta{code} is called with the id of the \emph{current} math archive as |#1|, or with |#1| empty if there is no current math archive. \end{sfunction} \end{sfragment} \begin{sfragment}{SMS-Mode} \stex has to extract formal content (i.e. modules and their symbols) from \LaTeX-files, that may otherwise contain arbitrary code, including macros that may not be defined unless the file is fully processed by \TeX. Those modules and symbols also may depend on other modules that have not yet been loaded. The naive way to achieve this, which would be to just suppress output (e.g. by storing it in a box register) and then \cs{input} the required file, does not work thanks to \TeX's limited \emph{file stack}, which would overflow quickly for modules that have a deeply nested list of dependencies. To solve those problems, \sTeX reads dependencies in what we call \emph{sms mode}, which can be summarized thusly: \begin{itemize} \item In a first pass, we parse the file token by token, ignoring everything other than a select list of macros and environments that introduce dependencies (such as \cs{importmodule} and \cs{begin}|{|\env{smodule}|}[sig=...]|). Instead of loading those, we remember them for later. \item After the file as been fully parsed thusly, the dependencies found are loaded, again in sms-mode. \item In a second pass, we parse the file \emph{again} in the same way, but this time execute all macros that are explicitly allowed in sms mode, such as \cs{importmodule}, \cs{symdecl}, \cs{notation}, \cs{symdef}, etc. \item all this parsing happens additionally in a \cs{setbox}\cs{throwaway}\cs{vbox}|{...}|-block to suppress any accidental output. \end{itemize} This means that \TeX's input stack never grows by more than $+1$, but still behaves \emph{as if} the dependencies were loaded recursively, at the detriment of being somewhat slow. \begin{sfunction}{stex_if_smsmode:}[pTF]{\stex_if_smsmode:} tests for whether we are currently in sms-mode. \end{sfunction} \begin{sfunction}{stex_file_in_smsmode:nn}{\stex_file_in_smsmode:nn,\stex_file_in_smsmode:on} \begin{syntax}\dcs\marg{filestring}\marg{setup-code}\end{syntax} sets up sms-mode and internal grouping, calls \meta{setup-code} and subsequently processes the file \meta{filestring} in sms-mode as described above. \end{sfunction} \begin{sfragment}{Second Pass} \stexvarmacro{macro} \begin{sfunction}{stex_sms_allow:N}{\stex_sms_allow:N} \begin{syntax}\dcs\marg{\cs{macro}}\end{syntax} registers the \cs{macro}-command to be allowed in sms mode. This only works, if \cs{macro} takes no arguments and/or does not touch the subsequent tokens. \end{sfunction} For macros taking arguments, we can use \stexmacro{stex_smsmode_do:} \begin{sfunction}{stex_sms_allow_escape:N}{\stex_sms_allow_escape:N} \begin{syntax}\dcs\marg{\cs{macro}}\end{syntax} registers the \cs{macro}-command to be allowed in sms mode. If \cs{macro} is subsequently encountered in sms-mode, parsing is halted and \cs{macro} can process arguments as desired. It then needs to continue parsing manually though, by calling \cs{stex_smsmode_do:} as (usually) its last token. \end{sfunction} \begin{sfunction}{stex_sms_allow_env:n}{\stex_sms_allow_env:n} \begin{syntax}\dcs\marg{envname}\end{syntax} registers the environment \meta{envname} to be allowed in sms mode. As with \cs{stex_sms_allow_escape:N}, the \cs{begin}|{|\meta{envname}|}| is escaped, hence the begin-code of the environment needs to call \cs{stex_smsmode_do:}. Since \cs{end}|{|\meta{envname}|}| never takes arguments, it does not need to be escaped. \end{sfunction} \begin{sfunction}{stex_smsmode_do:}{\stex_smsmode_do:} continues with sms-mode-style parsing. Does nothing if not in sms-mode, and is therefore safe to be called ``just in case''. \end{sfunction} \end{sfragment} \begin{sfragment}{First Pass} \stexmacro{g_stex_sms_import_code} \begin{sfunction}{stex_sms_allow_import:Nn,stex_sms_allow_import_env:nn}{\stex_sms_allow_import:Nn,\stex_sms_allow_import_env:nn} behave like \cs{stex_sms_allow_escape:N} and \cs{stex_sms_allow_env:n} respectively, but the macro or environment provided is now allowed in the \emph{first} pass of sms-mode. This macro should process arguments, add content to \cs{g_stex_sms_import_code}, and finally call \cs{stex_smsmode_do:}. The code provided in the \emph{second} argument is called before the first pass of sms-mode, as to set up functionality for these macros. For example, \cs{importmodule} provides code that redefines \cs{importmodule} to store the identified dependency in \cs{g_stex_sms_import_code} instead of activating it directly. \end{sfunction} \begin{svariable}{g_stex_sms_import_code}{\g_stex_sms_import_code} is built up in the first pass of sms mode and called subsequently; before the second pass. Code in this token list should load and activate dependencies found in the first pass. \end{svariable} \end{sfragment} \end{sfragment} \begin{sfragment}{Strings, File Paths, URIs} \begin{sfunction}{stex_str_if_starts_with:nn}[pTF]{\stex_str_if_starts_with:nn} \begin{syntax}\dcs\marg{first}\marg{second} \end{syntax} Checks whether the string \meta{first} starts with the string \meta{second} (i.e. \meta{second} is a prefix of \meta{first}). \end{sfunction} \begin{sfunction}{stex_str_if_ends_with:nn}[pTF]{\stex_str_if_ends_with:nn} \begin{syntax}\dcs\marg{first}\marg{second} \end{syntax} Checks whether the string \meta{first} ends with the string \meta{second} (i.e. \meta{second} is a suffix of \meta{first}). \end{sfunction} \begin{sfragment}{File Paths} \emph{File paths} are represented as \LaTeX3 sequences. The following methods make sure to \begin{itemize} \item canonicalize paths, i.e. resolve |..| and |.| segments, \item set all category codes to 12 (other), and \item tranform windows file paths containing |\| uniformly to |/|. \end{itemize} \stexvarmacro{macro} \begin{sfunction}{stex_file_resolve:Nn}{\stex_file_resolve:Nn, \stex_file_resolve:No, \stex_file_resolve:Nx} \begin{syntax}\dcs\marg{\cs{macro}}\marg{string} \end{syntax} resolves and canonicalizes the file path string \meta{string} and stores the result in \cs{macro}. \end{sfunction} \begin{sfunction}{stex_file_set:Nn}{\stex_file_set:Nn, \stex_file_set:No, \stex_file_set:Nx} \begin{syntax}\dcs\marg{\cs{macro}}\marg{string} \end{syntax} represents an already canonicalized file path string as a \LaTeX3 sequence and stores it in \cs{macro}. \end{sfunction} \begin{sfunction}{stex_if_file_absolute:N}[pTF]{\stex_if_file_absolute:N} \dcs tests whether the given file path (represented as a canonicalized \LaTeX3 sequence) is an absolute file path. \end{sfunction} \begin{sfunction}{stex_file_use:N}[EXP]{\stex_file_use:N} \dcs expands to a string representation of the given file path. \end{sfunction} \stexvarmacro{first} \stexvarmacro{second} \begin{sfunction}{stex_if_file_starts_with:NN}[TF]{\stex_if_file_starts_with:NN} \begin{syntax}\dcs\marg{\cs{first}}\marg{\cs{second}} \end{syntax} tests whether the file path \cs{first} is a child of \cs{second}. \emph{(Not expandable)} \end{sfunction} \stexvarmacro{source} \stexvarmacro{target} \begin{sfunction}{stex_file_split_off_ext:NN}{\stex_file_split_off_ext:NN} \begin{syntax}\dcs\marg{\cs{target}}\marg{\cs{source}} \end{syntax} splits off the file extension of \cs{source} and stores the resulting file path in \cs{target} \end{sfunction} \begin{sfunction}{stex_file_split_off_lang:NN}{\stex_file_split_off_lang:NN} \begin{syntax}\dcs\marg{\cs{target}}\marg{\cs{source}} \end{syntax} checks whether the file path \cs{source} ends with a language abbreviation (e.g. |.en|), if so removes it, and stores the result in \cs{target}. \end{sfunction} The following are primarily used in file hooks, but might occasionally be useful to call manually: \stexmacro{g_stex_current_file} \stexmacro{c_stex_main_file} \begin{sfunction}{stex_filestack_push:n}{\stex_filestack_push:n} pushes the given file to the file stack, recomputing \cs{g_stex_current_file}, the current language, document URI and namespace. \end{sfunction} \begin{sfunction}{stex_filestack_pop:}{\stex_filestack_pop:} pops the current top entry of the file stack. If the file stack is empty, resets to \cs{c_stex_main_file}. \end{sfunction} \begin{sfragment}{File Path Constants and Variables} \begin{svariable}{c_stex_pwd_file,c_stex_main_file}{\c_stex_pwd_file,\c_stex_main_file} store the parent working directory and the absolute path of the main file being processed (with guessed file extension |.tex|). \end{svariable} \begin{svariable}{c_stex_home_file}{\c_stex_home_file} stores the user's home directory. \end{svariable} \begin{svariable}{c_stex_mathhub_file}{\c_stex_mathhub_file} stores the user's MathHub directory; its string representation is stored in \cs{mathhub}. \end{svariable} \begin{svariable}{g_stex_current_file}{\g_stex_current_file} always points to the \emph{current} file. \end{svariable} \end{sfragment} \end{sfragment} \begin{sfragment}{URIs} \stexmacro{__stex_path_auth:n} \stexmacro{__stex_path_path:n} \stexmacro{__stex_path_module:n} \stexmacro{__stex_path_name:n} \stexmacro{stex_uri_resolve:Nn} \begin{sparagraph}[style=symdoc,for={__stex_path_auth:n,% __stex_path_path:n,__stex_path_module:n,__stex_path_name:n}] \mmt URIs are represented as token lists of the form |{|\cs{__stex_path_auth:n}\marg{authority} \cs{__stex_path_path:n}\marg{path} \cs{__stex_path_module:n}\marg{modulename} \cs{__stex_path_name:n}\marg{declname}|}|, all of which may be empty. Largely, URIs are used as strings only, but the above representation is used in \cs{stex_uri_resolve:Nn} to canonicalize URIs when they are computed the first time. \end{sparagraph} \stexvarmacro{uri} \begin{sfunction}{stex_map_uri:Nnnnn}{\stex_map_uri:Nnnnn} \begin{syntax} \dcs\marg{\cs{uri}}\marg{authority code} \marg{path code}\marg{modulename code}\marg{declname code} \end{syntax} executes the provided \meta{code}s with the components of the \cs{uri} as arguments. \end{sfunction} \begin{sfunction}{stex_uri_resolve:Nn}{\stex_uri_resolve:Nn, \stex_uri_resolve:No, \stex_uri_resolve:Nx} behaves analogously to \cs{stex_file_resolve:Nn}. \end{sfunction} \begin{sfunction}{stex_uri_set:Nn}{\stex_uri_set:Nn, \stex_uri_set:No, \stex_uri_set:Nx} behaves analogously to \cs{stex_file_set:Nn}. \end{sfunction} \begin{sfunction}{stex_uri_use:N}[EXP]{\stex_uri_use:N} behaves analogously to \cs{stex_file_use:N}. \end{sfunction} A common usage of URIs is computing the namespace of content elements (modules or documents) from the namespace of a math archive and some relative file path within that archive. \stexvarmacro{target} \stexvarmacro{repo_prop} \stexvarmacro{filepath} \begin{sfunction}{stex_uri_from_repo_file:NNNn}{\stex_uri_from_repo_file:NNNn} \begin{syntax} \dcs\marg{\cs{target}}\marg{\cs{repo_prop}}\marg{\cs{filepath}} \marg{ns\_field} \end{syntax} computes the namespace URI from the property list \cs{repo_prop} of some math archive, the file path \cs{filepath} and the archive field \marg{ns\_field} (|narr| or |ns|), and stores the result in \cs{target}. \end{sfunction} \begin{sfunction}{stex_uri_from_repo_file_nolang:NNNn}{\stex_uri_from_repo_file_nolang:NNNn} behaves like \cs{stex_uri_from_repo_file:NNNn}, but makes sure to split off language abbreviations from the file name (e.g. |.en|). \end{sfunction} \begin{sfunction}{stex_uri_from_current_file:Nn, stex_uri_from_current_file_nolang:Nn}{\stex_uri_from_current_file:Nn, \stex_uri_from_current_file_nolang:Nn} Special cases for \cs{stex_uri_from_repo_file}|[_nolang]:NNNn|, for \cs{repo_prop}|=|\cs{l_stex_current_archive_prop} and \cs{filepath}|=|\cs{g_stex_current_file}. \end{sfunction} \stexmacro{l_stex_current_doc_uri} \begin{sfunction}{stex_set_document_uri:}{\stex_set_document_uri:} sets the current value of \cs{l_stex_current_doc_uri} based on the current file and archive. \end{sfunction} \stexmacro{l_stex_current_ns_uri} \begin{sfunction}{stex_set_current_namespace:}{\stex_set_current_namespace:} sets the current value of \cs{l_stex_current_ns_uri} based on the current file and archive. \end{sfunction} \begin{sfunction}{stex_uri_add_module:NNn}{\stex_uri_add_module:NNn, \stex_uri_add_module:NNo} \begin{syntax} \dcs\marg{\cs{target}}\marg{\cs{uri}} \marg{name} \end{syntax} Checks that URI \cs{uri} has no module name, adds the provided \meta{name} and stores the result in \cs{target}. \end{sfunction} \begin{sfragment}{URI Constants and Variables} \begin{svariable}{l_stex_current_doc_uri}{\l_stex_current_doc_uri} always points to the current document URI. \end{svariable} \begin{svariable}{l_stex_current_ns_uri}{\l_stex_current_ns_uri} always points to the current content namespace. \end{svariable} \end{sfragment} \end{sfragment} \end{sfragment} \begin{sfragment}{Language Handling} \begin{svariable}{c_stex_languages_prop,c_stex_language_abbrevs_prop}{\c_stex_languages_prop,\c_stex_language_abbrevs_prop} Property lists converting babel languages to/from their abreviations; e.g. \begin{itemize} \item |\prop_item:Nn |\cs{c_stex_languages_prop}| {de}| yields |ngerman|, and \item \cs{c_stex_language_abbrevs_prop}| {ngerman}| yields |de|. \end{itemize} \end{svariable} \begin{svariable}{l_stex_current_language_str}{\l_stex_current_language_str} always stores the current language. \end{svariable} \begin{sfunction}{stex_set_language:n}{\stex_set_language:n, \stex_set_language:x, \stex_set_language:o} \begin{syntax}\dcs\marg{abbrev}\end{syntax} Sets \cs{l_stex_current_language_str}, and, if the \pkg{babel} package is loaded, calls \cs{selectlanguage} on the language corresponding to \marg{abbrev}. Note that the package option |lang=| automatically loads the \pkg{babel} package. If \meta{abbrev}|=tr|, additionally call \cs{selectlanguage} with the option |shorthands=:!|. Throws |error/unknownlanguage| if no language with abbreviation \marg{abbrev} is known. \end{sfunction} \begin{sfunction}{stex_language_from_file:}{\stex_language_from_file:} infers the current language from file ending (e.g. |.en.tex|) and sets it appropriately. Is called in a file hook, i.e. always switches language when inputting a file |..|. \end{sfunction} \end{sfragment} \begin{sfragment}{Inserting Annotations} \stex can be used to produce either \HTML or \PDF. In \HTML-mode, multiple macros exist to insert annotations. The same macros are also valid in \PDF mode but implemented as null operations. \begin{sfunction}{stex_suppress_html:n}{\stex_suppress_html:n} \begin{syntax}\dcs\marg{code}\end{syntax} turns annotations off temporarily in \meta{code} (e.g. as to not generate additional annotations for elaborated declarations, or in sms-mode). \end{sfunction} For that to work, code that inserts annotations should use \begin{sfunction}{stex_if_do_html:}[pTF]{\stex_if_do_html:} tests whether to generate \HTML annotations. \end{sfunction} \begin{sfunction}{stex@backend}{\stex@backend} should be set by a backend engine, such that a file |stex-backend-|\dcs{}|.cfg| exists. \end{sfunction} \begin{sfragment}{Backend macros} Such a backend config file should provide the following: \begin{sfunction}{stex_if_html_backend:}[pTF]{\stex_if_html_backend:} can be used to determine whether the backend produces \HTML (e.g. \rustex or \LaTeXML) or not (e.g. |pdflatex|). \cs{ifstexhtml} is set accordingly. \end{sfunction} \begin{sfunction}{stex_annotate:nnn}{\stex_annotate:nnn} \begin{syntax} \dcs\marg{attr}\marg{value}\marg{code} \end{syntax} In \HTML mode, annotates the output of \meta{code} with the \XML-attribute \meta{attr}|="|\meta{value}|"|. In \PDF mode, just calls \meta{code}. \end{sfunction} \begin{sfunction}{stex_annotate_invisible:nnn,stex_annotate_invisible:n}{\stex_annotate_invisible:nnn,\stex_annotate_invisible:n} \begin{syntax} \dcs[stex_annotate_invisible:n]\marg{code} \end{syntax} Should annotate \meta{code} with |shtml:visible="false" style="display:none;"|. In \PDF mode, does nothing. \dcs combines \cs{stex_annotate_invisible:n} and \cs{stex_annotate:nnn}. \end{sfunction} \begin{senv}{stex_annotate_env} \cs{begin}|{|\denv|}|\marg{attr}\marg{value} \meta{code} \cs{end}|{|\denv|}| should behave like \cs{stex_annotate:nnn}\marg{attr}\marg{value}\marg{code} \end{senv} \begin{sfunction}{stex_mathml_intent:nn,stex_mathml_arg:nn}{\stex_mathml_intent:nn,\stex_mathml_arg:nn} MathML Intent (TODO) \end{sfunction} \end{sfragment} \end{sfragment} \begin{sfragment}{Persisting Content from Math Archives in sms-Files} \begin{sfunction}{stex_persist:n}{\stex_persist:n,\stex_persist:e} \begin{syntax}\dcs\marg{code}\end{syntax} writes \meta{code} to the \cs{jobname}|.sms|-file, if |writesms| is active. \begin{texnote} \meta{code} is being read with \pkg{expl3} category codes (except for spaces having catcode 10), but not pretokenized; i.e. \meta{code} can safely change the current catcode scheme. \end{texnote} \end{sfunction} \begin{svariable}{c_stex_persist_mode_bool,c_stex_persist_write_mode_bool}{ \c_stex_persist_mode_bool,\c_stex_persist_write_mode_bool } whether |usesms| or |writesms| are active. \end{svariable} \end{sfragment} \begin{sfragment}{Utility Methods} \stexvarmacro{foo} \begin{sfunction}{stex_macro_body:N}[EXP]{\stex_macro_body:N} expands to the \emph{expansion} of the provided macro, including parameter tokens, with the original category codes intact; e.g. if \cs{def}\cs{foo}|#1{First #1}|, then \dcs\cs{foo} expands to |First #1|. \end{sfunction} \begin{sfunction}{stex_macro_definition:N}[EXP]{\stex_macro_definition:N} expands to the token list \emph{defining} the provided macro, including parameters, command attributes (i.e. \cs{long}, \cs{protected}), with the original category codes intact; e.g. if \cs{protected}\cs{def}\cs{foo}|#1{First #1}|, then \dcs\cs{foo} expands to \cs{protected}\cs{def}\cs{foo}|#1{First #1}|. \begin{texnote} Does not work with ``higher'' parameter tokens, i.e. |##1|, |####1| etc.\end{texnote} \end{sfunction} \stexvarmacro{macro} \begin{sfunction}{stex_deactivate_macro:Nn, stex_reactivate_macro:N}{\stex_deactivate_macro:Nn, \stex_reactivate_macro:N} \begin{syntax}\dcs \marg{\cs{macro}} \marg{msg} \end{syntax} Makes \cs{macro} throw an error message |error/deactivated-macro|\marg{msg}, notifying an author that the macro is only allowed in certain environments. \dcs[stex_reactivate_macro:N] restores the functionality of the macro. \end{sfunction} \begin{sfunction}{stex_kpsewhich:Nn}{\stex_kpsewhich:Nn} \begin{syntax} \dcs \marg{\cs{macro}} \marg{args} \end{syntax} Calls ``|kpsewhich| \meta{args}'' and stores the result in \cs{macro}, %^^A Foo \begin{texnote} Does not require |shell-escape| \end{texnote} %^^A %^^A %^^A \begin{arguments} %^^A \item Narf? %^^A \end{arguments} %^^A \end{sfunction} \begin{sfunction}{stex_get_env:Nn}{\stex_get_env:Nn} \begin{syntax} \dcs \marg{\cs{macro}} \marg{envvar} \end{syntax} Stores the value of the environment variable \meta{envvar} in \cs{macro}. \end{sfunction} \begin{sfunction}{stex_fatal_error:n}{\stex_fatal_error:n,\stex_fatal_error:nnn,\stex_fatal_error:nxx} Mimic the \cs{msg_error:}-macros, but make sure that \TeX\ stops processing. \begin{texnote} Calls |\input{non-existent file}|. \end{texnote} \end{sfunction} \begin{sfunction}{stex_ignore_spaces_and_pars:}{\stex_ignore_spaces_and_pars:} As the name suggests, ignores all subsequent spaces and \cs{par}s until the first non-expandable macro is encountered. Useful for e.g. ending \cs{symdecl} and related macros with, so that formatting sources with empty lines does not cause paragraph breaks. \end{sfunction} \begin{sfragment}{Group-like Behaviours} \begin{sfunction}{stex_pseudogroup_with:nn}{\stex_pseudogroup_with:nn} \begin{syntax}\dcs\marg{macros}\marg{code} \end{syntax} Calls \meta{code} and subsequently restores the values of the \meta{macros} given. \begin{texnote} Does \emph{not} work recursively! \end{texnote} \end{sfunction} \stexmacro{stex_pseudogroup_restore:N} \begin{sfunction}{stex_pseudogroup:nn}{\stex_pseudogroup:nn} \begin{syntax}\dcs\marg{code1}\marg{code2} \end{syntax} Expands \meta{code2}, and inserts the result after \meta{code1}. Works recursively and allows for restoring the values of macros in combination with \cs{stex_pseudogroup_restore:N}, but \emph{only for macros that take no arguments}: \end{sfunction} \begin{sfunction}{stex_pseudogroup_restore:N}[EXP]{\stex_pseudogroup_restore:N} \begin{syntax}\dcs\marg{\cs{macro}} \end{syntax} \end{sfunction} \begin{sexample} \stexvarmacro{foo} \stexvarmacro{num} \begin{stexcode}[gobble=8] |\cs{stex_pseudogroup:nn}|{ something changing |\cs{foo}| something changing |\cs{num}| }{ |\cs{stex_pseudogroup_restore:N}\cs{foo}| \int_set:Nn |\cs{num}| {\int_use:N |\cs{num}|} } \end{stexcode} restores the values of macro \cs{foo} and register \cs{num} after calling the first block. \end{sexample} Commands like \cs{symdecl} and \cs{importmodule} that generate (semantic) macros should be local \emph{to the current module}, e.g. \env{smodule}. For that purpose, we open a new ``metagroup'' with some identifier (e.g. \cs{l_stex_current_module_str}) and then execute the relevant code \emph{in the metagroup with that identifier}: \begin{sfunction}{stex_metagroup_new:n}{\stex_metagroup_new:n, \stex_metagroup_new:o} \begin{syntax}\dcs \marg{id}\end{syntax} Opens a new metagroup at the current \TeX\ group level with identifier \meta{id}. \end{sfunction} \begin{sfunction}{stex_metagroup_do_in:nn}{\stex_metagroup_do_in:nn, \stex_metagroup_do_in:nx} \begin{syntax}\dcs \marg{id}\marg{code}\end{syntax} Executes \meta{code} and adds its content to \cs{aftergroup} up until the \TeX\ group level of the metagroup with identifier \meta{id}. \end{sfunction} \end{sfragment} \end{sfragment} \end{smodule} %^^A^^A \begin{TemplateInterfaceDescription}{foo} %^^A^^A \TemplateArgument{1}{Something Here} %^^A^^A \TemplateSemantics{Some Narf Here} %^^A^^A \end{TemplateInterfaceDescription} %^^A^^A \begin{TemplateDescription}{foo}{bar} %^^A^^A \TemplateKey{narf}{Something Here} %^^A^^A \TemplateSemantics{Some Narf Here} %^^A^^A \end{TemplateDescription} %^^A^^A \begin{InstanceDescription}{foo}{newinst}{bar} %^^A^^A \InstanceKey{narf}{Something Here} %^^A^^A \InstanceSemantics{Some Narf Here} %^^A^^A \end{InstanceDescription} %^^A^^A \cs{stex_kpsewhich:Nn} %^^A \begin{function}{\stex_kpsewhich:Nn} %^^A Foo %^^A \begin{texnote} Foo! \end{texnote} %^^A %^^A \begin{syntax} \cs{stex_kpsewhich:Nn} \meta{something} \Arg{argh} %^^A \end{syntax} %^^A %^^A \begin{arguments} %^^A \item Narf? %^^A \end{arguments} %^^A %^^A \end{function}