diff options
Diffstat (limited to 'macros/latex/contrib/stex/source/stex')
-rw-r--r-- | macros/latex/contrib/stex/source/stex/Makefile | 23 | ||||
-rw-r--r-- | macros/latex/contrib/stex/source/stex/basics.dtx | 562 | ||||
-rw-r--r-- | macros/latex/contrib/stex/source/stex/features.dtx | 784 | ||||
-rw-r--r-- | macros/latex/contrib/stex/source/stex/inheritance.dtx | 575 | ||||
-rw-r--r-- | macros/latex/contrib/stex/source/stex/mathhub.dtx | 916 | ||||
-rw-r--r-- | macros/latex/contrib/stex/source/stex/metatheory.dtx | 179 | ||||
-rw-r--r-- | macros/latex/contrib/stex/source/stex/modules.dtx | 824 | ||||
-rw-r--r-- | macros/latex/contrib/stex/source/stex/others.dtx | 87 | ||||
-rw-r--r-- | macros/latex/contrib/stex/source/stex/references.dtx | 525 | ||||
-rw-r--r-- | macros/latex/contrib/stex/source/stex/sproof.dtx | 1053 | ||||
-rw-r--r-- | macros/latex/contrib/stex/source/stex/statements.dtx | 908 | ||||
-rw-r--r-- | macros/latex/contrib/stex/source/stex/stex.ins | 46 | ||||
-rw-r--r-- | macros/latex/contrib/stex/source/stex/symbols.dtx | 1263 | ||||
-rw-r--r-- | macros/latex/contrib/stex/source/stex/terms.dtx | 1037 |
14 files changed, 8782 insertions, 0 deletions
diff --git a/macros/latex/contrib/stex/source/stex/Makefile b/macros/latex/contrib/stex/source/stex/Makefile new file mode 100644 index 0000000000..2b9a63750b --- /dev/null +++ b/macros/latex/contrib/stex/source/stex/Makefile @@ -0,0 +1,23 @@ +DTX = $(shell ls *.dtx) +DOC = $(DTX:%.dtx=%.pdf) +INS = stex.ins + +PDFLATEX = pdflatex -interaction=batchmode +TEXDIR = ../../tex +TEXINPUTS = $(TEXDIR)//: + +all: package doc + +doc: $(DOC) + +package: $(DTX) $(INS) + $(PDFLATEX) $(INS) + mv *.sty *.cls $(TEXDIR) + +$(DOC): %.pdf: %.dtx + $(PDFLATEX) $< + biber -q $(basename $<) + $(PDFLATEX) $< + +echo: + @echo $(TEXINPUTS) diff --git a/macros/latex/contrib/stex/source/stex/basics.dtx b/macros/latex/contrib/stex/source/stex/basics.dtx new file mode 100644 index 0000000000..c2047a39a2 --- /dev/null +++ b/macros/latex/contrib/stex/source/stex/basics.dtx @@ -0,0 +1,562 @@ +% \iffalse meta-comment +% An Infrastructure for Semantic Macros and Module Scoping +% Copyright (c) 2019 Michael Kohlhase, all rights reserved +% this file is released under the +% LaTeX Project Public License (LPPL) +% +% The original of this file is in the public repository at +% http://github.com/sLaTeX/sTeX/ +% +% TODO update copyright +% +%<*driver> +\providecommand\bibfolder{../../lib/bib} +\input{../../doc/docheader} + +\begin{document} + \DocInput{\jobname.dtx} +\end{document} +%</driver> +% \fi +% +% \title{ \sTeX-Basics +% \thanks{Version {\fileversion} (last revised {\filedate})} +% } +% +% \author{Michael Kohlhase, Dennis Müller\\ +% FAU Erlangen-Nürnberg\\ +% \url{http://kwarc.info/} +% } +% +% \maketitle +% +%\ifinfulldoc\else +% This is the documentation for the \pkg{stex-basics} package. +% For a more high-level introduction, +% see \href{\basedocurl/manual.pdf}{the \sTeX Manual} or the +% \href{\basedocurl/stex.pdf}{full \sTeX documentation}. +% \fi +% +% \begin{documentation}\label{pkg:basics:doc} +% +% This sub package provides general set up code, auxiliary methods +% and abstractions for |xhtml| annotations. +% +%\ifinfulldoc\else +% \input{../../doc/packages/basics} +% \fi +% +% +% \section{Macros and Environments}\label{pkg:basics:doc:macros} +% +% \begin{function}{\sTeX , \stex} +% Both print this \stex logo. +% \end{function} +% +% \begin{function}{\stex_debug:nn} +% \begin{syntax} +% \cs{stex_debug:nn} \Arg{log-prefix} \Arg{message} ^^A \meta{comma list} +% \end{syntax} +% Logs \meta{message}, if the package option |debug| contains \meta{log-prefix}. +% \end{function} +% +% \subsection{HTML Annotations} +% +% \begin{function}{\if@latexml} +% \LaTeX2e conditional for \latexml +% \end{function} +% +% \begin{function}[pTF]{\latexml_if:} +% \LaTeX3 conditionals for \latexml. +% \end{function} +% +% \begin{function}[pTF]{\stex_if_do_html:} +% Whether to currently produce any HTML annotations (can be false +% in some advanced structuring environments, for example) +% \end{function} +% +% \begin{function}{\stex_suppress_html:n} +% Temporarily disables HTML annotations in its argument code +% \end{function} +% +% +% We have four macros for annotating generated HTML (via \latexml +% or \rustex) with attributes: +% +% \begin{function}{\stex_annotate:nnn, \stex_annotate_invisible:nnn, +% \stex_annotate_invisible:n} +% \begin{syntax} \cs{stex_annotate:nnn} \Arg{property} \Arg{resource} \Arg{content} \end{syntax} +% Annotates the HTML generated by \meta{content} with\\ +% \begin{center} +% |property="stex:|\meta{property}|", resource="|\meta{resource}|"|. +% \end{center} +% +% \cs{stex_annotate_invisible:n} adds the attributes\\ +% \begin{center} +% |stex:visible="false", style="display:none"|. +% \end{center} +% +% \cs{stex_annotate_invisible:nnn} combines the functionality of both. +% \end{function} +% +% \begin{environment}{stex_annotate_env} +% \begin{syntax} \cs{begin}|{stex_annotate_env}|\Arg{property}\Arg{resource} +% \meta{content} +% \cs{end}|{stex_annotate_env}| +% \end{syntax} +% behaves like \cs{stex_annotate:nnn} \Arg{property} \Arg{resource} +% \Arg{content}. +% \end{environment} +% +% \subsection{Babel Languages} +% +% \begin{variable}{\c_stex_languages_prop,\c_stex_language_abbrevs_prop} +% Map language abbreviations to their full babel names and vice versa. +% e.g. \cs{c_stex_languages_prop}|{en}| yields |english|, and +% \cs{c_stex_language_abbrevs_prop}|{english}| yields |en|. +% \end{variable} +% +% \subsection{Auxiliary Methods} +% +% \begin{function}{\stex_deactivate_macro:Nn , \stex_reactivate_macro:N} +% \begin{syntax}\cs{stex_deactivate_macro:Nn}\meta{cs}\Arg{environments}\end{syntax} +% Makes the macro \meta{cs} throw an error, indicating that it +% is only allowed in the context of \meta{environments}. +% +% \cs{stex_reactivate_macro:N}\meta{cs} reactivates it again, i.e. +% this happens ideally in the \meta{begin}-code of the associated +% environments. +% \end{function} +% +% \begin{function}{\ignorespacesandpars} +% ignores white space characters and |\par| control sequences. +% Expands tokens in the process. +% \end{function} +% +% \end{documentation} +% +% \begin{implementation} +% +% \section{\sTeX-Basics Implementation}\label{pkg:basics:impl} +% +% \subsection{The \sTeX Document Class} +% +% The \cls{stex} document class is pretty straight-forward: It largely extends the \cls{standalone} package +% and loads the \pkg{stex} package, passing all provided options on to the package. +% +% \begin{macrocode} +%<*cls> + +%%%%%%%%%%%%% basics.dtx %%%%%%%%%%%%% + +\RequirePackage{expl3,l3keys2e} +\ProvidesExplClass{stex}{2022/02/24}{3.0.0}{sTeX document class} +\LoadClass[border=1px,varwidth]{standalone} +\setlength\textwidth{15cm} + +\DeclareOption*{\PassOptionsToPackage{\CurrentOption}{stex}} +\ProcessOptions + +\RequirePackage{stex} +%</cls> +% \end{macrocode} +% +% \subsection{Preliminaries} +% +% \begin{macrocode} +%<*package> + +%%%%%%%%%%%%% basics.dtx %%%%%%%%%%%%% + +\RequirePackage{expl3,l3keys2e,ltxcmds} +\ProvidesExplPackage{stex}{2022/02/24}{3.0.0}{sTeX package} + +%\RequirePackage{morewrites} +%\RequirePackage{amsmath} + +% \end{macrocode} +% +% Package options: +% +% \begin{macrocode} +\keys_define:nn { stex } { + debug .clist_set:N = \c_stex_debug_clist , + lang .clist_set:N = \c_stex_languages_clist , + mathhub .tl_set_x:N = \mathhub , + sms .bool_set:N = \c_stex_persist_mode_bool , + image .bool_set:N = \c_tikzinput_image_bool, + unknown .code:n = {} +} +\ProcessKeysOptions { stex } +% \end{macrocode} +% +% \begin{macro}{\stex,\sTeX} +% The \sTeX logo: +% +% \begin{macrocode} +\protected\def\stex{% + \@ifundefined{texorpdfstring}% + {\let\texorpdfstring\@firstoftwo}% + {}% + \texorpdfstring{\raisebox{-.5ex}S\kern-.5ex\TeX}{sTeX}\xspace% +} +\def\sTeX{\stex} +% \end{macrocode} +% \end{macro} +% +% +% \subsection{Messages and logging} +% +% \begin{macrocode} +%<@@=stex_log> +% \end{macrocode} +% +% Warnings and error messages +% +% \begin{macrocode} +\msg_new:nnn{stex}{error/unknownlanguage}{ + Unknown~language:~#1 +} +\msg_new:nnn{stex}{warning/nomathhub}{ + MATHHUB~system~variable~not~found~and~no~ + \detokenize{\mathhub}-value~set! +} +\msg_new:nnn{stex}{error/deactivated-macro}{ + The~\detokenize{#1}~command~is~only~allowed~in~#2! +} +% \end{macrocode} +% +% \begin{macro}{\stex_debug:nn} +% +% A simple macro issuing package messages with subpath. +% +% \begin{macrocode} +\cs_new_protected:Nn \stex_debug:nn { + \clist_if_in:NnTF \c_stex_debug_clist { all } { + \exp_args:Nnnx\msg_set:nnn{stex}{debug / #1}{ + \\Debug~#1:~#2\\ + } + \msg_none:nn{stex}{debug / #1} + }{ + \clist_if_in:NnT \c_stex_debug_clist { #1 } { + \exp_args:Nnnx\msg_set:nnn{stex}{debug / #1}{ + \\Debug~#1:~#2\\ + } + \msg_none:nn{stex}{debug / #1} + } + } +} +% \end{macrocode} +% \end{macro} +% +% Redirecting messages: +% +% \begin{macrocode} +\clist_if_in:NnTF \c_stex_debug_clist {all} { + \msg_redirect_module:nnn{ stex }{ none }{ term } +}{ + \clist_map_inline:Nn \c_stex_debug_clist { + \msg_redirect_name:nnn{ stex }{ debug / ##1 }{ term } + } +} + +\stex_debug:nn{log}{debug~mode~on} +% \end{macrocode} +% +% +% \subsection{HTML Annotations} +% \begin{macrocode} +%<@@=stex_annotate> +\RequirePackage{rustex} +% \end{macrocode} +% +% We add the namespace abbreviation |ns:stex="http://kwarc.info/ns/sTeX"| to \rustex: +% +% \begin{macrocode} +\rustex_add_Namespace:nn{stex}{http://kwarc.info/ns/sTeX} +% \end{macrocode} +% +% Conditionals for \latexml: +% +% \begin{macro}{\if@latexml} +% \begin{macrocode} +\ifcsname if@latexml\endcsname\else + \expandafter\newif\csname if@latexml\endcsname\@latexmlfalse +\fi +% \end{macrocode} +% \end{macro} +% +% \begin{macro}[pTF]{\latexml_if:} +% \begin{macrocode} +\prg_new_conditional:Nnn \latexml_if: {p, T, F, TF} { + \if@latexml + \prg_return_true: + \else: + \prg_return_false: + \fi: +} +% \end{macrocode} +% \end{macro} +% +% \begin{variable}{\l_@@_arg_tl, \c_@@_emptyarg_tl} +% +% Used by annotation macros to ensure that the HTML output to annotate +% is not empty. +% +% \begin{macrocode} +\tl_new:N \l_@@_arg_tl +\tl_const:Nx \c_@@_emptyarg_tl { + \rustex_if:TF { + \rustex_direct_HTML:n { \c_ampersand_str lrm; } + }{~} +} +% \end{macrocode} +% \end{variable} +% +% \begin{macro}{\_@@_checkempty:n} +% \begin{macrocode} +\cs_new_protected:Nn \_@@_checkempty:n { + \tl_set:Nn \l_@@_arg_tl { #1 } + \tl_if_empty:NT \l_@@_arg_tl { + \tl_set_eq:NN \l_@@_arg_tl \c_@@_emptyarg_tl + } +} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}[pTF]{\stex_if_do_html:} +% Whether to (locally) produce HTML output +% \begin{macrocode} +\bool_new:N \_stex_html_do_output_bool +\bool_set_true:N \_stex_html_do_output_bool + +\prg_new_conditional:Nnn \stex_if_do_html: {p,T,F,TF} { + \bool_if:nTF \_stex_html_do_output_bool + \prg_return_true: \prg_return_false: +} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\stex_suppress_html:n} +% Whether to (locally) produce HTML output +% \begin{macrocode} +\cs_new_protected:Nn \stex_suppress_html:n { + \exp_args:Nne \use:nn { + \bool_set_false:N \_stex_html_do_output_bool + #1 + }{ + \stex_if_do_html:T { + \bool_set_true:N \_stex_html_do_output_bool + } + } +} +% \end{macrocode} +% \end{macro} +% +% +% \begin{environment}{stex_annotate_env} +% \begin{macro}{\stex_annotate:nnn, \stex_annotate_invisible:n, +% \stex_annotate_invisible:nnn} +% +% We define four macros for introducing attributes in the HTML +% output. The definitions depend on the ``backend'' used +% (\latexml, \rustex, \texttt{pdflatex}). +% +% The \texttt{pdflatex}-macros largely do nothing; the +% \rustex-implementations are pretty clear in what they do, +% the \latexml-implementations resort to perl bindings. +% +% \begin{macrocode} +\rustex_if:TF{ + \cs_new_protected:Nn \stex_annotate:nnn { + \_@@_checkempty:n { #3 } + \rustex_annotate_HTML:nn { + property="stex:#1" ~ + resource="#2" + } { + \mode_if_vertical:TF{ + \tl_use:N \l_@@_arg_tl\par + }{ + \tl_use:N \l_@@_arg_tl + } + } + } + \cs_new_protected:Nn \stex_annotate_invisible:n { + \_@@_checkempty:n { #1 } + \rustex_annotate_HTML:nn { + stex:visible="false" ~ + style:display="none" + } { + \mode_if_vertical:TF{ + \tl_use:N \l_@@_arg_tl\par + }{ + \tl_use:N \l_@@_arg_tl + } + } + } + \cs_new_protected:Nn \stex_annotate_invisible:nnn { + \_@@_checkempty:n { #3 } + \rustex_annotate_HTML:nn { + property="stex:#1" ~ + resource="#2" ~ + stex:visible="false" ~ + style:display="none" + } { + \mode_if_vertical:TF{ + \tl_use:N \l_@@_arg_tl\par + }{ + \tl_use:N \l_@@_arg_tl + } + } + } + \NewDocumentEnvironment{stex_annotate_env} { m m } { + \par + \rustex_annotate_HTML_begin:n { + property="stex:#1" ~ + resource="#2" + } + }{ + \par\rustex_annotate_HTML_end: + } +}{ + \latexml_if:TF { + \cs_new_protected:Nn \stex_annotate:nnn { + \_@@_checkempty:n { #3 } + \mode_if_math:TF { + \cs:w latexml@annotate@math\cs_end:{#1}{#2}{ + \tl_use:N \l_@@_arg_tl + } + }{ + \cs:w latexml@annotate@text\cs_end:{#1}{#2}{ + \tl_use:N \l_@@_arg_tl + } + } + } + \cs_new_protected:Nn \stex_annotate_invisible:n { + \_@@_checkempty:n { #1 } + \mode_if_math:TF { + \cs:w latexml@invisible@math\cs_end:{ + \tl_use:N \l_@@_arg_tl + } + } { + \cs:w latexml@invisible@text\cs_end:{ + \tl_use:N \l_@@_arg_tl + } + } + } + \cs_new_protected:Nn \stex_annotate_invisible:nnn { + \_@@_checkempty:n { #3 } + \cs:w latexml@annotate@invisible\cs_end:{#1}{#2}{ + \tl_use:N \l_@@_arg_tl + } + } + \NewDocumentEnvironment{stex_annotate_env} { m m } { + \par\begin{latexml@annotateenv}{#1}{#2} + }{ + \par\end{latexml@annotateenv} + } + }{ + \cs_new_protected:Nn \stex_annotate:nnn {#3} + \cs_new_protected:Nn \stex_annotate_invisible:n {} + \cs_new_protected:Nn \stex_annotate_invisible:nnn {} + \NewDocumentEnvironment{stex_annotate_env} { m m } {}{} + } +} +% \end{macrocode} +% \end{macro} +% \end{environment} +% +% \subsection{Babel Languages} +% \begin{macrocode} +%<@@=stex_language> +% \end{macrocode} +% +% \begin{variable}{\c_stex_languages_prop,\c_stex_language_abbrevs_prop} +% +% We store language abbreviations in two (mutually inverse) +% property lists: +% \begin{macrocode} +\prop_const_from_keyval:Nn \c_stex_languages_prop { + en = english , + de = ngerman , + ar = arabic , + bg = bulgarian , + ru = russian , + fi = finnish , + ro = romanian , + tr = turkish , + fr = french +} + +\prop_const_from_keyval:Nn \c_stex_language_abbrevs_prop { + english = en , + ngerman = de , + arabic = ar , + bulgarian = bg , + russian = ru , + finnish = fi , + romanian = ro , + turkish = tr , + french = fr +} +% todo: chinese simplified (zhs) +% chinese traditional (zht) +% \end{macrocode} +% \end{variable} +% +% we use the |lang|-package option to load the corresponding +% babel languages: +% +% \begin{macrocode} +\clist_if_empty:NF \c_stex_languages_clist { + \clist_clear:N \l_tmpa_clist + \clist_map_inline:Nn \c_stex_languages_clist { + \prop_get:NnNTF \c_stex_languages_prop { #1 } \l_tmpa_str { + \clist_put_right:No \l_tmpa_clist \l_tmpa_str + } { + \msg_error:nnx{stex}{error/unknownlanguage}{\l_tmpa_str} + } + } + \stex_debug:nn{lang} {Languages:~\clist_use:Nn \l_tmpa_clist {,~} } + \RequirePackage[\clist_use:Nn \l_tmpa_clist,]{babel} +} +% \end{macrocode} +% +% \subsection{Auxiliary Methods} +% +% \begin{macro}{\stex_deactivate_macro:Nn} +% \begin{macrocode} +\cs_new_protected:Nn \stex_deactivate_macro:Nn { + \exp_after:wN\let\csname \detokenize{#1} - orig\endcsname#1 + \def#1{ + \msg_error:nnnn{stex}{error/deactivated-macro}{#1}{#2} + } +} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\stex_reactivate_macro:N} +% \begin{macrocode} +\cs_new_protected:Nn \stex_reactivate_macro:N { + \exp_after:wN\let\exp_after:wN#1\csname \detokenize{#1} - orig\endcsname +} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\ignorespacesandpars} +% \begin{macrocode} +\protected\def\ignorespacesandpars{ + \begingroup\catcode13=10\relax + \@ifnextchar\par{ + \endgroup\expandafter\ignorespacesandpars\@gobble + }{ + \endgroup + } +} +%</package> +% \end{macrocode} +% \end{macro} +% +% \end{implementation} +% +% \PrintIndex diff --git a/macros/latex/contrib/stex/source/stex/features.dtx b/macros/latex/contrib/stex/source/stex/features.dtx new file mode 100644 index 0000000000..851af04984 --- /dev/null +++ b/macros/latex/contrib/stex/source/stex/features.dtx @@ -0,0 +1,784 @@ +% \iffalse meta-comment +% An Infrastructure for Semantic Macros and Module Scoping +% Copyright (c) 2019 Michael Kohlhase, all rights reserved +% this file is released under the +% LaTeX Project Public License (LPPL) +% +% The original of this file is in the public repository at +% http://github.com/sLaTeX/sTeX/ +% +% TODO update copyright +% +%<*driver> +\providecommand\bibfolder{../../lib/bib} +\input{../../doc/docheader} + +\begin{document} + \DocInput{\jobname.dtx} +\end{document} +%</driver> +% \fi +% +% \title{ \sTeX-Structural Features +% \thanks{Version {\fileversion} (last revised {\filedate})} +% } +% +% \author{Michael Kohlhase, Dennis Müller\\ +% FAU Erlangen-Nürnberg\\ +% \url{http://kwarc.info/} +% } +% +% \maketitle +% +%\ifinfulldoc\else +% This is the documentation for the \pkg{stex-features} package. +% For a more high-level introduction, +% see \href{\basedocurl/manual.pdf}{the \sTeX Manual} or the +% \href{\basedocurl/stex.pdf}{full \sTeX documentation}. +% +% \input{../../doc/packages/features} +% \fi +% +% \begin{documentation}\label{pkg:features:doc} +% +% Code related to structural features +% +% \section{Macros and Environments}\label{pkg:features:doc:macros} +% +% \subsection{Structures} +% +% \begin{environment}{mathstructure} +% TODO +% \end{environment} +% +% \end{documentation} +% +% \begin{implementation}\label{pkg:features:impl} +% +% \section{\sTeX-Structural Features Implementation} +% +% \begin{macrocode} +%<*package> + +%%%%%%%%%%%%% features.dtx %%%%%%%%%%%%% + +%<@@=stex_features> +% \end{macrocode} +% +% Warnings and error messages +% +% \begin{macrocode} +\msg_new:nnn{stex}{error/copymodule/notallowed}{ + Symbol~#1~can~not~be~assigned~in~copymodule~#2 +} +\msg_new:nnn{stex}{error/interpretmodule/nodefiniens}{ + Symbol~#1~not~assigned~in~interpretmodule~#2 +} + +% \end{macrocode} +% +% \subsection{Imports with modification} +% +% \begin{macrocode} +\cs_new_protected:Nn \stex_get_symbol_in_copymodule:n { + \tl_if_head_eq_catcode:nNTF { #1 } \relax { + \_@@_get_symbol_from_cs:n { #1 } + }{ + % argument is a string + % is it a command name? + \cs_if_exist:cTF { #1 }{ + \cs_set_eq:Nc \l_tmpa_tl { #1 } + \str_set:Nx \l_tmpa_str { \cs_argument_spec:N \l_tmpa_tl } + \str_if_empty:NTF \l_tmpa_str { + \exp_args:Nx \cs_if_eq:NNTF { + \tl_head:N \l_tmpa_tl + } \stex_invoke_symbol:n { + \exp_args:No \_@@_get_symbol_from_cs:n { \use:c { #1 } } + }{ + \_@@_get_symbol_from_string:n { #1 } + } + } { + \_@@_get_symbol_from_string:n { #1 } + } + }{ + % argument is not a command name + \_@@_get_symbol_from_string:n { #1 } + % \l_stex_all_symbols_seq + } + } +} + +\cs_new_protected:Nn \_@@_get_symbol_from_string:n { + \str_set:Nn \l_tmpa_str { #1 } + \bool_set_false:N \l_tmpa_bool + \bool_if:NF \l_tmpa_bool { + \tl_set:Nn \l_tmpa_tl { + \msg_set:nnn{stex}{error/unknownsymbol}{ + No~symbol~#1~found! + } + \msg_error:nn{stex}{error/unknownsymbol} + } + \str_set:Nn \l_tmpa_str { #1 } + \int_set:Nn \l_tmpa_int { \str_count:N \l_tmpa_str } + \seq_map_inline:Nn \l_@@_copymodule_fields_seq { + \str_set:Nn \l_tmpb_str { ##1 } + \str_if_eq:eeT { \l_tmpa_str } { + \str_range:Nnn \l_tmpb_str { -\l_tmpa_int } { -1 } + } { + \seq_map_break:n { + \tl_set:Nn \l_tmpa_tl { + \str_set:Nn \l_stex_get_symbol_uri_str { + ##1 + } + \_@@_get_symbol_check: + } + } + } + } + \l_tmpa_tl + } +} + +\cs_new_protected:Nn \_@@_get_symbol_from_cs:n { + \exp_args:NNx \tl_set:Nn \l_tmpa_tl + { \tl_tail:N \l_tmpa_tl } + \tl_if_single:NTF \l_tmpa_tl { + \exp_args:No \tl_if_head_is_group:nTF \l_tmpa_tl { + \exp_after:wN \str_set:Nn \exp_after:wN + \l_stex_get_symbol_uri_str \l_tmpa_tl + \_@@_get_symbol_check: + }{ + % TODO + % tail is not a single group + } + }{ + % TODO + % tail is not a single group + } +} + +\cs_new_protected:Nn \_@@_get_symbol_check: { + \exp_args:NNno \seq_set_split:Nnn \l_tmpa_seq {?} \l_stex_get_symbol_uri_str + \int_compare:nNnTF {\seq_count:N \l_tmpa_seq} = 3 { + \seq_pop_right:NN \l_tmpa_seq \l_tmpb_str + \str_set:Nx \l_tmpa_str {\seq_use:Nn \l_tmpa_seq ?} + \seq_if_in:NoF \l_@@_copymodule_modules_seq \l_tmpa_str { + \msg_error:nnxx{stex}{error/copymodule/notallowed}{\l_stex_get_symbol_uri_str}{ + \l_stex_current_copymodule_name_str\\Allowed:~\seq_use:Nn \l_@@_copymodule_modules_seq {,~} + } + } + }{ + \msg_error:nnxx{stex}{error/copymodule/notallowed}{\l_stex_get_symbol_uri_str}{ + \l_stex_current_copymodule_name_str~(inexplicably) + } + } +} + +\cs_new_protected:Nn \stex_copymodule_start:nnnn { + \stex_import_module_uri:nn { #1 } { #2 } + \str_set:Nx \l_stex_current_copymodule_name_str {#3} + \stex_import_require_module:nnnn + { \l_stex_import_ns_str } { \l_stex_import_archive_str } + { \l_stex_import_path_str } { \l_stex_import_name_str } + \stex_collect_imports:n {\l_stex_import_ns_str ?\l_stex_import_name_str } + \seq_set_eq:NN \l_@@_copymodule_modules_seq \l_stex_collect_imports_seq + \seq_clear:N \l_@@_copymodule_fields_seq + \seq_map_inline:Nn \l_@@_copymodule_modules_seq { + \seq_map_inline:cn {c_stex_module_##1_constants}{ + \exp_args:NNx \seq_put_right:Nn \l_@@_copymodule_fields_seq { + ##1 ? ####1 + } + } + } + \seq_clear:N \l_tmpa_seq + \exp_args:NNx \prop_set_from_keyval:Nn \l_stex_current_copymodule_prop { + name = \l_stex_current_copymodule_name_str , + module = \l_stex_current_module_str , + from = \l_stex_import_ns_str ?\l_stex_import_name_str , + includes = \l_tmpa_seq , + fields = \l_tmpa_seq + } + \stex_debug:nn{copymodule}{#4~for~module~{\l_stex_import_ns_str ?\l_stex_import_name_str} + as~\l_stex_current_module_str?\l_stex_current_copymodule_name_str} + \stex_debug:nn{copymodule}{modules:\seq_use:Nn \l_@@_copymodule_modules_seq {,~}} + \stex_debug:nn{copymodule}{fields:\seq_use:Nn \l_@@_copymodule_fields_seq {,~}} + \stex_if_smsmode:F { + \begin{stex_annotate_env} {#4} { + \l_stex_current_module_str?\l_stex_current_copymodule_name_str + } + \stex_annotate_invisible:nnn{from}{\l_stex_import_ns_str ?\l_stex_import_name_str}{} + } + \bool_set_eq:NN \l_@@_oldhtml_bool \_stex_html_do_output_bool + \bool_set_false:N \_stex_html_do_output_bool +} +\cs_new_protected:Nn \stex_copymodule_end:n { + \def \l_tmpa_cs ##1 ##2 {#1} + \bool_set_eq:NN \_stex_html_do_output_bool \l_@@_oldhtml_bool + \tl_clear:N \l_tmpa_tl + \tl_clear:N \l_tmpb_tl + \prop_get:NnN \l_stex_current_copymodule_prop {fields} \l_tmpa_seq + \seq_map_inline:Nn \l_@@_copymodule_modules_seq { + \seq_map_inline:cn {c_stex_module_##1_constants}{ + \tl_clear:N \l_tmpc_tl + \l_tmpa_cs{##1}{####1} + \str_if_exist:cTF {l_@@_copymodule_##1?####1_name_str} { + \tl_put_right:Nx \l_tmpa_tl { + \prop_set_from_keyval:cn { + l_stex_symdecl_\l_stex_current_module_str ? \use:c{l_@@_copymodule_##1?####1_name_str}_prop + }{ + \exp_after:wN \prop_to_keyval:N \csname + l_stex_symdecl_\l_stex_current_module_str ? \use:c{l_@@_copymodule_##1?####1_name_str}_prop + \endcsname + } + \seq_clear:c { + l_stex_symdecl_ + \l_stex_current_module_str ? \use:c{l_@@_copymodule_##1?####1_name_str} + _notations + } + } + \tl_put_right:Nx \l_tmpc_tl { + \stex_copy_notations:nn {\l_stex_current_module_str ? \use:c{l_@@_copymodule_##1?####1_name_str}}{##1?####1} + \stex_annotate_invisible:nnn{alias}{\use:c{l_@@_copymodule_##1?####1_name_str}}{} + } + \seq_put_right:Nx \l_tmpa_seq {\l_stex_current_module_str ? \use:c{l_@@_copymodule_##1?####1_name_str}} + \str_if_exist:cT {l_@@_copymodule_##1?####1_macroname_str} { + \tl_put_right:Nx \l_tmpc_tl { + \stex_annotate_invisible:nnn{macroname}{\use:c{l_@@_copymodule_##1?####1_macroname_str}}{} + } + \tl_put_right:Nx \l_tmpa_tl { + \tl_set:cx {\use:c{l_@@_copymodule_##1?####1_macroname_str}}{ + \stex_invoke_symbol:n { + \l_stex_current_module_str ? \use:c{l_@@_copymodule_##1?####1_name_str} + } + } + } + } + }{ + \tl_put_right:Nx \l_tmpc_tl { + \stex_copy_notations:nn {\l_stex_current_module_str ? \l_stex_current_copymodule_name_str / ####1 }{##1?####1} + } + \prop_set_eq:Nc \l_tmpa_prop {l_stex_symdecl_ ##1?####1 _prop} + \prop_put:Nnx \l_tmpa_prop { name }{ \l_stex_current_copymodule_name_str / ####1 } + \prop_put:Nnx \l_tmpa_prop { module }{ \l_stex_current_module_str } + \tl_put_right:Nx \l_tmpa_tl { + \prop_set_from_keyval:cn { + l_stex_symdecl_\l_stex_current_module_str ? \l_stex_current_copymodule_name_str / ####1_prop + }{ + \prop_to_keyval:N \l_tmpa_prop + } + \seq_clear:c { + l_stex_symdecl_ + \l_stex_current_module_str ? \l_stex_current_copymodule_name_str / ####1 + _notations + } + } + \seq_put_right:Nx \l_tmpa_seq {\l_stex_current_module_str ? \l_stex_current_copymodule_name_str / ####1 } + \str_if_exist:cT {l_@@_copymodule_##1?####1_macroname_str} { + \tl_put_right:Nx \l_tmpc_tl { + \stex_annotate_invisible:nnn{macroname}{\use:c{l_@@_copymodule_##1?####1_macroname_str}}{} + } + \tl_put_right:Nx \l_tmpa_tl { + \tl_set:cx {\use:c{l_@@_copymodule_##1?####1_macroname_str}}{ + \stex_invoke_symbol:n { + \l_stex_current_module_str ? \l_stex_current_copymodule_name_str / ####1 + } + } + } + } + } + \tl_if_exist:cT {l_@@_copymodule_##1?####1_def_tl}{ + \tl_put_right:Nx \l_tmpc_tl { + \stex_annotate_invisible:nnn{definiens}{}{$\use:c{l_@@_copymodule_##1?####1_def_tl}$} + } + } + \tl_put_right:Nx \l_tmpb_tl { + \stex_annotate:nnn{assignment} {##1?####1} { \l_tmpc_tl } + } + } + } + \prop_put:Nno \l_stex_current_copymodule_prop {fields} \l_tmpa_seq + \tl_put_left:Nx \l_tmpa_tl { + \prop_set_from_keyval:cn { + l_stex_copymodule_ \l_stex_current_module_str?\l_stex_current_copymodule_name_str _prop + }{ + \prop_to_keyval:N \l_stex_current_copymodule_prop + } + } + \exp_args:No \stex_add_to_current_module:n \l_tmpa_tl + \stex_debug:nn{copymodule}{result:\meaning \l_tmpa_tl} + \exp_args:Nx \stex_do_up_to_module:n { + \exp_args:No \exp_not:n \l_tmpa_tl + } + \l_tmpb_tl + \stex_if_smsmode:F { + \end{stex_annotate_env} + } +} + +\NewDocumentEnvironment {copymodule} { O{} m m}{ + \stex_copymodule_start:nnnn { #1 }{ #2 }{ #3 }{ structure } + \stex_deactivate_macro:Nn \symdecl {module~environments} + \stex_deactivate_macro:Nn \symdef {module~environments} + \stex_deactivate_macro:Nn \notation {module~environments} + \stex_reactivate_macro:N \assign + \stex_reactivate_macro:N \renamedecl + \stex_reactivate_macro:N \donotcopy + \stex_smsmode_do: +}{ + \stex_copymodule_end:n {} +} + +\NewDocumentEnvironment {interpretmodule} { O{} m m}{ + \stex_copymodule_start:nnnn { #1 }{ #2 }{ #3 }{ realization } + \stex_deactivate_macro:Nn \symdecl {module~environments} + \stex_deactivate_macro:Nn \symdef {module~environments} + \stex_deactivate_macro:Nn \notation {module~environments} + \stex_reactivate_macro:N \assign + \stex_reactivate_macro:N \renamedecl + \stex_reactivate_macro:N \donotcopy + \stex_smsmode_do: +}{ + \stex_copymodule_end:n { + \tl_if_exist:cF { + l_@@_copymodule_##1?##2_def_tl + }{ + \msg_error:nnxx{stex}{error/interpretmodule/nodefiniens}{ + ##1?##2 + }{\l_stex_current_copymodule_name_str} + } + } +} + +\NewDocumentCommand \donotcopy { O{} m}{ + \stex_import_module_uri:nn { #1 } { #2 } + \stex_collect_imports:n {\l_stex_import_ns_str ?\l_stex_import_name_str } + \seq_map_inline:Nn \l_stex_collect_imports_seq { + \seq_remove_all:Nn \l_@@_copymodule_modules_seq { ##1 } + \seq_map_inline:cn {c_stex_module_##1_constants}{ + \seq_remove_all:Nn \l_@@_copymodule_fields_seq { ##1 ? ####1 } + \bool_lazy_any_p:nT { + { \cs_if_exist_p:c {l_@@_copymodule_##1?####1_name_str}} + { \cs_if_exist_p:c {l_@@_copymodule_##1?####1_macroname_str}} + { \cs_if_exist_p:c {l_@@_copymodule_##1?####1_def_tl}} + }{ + % TODO throw error + } + } + } + + \prop_get:NnN \l_stex_current_copymodule_prop { includes } \l_tmpa_seq + \seq_put_right:Nx \l_tmpa_seq {\l_stex_import_ns_str ?\l_stex_import_name_str } + \prop_put:Nnx \l_stex_current_copymodule_prop {includes} \l_tmpa_seq +} + +\NewDocumentCommand \assign { m m }{ + \stex_get_symbol_in_copymodule:n {#1} + \stex_debug:nn{assign}{defining~{\l_stex_get_symbol_uri_str}~as~\detokenize{#2}} + \tl_set:cn {l_@@_copymodule_\l_stex_get_symbol_uri_str _def_tl}{#2} +} + +\keys_define:nn { stex / renamedecl } { + name .str_set_x:N = \l_stex_renamedecl_name_str +} +\cs_new_protected:Nn \_@@_renamedecl_args:n { + \str_clear:N \l_stex_renamedecl_name_str + + \keys_set:nn { stex / renamedecl } { #1 } +} + +\NewDocumentCommand \renamedecl { O{} m m}{ + \_@@_renamedecl_args:n { #1 } + \stex_get_symbol_in_copymodule:n {#2} + \stex_debug:nn{renamedecl}{renaming~{\l_stex_get_symbol_uri_str}~to~#3} + \str_set:cx {l_@@_copymodule_\l_stex_get_symbol_uri_str _macroname_str}{#3} + \str_if_empty:NTF \l_stex_renamedecl_name_str { + \tl_set:cx { #3 }{ \stex_invoke_symbol:n { + \l_stex_get_symbol_uri_str + } } + } { + \str_set:cx {l_@@_copymodule_\l_stex_get_symbol_uri_str _name_str}{\l_stex_renamedecl_name_str} + \stex_debug:nn{renamedecl}{@~\l_stex_current_module_str ? \l_stex_renamedecl_name_str} + \prop_set_eq:cc {l_stex_symdecl_ + \l_stex_current_module_str ? \l_stex_renamedecl_name_str + _prop + }{l_stex_symdecl_ \l_stex_get_symbol_uri_str _prop} + \seq_set_eq:cc {l_stex_symdecl_ + \l_stex_current_module_str ? \l_stex_renamedecl_name_str + _notations + }{l_stex_symdecl_ \l_stex_get_symbol_uri_str _notations} + \prop_put:cnx {l_stex_symdecl_ + \l_stex_current_module_str ? \l_stex_renamedecl_name_str + _prop + }{ name }{ \l_stex_renamedecl_name_str } + \prop_put:cnx {l_stex_symdecl_ + \l_stex_current_module_str ? \l_stex_renamedecl_name_str + _prop + }{ module }{ \l_stex_current_module_str } + \exp_args:NNx \seq_put_left:Nn \l_@@_copymodule_fields_seq { + \l_stex_current_module_str ? \l_stex_renamedecl_name_str + } + \tl_set:cx { #3 }{ \stex_invoke_symbol:n { + \l_stex_current_module_str ? \l_stex_renamedecl_name_str + } } + } +} + +\stex_deactivate_macro:Nn \assign {copymodules} +\stex_deactivate_macro:Nn \renamedecl {copymodules} +\stex_deactivate_macro:Nn \donotcopy {copymodules} + + +% \end{macrocode} +% +% +% +% \begin{macrocode} +\seq_new:N \l_stex_implicit_morphisms_seq +\NewDocumentCommand \implicitmorphism { O{} m m}{ + \stex_import_module_uri:nn { #1 } { #2 } + \stex_debug:nn{implicits}{ + Implicit~morphism:~ + \l_stex_module_ns_str ? \l_@@_name_str + } + \exp_args:NNx \seq_if_in:NnT \l_stex_all_modules_seq { + \l_stex_module_ns_str ? \l_@@_name_str + }{ + \msg_error:nnn{stex}{error/conflictingmodules}{ + \l_stex_module_ns_str ? \l_@@_name_str + } + } + + % TODO + + + + \seq_put_right:Nx \l_stex_implicit_morphisms_seq { + \l_stex_module_ns_str ? \l_@@_name_str + } +} + +% \end{macrocode} +% +% +% \subsection{The feature environment} +% +% \begin{environment}{structural@feature} +% \begin{macrocode} + +\NewDocumentEnvironment{structural@feature}{ m m m }{ + \stex_if_in_module:F { + \msg_set:nnn{stex}{error/nomodule}{ + Structural~Feature~has~to~occur~in~a~module:\\ + Feature~#2~of~type~#1\\ + In~File:~\stex_path_to_string:N \g_stex_currentfile_seq + } + \msg_error:nn{stex}{error/nomodule} + } + + \str_set:Nx \l_stex_module_name_str { + \prop_item:Nn \l_stex_current_module_prop + { name } / #2 - feature + } + + \str_set:Nx \l_stex_module_ns_str { + \prop_item:Nn \l_stex_current_module_prop + { ns } + } + + + \str_clear:N \l_tmpa_str + \seq_clear:N \l_tmpa_seq + \tl_clear:N \l_tmpa_tl + \exp_args:NNx \prop_set_from_keyval:Nn \l_stex_current_module_prop { + origname = #2, + name = \l_stex_module_name_str , + ns = \l_stex_module_ns_str , + imports = \exp_not:o { \l_tmpa_seq } , + constants = \exp_not:o { \l_tmpa_seq } , + content = \exp_not:o { \l_tmpa_tl } , + file = \exp_not:o { \g_stex_currentfile_seq } , + lang = \l_stex_module_lang_str , + sig = \l_tmpa_str , + meta = \l_tmpa_str , + feature = #1 , + } + + \stex_if_smsmode:F { + \begin{stex_annotate_env}{ feature:#1 }{} + \stex_annotate_invisible:nnn{header}{}{ #3 } + } +}{ + \str_set:Nx \l_tmpa_str { + c_stex_feature_ + \prop_item:Nn \l_stex_current_module_prop { ns } ? + \prop_item:Nn \l_stex_current_module_prop { name } + _prop + } + \prop_gset_eq:cN { \l_tmpa_str } \l_stex_current_module_prop + \prop_gset_eq:NN \g_stex_last_feature_prop \l_stex_current_module_prop + \stex_if_smsmode:F { + \end{stex_annotate_env} + } +} + +% \end{macrocode} +% \end{environment} +% +% +% \subsection{Features} +% +% \begin{environment}{structure} +% \begin{macrocode} + +\prop_new:N \l_stex_all_structures_prop + +\keys_define:nn { stex / features / structure } { + name .str_set_x:N = \l_@@_structure_name_str , +} + +\cs_new_protected:Nn \_@@_structure_args:n { + \str_clear:N \l_@@_structure_name_str + \keys_set:nn { stex / features / structure } { #1 } +} + +\NewDocumentEnvironment{mathstructure}{ O{} m }{ + \_@@_structure_args:n { #1 } + \str_if_empty:NT \l_@@_structure_name_str { + \str_set:Nx \l_@@_structure_name_str { #2 } + } + \exp_args:Nnnx + \begin{structural@feature}{ structure } + { \l_@@_structure_name_str }{} + \seq_clear:N \l_tmpa_seq + \prop_put:Nno \l_stex_current_module_prop { fields } \l_tmpa_seq + \stex_smsmode_do: +}{ + \prop_get:NnN \l_stex_current_module_prop { constants } \l_tmpa_seq + \prop_get:NnN \l_stex_current_module_prop { fields } \l_tmpb_seq + \str_set:Nx \l_tmpa_str { + \prop_item:Nn \l_stex_current_module_prop { ns } ? + \prop_item:Nn \l_stex_current_module_prop { name } + } + \seq_map_inline:Nn \l_tmpa_seq { + \exp_args:NNx \seq_put_right:Nn \l_tmpb_seq { \l_tmpa_str ? ##1 } + } + \prop_put:Nno \l_stex_current_module_prop { fields } { \l_tmpb_seq } + \exp_args:Nnx + \AddToHookNext { env / mathstructure / after }{ + \symdecl{ #2 }[type = \exp_not:N\collection,def={\STEXsymbol{module-type}{ + \_stex_term_math_oms:nnnn { \l_tmpa_str }{}{0}{} + }}, name = \prop_item:Nn \l_stex_current_module_prop { origname }] + \STEXexport { + \prop_put:Nno \exp_not:N \l_stex_all_structures_prop + {\prop_item:Nn \l_stex_current_module_prop { origname }} + {\l_tmpa_str} + \prop_put:Nno \exp_not:N \l_stex_all_structures_prop + {#2}{\l_tmpa_str} +% \seq_put_right:Nn \exp_not:N \l_stex_all_structures_seq { +% \prop_item:Nn \l_stex_current_module_prop { origname }, +% \l_tmpa_str +% } +% \seq_put_right:Nn \exp_not:N \l_stex_all_structures_seq { +% #2,\l_tmpa_str +% } +% \tl_set:cx { #2 } { +% \stex_invoke_structure:n { \l_tmpa_str } + } + } + + \end{structural@feature} + % \g_stex_last_feature_prop +} +% \end{macrocode} +% \end{environment} +% +% +% \begin{macro}{\instantiate} +% \begin{macrocode} +\seq_new:N \l_@@_structure_field_seq +\str_new:N \l_@@_structure_field_str +\str_new:N \l_@@_structure_def_tl +\prop_new:N \l_@@_structure_prop +\NewDocumentCommand \instantiate { m O{} m }{ + \prop_get:NnN \l_stex_all_structures_prop {#1} \l_tmpa_str + \prop_set_eq:Nc \l_@@_structure_prop { + c_stex_feature_\l_tmpa_str _prop + } + \seq_set_from_clist:Nn \l_@@_structure_field_seq { #2 } + \seq_map_inline:Nn \l_@@_structure_field_seq { + \seq_set_split:Nnn \l_tmpa_seq{=}{ ##1 } + \int_compare:nNnTF {\seq_count:N \l_tmpa_seq} > 1 { + \seq_get_left:NN \l_tmpa_seq \l_tmpa_tl + \exp_args:NNno \seq_set_split:Nnn \l_tmpb_seq + {!} \l_tmpa_tl + \int_compare:nNnTF {\seq_count:N \l_tmpb_seq} > 1 { + \str_set:Nx \l_@@_structure_field_str {\seq_item:Nn \l_tmpb_seq 1} + \seq_get_right:NN \l_tmpb_seq \l_tmpb_tl + \seq_get_right:NN \l_tmpa_seq \l_tmpa_tl + }{ + \str_set:Nx \l_@@_structure_field_str \l_tmpa_tl + \seq_get_right:NN \l_tmpa_seq \l_tmpa_tl + \exp_args:NNno \seq_set_split:Nnn \l_tmpb_seq{!} + \l_tmpa_tl + \int_compare:nNnTF {\seq_count:N \l_tmpb_seq} > 1 { + \seq_get_left:NN \l_tmpb_seq \l_tmpa_tl + \seq_get_right:NN \l_tmpb_seq \l_tmpb_tl + }{ + \tl_clear:N \l_tmpb_tl + } + } + }{ + \seq_set_split:Nnn \l_tmpa_seq{!}{ ##1 } + \int_compare:nNnTF {\seq_count:N \l_tmpa_seq} > 1 { + \str_set:Nx \l_@@_structure_field_str {\seq_item:Nn \l_tmpa_seq 1} + \seq_get_right:NN \l_tmpa_seq \l_tmpb_tl + \tl_clear:N \l_tmpa_tl + }{ + % TODO throw error + } + } + % \l_tmpa_str: name + % \l_tmpa_tl: definiens + % \l_tmpb_tl: notation + \tl_if_empty:NT \l_@@_structure_field_str { + % TODO throw error + } + \str_clear:N \l_tmpb_str + + \prop_get:NnN \l_@@_structure_prop { fields } \l_tmpa_seq + \seq_map_inline:Nn \l_tmpa_seq { + \seq_set_split:Nnn \l_tmpb_seq ? { ####1 } + \seq_get_right:NN \l_tmpb_seq \l_tmpb_str + \str_if_eq:NNT \l_@@_structure_field_str \l_tmpb_str { + \seq_map_break:n { + \str_set:Nn \l_tmpb_str { ####1 } + } + } + } + \prop_get:cnN { l_stex_symdecl_ \l_tmpb_str _prop } {args} + \l_tmpb_str + + \tl_if_empty:NTF \l_tmpb_tl { + \tl_if_empty:NF \l_tmpa_tl { + \exp_args:Nx \use:n { + \symdecl{#3/\l_@@_structure_field_str}[args=\l_tmpb_str,def={\exp_args:No\exp_not:n{\l_tmpa_tl}}] + } + } + }{ + \tl_if_empty:NTF \l_tmpa_tl { + \exp_args:Nx \use:n { + \symdef{#3/\l_@@_structure_field_str}[args=\l_tmpb_str]\exp_after:wN\exp_not:n\exp_after:wN{\l_tmpb_tl} + } + + }{ + \exp_args:Nx \use:n { + \symdef{#3/\l_@@_structure_field_str}[args=\l_tmpb_str,def={\exp_args:No\exp_not:n{\l_tmpa_tl}}] + \exp_after:wN\exp_not:n\exp_after:wN{\l_tmpb_tl} + } + } + } +% \par \prop_item:Nn \l_stex_current_module_prop {ns} ? +% \prop_item:Nn \l_stex_current_module_prop {name} ? +% #3/\l_@@_structure_field_str +% \par +% \expandafter\present\csname +% l_stex_symdecl_ +% \prop_item:Nn \l_stex_current_module_prop {ns} ? +% \prop_item:Nn \l_stex_current_module_prop {name} ? +% #3/\l_@@_structure_field_str +% _prop +% \endcsname + } + + \tl_clear:N \l_@@_structure_def_tl + + \prop_get:NnN \l_@@_structure_prop { fields } \l_tmpa_seq + \seq_map_inline:Nn \l_tmpa_seq { + \seq_set_split:Nnn \l_tmpb_seq ? { ##1 } + \seq_get_right:NN \l_tmpb_seq \l_tmpa_str + \exp_args:Nx \use:n { + \tl_put_right:Nn \exp_not:N \l_@@_structure_def_tl { + + } + } + + \prop_if_exist:cF { + l_stex_symdecl_ + \prop_item:Nn \l_stex_current_module_prop {ns} ? + \prop_item:Nn \l_stex_current_module_prop {name} ? + #3/\l_tmpa_str + _prop + }{ + \prop_get:cnN { l_stex_symdecl_ ##1 _prop } {args} + \l_tmpb_str + \exp_args:Nx \use:n { + \symdecl{#3/\l_tmpa_str}[args=\l_tmpb_str] + } + } + } + + \symdecl*{#3}[type={\STEXsymbol{module-type}{ + \_stex_term_math_oms:nnnn { + \prop_item:Nn \l_@@_structure_prop {ns} ? + \prop_item:Nn \l_@@_structure_prop {name} + }{}{0}{} + }}] + + % TODO: -> sms file + + \tl_set:cx{ #3 }{ + \stex_invoke_structure:nnn { + \prop_item:Nn \l_stex_current_module_prop {ns} ? + \prop_item:Nn \l_stex_current_module_prop {name} ? #3 + } { + \prop_item:Nn \l_@@_structure_prop {ns} ? + \prop_item:Nn \l_@@_structure_prop {name} + } + } + \stex_smsmode_do: +} +% \end{macrocode} +% \end{macro} +% +% +% +% \begin{macro}{\stex_invoke_structure:nnn} +% \begin{macrocode} +% #1: URI of the instance +% #2: URI of the instantiated module +\cs_new_protected:Nn \stex_invoke_structure:nnn { + \tl_if_empty:nTF{ #3 }{ + \prop_set_eq:Nc \l_@@_structure_prop { + c_stex_feature_ #2 _prop + } + \tl_clear:N \l_tmpa_tl + \prop_get:NnN \l_@@_structure_prop { fields } \l_tmpa_seq + \seq_map_inline:Nn \l_tmpa_seq { + \seq_set_split:Nnn \l_tmpb_seq ? { ##1 } + \seq_get_right:NN \l_tmpb_seq \l_tmpa_str + \cs_if_exist:cT { + stex_notation_ #1/\l_tmpa_str \c_hash_str\c_hash_str _cs + }{ + \tl_if_empty:NF \l_tmpa_tl { + \tl_put_right:Nn \l_tmpa_tl {,} + } + \tl_put_right:Nx \l_tmpa_tl { + \stex_invoke_symbol:n {#1/\l_tmpa_str}! + } + } + } + \exp_args:No \mathstruct \l_tmpa_tl + }{ + \stex_invoke_symbol:n{#1/#3} + } +} +% \end{macrocode} +% \end{macro} +% +% \begin{macrocode} +%</package> +% \end{macrocode} +% +% \end{implementation} +% +% \PrintIndex diff --git a/macros/latex/contrib/stex/source/stex/inheritance.dtx b/macros/latex/contrib/stex/source/stex/inheritance.dtx new file mode 100644 index 0000000000..692d7b952c --- /dev/null +++ b/macros/latex/contrib/stex/source/stex/inheritance.dtx @@ -0,0 +1,575 @@ +% \iffalse meta-comment +% An Infrastructure for Semantic Macros and Module Scoping +% Copyright (c) 2019 Michael Kohlhase, all rights reserved +% this file is released under the +% LaTeX Project Public License (LPPL) +% +% The original of this file is in the public repository at +% http://github.com/sLaTeX/sTeX/ +% +% TODO update copyright +% +%<*driver> +\providecommand\bibfolder{../../lib/bib} +\input{../../doc/docheader} + +\begin{document} + \DocInput{\jobname.dtx} +\end{document} +%</driver> +% \fi +% +% \title{ \sTeX-Module Inheritance +% \thanks{Version {\fileversion} (last revised {\filedate})} +% } +% +% \author{Michael Kohlhase, Dennis Müller\\ +% FAU Erlangen-Nürnberg\\ +% \url{http://kwarc.info/} +% } +% +% \maketitle +% +%\ifinfulldoc\else +% This is the documentation for the \pkg{stex-inheritance} package. +% For a more high-level introduction, +% see \href{\basedocurl/manual.pdf}{the \sTeX Manual} or the +% \href{\basedocurl/stex.pdf}{full \sTeX documentation}. +% \fi +% +% \begin{documentation}\label{pkg:inheritance:doc} +% +% Code related to Module Inheritance, in particular \emph{sms mode}. +% +%\ifinfulldoc\else +% \input{../../doc/packages/inheritance} +%\fi +% +% \section{Macros and Environments}\label{pkg:inheritance:doc:macros} +% +% \subsection{SMS Mode} +% ``SMS Mode'' is used when loading modules from external tex files. +% It deactivates any output and ignores all \TeX\ commands +% not explicitly allowed via the following lists -- all of which either +% declare module content or are needed in order to declare module content: +% +% \begin{variable}{\g_stex_smsmode_allowedmacros_tl} +% Macros that are executed as is; i.e. sms mode continues immediately after. +% These macros may not take any arguments or otherwise gobble tokens. +% +% Initially: \cs{makeatletter}, \cs{makeatother}, \cs{ExplSyntaxOn}, +% \cs{ExplSyntaxOff}. +% \end{variable} +% +% \begin{variable}{\g_stex_smsmode_allowedmacros_escape_tl} +% Macros that are executed and potentially gobble up further tokens. +% These macros need to make sure, that the very last token they ultimately +% expand to is \cs{stex_smsmode_do:}. +% +% Initially: \cs{symdecl}, \cs{notation}, \cs{symdef}, +% \cs{importmodule}, \cs{STEXexport}, \cs{inlineass}, \cs{inlinedef}, +% \cs{inlineex}, \cs{endinput}, \cs{setnotation}, \cs{copynotation}. +% \end{variable} +% +% \begin{variable}{\g_stex_smsmode_allowedenvs_seq} +% The names of environments that should be allowed in SMS mode. +% The corresponding \cs{begin}-statements are treated like +% the macros in \cs{g_stex_smsmode_allowedmacros_escape_tl}, so +% \cs{stex_smsmode_do:} needs to be the last token in the +% \cs{begin}-code. Since \cs{end}-statements take no arguments anyway, +% those are called directly and sms mode continues afterwards. +% +% Initially: |smodule|, |copymodule|, |interpretmodule|, |sdefinition|, +% |sexample|, |sassertion|, |sparagraph|. +% \end{variable} +% +% \begin{function}[pTF]{\stex_if_smsmode:} +% Tests whether SMS mode is currently active. +% \end{function} +% +% \begin{function}{\stex_file_in_smsmode:nn} +% \begin{syntax} \cs{stex_in_smsmode:nn} \Arg{filename} \Arg{code} \end{syntax} +% Executes \meta{code} in SMS mode, followed by the content of \meta{filename}. +% \meta{code} can be used e.g. to set the current repository, and is +% executed within a new tex group, and the same group as the file content. +% \end{function} +% +% \begin{function}{\stex_smsmode_do:} +% Starts gobbling tokens until one is encountered that is allowed in SMS mode. +% \end{function} +% +% \subsection{Imports and Inheritance} +% +% \begin{function}{\importmodule} +% \begin{syntax} \cs{importmodule}|[|\meta{archive-ID}|]|\Arg{module-path} \end{syntax} +% Imports a module by reading it from a file and ``activating'' it. +% \sTeX determines the module and its containing file by passing its +% arguments on to \cs{stex_import_module_path:nn}. +% +% \end{function} +% +% \begin{function}{\usemodule} +% \begin{syntax} \cs{importmodule}|[|\meta{archive-ID}|]|\Arg{module-path} \end{syntax} +% Like \cs{importmodule}, but does not export its contents; +% i.e. including the current module will not activate the used module +% \end{function} +% +% \begin{function}{\stex_import_module_uri:nn} +% \begin{syntax} \cs{stex_import_module_uri:nn} \Arg{archive-ID} \Arg{module-path} \end{syntax} +% Determines the URI of a module by splitting +% \meta{module-path} into \meta{path}|?|\meta{name}. If \meta{module-path} +% does \emph{not} contain a |?|-character, we consider it to be the \meta{name}, +% and \meta{path} to be empty. +% +% If \meta{archive-ID} is empty, it is automatically set to the +% ID of the current archive (if one exists). +% +% \begin{enumerate} +% \item If \meta{archive-ID} is empty: +% \begin{enumerate} +% \item If \meta{path} is empty, then +% \meta{name} must have been declared earlier in the same file +% and retrievable from \cs{g_stex_modules_in_file_seq}, or +% a file with name \meta{name}|.|\meta{lang}|.tex| must exist +% in the same folder, containing a module \meta{name}. +% +% That module should have the same namespace as the current one. +% \item If \meta{path} is not empty, it must point to the relative +% path of the containing file as well as the namespace. +% \end{enumerate} +% \item Otherwise: +% \begin{enumerate} +% \item If \meta{path} is empty, then +% \meta{name} must have been declared earlier in the same file +% and retrievable from \cs{g_stex_modules_in_file_seq}, or +% a file with name \meta{name}|.|\meta{lang}|.tex| must exist +% in the top |source| folder of the archive, +% containing a module \meta{name}. +% +% That module should lie directly in the namespace +% of the archive. +% \item If \meta{path} is not empty, it must point to the +% path of the containing file as well as the namespace, +% relative to the namespace of the archive. +% +% If a module by that namespace exists, it is returned. +% Otherwise, we call \cs{stex_require_module:nn} +% on the |source| directory of the archive to find the +% file. +% \end{enumerate} +% \end{enumerate} +% \end{function} +% \begin{variable}{ +% \l_stex_import_name_str,\l_stex_import_archive_str,\l_stex_import_path_str,\l_stex_import_ns_str +% } +% stores the result in these four variables. +% \end{variable} +% +% \begin{function}{\stex_import_require_module:nnnn} +% \begin{syntax} \Arg{ns} \Arg{archive-ID} \Arg{path} \Arg{name} \end{syntax} +% Checks whether a module with URI \meta{ns}|?|\meta{name} already +% exists. If not, it looks for a plausible file that declares +% a module with that URI. +% +% Finally, activates that module by executing its |_code|-macro. +% \end{function} +% +% \end{documentation} +% +% \begin{implementation}\label{pkg:inheritance:impl} +% +% \section{\sTeX-Module Inheritance Implementation} +% +% \begin{macrocode} +%<*package> + +%%%%%%%%%%%%% inheritance.dtx %%%%%%%%%%%%% + +% \end{macrocode} +% +% \subsection{SMS Mode} +% \begin{macrocode} +%<@@=stex_smsmode> +% \end{macrocode} +% +% \begin{variable}{ +% \g_stex_smsmode_allowedmacros_tl, +% \g_stex_smsmode_allowedmacros_escape_tl, +% \g_stex_smsmode_allowedenvs_seq +% } +% \begin{macrocode} +\tl_new:N \g_stex_smsmode_allowedmacros_tl +\tl_new:N \g_stex_smsmode_allowedmacros_escape_tl +\seq_new:N \g_stex_smsmode_allowedenvs_seq + +\tl_set:Nn \g_stex_smsmode_allowedmacros_tl { + \makeatletter + \makeatother + \ExplSyntaxOn + \ExplSyntaxOff + \rustexBREAK +} + +\tl_set:Nn \g_stex_smsmode_allowedmacros_escape_tl { + \symdef + \importmodule + \notation + \symdecl + \STEXexport + \inlineass + \inlinedef + \inlineex + \endinput + \setnotation + \copynotation +} + +\exp_args:NNx \seq_set_from_clist:Nn \g_stex_smsmode_allowedenvs_seq { + \tl_to_str:n { + smodule, + copymodule, + interpretmodule, + sdefinition, + sexample, + sassertion, + sparagraph + } +} +% \end{macrocode} +% \end{variable} +% +% \begin{macro}[pTF]{\stex_if_smsmode:} +% \begin{macrocode} +\bool_new:N \g_@@_bool +\bool_set_false:N \g_@@_bool +\prg_new_conditional:Nnn \stex_if_smsmode: { p, T, F, TF } { + \bool_if:NTF \g_@@_bool \prg_return_true: \prg_return_false: +} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\_@@_in_smsmode:nn} +% \begin{macrocode} +\cs_new_protected:Nn \_@@_in_smsmode:nn { + \vbox_set:Nn \l_tmpa_box { + \bool_set_eq:cN { l_@@_#1_bool } \g_@@_bool + \bool_gset_true:N \g_@@_bool + #2 + \bool_gset_eq:Nc \g_@@_bool { l_@@_#1_bool } + } + \box_clear:N \l_tmpa_box +} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\stex_file_in_smsmode:nn} +% \begin{macrocode} +\quark_new:N \q_@@_break + +\cs_new_protected:Nn \stex_file_in_smsmode:nn { + \stex_filestack_push:n{#1} + \_@@_in_smsmode:nn{#1} { + #2 + \everyeof{\q_@@_break\noexpand} + \expandafter\expandafter\expandafter + \stex_smsmode_do: + \csname @ @ input\endcsname "#1"\relax + } + \stex_filestack_pop: +} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\stex_smsmode_do:} +% is executed on encountering |\| in smsmode. +% It checks whether the corresponding command is allowed and executes +% or ignores it accordingly: +% \begin{macrocode} +\cs_new_protected:Npn \stex_smsmode_do: { + \stex_if_smsmode:T { + \_@@_do:w + } +} +\cs_new_protected:Npn \_@@_do:w #1 { + \exp_args:Nx \tl_if_empty:nTF { \tl_tail:n{ #1 }}{ + \expandafter\if\expandafter\relax\noexpand#1 + \expandafter\_@@_do_aux:N\expandafter#1 + \else\expandafter\_@@_do:w\fi + }{ + \_@@_do:w %#1 + } +} +\cs_new_protected:Nn \_@@_do_aux:N { + \cs_if_eq:NNF #1 \q_@@_break { + \tl_if_in:NnTF \g_stex_smsmode_allowedmacros_tl {#1} { + #1\_@@_do:w + }{ + \tl_if_in:NnTF \g_stex_smsmode_allowedmacros_escape_tl {#1} { + #1 + }{ + \cs_if_eq:NNTF \begin #1 { + \_@@_check_begin:n + }{ + \cs_if_eq:NNTF \end #1 { + \_@@_check_end:n + }{ + \_@@_do:w + } + } + } + } + } +} + +\cs_new_protected:Nn \_@@_check_begin:n { + \seq_if_in:NxTF \g_stex_smsmode_allowedenvs_seq { \detokenize{#1} }{ + \begin{#1} + }{ + \_@@_do:w + } +} +\cs_new_protected:Nn \_@@_check_end:n { + \seq_if_in:NxTF \g_stex_smsmode_allowedenvs_seq { \detokenize{#1} }{ + \end{#1}\_@@_do:w + }{ + \str_if_eq:nnTF{#1}{document}{\endinput}{\_@@_do:w} + } +} +% \end{macrocode} +% \end{macro} +% + +% \subsection{Inheritance} +% \begin{macrocode} +%<@@=stex_importmodule> +% \end{macrocode} +% +% \begin{macro}{\stex_import_module_uri:nn} +% \begin{macrocode} +\cs_new_protected:Nn \stex_import_module_uri:nn { + \str_set:Nx \l_stex_import_archive_str { #1 } + \str_set:Nn \l_stex_import_path_str { #2 } + + \exp_args:NNNo \seq_set_split:Nnn \l_tmpb_seq ? { \l_stex_import_path_str } + \seq_pop_right:NN \l_tmpb_seq \l_stex_import_name_str + \str_set:Nx \l_stex_import_path_str { \seq_use:Nn \l_tmpb_seq ? } + + \stex_modules_current_namespace: + \bool_lazy_all:nTF { + {\str_if_empty_p:N \l_stex_import_archive_str} + {\str_if_empty_p:N \l_stex_import_path_str} + {\stex_if_module_exists_p:n { \l_stex_module_ns_str ? \l_stex_import_name_str } } + }{ + \str_set_eq:NN \l_stex_import_path_str \l_stex_modules_subpath_str + \str_set_eq:NN \l_stex_import_ns_str \l_stex_module_ns_str + }{ + \str_if_empty:NT \l_stex_import_archive_str { + \prop_if_exist:NT \l_stex_current_repository_prop { + \prop_get:NnN \l_stex_current_repository_prop { id } \l_stex_import_archive_str + } + } + \str_if_empty:NTF \l_stex_import_archive_str { + \str_if_empty:NF \l_stex_import_path_str { + \str_set:Nx \l_stex_import_ns_str { + \l_stex_module_ns_str / \l_stex_import_path_str + } + } + }{ + \stex_require_repository:n \l_stex_import_archive_str + \prop_get:cnN { c_stex_mathhub_\l_stex_import_archive_str _manifest_prop } { ns } + \l_stex_import_ns_str + \str_if_empty:NF \l_stex_import_path_str { + \str_set:Nx \l_stex_import_ns_str { + \l_stex_import_ns_str / \l_stex_import_path_str + } + } + } + } +} +% \end{macrocode} +% \end{macro} +% +% \begin{variable}{ +% \l_stex_import_name_str,\l_stex_import_archive_str,\l_stex_import_path_str,\l_stex_import_ns_str +% } +% Store the return values of \cs{stex_import_module_uri:nn}. +% \begin{macrocode} +\str_new:N \l_stex_import_name_str +\str_new:N \l_stex_import_archive_str +\str_new:N \l_stex_import_path_str +\str_new:N \l_stex_import_ns_str +% \end{macrocode} +% \end{variable} +% +% \begin{macro}{\stex_import_require_module:nnnn} +% \begin{syntax} \Arg{ns} \Arg{archive-ID} \Arg{path} \Arg{name} \end{syntax} +% \begin{macrocode} +\cs_new_protected:Nn \stex_import_require_module:nnnn { + \exp_args:Nx \stex_if_module_exists:nF { #1 ? #4 } { + + % archive + \str_set:Nx \l_tmpa_str { #2 } + \str_if_empty:NTF \l_tmpa_str { + \seq_set_eq:NN \l_tmpa_seq \g_stex_currentfile_seq + } { + \stex_path_from_string:Nn \l_tmpb_seq { \l_tmpa_str } + \seq_concat:NNN \l_tmpa_seq \c_stex_mathhub_seq \l_tmpb_seq + \seq_put_right:Nn \l_tmpa_seq { source } + } + + % path + \str_set:Nx \l_tmpb_str { #3 } + \str_if_empty:NTF \l_tmpb_str { + \str_set:Nx \l_tmpa_str { \stex_path_to_string:N \l_tmpa_seq / #4 } + + \ltx@ifpackageloaded{babel} { + \exp_args:NNx \prop_get:NnNF \c_stex_language_abbrevs_prop + { \languagename } \l_tmpb_str { + \msg_error:nnx{stex}{error/unknownlanguage}{\languagename} + } + } { + \str_clear:N \l_tmpb_str + } + + \stex_debug:nn{modules}{Checking~\l_tmpa_str.\l_tmpb_str.tex} + \IfFileExists{ \l_tmpa_str.\l_tmpb_str.tex }{ + \str_gset:Nx \g_@@_file_str { \l_tmpa_str.\l_tmpb_str.tex } + }{ + \stex_debug:nn{modules}{Checking~\l_tmpa_str.tex} + \IfFileExists{ \l_tmpa_str.tex }{ + \str_gset:Nx \g_@@_file_str { \l_tmpa_str.tex } + }{ + % try english as default + \stex_debug:nn{modules}{Checking~\l_tmpa_str.en.tex} + \IfFileExists{ \l_tmpa_str.en.tex }{ + \str_gset:Nx \g_@@_file_str { \l_tmpa_str.en.tex } + }{ + \msg_error:nnx{stex}{error/unknownmodule}{#1?#4} + } + } + } + + } { + \seq_set_split:NnV \l_tmpb_seq / \l_tmpb_str + \seq_concat:NNN \l_tmpa_seq \l_tmpa_seq \l_tmpb_seq + + \ltx@ifpackageloaded{babel} { + \exp_args:NNx \prop_get:NnNF \c_stex_language_abbrevs_prop + { \languagename } \l_tmpb_str { + \msg_error:nnx{stex}{error/unknownlanguage}{\languagename} + } + } { + \str_clear:N \l_tmpb_str + } + + \stex_path_to_string:NN \l_tmpa_seq \l_tmpa_str + + \stex_debug:nn{modules}{Checking~\l_tmpa_str/#4.\l_tmpb_str.tex} + \IfFileExists{ \l_tmpa_str/#4.\l_tmpb_str.tex }{ + \str_gset:Nx \g_@@_file_str { \l_tmpa_str/#4.\l_tmpb_str.tex } + }{ + \stex_debug:nn{modules}{Checking~\l_tmpa_str/#4.tex} + \IfFileExists{ \l_tmpa_str/#4.tex }{ + \str_gset:Nx \g_@@_file_str { \l_tmpa_str/#4.tex } + }{ + % try english as default + \stex_debug:nn{modules}{Checking~\l_tmpa_str/#4.en.tex} + \IfFileExists{ \l_tmpa_str/#4.en.tex }{ + \str_gset:Nx \g_@@_file_str { \l_tmpa_str/#4.en.tex } + }{ + \stex_debug:nn{modules}{Checking~\l_tmpa_str.\l_tmpb_str.tex} + \IfFileExists{ \l_tmpa_str.\l_tmpb_str.tex }{ + \str_gset:Nx \g_@@_file_str { \l_tmpa_str.\l_tmpb_str.tex } + }{ + \stex_debug:nn{modules}{Checking~\l_tmpa_str.tex} + \IfFileExists{ \l_tmpa_str.tex }{ + \str_gset:Nx \g_@@_file_str { \l_tmpa_str.tex } + }{ + % try english as default + \stex_debug:nn{modules}{Checking~\l_tmpa_str.en.tex} + \IfFileExists{ \l_tmpa_str.en.tex }{ + \str_gset:Nx \g_@@_file_str { \l_tmpa_str.en.tex } + }{ + \msg_error:nnx{stex}{error/unknownmodule}{#1?#4} + } + } + } + } + } + } + } + + \exp_args:No \stex_file_in_smsmode:nn { \g_@@_file_str } { + \seq_clear:N \l_stex_all_modules_seq + \str_clear:N \l_stex_current_module_str + \str_set:Nx \l_tmpb_str { #2 } + \str_if_empty:NF \l_tmpb_str { + \stex_set_current_repository:n { #2 } + } + \stex_debug:nn{modules}{Loading~\g_@@_file_str} + } + + \stex_if_module_exists:nF { #1 ? #4 } { + \msg_error:nnx{stex}{error/unknownmodule}{ + #1?#4~(in~file~\g_@@_file_str) + } + } + } + \stex_activate_module:n { #1 ? #4 } +} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\importmodule} +% \begin{macrocode} +\NewDocumentCommand \importmodule { O{} m } { + \stex_import_module_uri:nn { #1 } { #2 } + \stex_debug:nn{modules}{Importing~module:~ + \l_stex_import_ns_str ? \l_stex_import_name_str + } + \stex_if_smsmode:F { + \stex_import_require_module:nnnn + { \l_stex_import_ns_str } { \l_stex_import_archive_str } + { \l_stex_import_path_str } { \l_stex_import_name_str } + \stex_annotate_invisible:nnn + {import} {\l_stex_import_ns_str ? \l_stex_import_name_str} {} + } + \exp_args:Nx \stex_add_to_current_module:n { + \stex_import_require_module:nnnn + { \l_stex_import_ns_str } { \l_stex_import_archive_str } + { \l_stex_import_path_str } { \l_stex_import_name_str } + } + \exp_args:Nx \stex_add_import_to_current_module:n { + \l_stex_import_ns_str ? \l_stex_import_name_str + } + \stex_smsmode_do: + \ignorespacesandpars +} +\stex_deactivate_macro:Nn \importmodule {module~environments} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\usemodule} +% \begin{macrocode} +\NewDocumentCommand \usemodule { O{} m } { + \stex_if_smsmode:F { + \stex_import_module_uri:nn { #1 } { #2 } + \stex_import_require_module:nnnn + { \l_stex_import_ns_str } { \l_stex_import_archive_str } + { \l_stex_import_path_str } { \l_stex_import_name_str } + \stex_annotate_invisible:nnn + {usemodule} {\l_stex_import_ns_str ? \l_stex_import_name_str} {} + } + \stex_smsmode_do: + \ignorespacesandpars +} +% \end{macrocode} +% \end{macro} +% +% \begin{macrocode} +%</package> +% \end{macrocode} +% +% \end{implementation} +% +% \PrintIndex diff --git a/macros/latex/contrib/stex/source/stex/mathhub.dtx b/macros/latex/contrib/stex/source/stex/mathhub.dtx new file mode 100644 index 0000000000..16ff57ede8 --- /dev/null +++ b/macros/latex/contrib/stex/source/stex/mathhub.dtx @@ -0,0 +1,916 @@ +% \iffalse meta-comment +% An Infrastructure for Semantic Macros and Module Scoping +% Copyright (c) 2019 Michael Kohlhase, all rights reserved +% this file is released under the +% LaTeX Project Public License (LPPL) +% +% The original of this file is in the public repository at +% http://github.com/sLaTeX/sTeX/ +% +% TODO update copyright +% +%<*driver> +\providecommand\bibfolder{../../lib/bib} +\input{../../doc/docheader} + +\begin{document} + \DocInput{\jobname.dtx} +\end{document} +%</driver> +% \fi +% +% \title{ \sTeX-MathHub +% \thanks{Version {\fileversion} (last revised {\filedate})} +% } +% +% \author{Michael Kohlhase, Dennis Müller\\ +% FAU Erlangen-Nürnberg\\ +% \url{http://kwarc.info/} +% } +% +% \maketitle +% +%\ifinfulldoc\else +% This is the documentation for the \pkg{stex-mathhub} package. +% For a more high-level introduction, +% see \href{\basedocurl/manual.pdf}{the \sTeX Manual} or the +% \href{\basedocurl/stex.pdf}{full \sTeX documentation}. +% \fi +% +% +% \begin{documentation}\label{pkg:mathhub:doc} +% +% This sub package provides code for handling \sTeX archives, +% files, file paths and related methods. +% +% \ifinfulldoc\else +% \begin{sfragment}{Manual}\input{../../doc/packages/mathhub}\end{sfragment} +% \fi +% +% \section{Macros and Environments}\label{pkg:mathhub:doc:macros} +% +% \begin{function}{\stex_kpsewhich:n} +% |\stex_kpsewhich:n| executes kpsewhich and stores the return +% in\\ |\l_stex_kpsewhich_return_str|. This does not require +% shell escaping. +% \end{function} +% +% \subsection{Files, Paths, URIs} +% +% \begin{function}{\stex_path_from_string:Nn} +% +% \begin{syntax} \cs{stex_path_from_string:Nn} \meta{path-variable} \Arg{string} \end{syntax} +% turns the \meta{string} into a path by splitting it at |/|-characters +% and stores the result in \meta{path-variable}. Also applies +% \cs{stex_path_canonicalize:N}. +% \end{function} +% +% \begin{function}{\stex_path_to_string:NN, \stex_path_to_string:N} +% The inverse; turns a path into a string and stores it in the second +% argument variable, or leaves it in the input stream. +% \end{function} +% +% \begin{function}{\stex_path_canonicalize:N} +% Canonicalizes the path provided; in particular, resolves |.| and |..| +% path segments. +% \end{function} +% +% \begin{function}[pTF]{\stex_path_if_absolute:N} +% Checks whether the path provided is \emph{absolute}, i.e. starts +% with an empty segment +% \end{function} +% +% \begin{variable}{\c_stex_pwd_seq, \c_stex_pwd_str, \c_stex_mainfile_seq, \c_stex_mainfile_str} +% Store the current working directory as path-sequence and string, +% respectively, and the (heuristically guessed) full path to the +% main file, based on the PWD and |\jobname|. +% \end{variable} +% +% \begin{variable}{\g_stex_currentfile_seq} +% The file being currently processed (respecting |\input| etc.) +% \end{variable} +% +% \begin{function}{\stex_filestack_push:n,\stex_filestack_pop:} +% Push and pop (repsectively) a file path to the file stack, +% to keep track of the current file. Are called in hooks |file/before| +% and |file/after|, respectively. +% \end{function} +% +% \subsection{MathHub Archives} +% +% \begin{variable}{\mathhub, \c_stex_mathhub_seq, \c_stex_mathhub_str} +% We determine the path to the local MathHub folder via one of +% three means, in order of precedence: +% \begin{enumerate} +% \item The |mathhub| package option, or +% \item the |\mathhub|-macro, if it has been defined before +% the |\usepackage{stex}|-statement, or +% \item the |MATHHUB| system variable. +% \end{enumerate} +% In all three cases, \cs{c_stex_mathhub_seq} and +% \cs{c_stex_mathhub_str} are set accordingly. +% \end{variable} +% +% \begin{variable}{\l_stex_current_repository_prop} +% Always points to the \emph{current} MathHub repository (if +% we currently are in one). Has the following fields corresponding +% to the entries in the |MANIFEST.MF|-file: +% \begin{itemize} +% \item[|id|:] The name of the archive, including its group (e.g. |smglom/calculus|), +% \item[|ns|:] The content namespace (for modules and symbols), +% \item[|narr|:] the narration namespace (for document references), +% \item[|docurl|:] The URL that is used as a basis for \emph{external references}, +% \item[|deps|:] All archives that this archive depends on (currently not in use). +% \end{itemize} +% \end{variable} +% +% \begin{function}{\stex_set_current_repository:n} +% Sets the current repository to the one with the provided ID. +% calls \cs{__stex_mathhub_do_manifest:n}, so works whether this +% repository's |MANIFEST.MF|-file has already been read or not. +% \end{function} +% +% \begin{function}{\stex_require_repository:n} +% Calls \cs{__stex_mathhub_do_manifest:n} iff the corresponding +% archive property list does not already exist, and +% adds a corresponding definition to the |.sms|-file. +% \end{function} +% +% \begin{function}{\stex_in_repository:nn} +% \begin{syntax}\cs{stex_in_repository:nn}\Arg{repository-name}\Arg{code}\end{syntax} +% Change the current repository to \Arg{repository-name} (or not, if \Arg{repository-name} is +% empty), and passes its ID on to \Arg{code} as |#1|. Switches back +% to the previous repository after executing \Arg{code}. +% \end{function} +% +% \subsection{Using Content in Archives} +% +% \begin{function}[EXP]{\mhpath} +% \begin{syntax}\cs{mhpath}\Arg{archive-ID}\Arg{filename}\end{syntax} +% Expands to the full path of file \meta{filename} in repository \meta{archive-ID}. +% Does not check whether the file or the repository exist. +% \end{function} +% +% \begin{function}{\inputref,\mhinput} +% \begin{syntax}\cs{inputref}|[|\meta{archive-ID}|]|\Arg{filename}\end{syntax} +% Both \cs{input} the file \meta{filename} in archive \meta{archive-ID} (relative +% to the |source|-subdirectory). \cs{mhinput} does so directly. +% \cs{inputref} does so within an |\begingroup|...|\endgroup|-block, +% and skips it in |html|-mode, inserting a \emph{reference} to the +% file instead. +% +% Both also set |\ifinputref| to true. +% \end{function} +% +% \begin{function}{\addmhbibresource} +% \begin{syntax}\cs{inputref}|[|\meta{archive-ID}|]|\Arg{filename}\end{syntax} +% Adds a |.bib|-file \meta{filename} in archive \meta{archive-ID} (relative +% to the top-directory of the archive!). +% \end{function} +% +% \begin{function}{\libinput} +% \begin{syntax} \cs{libinput}\Arg{filename} \end{syntax} +% Inputs \meta{filename}|.tex| from the |lib| folders in the +% current archive and the |meta-inf|-archive of the current archive group(s) +% (if existent) in descending order. Throws an error if no file by that name exists in +% any of the relevant |lib|-folders. +% \end{function} +% +% \begin{function}{\libusepackage} +% \begin{syntax} \cs{libusepackage}[\meta{args}]\Arg{filename} \end{syntax} +% Like \cs{libinput}, but looks for |.sty|-files and calls +% |\usepackage[\meta{args}]\Arg{filename}| instead of \cs{input}. +% +% Throws an error, if none or more than one suitable package file is found. +% \end{function} +% +% \begin{function}{\mhgraphics,\cmhgraphics} +% \emph{If} the \pkg{graphicx} package is loaded, these +% macros are defined at |\begin{document}|. +% +% \cs{mhgraphics} takes the same arguments as \cs{includegraphics}, +% with the additional optional key |mhrepos|. It then resolves +% the file path in |\mhgraphics[mhrepos=Foo/Bar]{foo/bar.png}| +% relative to the |source|-folder of the |Foo/Bar|-archive. +% +% \cs{cmhgraphics} additional wraps the image in a |center|-environment. +% \end{function} +% +% \begin{function}{\lstinputmhlisting,\clstinputmhlisting} +% Like \cs{mhgraphics}, but only defined if the \pkg{listings}-package +% is loaded, and with \cs{lstinputlisting} instead of \cs{includegraphics}. +% \end{function} +% +% \end{documentation} +% +% \begin{implementation} +% +% \section{\sTeX-MathHub Implementation}\label{pkg:mathhub:doc:impl} +% +% \begin{macrocode} +%<*package> + +%%%%%%%%%%%%% mathhub.dtx %%%%%%%%%%%%% + +%<@@=stex_path> +% \end{macrocode} +% +% Warnings and error messages +% +% \begin{macrocode} +\msg_new:nnn{stex}{error/norepository}{ + No~archive~#1~found~in~#2 +} +\msg_new:nnn{stex}{error/notinarchive}{ + Not~currently~in~an~archive,~but~\detokenize{#1}~ + needs~one! +} +\msg_new:nnn{stex}{error/nofile}{ + \detokenize{#1}~could~not~find~file~#2 +} +\msg_new:nnn{stex}{error/twofiles}{ + \detokenize{#1}~found~two~candidates~for~#2 +} +% \end{macrocode} +% +% \subsubsection{Generic Path Handling} +% +% We treat paths as \LaTeX3-sequences (of the individual +% path segments, i.e. separated by a /-character) unix-style; +% i.e. a path is absolute if the sequence starts with an empty +% entry. +% +% \begin{macro}{\stex_path_from_string:Nn} +% \begin{macrocode} +\cs_new_protected:Nn \stex_path_from_string:Nn { + \str_set:Nx \l_tmpa_str { #2 } + \str_if_empty:NTF \l_tmpa_str { + \seq_clear:N #1 + }{ + \exp_args:NNNo \seq_set_split:Nnn #1 / { \l_tmpa_str } + \sys_if_platform_windows:T{ + \seq_clear:N \l_tmpa_tl + \seq_map_inline:Nn #1 { + \seq_set_split:Nnn \l_tmpb_tl \c_backslash_str { ##1 } + \seq_concat:NNN \l_tmpa_tl \l_tmpa_tl \l_tmpb_tl + } + \seq_set_eq:NN #1 \l_tmpa_tl + } + \stex_path_canonicalize:N #1 + } +} + +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\stex_path_to_string:NN,\stex_path_to_string:N} +% \begin{macrocode} +\cs_new_protected:Nn \stex_path_to_string:NN { + \exp_args:NNe \str_set:Nn #2 { \seq_use:Nn #1 / } +} + +\cs_new:Nn \stex_path_to_string:N { + \seq_use:Nn #1 / +} +% \end{macrocode} +% \end{macro} +% +% \begin{variable}{\c_@@_dot_str,\c_@@_up_str} +% +% |.| and |..|, respectively. +% +% \begin{macrocode} +\str_const:Nn \c_@@_dot_str {.} +\str_const:Nn \c_@@_up_str {..} +% \end{macrocode} +% \end{variable} +% +% \begin{macro}{\stex_path_canonicalize:N} +% +% Canonicalizes the path provided; in particular, resolves |.| and |..| +% path segments. +% +% \begin{macrocode} +\cs_new_protected:Nn \stex_path_canonicalize:N { + \seq_if_empty:NF #1 { + \seq_clear:N \l_tmpa_seq + \seq_get_left:NN #1 \l_tmpa_tl + \str_if_empty:NT \l_tmpa_tl { + \seq_put_right:Nn \l_tmpa_seq {} + } + \seq_map_inline:Nn #1 { + \str_set:Nn \l_tmpa_tl { ##1 } + \str_if_eq:NNF \l_tmpa_tl \c_@@_dot_str { + \str_if_eq:NNTF \l_tmpa_tl \c_@@_up_str { + \seq_if_empty:NTF \l_tmpa_seq { + \exp_args:NNo \seq_put_right:Nn \l_tmpa_seq { + \c_@@_up_str + } + }{ + \seq_get_right:NN \l_tmpa_seq \l_tmpa_tl + \str_if_eq:NNTF \l_tmpa_tl \c_@@_up_str { + \exp_args:NNo \seq_put_right:Nn \l_tmpa_seq { + \c_@@_up_str + } + }{ + \seq_pop_right:NN \l_tmpa_seq \l_tmpb_tl + } + } + }{ + \str_if_empty:NF \l_tmpa_tl { + \exp_args:NNo \seq_put_right:Nn \l_tmpa_seq { \l_tmpa_tl } + } + } + } + } + \seq_gset_eq:NN #1 \l_tmpa_seq + } +} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}[pTF]{\stex_path_if_absolute:N} +% \begin{macrocode} +\prg_new_conditional:Nnn \stex_path_if_absolute:N {p, T, F, TF} { + \seq_if_empty:NTF #1 { + \prg_return_false: + }{ + \seq_get_left:NN #1 \l_tmpa_tl + \sys_if_platform_windows:TF{ + \str_if_in:NnTF \l_tmpa_tl {:}{ + \prg_return_true: + }{ + \prg_return_false: + } + }{ + \str_if_empty:NTF \l_tmpa_tl { + \prg_return_true: + }{ + \prg_return_false: + } + } + } +} +% \end{macrocode} +% \end{macro} +% +% \subsubsection{PWD and kpsewhich} +% +% \begin{macro}{\stex_kpsewhich:n} +% \begin{macrocode} +\str_new:N\l_stex_kpsewhich_return_str +\cs_new_protected:Nn \stex_kpsewhich:n { + \sys_get_shell:nnN { kpsewhich ~ #1 } { } \l_tmpa_tl + \exp_args:NNo\str_set:Nn\l_stex_kpsewhich_return_str{\l_tmpa_tl} + \tl_trim_spaces:N \l_stex_kpsewhich_return_str +} +% \end{macrocode} +% \end{macro} +% +% We determine the PWD +% +% \begin{variable}{\c_stex_pwd_seq,\c_stex_pwd_str} +% \begin{macrocode} +\sys_if_platform_windows:TF{ + \begingroup\escapechar=-1\catcode`\\=12 + \exp_args:Nx\stex_kpsewhich:n{-expand-var~\c_percent_str CD\c_percent_str} + \exp_args:NNx\str_replace_all:Nnn\l_stex_kpsewhich_return_str{\c_backslash_str}/ + \exp_args:Nnx\use:nn{\endgroup}{\str_set:Nn\exp_not:N\l_stex_kpsewhich_return_str{\l_stex_kpsewhich_return_str}} +}{ + \stex_kpsewhich:n{-var-value~PWD} +} + +\stex_path_from_string:Nn\c_stex_pwd_seq\l_stex_kpsewhich_return_str +\stex_path_to_string:NN\c_stex_pwd_seq\c_stex_pwd_str +\stex_debug:nn {mathhub} {PWD:~\str_use:N\c_stex_pwd_str} +% \end{macrocode} +% \end{variable} +% +% \subsubsection{File Hooks and Tracking} +% \begin{macrocode} +%<@@=stex_files> +% \end{macrocode} +% +% We introduce hooks for file inputs that keep track of the +% absolute paths of files used. This will be useful to keep track +% of modules, their archives, namespaces etc. +% +% Note that the absolute paths are only accurate in |\input|-statements +% for paths relative to the PWD, so they shouldn't be relied upon +% in any other setting than for \sTeX-purposes. +% +% \begin{variable}{\g_@@_stack} +% +% keeps track of file changes +% +% \begin{macrocode} +\seq_gclear_new:N\g_@@_stack +% \end{macrocode} +% \end{variable} +% +% \begin{variable}{\c_stex_mainfile_seq, \c_stex_mainfile_str} +% \begin{macrocode} +\str_set:Nx \c_stex_mainfile_str {\c_stex_pwd_str/\jobname.tex} +\stex_path_from_string:Nn \c_stex_mainfile_seq + \c_stex_mainfile_str +% \end{macrocode} +% \end{variable} +% +% \begin{variable}{\g_stex_currentfile_seq} +% \begin{macrocode} +\seq_gclear_new:N\g_stex_currentfile_seq +% \end{macrocode} +% \end{variable} +% +% \begin{macro}{\stex_filestack_push:n} +% \begin{macrocode} +\cs_new_protected:Nn \stex_filestack_push:n { + \stex_path_from_string:Nn\g_stex_currentfile_seq{#1} + \stex_path_if_absolute:NF\g_stex_currentfile_seq{ + \stex_path_from_string:Nn\g_stex_currentfile_seq{ + \c_stex_pwd_str/#1 + } + } + \seq_gset_eq:NN\g_stex_currentfile_seq\g_stex_currentfile_seq + \exp_args:NNo\seq_gpush:Nn\g_@@_stack\g_stex_currentfile_seq +} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\stex_filestack_pop:} +% \begin{macrocode} +\cs_new_protected:Nn \stex_filestack_pop: { + \seq_if_empty:NF\g_@@_stack{ + \seq_gpop:NN\g_@@_stack\l_tmpa_seq + } + \seq_if_empty:NTF\g_@@_stack{ + \seq_gset_eq:NN\g_stex_currentfile_seq\c_stex_mainfile_seq + }{ + \seq_get:NN\g_@@_stack\l_tmpa_seq + \seq_gset_eq:NN\g_stex_currentfile_seq\l_tmpa_seq + } +} +% \end{macrocode} +% \end{macro} +% +% Hooks for the current file: +% +% \begin{macrocode} +\AddToHook{file/before}{ + \stex_filestack_push:n{\CurrentFilePath/\CurrentFile} +} +\AddToHook{file/after}{ + \stex_filestack_pop: +} +% \end{macrocode} +% +% \subsection{MathHub Repositories} +% \begin{macrocode} +%<@@=stex_mathhub> +% \end{macrocode} +% +% \begin{variable}{\mathhub, \c_stex_mathhub_seq, \c_stex_mathhub_str} +% The path to the mathhub directory. If the \cs{mathhub}-macro is not set, +% we query |kpsewhich| for the |MATHHUB| system variable. +% \begin{macrocode} +\str_if_empty:NTF\mathhub{ + \sys_if_platform_windows:TF{ + \begingroup\escapechar=-1\catcode`\\=12 + \exp_args:Nx\stex_kpsewhich:n{-expand-var~\c_percent_str MATHHUB\c_percent_str} + \exp_args:NNx\str_replace_all:Nnn\l_stex_kpsewhich_return_str{\c_backslash_str}/ + \exp_args:Nnx\use:nn{\endgroup}{\str_set:Nn\exp_not:N\l_stex_kpsewhich_return_str{\l_stex_kpsewhich_return_str}} + }{ + \stex_kpsewhich:n{-var-value~MATHHUB} + } + \str_set_eq:NN\c_stex_mathhub_str\l_stex_kpsewhich_return_str + + \str_if_empty:NTF\c_stex_mathhub_str{ + \msg_warning:nn{stex}{warning/nomathhub} + }{ + \stex_debug:nn{mathhub}{MathHub:~\str_use:N\c_stex_mathhub_str} + \exp_args:NNo \stex_path_from_string:Nn\c_stex_mathhub_seq\c_stex_mathhub_str + } +}{ + \stex_path_from_string:Nn \c_stex_mathhub_seq \mathhub + \stex_path_if_absolute:NF \c_stex_mathhub_seq { + \exp_args:NNx \stex_path_from_string:Nn \c_stex_mathhub_seq { + \c_stex_pwd_str/\mathhub + } + } + \stex_path_to_string:NN\c_stex_mathhub_seq\c_stex_mathhub_str + \stex_debug:nn{mathhub} {MathHub:~\str_use:N\c_stex_mathhub_str} +} +% \end{macrocode} +% \end{variable} +% +% \begin{macro}{\_@@_do_manifest:n} +% Checks whether the manifest for archive |#1| already exists, and +% if not, finds and parses the corresponding manifest file +% \begin{macrocode} +\cs_new_protected:Nn \_@@_do_manifest:n { + \prop_if_exist:cF {c_stex_mathhub_#1_manifest_prop} { + \str_set:Nx \l_tmpa_str { #1 } + \prop_new:c { c_stex_mathhub_#1_manifest_prop } + \seq_set_split:NnV \l_tmpa_seq / \l_tmpa_str + \seq_concat:NNN \l_tmpa_seq \c_stex_mathhub_seq \l_tmpa_seq + \_@@_find_manifest:N \l_tmpa_seq + \seq_if_empty:NTF \l_@@_manifest_file_seq { + \msg_error:nnxx{stex}{error/norepository}{#1}{ + \stex_path_to_string:N \c_stex_mathhub_str + } + } { + \exp_args:No \_@@_parse_manifest:n { \l_tmpa_str } + } + } +} +% \end{macrocode} +% \end{macro} +% +% \begin{variable}{\l_@@_manifest_file_seq} +% \begin{macrocode} +\seq_new:N\l_@@_manifest_file_seq +% \end{macrocode} +% \end{variable} +% +% \begin{macro}{\_@@_find_manifest:N} +% +% Attempts to find the |MANIFEST.MF| in some file path and +% stores its path in \cs{l_@@_manifest_file_seq}: +% +% \begin{macrocode} +\cs_new_protected:Nn \_@@_find_manifest:N { + \seq_set_eq:NN\l_tmpa_seq #1 + \bool_set_true:N\l_tmpa_bool + \bool_while_do:Nn \l_tmpa_bool { + \seq_if_empty:NTF \l_tmpa_seq { + \bool_set_false:N\l_tmpa_bool + }{ + \file_if_exist:nTF{ + \stex_path_to_string:N\l_tmpa_seq/MANIFEST.MF + }{ + \seq_put_right:Nn\l_tmpa_seq{MANIFEST.MF} + \bool_set_false:N\l_tmpa_bool + }{ + \file_if_exist:nTF{ + \stex_path_to_string:N\l_tmpa_seq/META-INF/MANIFEST.MF + }{ + \seq_put_right:Nn\l_tmpa_seq{META-INF} + \seq_put_right:Nn\l_tmpa_seq{MANIFEST.MF} + \bool_set_false:N\l_tmpa_bool + }{ + \file_if_exist:nTF{ + \stex_path_to_string:N\l_tmpa_seq/meta-inf/MANIFEST.MF + }{ + \seq_put_right:Nn\l_tmpa_seq{meta-inf} + \seq_put_right:Nn\l_tmpa_seq{MANIFEST.MF} + \bool_set_false:N\l_tmpa_bool + }{ + \seq_pop_right:NN\l_tmpa_seq\l_tmpa_tl + } + } + } + } + } + \seq_set_eq:NN\l_@@_manifest_file_seq\l_tmpa_seq +} +% \end{macrocode} +% \end{macro} +% +% \begin{variable}{\c_@@_manifest_ior} +% +% File variable used for |MANIFEST|-files +% +% \begin{macrocode} +\ior_new:N \c_@@_manifest_ior +% \end{macrocode} +% \end{variable} +% +% \begin{macro}{\_@@_parse_manifest:n} +% +% Stores the entries in manifest file in the +% corresponding property list: +% +% \begin{macrocode} +\cs_new_protected:Nn \_@@_parse_manifest:n { + \seq_set_eq:NN \l_tmpa_seq \l_@@_manifest_file_seq + \ior_open:Nn \c_@@_manifest_ior {\stex_path_to_string:N \l_tmpa_seq} + \ior_map_inline:Nn \c_@@_manifest_ior { + \str_set:Nn \l_tmpa_str {##1} + \exp_args:NNoo \seq_set_split:Nnn + \l_tmpb_seq \c_colon_str \l_tmpa_str + \seq_pop_left:NNTF \l_tmpb_seq \l_tmpa_tl { + \exp_args:NNe \str_set:Nn \l_tmpb_tl { + \exp_args:NNo \seq_use:Nn \l_tmpb_seq \c_colon_str + } + \exp_args:No \str_case:nnTF \l_tmpa_tl { + {id} { + \prop_gput:cno { c_stex_mathhub_#1_manifest_prop } + { id } \l_tmpb_tl + } + {narration-base} { + \prop_gput:cno { c_stex_mathhub_#1_manifest_prop } + { narr } \l_tmpb_tl + } + {url-base} { + \prop_gput:cno { c_stex_mathhub_#1_manifest_prop } + { docurl } \l_tmpb_tl + } + {source-base} { + \prop_gput:cno { c_stex_mathhub_#1_manifest_prop } + { ns } \l_tmpb_tl + } + {ns} { + \prop_gput:cno { c_stex_mathhub_#1_manifest_prop } + { ns } \l_tmpb_tl + } + {dependencies} { + \prop_gput:cno { c_stex_mathhub_#1_manifest_prop } + { deps } \l_tmpb_tl + } + }{}{} + }{} + } + \ior_close:N \c_@@_manifest_ior +} +% \end{macrocode} +% \end{macro} +% +% +% \begin{macro}{\stex_set_current_repository:n} +% \begin{macrocode} +\cs_new_protected:Nn \stex_set_current_repository:n { + \stex_require_repository:n { #1 } + \prop_set_eq:Nc \l_stex_current_repository_prop { + c_stex_mathhub_#1_manifest_prop + } +} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\stex_require_repository:n} +% \begin{macrocode} +\cs_new_protected:Nn \stex_require_repository:n { + \prop_if_exist:cF { c_stex_mathhub_#1_manifest_prop } { + \stex_debug:nn{mathhub}{Opening~archive:~#1} + \_@@_do_manifest:n { #1 } + } +} +% \end{macrocode} +% \end{macro} +% +%\begin{variable}{\l_stex_current_repository_prop} +% +% Current MathHub repository +% +% \begin{macrocode} +%\prop_new:N \l_stex_current_repository_prop + +\_@@_find_manifest:N \c_stex_pwd_seq +\seq_if_empty:NTF \l_@@_manifest_file_seq { + \stex_debug:nn{mathhub}{Not~currently~in~a~MathHub~repository} +} { + \_@@_parse_manifest:n { main } + \prop_get:NnN \c_stex_mathhub_main_manifest_prop {id} + \l_tmpa_str + \prop_set_eq:cN { c_stex_mathhub_\l_tmpa_str _manifest_prop } + \c_stex_mathhub_main_manifest_prop + \exp_args:Nx \stex_set_current_repository:n { \l_tmpa_str } + \stex_debug:nn{mathhub}{Current~repository:~ + \prop_item:Nn \l_stex_current_repository_prop {id} + } +} +% \end{macrocode} +% \end{variable} +% +% \begin{macro}{\stex_in_repository:nn} +% Executes the code in the second argument in the context +% of the repository whose ID is provided as the first argument. +% \begin{macrocode} +\cs_new_protected:Nn \stex_in_repository:nn { + \str_set:Nx \l_tmpa_str { #1 } + \cs_set:Npn \l_tmpa_cs ##1 { #2 } + \str_if_empty:NTF \l_tmpa_str { + \prop_if_exist:NTF \l_stex_current_repository_prop { + \stex_debug:nn{mathhub}{do~in~current~repository:~\prop_item:Nn \l_stex_current_repository_prop { id }} + \exp_args:Ne \l_tmpa_cs{ + \prop_item:Nn \l_stex_current_repository_prop { id } + } + }{ + \l_tmpa_cs{} + } + }{ + \stex_debug:nn{mathhub}{in~repository:~\l_tmpa_str} + \stex_require_repository:n \l_tmpa_str + \str_set:Nx \l_tmpa_str { #1 } + \exp_args:Nne \use:nn { + \stex_set_current_repository:n \l_tmpa_str + \exp_args:Nx \l_tmpa_cs{\l_tmpa_str} + }{ + \stex_debug:nn{mathhub}{switching~back~to:~ + \prop_if_exist:NTF \l_stex_current_repository_prop { + \prop_item:Nn \l_stex_current_repository_prop { id }:~ + \meaning\l_stex_current_repository_prop + }{ + no~repository + } + } + \prop_if_exist:NTF \l_stex_current_repository_prop { + \stex_set_current_repository:n { + \prop_item:Nn \l_stex_current_repository_prop { id } + } + }{ + \let\exp_not:N\l_stex_current_repository_prop\exp_not:N\undefined + } + } + } +} +% \end{macrocode} +% \end{macro} +% +% \subsection{Using Content in Archives} +% +% \begin{macro}{\mhpath} +% \begin{macrocode} +\def \mhpath #1 #2 { + \exp_args:Ne \tl_if_empty:nTF{#1}{ + \c_stex_mathhub_str / + \prop_item:Nn \l_stex_current_repository_prop { id } + / source / #2 + }{ + \c_stex_mathhub_str / #1 / source / #2 + } +} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\inputref,\mhinput} +% \begin{macrocode} +\newif \ifinputref \inputreffalse + +\cs_new_protected:Nn \_@@_mhinput:nn { + \stex_in_repository:nn {#1} { + \ifinputref + \input{ \c_stex_mathhub_str / ##1 / source / #2 } + \else + \inputreftrue + \input{ \c_stex_mathhub_str / ##1 / source / #2 } + \inputreffalse + \fi + } +} +\NewDocumentCommand \mhinput { O{} m}{ + \stex_mhinput:nn{ #1 }{ #2 } +} + +\cs_new_protected:Nn \_@@_inputref:nn { + \stex_in_repository:nn {#1} { + \bool_lazy_any:nTF { + {\rustex_if_p:} + {\latexml_if_p:} + } { + \str_clear:N \l_tmpa_str + \prop_get:NnNF \l_stex_current_repository_prop { narr } \l_tmpa_str { + \prop_get:NnNF \l_stex_current_repository_prop { ns } \l_tmpa_str {} + } + \stex_annotate_invisible:nnn{inputref}{ + \l_tmpa_str / #2 + }{} + }{ + \begingroup + \inputreftrue + \input{ \c_stex_mathhub_str / ##1 / source / #2 } + \endgroup + } + } +} +\NewDocumentCommand \inputref { O{} m}{ + \_@@_inputref:nn{ #1 }{ #2 } +} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\addmhbibresource} +% \begin{macrocode} +\cs_new_protected:Nn \_@@_mhbibresource:nn { + \stex_in_repository:nn {#1} { + \addbibresource{ \c_stex_mathhub_str / ##1 / #2 } + } +} +\newcommand\addmhbibresource[2][]{ + \_@@_mhbibresource:nn{ #1 }{ #2 } +} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\libinput} +% \begin{macrocode} +\cs_new_protected:Npn \libinput #1 { + \prop_if_exist:NF \l_stex_current_repository_prop { + \msg_error:nnn{stex}{error/notinarchive}\libinput + } + \prop_get:NnNF \l_stex_current_repository_prop {id} \l_tmpa_str { + \msg_error:nnn{stex}{error/notinarchive}\libinput + } + \seq_clear:N \l_@@_libinput_files_seq + \seq_set_eq:NN \l_tmpa_seq \c_stex_mathhub_seq + \seq_set_split:NnV \l_tmpb_seq / \l_tmpa_str + + \bool_while_do:nn { ! \seq_if_empty_p:N \l_tmpb_seq }{ + \str_set:Nx \l_tmpa_str {\stex_path_to_string:N \l_tmpa_seq / meta-inf / lib / #1.tex} + \IfFileExists{ \l_tmpa_str }{ + \seq_put_right:No \l_@@_libinput_files_seq \l_tmpa_str + }{} + \seq_pop_left:NN \l_tmpb_seq \l_tmpa_str + \seq_put_right:No \l_tmpa_seq \l_tmpa_str + } + + \str_set:Nx \l_tmpa_str {\stex_path_to_string:N \l_tmpa_seq / lib / #1.tex} + \IfFileExists{ \l_tmpa_str }{ + \seq_put_right:No \l_@@_libinput_files_seq \l_tmpa_str + }{} + + \seq_if_empty:NTF \l_@@_libinput_files_seq { + \msg_error:nnxx{stex}{error/nofile}{\exp_not:N\libinput}{#1.tex} + }{ + \seq_map_inline:Nn \l_@@_libinput_files_seq { + \input{ ##1 } + } + } +} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\libusepackage} +% \begin{macrocode} +\NewDocumentCommand \libusepackage {O{} m} { + \prop_if_exist:NF \l_stex_current_repository_prop { + \msg_error:nnn{stex}{error/notinarchive}\libusepackage + } + \prop_get:NnNF \l_stex_current_repository_prop {id} \l_tmpa_str { + \msg_error:nnn{stex}{error/notinarchive}\libusepackage + } + \seq_clear:N \l_@@_libinput_files_seq + \seq_set_eq:NN \l_tmpa_seq \c_stex_mathhub_seq + \seq_set_split:NnV \l_tmpb_seq / \l_tmpa_str + + \bool_while_do:nn { ! \seq_if_empty_p:N \l_tmpb_seq }{ + \str_set:Nx \l_tmpa_str {\stex_path_to_string:N \l_tmpa_seq / meta-inf / lib / #2} + \IfFileExists{ \l_tmpa_str.sty }{ + \seq_put_right:No \l_@@_libinput_files_seq \l_tmpa_str + }{} + \seq_pop_left:NN \l_tmpb_seq \l_tmpa_str + \seq_put_right:No \l_tmpa_seq \l_tmpa_str + } + + \str_set:Nx \l_tmpa_str {\stex_path_to_string:N \l_tmpa_seq / lib / #2} + \IfFileExists{ \l_tmpa_str.sty }{ + \seq_put_right:No \l_@@_libinput_files_seq \l_tmpa_str + }{} + + \seq_if_empty:NTF \l_@@_libinput_files_seq { + \msg_error:nnxx{stex}{error/nofile}{\exp_not:N\libusepackage}{#2.sty} + }{ + \int_compare:nNnTF {\seq_count:N \l_@@_libinput_files_seq} = 1 { + \seq_map_inline:Nn \l_@@_libinput_files_seq { + \usepackage[#1]{ ##1 } + } + }{ + \msg_error:nnxx{stex}{error/twofiles}{\exp_not:N\libusepackage}{#2.sty} + } + } +} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\mhgraphics,\cmhgraphics} +% \begin{macrocode} + +\AddToHook{begindocument}{ + \ltx@ifpackageloaded{graphicx}{ + \define@key{Gin}{mhrepos}{\def\Gin@mhrepos{#1}} + \newcommand\mhgraphics[2][]{% + \def\Gin@mhrepos{}\setkeys{Gin}{#1}% + \includegraphics[#1]{\mhpath\Gin@mhrepos{#2}}} + \newcommand\cmhgraphics[2][]{\begin{center}\mhgraphics[#1]{#2}\end{center}} + }{} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\lstinputmhlisting,\clstinputmhlisting} +% \begin{macrocode} + \ltx@ifpackageloaded{listings}{ + \define@key{lst}{mhrepos}{\def\lst@mhrepos{#1}} + \newcommand\lstinputmhlisting[2][]{% + \def\lst@mhrepos{}\setkeys{lst}{#1}% + \lstinputlisting[#1]{\mhpath\lst@mhrepos{#2}}} + \newcommand\clstinputmhlisting[2][]{\begin{center}\lstinputmhlisting[#1]{#2}\end{center}} + }{} +} + +%</package> +% \end{macrocode} +% \end{macro} +% +% \end{implementation} +% +% \PrintIndex diff --git a/macros/latex/contrib/stex/source/stex/metatheory.dtx b/macros/latex/contrib/stex/source/stex/metatheory.dtx new file mode 100644 index 0000000000..a477e67f63 --- /dev/null +++ b/macros/latex/contrib/stex/source/stex/metatheory.dtx @@ -0,0 +1,179 @@ +% \iffalse meta-comment +% An Infrastructure for Semantic Macros and Module Scoping +% Copyright (c) 2019 Michael Kohlhase, all rights reserved +% this file is released under the +% LaTeX Project Public License (LPPL) +% +% The original of this file is in the public repository at +% http://github.com/sLaTeX/sTeX/ +% +% TODO update copyright +% +%<*driver> +\providecommand\bibfolder{../../lib/bib} +\input{../../doc/docheader} + +\begin{document} + \DocInput{\jobname.dtx} +\end{document} +%</driver> +% \fi +% +% \title{ \sTeX-Metatheory +% \thanks{Version {\fileversion} (last revised {\filedate})} +% } +% +% \author{Michael Kohlhase, Dennis Müller\\ +% FAU Erlangen-Nürnberg\\ +% \url{http://kwarc.info/} +% } +% +% \maketitle +% +%\ifinfulldoc\else +% This is the documentation for the \pkg{stex-metatheory} package. +% For a more high-level introduction, +% see \href{\basedocurl/manual.pdf}{the \sTeX Manual} or the +% \href{\basedocurl/stex.pdf}{full \sTeX documentation}. +% +% \input{../../doc/packages/metatheory} +% \fi +% +% \begin{documentation}\label{pkg:metatheory:doc} +% +% The default meta theory for an \sTeX module. Contains +% symbols so ubiquitous, that it is virtually impossible +% to describe any flexiformal content without them, or +% that are required to annotate even the most primitive symbols +% with meaningful (foundation-independent) ``type''-annotations, +% or required for basic structuring principles (theorems, definitions). +% +% Foundations should ideally instantiate these symbols +% with their formal counterparts, e.g. |isa| corresponds +% to a typing operation in typed setting, or the $\in$-operator +% in set-theoretic contexts; |bind| corresponds to a universal +% quantifier in ($n$th-order) logic, or a $\Pi$ in dependent type +% theories. +% +% \section{Symbols}\label{pkg:metatheory:symbols} +% +% \end{documentation} +% +% \begin{implementation}\label{pkg:metatheory:impl} +% +% \section{\sTeX-Metatheory Implementation} +% +% \begin{macrocode} +%<*package> +%<@@=stex_modules> + +%%%%%%%%%%%%% metatheory.dtx %%%%%%%%%%%%% + +\str_const:Nn \c_stex_metatheory_ns_str {http://mathhub.info/sTeX} +\begingroup +\stex_module_setup:nn{ + ns=\c_stex_metatheory_ns_str, + meta=NONE +}{Metatheory} +\stex_reactivate_macro:N \symdecl +\stex_reactivate_macro:N \notation +\stex_reactivate_macro:N \symdef +\ExplSyntaxOff +\csname stex_suppress_html:n\endcsname{ + % is-a (a:A, a \in A, a is an A, etc.) + \symdecl{isa}[args=ai] + \notation{isa}[typed]{#1 \comp{:} #2}{##1 \comp, ##2} + \notation{isa}[in]{#1 \comp\in #2}{##1 \comp, ##2} + \notation{isa}[pred]{#2\comp(#1 \comp)}{##1 \comp, ##2} + + % bind (\forall, \Pi, \lambda etc.) + \symdecl{bind}[args=Bi] + \notation{bind}[forall]{\comp\forall #1.\;#2}{##1 \comp, ##2} + \notation{bind}[Pi]{\comp\prod_{#1}#2}{##1 \comp, ##2} + \notation{bind}[depfun]{\comp( #1 \comp{)\;\to\;} #2}{##1 \comp, ##2} + + % dummy variable + \symdecl{dummyvar} + \notation{dummyvar}[underscore]{\comp\_} + \notation{dummyvar}[dot]{\comp\cdot} + \notation{dummyvar}[dash]{\comp{{\rm --}}} + + %fromto (function space, Hom-set, implication etc.) + \symdecl{fromto}[args=ai] + \notation{fromto}[xarrow]{#1 \comp\to #2}{##1 \comp\times ##2} + \notation{fromto}[arrow]{#1 \comp\to #2}{##1 \comp\to ##2} + + % mapto (lambda etc.) + %\symdecl{mapto}[args=Bi] + %\notation{mapto}[mapsto]{#1 \comp\mapsto #2}{#1 \comp, #2} + %\notation{mapto}[lambda]{\comp\lambda #1 \comp.\; #2}{#1 \comp, #2} + %\notation{mapto}[lambdau]{\comp\lambda_{#1} \comp.\; #2}{#1 \comp, #2} + + % function/operator application + \symdecl{apply}[args=ia] + \notation{apply}[prec=0;0x\infprec,parens]{#1 \comp( #2 \comp)}{##1 \comp, ##2} + \notation{apply}[prec=0;0x\infprec,lambda]{#1 \; #2 }{##1 \; ##2} + + % ``type'' of all collections (sets,classes,types,kinds) + \symdecl{collection} + \notation{collection}[U]{\comp{\mathcal{U}}} + \notation{collection}[set]{\comp{\textsf{Set}}} + + % collection of propositions/booleans/truth values + \symdecl{prop}[name=proposition] + \notation{prop}[prop]{\comp{{\rm prop}}} + \notation{prop}[BOOL]{\comp{{\rm BOOL}}} + + % sequences + \symdecl{seqtype}[args=1] + \notation{seqtype}[kleene]{#1^{\comp\ast}} + + \symdef{sequence-index}[args=2,li,prec=nobrackets]{{#1}_{#2}} + \notation{sequence-index}[ui,prec=nobrackets]{{#1}^{#2}} + + \symdef{aseqdots}[args=a,prec=nobrackets]{#1\comp{,\ellipses}}{##1\comp,##2} + \symdef{aseqfromto}[args=ai,prec=nobrackets]{#1\comp{,\ellipses,}#2}{##1\comp,##2} + \symdef{aseqfromtovia}[args=aii,prec=nobrackets]{#1\comp{,\ellipses,}#2\comp{,\ellipses,}#3}{##1\comp,##2} + + % letin (``let'', local definitions, variable substitution) + \symdecl{letin}[args=bii] + \notation{letin}[let]{\comp{{\rm let}}\;#1\comp{=}#2\;\comp{{\rm in}}\;#3} + \notation{letin}[subst]{#3 \comp[ #1 \comp/ #2 \comp]} + \notation{letin}[frac]{#3 \comp[ \frac{#2}{#1} \comp]} + + % structures + \symdecl*{module-type}[args=1] + \notation{module-type}{\mathtt{MOD} #1} + \symdecl{mathstruct}[name=mathematical-structure,args=a] % TODO + \notation{mathstruct}[angle,prec=nobrackets]{\comp\langle #1 \comp\rangle}{##1 \comp, ##2} + +} + \ExplSyntaxOn + \stex_add_to_current_module:n{ + \let\nappa\apply + \def\nappli#1#2#3#4{\apply{#1}{\naseqli{#2}{#3}{#4}}} + \def\nappui#1#2#3#4{\apply{#1}{\nasequi{#2}{#3}{#4}}} + \def\livar{\csname sequence-index\endcsname[li]} + \def\uivar{\csname sequence-index\endcsname[ui]} + \def\naseqli#1#2#3{\aseqfromto{\livar{#1}{#2}}{\livar{#1}{#3}}} + \def\nasequi#1#2#3{\aseqfromto{\uivar{#1}{#2}}{\uivar{#1}{#3}}} + \def\nappe#1#2#3{\apply{#1}{\aseqfromto{#2}{#3}}} + } +\_@@_end_module: +\endgroup +% \end{macrocode} +% +% +% \begin{macrocode} +%</package> +% \end{macrocode} +% +% \end{implementation} +% +% \PrintIndex + +% \endinput +% Local Variables: +% mode: doctex +% TeX-master: t +% End: diff --git a/macros/latex/contrib/stex/source/stex/modules.dtx b/macros/latex/contrib/stex/source/stex/modules.dtx new file mode 100644 index 0000000000..f345e3066b --- /dev/null +++ b/macros/latex/contrib/stex/source/stex/modules.dtx @@ -0,0 +1,824 @@ +% \iffalse meta-comment +% An Infrastructure for Semantic Macros and Module Scoping +% Copyright (c) 2019 Michael Kohlhase, all rights reserved +% this file is released under the +% LaTeX Project Public License (LPPL) +% +% The original of this file is in the public repository at +% http://github.com/sLaTeX/sTeX/ +% +% TODO update copyright +% +%<*driver> +\providecommand\bibfolder{../../lib/bib} +\input{../../doc/docheader} + +\begin{document} + \DocInput{\jobname.dtx} +\end{document} +%</driver> +% \fi +% +% \title{ \sTeX-Modules +% \thanks{Version {\fileversion} (last revised {\filedate})} +% } +% +% \author{Michael Kohlhase, Dennis Müller\\ +% FAU Erlangen-Nürnberg\\ +% \url{http://kwarc.info/} +% } +% +% \maketitle +% +%\ifinfulldoc\else +% This is the documentation for the \pkg{stex-modules} package. +% For a more high-level introduction, +% see \href{\basedocurl/manual.pdf}{the \sTeX Manual} or the +% \href{\basedocurl/stex.pdf}{full \sTeX documentation}.\fi +% +% +% \begin{documentation}\label{pkg:modules:doc} +% +% This sub package contains code related to Modules +% +% \ifinfulldoc\else +% \input{../../doc/packages/modules} +% \fi +% +% \section{Macros and Environments}\label{pkg:modules:doc:macros} +% +% The content of a module with uri \meta{<URI>} is stored in four +% macros. All modifications of these macros are global: +% \begin{variable}{\c_stex_module_<URI>_prop} +% A property list with the following fields: +% \begin{itemize} +% \item[|name|] The \emph{name} of the module, +% \item[|ns|] the \emph{namespace} in field |ns|, +% \item[|file|] the \emph{file} containing the module, +% as a sequence of path fragments +% \item[|lang|] the module's \emph{language}, +% \item[|sig|] the language of the signature module, if the +% current file is a translation from some other language, +% \item[|deprecate|] if this module is deprecated, the module +% that replaces it, +% \item[|meta|] the metatheory of the module. +% \end{itemize} +% \end{variable} +% +% \begin{variable}{\c_stex_module_<URI>_code} +% The code to execute when this module is activated (i.e. imported), +% e.g. to set all the semantic macros, notations, etc. +% \end{variable} +% +% \begin{variable}{\c_stex_module_<URI>_constants} +% The names of all constants declared in the module +% \end{variable} +% +% \begin{variable}{\c_stex_module_<URI>_constants} +% The full URIs of all modules imported in this module +% \end{variable} +% +% \begin{variable}{\l_stex_current_module_str} +% \cs{l_stex_current_module_str} always +% contains the URI of the current module (if existent). +% \end{variable} +% +% \begin{variable}{\l_stex_all_modules_seq} +% Stores full URIs for all modules currently in scope. +% \end{variable} +% +% \begin{function}[pTF]{\stex_if_in_module:} +% Conditional for whether we are currently in a module +% \end{function} +% +% \begin{function}[pTF]{\stex_if_module_exists:n} +% Conditional for whether a module with the provided URI +% is already known. +% \end{function} +% +% \begin{function}{\stex_add_to_current_module:n,\STEXexport} +% Adds the provided tokens to the |_code| control sequence of the +% current module. +% +% \cs{stex_add_to_current_module:n} is used internally, +% \cs{STEXexport} is intended for users and additionally executes +% the provided code immediately. +% \end{function} +% +% \begin{function}{\stex_add_constant_to_current_module:n} +% Adds the declaration with the provided name to the |_constants| +% control sequence of the current module. +% \end{function} +% +% \begin{function}{\stex_add_import_to_current_module:n} +% Adds the module with the provided full URI to the |_imports| +% control sequence of the current module. +% \end{function} +% +% \begin{function}{\stex_collect_imports:n} +% Iterates over all imports of the provided (full URI of a) module +% and stores them as a topologically sorted list -- including +% the provided module as the last element -- in +% |\l_stex_collect_imports_seq| +% \end{function} +% +% \begin{function}{\stex_do_up_to_module:n} +% Code that is \emph{exported} from module (such as symbol declarations) +% should be local \emph{to the current module}. For that reason, ideally +% all symbol declarations and similar commands should be called directly +% in the module environment, however, that is not always feasible, e.g. +% in structural features or |sparapraph|s. \cs{stex_do_up_to_module} +% therefore executes the provided code repeatedly in an \cs{aftergroup} +% up until the group level is equal to that of the innermost smodule environment. +% \end{function} +% +% \begin{function}{\stex_modules_current_namespace:} +% Computes the current namespace as follows: +% +% If the current file is |.../source/sub/file.tex| in some archive +% with namespace |http://some.namespace/foo|, then the namespace of +% is |http://some.namespace/foo/sub/file|. Otherwise, the namespace +% is the absolute file path of the current file (i.e. starting with |file:///|). +% +% The result is stored in |\l_stex_modules_ns_str|. Additionally, the sub path +% relative to the current repository is stored in |\l_stex_modules_subpath_str|. +% \end{function} +% +% \subsection{The \texttt{smodule} environment} +% +% \begin{environment}{module} +% \begin{syntax} \cs{begin}|{module}[|\meta{options}|]|\Arg{name}\end{syntax} +% +% Opens a new module with name \meta{name}. Options are: +% \begin{itemize} +% \item[|title|] (\meta{token list}) to display in customizations. +% \item[|type|] (\meta{string}$\ast$) for use in customizations. +% \item[|deprecate|] (\meta{module}) if set, will throw a warning +% when loaded, urging to use \meta{module} instead. +% \item[|id|] (\meta{string}) for cross-referencing. +% \item[|ns|] (\meta{URI}) the namespace to use. \emph{Should not be used, +% unless you know precisely what you're doing}. If not explicitly set, is +% computed using \cs{stex_modules_current_namespace:}. +% \item[|lang|] (\meta{language}) if not set, computed from the current file name (e.g. |foo.en.tex|). +% \item[|sig|] (\meta{language}) if the current file is a translation of a file with the same base name +% but a different language suffix, setting |sig=<lang>| will preload the module +% from that language file. This helps ensuring that the (formal) content of both modules +% is (almost) identical across languages and avoids duplication. +% \item[|creators|] (\meta{string}$\ast$) names of the creators. +% \item[|contributors|] (\meta{string}$\ast$) names of contributors. +% \item[|srccite|] (\meta{string}) a source citation for the content of this module. +% \end{itemize} +% +% \begin{function}{\stex_module_setup:nn} +% \begin{syntax}\cs{stex_module_setup:nn}\Arg{params}\Arg{name}\end{syntax} +% Sets up a new module with name \meta{name} and optional parameters +% \meta{params}. In particular, sets +% \cs{l_stex_current_module_str} appropriately. +% \end{function} +% +% \end{environment} +% +% \begin{function}{\stexpatchmodule} +% \begin{syntax} \cs{stexpatchmodule} [\meta{type}] \Arg{begincode} \Arg{endcode} \end{syntax} +% Customizes the presentation for those |smodule|-environments +% with |type=|\meta{type}, or all others if no \meta{type} is given. +% \end{function} +% +% \begin{function}{\STEXModule} +% \begin{syntax} \cs{STEXModule} \Arg{fragment} \end{syntax} +% Attempts to find a module whose URI ends with \meta{fragment} +% in the current scope and passes the full URI on to +% \cs{stex_invoke_module:n}. +% \end{function} +% +% \begin{function}{\stex_invoke_module:n} +% Invoked by \cs{STEXModule}. Needs to be followed either +% by |!\macro| or |?|\Arg{symbolname}. In the first case, +% it stores the full URI in \cs{macro}; in the second +% case, it invokes the symbol \meta{symbolname} in the +% selected module. +% \end{function} +% +% \begin{function}{\stex_activate_module:n} +% Activate the module with the provided URI; i.e. executes +% all macro code of the module's |_code|-macro (does +% nothing if the module is already activated in the current +% context) and adds the module to \cs{l_stex_all_modules_seq}. +% \end{function} +% +% \end{documentation} +% +% \begin{implementation}\label{pkg:modules:impl} +% +% \section{\sTeX-Modules Implementation} +% +% \begin{macrocode} +%<*package> + +%%%%%%%%%%%%% modules.dtx %%%%%%%%%%%%% + +%<@@=stex_modules> +% \end{macrocode} +% +% Warnings and error messages +% +% \begin{macrocode} +\msg_new:nnn{stex}{error/unknownmodule}{ + No~module~#1~found +} +\msg_new:nnn{stex}{error/syntax}{ + Syntax~error:~#1 +} +\msg_new:nnn{stex}{error/siglanguage}{ + Module~#1~declares~signature~#2,~but~does~not~ + declare~its~language +} +\msg_new:nnn{stex}{warning/deprecated}{ + #1~is~deprecated;~please~use~#2~instead! +} + +\msg_new:nnn{stex}{error/conflictingmodules}{ + Conflicting~imports~for~module~#1 +} +% \end{macrocode} +% +% +% \begin{variable}{\l_stex_current_module_str} +% The current module: +% \begin{macrocode} +\str_new:N \l_stex_current_module_str +% \end{macrocode} +% \end{variable} +% +% \begin{variable}{\l_stex_all_modules_seq} +% Stores all available modules +% \begin{macrocode} +\seq_new:N \l_stex_all_modules_seq +% \end{macrocode} +% \end{variable} +% +% \begin{macro}[pTF]{\stex_if_in_module:} +% \begin{macrocode} +\prg_new_conditional:Nnn \stex_if_in_module: {p, T, F, TF} { + \str_if_empty:NTF \l_stex_current_module_str + \prg_return_false: \prg_return_true: +} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}[pTF]{\stex_if_module_exists:n} +% \begin{macrocode} +\prg_new_conditional:Nnn \stex_if_module_exists:n {p, T, F, TF} { + \prop_if_exist:cTF { c_stex_module_#1_prop } + \prg_return_true: \prg_return_false: +} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\stex_add_to_current_module:n,\STEXexport} +% +% Only allowed within modules: +% +% \begin{macrocode} +\cs_new_protected:Nn \stex_add_to_current_module:n { + \tl_gput_right:cn {c_stex_module_\l_stex_current_module_str _code} { #1 } +} +\cs_new_protected:Npn \STEXexport { + \begingroup + \newlinechar=-1\relax + \endlinechar=-1\relax + %\catcode`\ = 9\relax + \expandafter\endgroup\_@@_export:n +} +\cs_new_protected:Nn \_@@_export:n { + \ignorespaces #1 + \stex_add_to_current_module:n { \ignorespaces #1 } + \stex_smsmode_do: +} +\stex_deactivate_macro:Nn \STEXexport {module~environments} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\stex_add_constant_to_current_module:n} +% \begin{macrocode} +\cs_new_protected:Nn \stex_add_constant_to_current_module:n { + \str_set:Nx \l_tmpa_str { #1 } + \seq_gput_right:co {c_stex_module_\l_stex_current_module_str _constants} { \l_tmpa_str } +} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\stex_add_import_to_current_module:n} +% \begin{macrocode} +\cs_new_protected:Nn \stex_add_import_to_current_module:n { + \str_set:Nx \l_tmpa_str { #1 } + \exp_args:Nno + \seq_if_in:cnF{c_stex_module_\l_stex_current_module_str _imports}\l_tmpa_str{ + \seq_gput_right:co{c_stex_module_\l_stex_current_module_str _imports}\l_tmpa_str + } +} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\stex_collect_imports:n} +% \begin{macrocode} +\cs_new_protected:Nn \stex_collect_imports:n { + \seq_clear:N \l_stex_collect_imports_seq + \_@@_collect_imports:n {#1} +} +\cs_new_protected:Nn \_@@_collect_imports:n { + \seq_map_inline:cn {c_stex_module_#1_imports} { + \seq_if_in:NnF \l_stex_collect_imports_seq { ##1 } { + \_@@_collect_imports:n { ##1 } + } + } + \seq_if_in:NnF \l_stex_collect_imports_seq { #1 } { + \seq_put_right:Nx \l_stex_collect_imports_seq { #1 } + } +} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\stex_do_up_to_module:n} +% \begin{macrocode} +\int_new:N \l_@@_group_depth_int +\tl_new:N \l_@@_aftergroup_tl +\cs_new_protected:Nn \stex_do_up_to_module:n { + \int_compare:nNnTF \l_@@_group_depth_int = \currentgrouplevel { + #1 + }{ + #1 + \expandafter \tl_gset:Nn \expandafter \l_@@_aftergroup_tl \expandafter { \l_@@_aftergroup_tl #1 } + \aftergroup\_@@_aftergroup_do: + } +} +\cs_new_protected:Nn \_@@_aftergroup_do: { + \int_compare:nNnTF \l_@@_group_depth_int = \currentgrouplevel { + \l_@@_aftergroup_tl + \tl_clear:N \l_@@_aftergroup_tl + }{ + \l_@@_aftergroup_tl + \aftergroup\_@@_aftergroup_do: + } +} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\stex_modules_compute_namespace:nN} +% Computes the appropriate namespace from the top-level namespace +% of a repository (|#1|) and a file path +% (|#2|). +% +% +% \begin{macrocode} + +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\stex_modules_current_namespace:} +% +% Computes the current namespace based on the current +% MathHub repository (if existent) and the current file. +% +% \begin{macrocode} +\str_new:N \l_stex_modules_ns_str +\str_new:N \l_stex_modules_subpath_str +\cs_new_protected:Nn \_@@_compute_namespace:nN { + \str_set:Nx \l_tmpa_str { #1 } + \seq_set_eq:NN \l_tmpa_seq #2 + % split off file extension + \seq_pop_right:NN \l_tmpa_seq \l_tmpb_str + \exp_args:NNno \seq_set_split:Nnn \l_tmpb_seq . \l_tmpb_str + \seq_get_left:NN \l_tmpb_seq \l_tmpb_str + \seq_put_right:No \l_tmpa_seq \l_tmpb_str + + \bool_set_true:N \l_tmpa_bool + \bool_while_do:Nn \l_tmpa_bool { + \seq_pop_left:NN \l_tmpa_seq \l_tmpb_str + \exp_args:No \str_case:nnTF { \l_tmpb_str } { + {source} { \bool_set_false:N \l_tmpa_bool } + }{}{ + \seq_if_empty:NT \l_tmpa_seq { + \bool_set_false:N \l_tmpa_bool + } + } + } + + \stex_path_to_string:NN \l_tmpa_seq \l_stex_modules_subpath_str + \str_if_empty:NTF \l_stex_modules_subpath_str { + \str_set_eq:NN \l_stex_modules_ns_str \l_tmpa_str + }{ + \str_set:Nx \l_stex_modules_ns_str { + \l_tmpa_str/\l_stex_modules_subpath_str + } + } +} + +\cs_new_protected:Nn \stex_modules_current_namespace: { + \str_clear:N \l_stex_modules_subpath_str + \prop_if_exist:NTF \l_stex_current_repository_prop { + \prop_get:NnN \l_stex_current_repository_prop { ns } \l_tmpa_str + \_@@_compute_namespace:nN \l_tmpa_str \g_stex_currentfile_seq + }{ + % split off file extension + \seq_set_eq:NN \l_tmpa_seq \g_stex_currentfile_seq + \seq_pop_right:NN \l_tmpa_seq \l_tmpb_str + \exp_args:NNno \seq_set_split:Nnn \l_tmpb_seq . \l_tmpb_str + \seq_get_left:NN \l_tmpb_seq \l_tmpb_str + \seq_put_right:No \l_tmpa_seq \l_tmpb_str + \str_set:Nx \l_stex_modules_ns_str { + file:/\stex_path_to_string:N \l_tmpa_seq + } + } +} +% \end{macrocode} +% \end{macro} +% +% \subsubsection{The \texttt{smodule} environment} +% +% |smodule| arguments: +% +% \begin{macrocode} +\keys_define:nn { stex / module } { + title .tl_set:N = \smoduletitle , + type .str_set_x:N = \smoduletype , + id .str_set_x:N = \smoduleid , + deprecate .str_set_x:N = \l_stex_module_deprecate_str , + ns .str_set_x:N = \l_stex_module_ns_str , + lang .str_set_x:N = \l_stex_module_lang_str , + sig .str_set_x:N = \l_stex_module_sig_str , + creators .str_set_x:N = \l_stex_module_creators_str , + contributors .str_set_x:N = \l_stex_module_contributors_str , + meta .str_set_x:N = \l_stex_module_meta_str , + srccite .str_set_x:N = \l_stex_module_srccite_str +} + +\cs_new_protected:Nn \_@@_args:n { + \str_clear:N \smoduletitle + \str_clear:N \smoduletype + \str_clear:N \smoduleid + \str_clear:N \l_stex_module_ns_str + \str_clear:N \l_stex_module_deprecate_str + \str_clear:N \l_stex_module_lang_str + \str_clear:N \l_stex_module_sig_str + \str_clear:N \l_stex_module_creators_str + \str_clear:N \l_stex_module_contributors_str + \str_clear:N \l_stex_module_meta_str + \str_clear:N \l_stex_module_srccite_str + \keys_set:nn { stex / module } { #1 } +} + +% module parameters here? In the body? + +% \end{macrocode} +% +% \begin{macro}{\stex_module_setup:nn} +% Sets up a new module property list: +% \begin{macrocode} +\cs_new_protected:Nn \stex_module_setup:nn { + \str_set:Nx \l_stex_module_name_str { #2 } + \_@@_args:n { #1 } +% \end{macrocode} +% +% First, we set up the name and namespace of the module. +% +% Are we in a nested module? +% +% \begin{macrocode} + \stex_if_in_module:TF { + % Nested module + \prop_get:cnN {c_stex_module_\l_stex_current_module_str _prop} + { ns } \l_stex_module_ns_str + \str_set:Nx \l_stex_module_name_str { + \prop_item:cn {c_stex_module_\l_stex_current_module_str _prop} + { name } / \l_stex_module_name_str + } + }{ + % not nested: + \str_if_empty:NT \l_stex_module_ns_str { + \stex_modules_current_namespace: + \str_set_eq:NN \l_stex_module_ns_str \l_stex_modules_ns_str + \exp_args:NNNo \seq_set_split:Nnn \l_tmpa_seq + / {\l_stex_module_ns_str} + \seq_pop_right:NN \l_tmpa_seq \l_tmpa_str + \str_if_eq:NNT \l_tmpa_str \l_stex_module_name_str { + \str_set:Nx \l_stex_module_ns_str { + \stex_path_to_string:N \l_tmpa_seq + } + } + } + } +% \end{macrocode} +% +% Next, we determine the language of the module: +% +% \begin{macrocode} + \str_if_empty:NT \l_stex_module_lang_str { + \seq_get_right:NN \g_stex_currentfile_seq \l_tmpa_str + \seq_set_split:NnV \l_tmpa_seq . \l_tmpa_str + \seq_pop_right:NN \l_tmpa_seq \l_tmpa_str % .tex + \seq_pop_left:NN \l_tmpa_seq \l_tmpa_str % <filename> + \seq_if_empty:NF \l_tmpa_seq { %remaining element should be language + \stex_debug:nn{modules} {Language~\l_stex_module_lang_str~ + inferred~from~file~name} + \seq_pop_left:NN \l_tmpa_seq \l_stex_module_lang_str + } + } + + \stex_if_smsmode:F { \str_if_empty:NF \l_stex_module_lang_str { + \prop_get:NVNTF \c_stex_languages_prop \l_stex_module_lang_str + \l_tmpa_str { + \ltx@ifpackageloaded{babel}{ + \exp_args:Nx \selectlanguage { \l_tmpa_str } + }{} + } { + \msg_error:nnx{stex}{error/unknownlanguage}{\l_tmpa_str} + } + }} +% \end{macrocode} +% +% We check if we need to extend a signature module, and set +% \cs{l_stex_current_module_prop} accordingly: +% +% \begin{macrocode} + \str_if_empty:NTF \l_stex_module_sig_str { + \exp_args:Nnx \prop_gset_from_keyval:cn { + c_stex_module_\l_stex_module_ns_str?\l_stex_module_name_str _prop + } { + name = \l_stex_module_name_str , + ns = \l_stex_module_ns_str , + file = \exp_not:o { \g_stex_currentfile_seq } , + lang = \l_stex_module_lang_str , + sig = \l_stex_module_sig_str , + deprecate = \l_stex_module_deprecate_str , + meta = \l_stex_module_meta_str + } + \seq_clear:c {c_stex_module_\l_stex_module_ns_str?\l_stex_module_name_str _imports} + \seq_clear:c {c_stex_module_\l_stex_module_ns_str?\l_stex_module_name_str _constants} + \tl_clear:c {c_stex_module_\l_stex_module_ns_str?\l_stex_module_name_str _code} + \str_set:Nx\l_stex_current_module_str{\l_stex_module_ns_str?\l_stex_module_name_str} +% \end{macrocode} +% +% We load the metatheory: +% +% \begin{macrocode} + \str_if_empty:NT \l_stex_module_meta_str { + \str_set:Nx \l_stex_module_meta_str { + \c_stex_metatheory_ns_str ? Metatheory + } + } + \str_if_eq:VnF \l_stex_module_meta_str {NONE} { + \bool_set_true:N \l_stex_in_meta_bool + \exp_args:Nx \stex_add_to_current_module:n { + \bool_set_true:N \l_stex_in_meta_bool + \stex_activate_module:n {\l_stex_module_meta_str} + \bool_set_false:N \l_stex_in_meta_bool + } + \stex_activate_module:n {\l_stex_module_meta_str} + \bool_set_false:N \l_stex_in_meta_bool + } + }{ + \str_if_empty:NT \l_stex_module_lang_str { + \msg_error:nnxx{stex}{error/siglanguage}{ + \l_stex_module_ns_str?\l_stex_module_name_str + }{\l_stex_module_sig_str} + } + + \seq_set_eq:NN \l_tmpa_seq \g_stex_currentfile_seq + \seq_pop_right:NN \l_tmpa_seq \l_tmpa_str + \seq_set_split:NnV \l_tmpb_seq . \l_tmpa_str + \seq_pop_right:NN \l_tmpb_seq \l_tmpa_str % .tex + \seq_pop_left:NN \l_tmpb_seq \l_tmpa_str % <filename> + \str_set:Nx \l_tmpa_str { + \stex_path_to_string:N \l_tmpa_seq / + \l_tmpa_str . \l_stex_module_sig_str .tex + } + \IfFileExists \l_tmpa_str { + \exp_args:No \stex_file_in_smsmode:nn { \l_tmpa_str } { + \str_clear:N \l_stex_current_module_str + \seq_clear:N \l_stex_all_modules_seq + \stex_debug:nn{modules}{Loading~signature~\l_tmpa_str} + } + }{ + \msg_error:nnx{stex}{error/unknownmodule}{for~signature~\l_tmpa_str} + } + \stex_if_smsmode:F { + \stex_activate_module:n { + \l_stex_module_ns_str ? \l_stex_module_name_str + } + } + \str_set:Nx\l_stex_current_module_str{\l_stex_module_ns_str?\l_stex_module_name_str} + } + \str_if_empty:NF \l_stex_module_deprecate_str { + \msg_warning:nnxx{stex}{warning/deprecated}{ + Module~\l_stex_current_module_str + }{ + \l_stex_module_deprecate_str + } + } + \seq_put_right:Nx \l_stex_all_modules_seq { + \l_stex_module_ns_str ? \l_stex_module_name_str + } +} +% \end{macrocode} +% \end{macro} +% +% \begin{environment}{smodule} +% +% The |module| environment. +% +% \begin{macro}{\_@@_begin_module:} +% +% implements |\begin{smodule}| +% +% \begin{macrocode} +\cs_new_protected:Nn \_@@_begin_module: { + \stex_reactivate_macro:N \STEXexport + \stex_reactivate_macro:N \importmodule + \stex_reactivate_macro:N \symdecl + \stex_reactivate_macro:N \notation + \stex_reactivate_macro:N \symdef + + \stex_debug:nn{modules}{ + New~module:\\ + Namespace:~\l_stex_module_ns_str\\ + Name:~\l_stex_module_name_str\\ + Language:~\l_stex_module_lang_str\\ + Signature:~\l_stex_module_sig_str\\ + Metatheory:~\l_stex_module_meta_str\\ + File:~\stex_path_to_string:N \g_stex_currentfile_seq + } + + \stex_if_smsmode:F{ + \begin{stex_annotate_env} {theory} { + \l_stex_module_ns_str ? \l_stex_module_name_str + } + + \stex_annotate_invisible:nnn{header}{} { + \stex_annotate:nnn{language}{ \l_stex_module_lang_str }{} + \stex_annotate:nnn{signature}{ \l_stex_module_sig_str }{} + \str_if_eq:VnF \l_stex_module_meta_str {NONE} { + \stex_annotate:nnn{metatheory}{ \l_stex_module_meta_str }{} + } + \str_if_empty:NF \smoduletype { + \stex_annotate:nnn{type}{\smoduletype}{} + } + } + } + \int_set:Nn \l_@@_group_depth_int {\currentgrouplevel} + % TODO: Inherit metatheory for nested modules? +} +\iffalse \end{stex_annotate_env} \fi %^^A make syntax highlighting work again +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\_@@_end_module:} +% +% implements |\end{module}| +% +% \begin{macrocode} +\cs_new_protected:Nn \_@@_end_module: { + \stex_debug:nn{modules}{Closing~module~\prop_item:cn {c_stex_module_\l_stex_current_module_str _prop} { name }} +} +% \end{macrocode} +% \end{macro} +% +% The core environment +% +% \begin{macrocode} +\iffalse \begin{stex_annotate_env} \fi %^^A make syntax highlighting work again +\NewDocumentEnvironment { smodule } { O{} m } { + \stex_module_setup:nn{#1}{#2} + \par + \stex_if_smsmode:F{ + \tl_clear:N \l_tmpa_tl + \clist_map_inline:Nn \smoduletype { + \tl_if_exist:cT {_@@_smodule_##1_start:}{ + \tl_set:Nn \l_tmpa_tl {\use:c{_@@_smodule_##1_start:}} + } + } + \tl_if_empty:NTF \l_tmpa_tl { + \_@@_smodule_start: + }{ + \l_tmpa_tl + } + } + \_@@_begin_module: + \str_if_empty:NF \smoduleid { + \stex_ref_new_doc_target:n \smoduleid + } + \stex_smsmode_do: +} { + \_@@_end_module: + \stex_if_smsmode:F { + \end{stex_annotate_env} + \clist_set:No \l_tmpa_clist \smoduletype + \tl_clear:N \l_tmpa_tl + \clist_map_inline:Nn \l_tmpa_clist { + \tl_if_exist:cT {_@@_smodule_##1_end:}{ + \tl_set:Nn \l_tmpa_tl {\use:c{_@@_smodule_##1_end:}} + } + } + \tl_if_empty:NTF \l_tmpa_tl { + \_@@_smodule_end: + }{ + \l_tmpa_tl + } + } +} +% \end{macrocode} +% \end{environment} +% +% \begin{macro}{\stexpatchmodule} +% \begin{macrocode} +\cs_new_protected:Nn \_@@_smodule_start: {} +\cs_new_protected:Nn \_@@_smodule_end: {} + +\newcommand\stexpatchmodule[3][] { + \str_set:Nx \l_tmpa_str{ #1 } + \str_if_empty:NTF \l_tmpa_str { + \tl_set:Nn \_@@_smodule_start: { #2 } + \tl_set:Nn \_@@_smodule_end: { #3 } + }{ + \exp_after:wN \tl_set:Nn \csname _@@_smodule_#1_start:\endcsname{ #2 } + \exp_after:wN \tl_set:Nn \csname _@@_smodule_#1_end:\endcsname{ #3 } + } +} +% \end{macrocode} +% \end{macro} +% +% \subsubsection{Invoking modules} +% +% \begin{macro}{\STEXModule,\stex_invoke_module:n} +% \begin{macrocode} +\NewDocumentCommand \STEXModule { m } { + \exp_args:NNx \str_set:Nn \l_tmpa_str { #1 } + \int_set:Nn \l_tmpa_int { \str_count:N \l_tmpa_str } + \tl_set:Nn \l_tmpa_tl { + \msg_error:nnx{stex}{error/unknownmodule}{#1} + } + \seq_map_inline:Nn \l_stex_all_modules_seq { + \str_set:Nn \l_tmpb_str { ##1 } + \str_if_eq:eeT { \l_tmpa_str } { + \str_range:Nnn \l_tmpb_str { -\l_tmpa_int } { -1 } + } { + \seq_map_break:n { + \tl_set:Nn \l_tmpa_tl { + \stex_invoke_module:n { ##1 } + } + } + } + } + \l_tmpa_tl +} + +\cs_new_protected:Nn \stex_invoke_module:n { + \stex_debug:nn{modules}{Invoking~module~#1} + \peek_charcode_remove:NTF ! { + \_@@_invoke_uri:nN { #1 } + } { + \peek_charcode_remove:NTF ? { + \_@@_invoke_symbol:nn { #1 } + } { + \msg_error:nnx{stex}{error/syntax}{ + ?~or~!~expected~after~ + \c_backslash_str STEXModule{#1} + } + } + } +} + +\cs_new_protected:Nn \_@@_invoke_uri:nN { + \str_set:Nn #2 { #1 } +} + +\cs_new_protected:Nn \_@@_invoke_symbol:nn { + \stex_invoke_symbol:n{#1?#2} +} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\stex_activate_module:n} +% \begin{macrocode} +\bool_new:N \l_stex_in_meta_bool +\bool_set_false:N \l_stex_in_meta_bool +\cs_new_protected:Nn \stex_activate_module:n { + \stex_debug:nn{modules}{Activating~module~#1} + \seq_if_in:NnT \l_stex_implicit_morphisms_seq { #1 }{ + \msg_error:nnn{stex}{error/conflictingmodules}{ #1 } + } + \exp_args:NNx \seq_if_in:NnF \l_stex_all_modules_seq { #1 } { + \seq_put_right:Nx \l_stex_all_modules_seq { #1 } + \use:c{ c_stex_module_#1_code } + } +} +% \end{macrocode} +% \end{macro} +% +% \begin{macrocode} +%</package> +% \end{macrocode} +% +% \end{implementation} +% +% \PrintIndex diff --git a/macros/latex/contrib/stex/source/stex/others.dtx b/macros/latex/contrib/stex/source/stex/others.dtx new file mode 100644 index 0000000000..1905079a9c --- /dev/null +++ b/macros/latex/contrib/stex/source/stex/others.dtx @@ -0,0 +1,87 @@ +% \iffalse meta-comment +% An Infrastructure for Semantic Macros and Module Scoping +% Copyright (c) 2019 Michael Kohlhase, all rights reserved +% this file is released under the +% LaTeX Project Public License (LPPL) +% +% The original of this file is in the public repository at +% http://github.com/sLaTeX/sTeX/ +% +% TODO update copyright +% +%<*driver> +\providecommand\bibfolder{../../lib/bib} +\input{../../doc/docheader} + +\begin{document} + \DocInput{\jobname.dtx} +\end{document} +%</driver> +% \fi +% +% \title{ \sTeX-Others +% \thanks{Version {\fileversion} (last revised {\filedate})} +% } +% +% \author{Michael Kohlhase, Dennis Müller\\ +% FAU Erlangen-Nürnberg\\ +% \url{http://kwarc.info/} +% } +% +% \maketitle +% +% \begin{documentation}\label{pkg:finally:doc} +% +% +% \end{documentation} +% +% \begin{implementation}\label{pkg:finally:impl} +% +% Some auxiliary code, and clean up to be executed at the +% end of the package. +% +% \section{\sTeX-Others Implementation} +% +% \begin{macrocode} +%<*package> + +%%%%%%%%%%%%% others.dtx %%%%%%%%%%%%% + +%<@@=stex_others> +% \end{macrocode} +% +% Warnings and error messages +% +% \begin{macrocode} + % None +% \end{macrocode} +% +% \begin{macro}{\MSC} +% +% Math subject classifier +% +% \begin{macrocode} +\NewDocumentCommand \MSC {m} { + % TODO +} +% \end{macrocode} +% \end{macro} +% +% +% Patching \pkg{tikzinput}, if loaded +% +% \begin{macrocode} +\@ifpackageloaded{tikzinput}{ + \RequirePackage{stex-tikzinput} +}{} +% \end{macrocode} +% +% +% +% \begin{macrocode} +%</package> +% \end{macrocode} +% +% \end{implementation} +% +% \PrintIndex diff --git a/macros/latex/contrib/stex/source/stex/references.dtx b/macros/latex/contrib/stex/source/stex/references.dtx new file mode 100644 index 0000000000..3153eeabab --- /dev/null +++ b/macros/latex/contrib/stex/source/stex/references.dtx @@ -0,0 +1,525 @@ +% \iffalse meta-comment +% An Infrastructure for Semantic Macros and Module Scoping +% Copyright (c) 2019 Michael Kohlhase, all rights reserved +% this file is released under the +% LaTeX Project Public License (LPPL) +% +% The original of this file is in the public repository at +% http://github.com/sLaTeX/sTeX/ +% +% TODO update copyright +% +%<*driver> +\providecommand\bibfolder{../../lib/bib} +\input{../../doc/docheader} + +\begin{document} + \DocInput{\jobname.dtx} +\end{document} +%</driver> +% \fi +% +% \title{ \sTeX-References +% \thanks{Version {\fileversion} (last revised {\filedate})} +% } +% +% \author{Michael Kohlhase, Dennis Müller\\ +% FAU Erlangen-Nürnberg\\ +% \url{http://kwarc.info/} +% } +% +% \maketitle +% +%\ifinfulldoc\else +% This is the documentation for the \pkg{stex-references} package. +% For a more high-level introduction, +% see \href{\basedocurl/manual.pdf}{the \sTeX Manual} or the +% \href{\basedocurl/stex.pdf}{full \sTeX documentation}. +% \fi +% +% \begin{documentation}\label{pkg:sref:doc} +% +% This sub package contains code related to links and cross-references +% +%\ifinfulldoc\else +% \input{../../doc/packages/references} +% \fi +% +% \section{Macros and Environments}\label{pkg:sref:doc:macros} +% +% \begin{function}{\STEXreftitle} +% \begin{syntax} \cs{STEXreftitle}\Arg{some title} \end{syntax} +% +% Sets the title of the current document to \meta{some title}. +% A reference to the current document from \emph{some other} +% document will then be displayed accordingly. e.g. +% if |\STEXreftitle{foo book}| is called, then referencing +% Definition 3.5 in this document in another document will display +% |Definition 3.5 in foo book|. +% \end{function} +% +% \begin{function}{\stex_get_document_uri:} +% Computes the current document uri from the current archive's +% |narr|-field and its location relative to the archive's +% |source|-directory. Reference targets are computed from +% this URI and the reference-id. +% +% \begin{variable}{\l_stex_current_docns_str} +% Stores its result in |\l_stex_current_docns_str| +% \end{variable} +% \end{function} +% +% \begin{function}{\stex_get_document_url:} +% Computes the current URL from the current archive's +% |docurl|-field and its location relative to the archive's +% |source|-directory. Reference targets are computed from +% this URL and the reference-id, if this document is only included +% in SMS mode. +% +% \begin{variable}{\l_stex_current_docurl_str} +% Stores its result in |\l_stex_current_docurl_str| +% \end{variable} +% \end{function} +% +% \subsection{Setting Reference Targets} +% +% \begin{function}{\stex_ref_new_doc_target:n} +% \begin{syntax} \cs{stex_ref_new_doc_target:n}\Arg{id} \end{syntax} +% +% Sets a new reference target with id \meta{id}. +% \end{function} +% +% \begin{function}{\stex_ref_new_sym_target:n} +% \begin{syntax} \cs{stex_ref_new_sym_target:n}\Arg{uri} \end{syntax} +% +% Sets a new reference target for the symbol \meta{uri}. +% \end{function} +% +% \subsection{Using References} +% +% \begin{function}{\sref} +% \begin{syntax} \cs{sref}|[|\meta{opt-args}|]|\Arg{id} \end{syntax} +% References the label with if \meta{id}. +% Optional arguments: TODO +% \end{function} +% +% \begin{function}{\srefsym} +% \begin{syntax} \cs{srefsym}|[|\meta{opt-args}|]|\Arg{symbol} \end{syntax} +% Like \cs{sref}, but references the \emph{canonical label} for +% the provided symbol. The canonical target is the last of the following +% occuring in the document: +% \begin{itemize} +% \item A \cs{definiendum} or \cs{definame} for \meta{symbol}, +% \item The |sassertion|, |sexample| or |sparagraph| with |for=|\meta{symbol} that +% generated \meta{symbol} in the first place, or +% \item A \cs{sparagraph} with |type=symdoc| and |for=|\meta{symbol}. +% \end{itemize} +% \end{function} +% +% \begin{function}{\srefsymuri} +% \begin{syntax} \cs{srefsymuri}\Arg{URI}\Arg{text} \end{syntax} +% A convenient short-hand for |\srefsym[linktext={text}]{URI}|, +% but requires the first argument to be a full URI already. +% Intended to be used in e.g. \cs{compemph@uri}, \cs{defemph@uri}, etc. +% \end{function} +% +% \end{documentation} +% +% \begin{implementation}\label{pkg:sref:impl} +% +% \section{\sTeX-References Implementation} +% +% \begin{macrocode} +%<*package> + +%%%%%%%%%%%%% references.dtx %%%%%%%%%%%%% + +%<@@=stex_refs> +% \end{macrocode} +% +% Warnings and error messages +% +% \begin{macrocode} + +% \end{macrocode} +% +% References are stored in the file |\jobname.sref|, to enable +% cross-referencing external documents. +% +% \begin{macrocode} +%\iow_new:N \c_@@_refs_iow +\AddToHook{begindocument}{ +% \iow_open:Nn \c_@@_refs_iow {\jobname.sref} +} +\AddToHook{enddocument}{ +% \iow_close:N \c_@@_refs_iow +} +% \end{macrocode} +% +% \begin{macro}{\STEXreftitle} +% \begin{macrocode} +\str_set:Nn \g_@@_title_tl {Unnamed~Document} + +\NewDocumentCommand \STEXreftitle { m } { + \tl_gset:Nx \g_@@_title_tl { #1 } +} +% \end{macrocode} +% \end{macro} +% +% \subsection{Document URIs and URLs} +% +% \begin{variable}{\l_stex_current_docns_str} +% \begin{macrocode} +\str_new:N \l_stex_current_docns_str +% \end{macrocode} +% \end{variable} +% +% \begin{macro}{\stex_get_document_uri:} +% \begin{macrocode} +\cs_new_protected:Nn \stex_get_document_uri: { + \seq_set_eq:NN \l_tmpa_seq \g_stex_currentfile_seq + \seq_pop_right:NN \l_tmpa_seq \l_tmpb_str + \exp_args:NNno \seq_set_split:Nnn \l_tmpb_seq . \l_tmpb_str + \seq_get_left:NN \l_tmpb_seq \l_tmpb_str + \seq_put_right:No \l_tmpa_seq \l_tmpb_str + + \str_clear:N \l_tmpa_str + \prop_if_exist:NT \l_stex_current_repository_prop { + \prop_get:NnNF \l_stex_current_repository_prop { narr } \l_tmpa_str { + \prop_get:NnNF \l_stex_current_repository_prop { ns } \l_tmpa_str {} + } + } + + \str_if_empty:NTF \l_tmpa_str { + \str_set:Nx \l_stex_current_docns_str { + file:/\stex_path_to_string:N \l_tmpa_seq + } + }{ + \bool_set_true:N \l_tmpa_bool + \bool_while_do:Nn \l_tmpa_bool { + \seq_pop_left:NN \l_tmpa_seq \l_tmpb_str + \exp_args:No \str_case:nnTF { \l_tmpb_str } { + {source} { \bool_set_false:N \l_tmpa_bool } + }{}{ + \seq_if_empty:NT \l_tmpa_seq { + \bool_set_false:N \l_tmpa_bool + } + } + } + + \seq_if_empty:NTF \l_tmpa_seq { + \str_set_eq:NN \l_stex_current_docns_str \l_tmpa_str + }{ + \str_set:Nx \l_stex_current_docns_str { + \l_tmpa_str/\stex_path_to_string:N \l_tmpa_seq + } + } + } +} +% \end{macrocode} +% \end{macro} +% +% \begin{variable}{\l_stex_current_docurl_str} +% \begin{macrocode} +\str_new:N \l_stex_current_docurl_str +% \end{macrocode} +% \end{variable} +% +% \begin{macro}{\stex_get_document_url:} +% \begin{macrocode} +\cs_new_protected:Nn \stex_get_document_url: { + \seq_set_eq:NN \l_tmpa_seq \g_stex_currentfile_seq + \seq_pop_right:NN \l_tmpa_seq \l_tmpb_str + \exp_args:NNno \seq_set_split:Nnn \l_tmpb_seq . \l_tmpb_str + \seq_get_left:NN \l_tmpb_seq \l_tmpb_str + \seq_put_right:No \l_tmpa_seq \l_tmpb_str + + \str_clear:N \l_tmpa_str + \prop_if_exist:NT \l_stex_current_repository_prop { + \prop_get:NnNF \l_stex_current_repository_prop { docurl } \l_tmpa_str { + \prop_get:NnNF \l_stex_current_repository_prop { narr } \l_tmpa_str { + \prop_get:NnNF \l_stex_current_repository_prop { ns } \l_tmpa_str {} + } + } + } + + \str_if_empty:NTF \l_tmpa_str { + \str_set:Nx \l_stex_current_docurl_str { + file:/\stex_path_to_string:N \l_tmpa_seq + } + }{ + \bool_set_true:N \l_tmpa_bool + \bool_while_do:Nn \l_tmpa_bool { + \seq_pop_left:NN \l_tmpa_seq \l_tmpb_str + \exp_args:No \str_case:nnTF { \l_tmpb_str } { + {source} { \bool_set_false:N \l_tmpa_bool } + }{}{ + \seq_if_empty:NT \l_tmpa_seq { + \bool_set_false:N \l_tmpa_bool + } + } + } + + \seq_if_empty:NTF \l_tmpa_seq { + \str_set_eq:NN \l_stex_current_docurl_str \l_tmpa_str + }{ + \str_set:Nx \l_stex_current_docurl_str { + \l_tmpa_str/\stex_path_to_string:N \l_tmpa_seq + } + } + } +} +% \end{macrocode} +% \end{macro} +% +% \subsection{Setting Reference Targets} +% +% \begin{macrocode} +\str_const:Nn \c_@@_url_str{URL} +\str_const:Nn \c_@@_ref_str{REF} +\str_new:N \l_@@_curr_label_str +% @currentlabel -> number +% @currentlabelname -> title +% @currentHref -> name.number <- id of some kind +% \theH# -> \arabic{section} +% \the# -> number +% \hyper@makecurrent{#} +\int_new:N \l_@@_unnamed_counter_int +% \end{macrocode} +% +% \begin{macro}{\stex_ref_new_doc_target:n} +% \begin{macrocode} +\cs_new_protected:Nn \stex_ref_new_doc_target:n { + \stex_get_document_uri: + \str_clear:N \l_@@_curr_label_str + \str_set:Nx \l_tmpa_str { #1 } + \str_if_empty:NT \l_tmpa_str { + \int_incr:N \l_@@_unnamed_counter_int + \str_set:Nx \l_tmpa_str {REF\int_use:N \l_@@_unnamed_counter_int} + } + \str_set:Nx \l_@@_curr_label_str { + \l_stex_current_docns_str?\l_tmpa_str + } + \seq_if_exist:cF{g_@@_labels_\l_tmpa_str _seq}{ + \seq_new:c {g_@@_labels_\l_tmpa_str _seq} + } + \seq_if_in:coF{g_@@_labels_\l_tmpa_str _seq}\l_@@_curr_label_str { + \seq_gput_right:co{g_@@_labels_\l_tmpa_str _seq}\l_@@_curr_label_str + } + \stex_if_smsmode:TF { + \stex_get_document_url: + \str_gset_eq:cN {sref_url_\l_@@_curr_label_str _str}\l_stex_current_docurl_str + \str_gset_eq:cN {sref_\l_@@_curr_label_str _type}\c_@@_url_str + }{ + %\iow_now:Nx \c_@@_refs_iow { \l_tmpa_str~=~\expandafter\unexpanded\expandafter{\@currentlabel}~in~\exp_args:No\unexpanded\g_@@_title_tl,} + \exp_args:Nx\label{sref_\l_@@_curr_label_str} + \immediate\write\@auxout{\stexauxadddocref{\l_stex_current_docns_str}{\l_tmpa_str}} + \str_gset:cx {sref_\l_@@_curr_label_str _type}\c_@@_ref_str + } +} +% \end{macrocode} +% \end{macro} +% +% The following is used to set the necessary macros in the |.aux|-file. +% +% \begin{macrocode} +\cs_new_protected:Npn \stexauxadddocref #1 #2 { + \str_set:Nn \l_tmpa_str {#1?#2} + \str_gset_eq:cN{sref_#1?#2_type}\c_@@_ref_str + \seq_if_exist:cF{g_@@_labels_#2_seq}{ + \seq_new:c {g_@@_labels_#2_seq} + } + \seq_if_in:coF{g_@@_labels_#2_seq}\l_tmpa_str { + \seq_gput_right:co{g_@@_labels_#2_seq}\l_tmpa_str + } +} +% \end{macrocode} +% To avoid resetting the same macros when the |.aux|-file is read +% at the end of the document: +% +% \begin{macrocode} +\AtEndDocument{ + \def\stexauxadddocref#1 #2 {}{} +} +% \end{macrocode} +% +% \begin{macro}{\stex_ref_new_sym_target:n} +% \begin{macrocode} +\cs_new_protected:Nn \stex_ref_new_sym_target:n { + \stex_if_smsmode:TF { + \str_if_exist:cF{sref_sym_#1_type}{ + \stex_get_document_url: + \str_gset_eq:cN {sref_sym_url_#1_str}\l_stex_current_docurl_str + \str_gset_eq:cN {sref_sym_#1_type}\c_@@_url_str + } + }{ + \str_if_empty:NF \l_@@_curr_label_str { + \str_gset_eq:cN {sref_sym_#1_label_str}\l_@@_curr_label_str + \immediate\write\@auxout{ + \exp_not:N\expandafter\def\exp_not:N\csname sref_sym_#1_label_str\exp_not:N\endcsname{ + \l_@@_curr_label_str + } + } + } + } +} +% \end{macrocode} +% \end{macro} +% +% \subsection{Using References} +% +% \begin{macrocode} +\str_new:N \l_@@_indocument_str +% \end{macrocode} +% +% \begin{macro}{\sref} +% Optional arguments: +% \begin{macrocode} + +\keys_define:nn { stex / sref } { + linktext .tl_set:N = \l_@@_linktext_tl , + fallback .tl_set:N = \l_@@_fallback_tl , + pre .tl_set:N = \l_@@_pre_tl , + post .tl_set:N = \l_@@_post_tl , +} +\cs_new_protected:Nn \_@@_args:n { + \tl_clear:N \l_@@_linktext_tl + \tl_clear:N \l_@@_fallback_tl + \tl_clear:N \l_@@_pre_tl + \tl_clear:N \l_@@_post_tl + \str_clear:N \l_@@_repo_str + \keys_set:nn { stex / sref } { #1 } +} +% \end{macrocode} +% The actual macro: +% \begin{macrocode} +\NewDocumentCommand \sref { O{} m}{ + \_@@_args:n { #1 } + \str_if_empty:NTF \l_@@_indocument_str { + \str_set:Nx \l_tmpa_str { #2 } + \exp_args:NNno \seq_set_split:Nnn \l_tmpa_seq ? \l_tmpa_str + \int_compare:nNnTF {\seq_count:N \l_tmpa_seq} = 1 { + \seq_if_exist:cTF{g_@@_labels_\l_tmpa_str _seq}{ + \seq_get_left:cNF {g_@@_labels_\l_tmpa_str _seq} \l_tmpa_str { + \str_clear:N \l_tmpa_str + } + }{ + \str_clear:N \l_tmpa_str + } + }{ + \seq_pop_left:NN \l_tmpa_seq \l_tmpb_str + \seq_pop_right:NN \l_tmpa_seq \l_tmpa_str + \int_set:Nn \l_tmpa_int { \exp_args:Ne \str_count:n {\l_tmpb_str?\l_tmpa_str} } + \seq_if_exist:cTF{g_@@_labels_\l_tmpa_str _seq}{ + \str_set_eq:NN \l_tmpc_str \l_tmpa_str + \str_clear:N \l_tmpa_str + \seq_map_inline:cn {g_@@_labels_\l_tmpc_str _seq} { + \str_if_eq:eeT { \l_tmpb_str?\l_tmpc_str }{ + \str_range:nnn { ##1 }{ -\l_tmpa_int}{ -1 } + }{ + \seq_map_break:n { + \str_set:Nn \l_tmpa_str { ##1 } + } + } + } + }{ + \str_clear:N \l_tmpa_str + } + } + \str_if_empty:NTF \l_tmpa_str { + \tl_if_empty:NTF \l_@@_linktext_tl \l_@@_fallback_tl \l_@@_linktext_tl + }{ + \str_if_eq:cNTF {sref_\l_tmpa_str _type} \c_@@_ref_str { + \tl_if_empty:NTF \l_@@_linktext_tl { + \cs_if_exist:cTF{autoref}{ + \l_@@_pre_tl\exp_args:Nx\autoref{sref_\l_tmpa_str}\l_@@_post_tl + }{ + \l_@@_pre_tl\exp_args:Nx\ref{sref_\l_tmpa_str}\l_@@_post_tl + } + }{ + \ltx@ifpackageloaded{hyperref}{ + \hyperref[sref_\l_tmpa_str]\l_@@_linktext_tl + }{ + \l_@@_linktext_tl + } + } + }{ + \ltx@ifpackageloaded{hyperref}{ + \href{\use:c{sref_url_\l_tmpa_str _str}}{\tl_if_empty:NTF \l_@@_linktext_tl \l_@@_fallback_tl \l_@@_linktext_tl} + }{ + \tl_if_empty:NTF \l_@@_linktext_tl \l_@@_fallback_tl \l_@@_linktext_tl + } + } + } + }{ + % TODO + } +} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\srefsym} +% \begin{macrocode} +\NewDocumentCommand \srefsym { O{} m}{ + \stex_get_symbol:n { #2 } + \_@@_sym_aux:nn{#1}{\l_stex_get_symbol_uri_str} +} + +\cs_new_protected:Nn \_@@_sym_aux:nn { + \str_if_exist:cTF {sref_sym_#2 _label_str }{ + \sref[#1]{\use:c{sref_sym_#2 _label_str}} + }{ + \_@@_args:n { #1 } + \str_if_empty:NTF \l_@@_indocument_str { + \tl_if_exist:cTF{sref_sym_#2 _type}{ + % doc uri in \l_tmpb_str + \str_set:Nx \l_tmpa_str {\use:c{sref_sym_#2 _type}} + \str_if_eq:NNTF \l_tmpa_str \c_@@_ref_str { + % reference + \tl_if_empty:NTF \l_@@_linktext_tl { + \cs_if_exist:cTF{autoref}{ + \l_@@_pre_tl\autoref{sref_sym_#2}\l_@@_post_tl + }{ + \l_@@_pre_tl\ref{sref_sym_#2}\l_@@_post_tl + } + }{ + \ltx@ifpackageloaded{hyperref}{ + \hyperref[sref_sym_#2]\l_@@_linktext_tl + }{ + \l_@@_linktext_tl + } + } + }{ + % URL + \ltx@ifpackageloaded{hyperref}{ + \href{\use:c{sref_sym_url_#2 _str}}{\tl_if_empty:NTF \l_@@_linktext_tl \l_@@_fallback_tl \l_@@_linktext_tl} + }{ + \tl_if_empty:NTF \l_@@_linktext_tl \l_@@_fallback_tl \l_@@_linktext_tl + } + } + }{ + \tl_if_empty:NTF \l_@@_linktext_tl \l_@@_fallback_tl \l_@@_linktext_tl + } + }{ + % TODO + } + } +} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\srefsymuri} +% \begin{macrocode} +\cs_new_protected:Npn \srefsymuri #1 #2 { + \_@@_sym_aux:nn{linktext={#2}}{#1} +} +% \end{macrocode} +% \end{macro} +% +% \begin{macrocode} +%</package> +% \end{macrocode} +% +% \end{implementation} +% +% \PrintIndex diff --git a/macros/latex/contrib/stex/source/stex/sproof.dtx b/macros/latex/contrib/stex/source/stex/sproof.dtx new file mode 100644 index 0000000000..f3cbdb869a --- /dev/null +++ b/macros/latex/contrib/stex/source/stex/sproof.dtx @@ -0,0 +1,1053 @@ +% \iffalse meta-comment +% An Infrastructure for Structural Markup for Proofs +% Copyright (c) 2019 Michael Kohlhase, all rights reserved +% this file is released under the +% LaTeX Project Public License (LPPL) +% +% The original of this file is in the public repository at +% http://github.com/sLaTeX/sTeX/ +% \fi +% +% \iffalse +%<*driver> +\def\bibfolder{../../lib/bib} +\input{../../doc/docheader} + +\begin{document} + \DocInput{\jobname.dtx} +\end{document} +%</driver> +% \fi +% +% \iffalse\CheckSum{341}\fi +% +% ^^A \changes{v0.9}{2005/06/14}{First Version with Documentation} +% +% \GetFileInfo{sproof.sty} +% +% \title{\sTeX-Proofs: Structural Markup for Proofs\thanks{Version {\fileversion} (last revised +% {\filedate})}} +% \author{Michael Kohlhase, Dennis Müller\\ +% FAU Erlangen-N\"urnberg\\ +% \url{http://kwarc.info/kohlhase}} +% \maketitle +% +%\ifinfulldoc\else +% This is the documentation for the \pkg{stex-proofs} package. +% For a more high-level introduction, +% see \href{\basedocurl/manual.pdf}{the \sTeX Manual} or the +% \href{\basedocurl/stex.pdf}{full \sTeX documentation}. +% +% \input{../../doc/packages/sproofs} +% \fi +% +% \begin{documentation} +% +% The |sproof| package is part of the {\stex} collection, a version of {\TeX/\LaTeX} that +% allows to markup {\TeX/\LaTeX} documents semantically without leaving the document +% format, essentially turning {\TeX/\LaTeX} into a document format for mathematical +% knowledge management (MKM). +% +% This package supplies macros and environment that allow to annotate the structure of +% mathematical proofs in {\stex} files. This structure can be used by MKM systems for +% added-value services, either directly from the \sTeX sources, or after translation. +% +% \newpage\tableofcontents\newpage +% +%\section{Introduction}\label{sec:sproof} +% +% The |sproof| ({\twintoo{semantic}{proofs}}) package supplies macros and environment that +% allow to annotate the structure of mathematical proofs in {\stex} files. This structure +% can be used by MKM systems for added-value services, either directly from the \sTeX +% sources, or after translation. Even though it is part of the {\stex} collection, it can +% be used independently, like it's sister package |statements|. +% +% {\stex} is a version of {\TeX/\LaTeX} that allows to markup {\TeX/\LaTeX} documents +% semantically without leaving the document format, essentially turning {\TeX/\LaTeX} into +% a document format for mathematical knowledge management (MKM). +% +% \begin{exfig}\scriptsize +% \begin{verbatim} +% \begin{sproof}[id=simple-proof] +% {We prove that $\sum_{i=1}^n{2i-1}=n^{2}$ by induction over $n$} +% \begin{spfcases}{For the induction we have to consider the following cases:} +% \begin{spfcase}{$n=1$} +% \begin{spfstep}[type=inline] then we compute $1=1^2$\end{spfstep} +% \end{spfcase} +% \begin{spfcase}{$n=2$} +% \begin{sproofcomment}[type=inline] +% This case is not really necessary, but we do it for the +% fun of it (and to get more intuition). +% \end{sproofcomment} +% \begin{spfstep}[type=inline] We compute $1+3=2^{2}=4$.\end{spfstep} +% \end{spfcase} +% \begin{spfcase}{$n>1$} +% \begin{spfstep}[type=assumption,id=ind-hyp] +% Now, we assume that the assertion is true for a certain $k\geq 1$, +% i.e. $\sum_{i=1}^k{(2i-1)}=k^{2}$. +% \end{spfstep} +% \begin{sproofcomment} +% We have to show that we can derive the assertion for $n=k+1$ from +% this assumption, i.e. $\sum_{i=1}^{k+1}{(2i-1)}=(k+1)^{2}$. +% \end{sproofcomment} +% \begin{spfstep} +% We obtain $\sum_{i=1}^{k+1}{2i-1}=\sum_{i=1}^k{2i-1}+2(k+1)-1$ +% \begin{justification}[method=arith:split-sum] +% by splitting the sum. +% \end{justification} +% \end{spfstep} +% \begin{spfstep} +% Thus we have $\sum_{i=1}^{k+1}{(2i-1)}=k^2+2k+1$ +% \begin{justification}[method=fertilize] +% by inductive hypothesis. +% \end{justification} +% \end{spfstep} +% \begin{spfstep}[type=conclusion] +% We can \begin{justification}[method=simplify]simplify\end{justification} +% the right-hand side to ${k+1}^2$, which proves the assertion. +% \end{spfstep} +% \end{spfcase} +% \begin{spfstep}[type=conclusion] +% We have considered all the cases, so we have proven the assertion. +% \end{spfstep} +% \end{spfcases} +% \end{sproof} +% \end{verbatim} +% \vspace*{-.5cm} +% \caption{A very explicit proof, marked up semantically}\label{fig:proof:src} +% \end{exfig} +% +% We will go over the general intuition by way of our running example (see +% Figure~\ref{fig:proof:src} for the source and Figure~\ref{fig:proof:result} for the +% formatted result).\ednote{talk a bit more about proofs and their structure,... maybe +% copy from OMDoc spec. } +% +% \section{The User Interface} +% +% \subsection{Package Options}\label{sec:user:options} +% +% The |sproof| package takes a single option: \DescribeMacro{showmeta}|showmeta|. If +% this is set, then the metadata keys are shown (see~\cite{Kohlhase:metakeys} for details +% and customization options). +% +% \subsection{Proofs and Proof steps} +% +% \DescribeEnv{sproof} The |proof| environment is the main container for proofs. It takes +% an optional |KeyVal| argument that allows to specify the |id| (identifier) and |for| +% (for which assertion is this a proof) keys. The regular argument of the |proof| +% environment contains an introductory comment, that may be used to announce the proof +% style. The |proof| environment contains a sequence of |\step|, |proofcomment|, and +% |pfcases| environments that are used to markup the proof steps. The |proof| environment +% has a variant |Proof|, which does not use the proof end marker. This is convenient, if a +% proof ends in a case distinction, which brings it's own proof end marker with it. +% \DescribeEnv{sProof} The |Proof| environment is a variant of |proof| that does not mark +% the end of a proof with a little box; presumably, since one of the subproofs already has +% one and then a box supplied by the outer proof would generate an otherwise empty line. +% \DescribeMacro{\spfidea} The |\spfidea| macro allows to give a one-paragraph +% description of the proof idea. +% +% For one-line proof sketches, we use the \DescribeMacro{spfsketch}|\spfsketch| macro, +% which takes the |KeyVal| argument as |sproof| and another one: a natural language text +% that sketches the proof. +% +% \DescribeEnv{spfstep} Regular proof steps are marked up with the |step| environment, which +% takes an optional |KeyVal| argument for annotations. A proof step usually contains a +% local assertion (the text of the step) together with some kind of evidence that this can +% be derived from already established assertions. +% +% Note that both |\premise| and |\justarg| can be used with an empty second argument to +% mark up premises and arguments that are not explicitly mentioned in the text. +% +% \begin{exfig} +% \begin{sproof}[id=simple-proof] +% {We prove that $\sum_{i=1}^n{2i-1}=n^{2}$ by induction over $n$} +% \begin{spfcases}{For the induction we have to consider the following cases:} +% \begin{spfcase}{$n=1$} +% \begin{spfstep}[type=inline] then we compute $1=1^2$\end{spfstep} +% \end{spfcase} +% \begin{spfcase}{$n=2$} +% \begin{sproofcomment}[type=inline] +% This case is not really necessary, but we do it for the fun +% of it (and to get more intuition). +% \end{sproofcomment} +% \begin{spfstep}[type=inline] +% We compute $1+3=2^{2}=4$ +% \end{spfstep} +% \end{spfcase} +% \begin{spfcase}{$n>1$} +% \begin{spfstep}[type=hypothesis,id=ind-hyp] +% Now, we assume that the assertion is true for a certain $k\geq 1$, i.e. +% $\sum_{i=1}^k{(2i-1)}=k^{2}$. +% \end{spfstep} +% \begin{sproofcomment} +% We have to show that we can derive the assertion for $n=k+1$ from this +% assumption, i.e. $\sum_{i=1}^{k+1}{(2i-1)}=(k+1)^{2}$. +% \end{sproofcomment} +% \begin{spfstep}[id=splitit] +% We obtain $\sum_{i=1}^{k+1}{(2i-1)}=\sum_{i=1}^k{(2i-1)}+2(k+1)-1$ +% \begin{justification}[method=arith:split-sum] +% by splitting the sum +% \end{justification} +% \end{spfstep} +% \begin{spfstep}[id=byindhyp] +% Thus we have $\sum_{i=1}^{k+1}{(2i-1)}=k^2+2k+1$ +% \begin{justification}[method=fertilize] +% by \premise[ind-hyp]{inductive hypothesis}. +% \end{justification} +% \end{spfstep} +% \begin{spfstep}[type=conclusion] +% We can \begin{justification}[method=simplify-eq] +% simplify the {\justarg[rhs]{right-hand side}} +% \end{justification} to $(k+1)^2$, which proves the assertion. +% \end{spfstep} +% \end{spfcase} +% \begin{spfstep}[type=conclusion] +% We have considered all the cases, so we have proven the assertion. +% \end{spfstep} +% \end{spfcases} +% \end{sproof} +% \caption{The formatted result of the proof in Figure~\ref{fig:proof:src}}\label{fig:proof:result} +% \end{exfig} +% +% \subsection{Justifications} +% +% \DescribeEnv{justification} This evidence is marked up with the |justification| +% environment in the |sproof| package. This environment totally invisible to the formatted +% result; it wraps the text in the proof step that corresponds to the evidence. The +% environment takes an optional |KeyVal| argument, which can have the |method| key, whose +% value is the name of a proof method (this will only need to mean something to the +% application that consumes the semantic annotations). Furthermore, the justification can +% contain ``premises'' (specifications to assertions that were used justify the step) and +% ``arguments'' (other information taken into account by the proof method). +% +% \DescribeMacro{\premise} The |\premise| macro allows to mark up part of the text as +% reference to an assertion that is used in the argumentation. In the example in +% Figure~\ref{fig:proof:src} we have used the |\premise| macro to identify the inductive +% hypothesis. +% +% \DescribeMacro{\justarg} The |\justarg| macro is very similar to |\premise| with the +% difference that it is used to mark up arguments to the proof method. Therefore the +% content of the first argument is interpreted as a mathematical object rather than as an +% identifier as in the case of |\premise|. In our example, we specified that the +% simplification should take place on the right hand side of the equation. Other examples +% include proof methods that instantiate. Here we would indicate the substituted object in +% a |\justarg| macro. +% +% \subsection{Proof Structure} +% +% \DescribeEnv{subproof} The |pfcases| environment is used to mark up a subproof. This +% environment takes an optional |KeyVal| argument for semantic annotations and a second +% argument that allows to specify an introductory comment (just like in the |proof| +% environment). The \DescribeMacro{method}|method| key can be used to give the name of the +% proof method executed to make this subproof. +% +% \DescribeEnv{spfcases} The |pfcases| environment is used to mark up a proof by +% cases. Technically it is a variant of the |subproof| where the |method| is +% |by-cases|. Its contents are |spfcase| environments that mark up the cases one by one. +% +% \DescribeEnv{spfcase} The content of a |pfcases| environment are a sequence of case +% proofs marked up in the |pfcase| environment, which takes an optional |KeyVal| argument +% for semantic annotations. The second argument is used to specify the the description of +% the case under consideration. The content of a |pfcase| environment is the same as that +% of a |proof|, i.e. |step|s, |proofcomment|s, and |pfcases| +% environments. \DescribeMacro{\spfcasesketch}|\spfcasesketch| is a variant of the |spfcase| +% environment that takes the same arguments, but instead of the |spfstep|s in the body +% uses a third argument for a proof sketch. +% +% \DescribeEnv{sproofcomment} The |proofcomment| environment is much like a |step|, only +% that it does not have an object-level assertion of its own. Rather than asserting some +% fact that is relevant for the proof, it is used to explain where the proof is going, +% what we are attempting to to, or what we have achieved so far. As such, it cannot be the +% target of a |\premise|. +% +% \subsection{Proof End Markers} +% +% Traditionally, the end of a mathematical proof is marked with a little box at the end of +% the last line of the proof (if there is space and on the end of the next line if there +% isn't), like so:\sproofend +% +% The |sproof| package provides the \DescribeMacro{\sproofend}|\sproofend| macro for +% this. If a different symbol for the proof end is to be used (e.g. {\sl{q.e.d}}), then +% this can be obtained by specifying it using the +% \DescribeMacro{\sProofEndSymbol}|\sProofEndSymbol| configuration macro (e.g. by specifying +% |\sProofEndSymbol{q.e.d}|). +% +% Some of the proof structuring macros above will insert proof end symbols for sub-proofs, +% in most cases, this is desirable to make the proof structure explicit, but sometimes +% this wastes space (especially, if a proof ends in a case analysis which will supply its +% own proof end marker). To suppress it locally, just set |proofend={}| in them or use use +% |\sProofEndSymbol{}|. +% +% \subsection{Configuration of the Presentation}\label{sec:user:conf} +% +% Finally, we provide configuration hooks in Figure~\ref{fig:hooks} for the keywords in +% proofs. These are mainly intended for package authors building on |statements|, e.g. for +% multi-language support.\ednote{we might want to develop an extension +% \texttt{sproof-babel} in the future.}. +%\begin{figure}[ht]\centering +% \begin{tabular}{|lll|}\hline +% Environment & configuration macro & value\\\hline\hline +% \texttt{sproof} & \texttt{\textbackslash spf@proof@kw} & \makeatletter\spf@proof@kw\\\hline +% \texttt{sketchproof} & \texttt{\textbackslash spf@sketchproof@kw} & \makeatletter\spf@proofsketch@kw\\\hline +% \end{tabular} +% \caption{Configuration Hooks for Semantic Proof Markup}\label{fig:hooks} +% \end{figure} +% The proof step labels can be customized via the +% \DescribeMacro{\pstlabelstyle}|\pstlabelstyle| macro: |\pstlabelstyle{|\meta{style}|}| +% sets the style; see Figure~\ref{fig:pstlabel} for an overview of styles. Package writers +% can add additional styles by adding a macro |\pst@make@label@|\meta{style} that takes +% two arguments: a comma-separated list of ordinals that make up the prefix and the current +% ordinal. Note that comma-separated lists can be conveniently iterated over by the +% {\LaTeX} |\@for|\ldots|:=|\ldots|\do{|\ldots|}| macro; see Figure~\ref{fig:pstlabel} for +% examples. +% +% \section{Limitations}\label{sec:limitations} +% +% In this section we document known limitations. If you want to help alleviate them, +% please feel free to contact the package author. Some of them are currently discussed in +% the \sTeX issue tracker at \cite{sTeX:github:on}. +% \begin{enumerate} +% \item The numbering scheme of proofs cannot be changed. It is more geared for teaching +% proof structures (the author's main use case) and not for writing papers.\lec{reported +% by Tobias Pfeiffer (fixed)} +% \item currently proof steps are formatted by the {\LaTeX} |description| environment. We +% would like to configure this, e.g. to use the |inparaenum| environment for more +% condensed proofs. I am just not sure what the best user interface would be I can +% imagine redefining an internal environment |spf@proofstep@list| or adding a key +% |prooflistenv| to the |proof| environment that allows to specify the environment +% directly. Maybe we should do both. +% \end{enumerate} +% +% \end{documentation} +% +% \begin{implementation} +% +% \section{The Implementation} +% +% \subsection{Package Options}\label{sec:impl:options} +% +% We declare some switches which will modify the behavior according to the package +% options. Generally, an option |xxx| will just set the appropriate switches to true +% (otherwise they stay false).\ednote{need an implementation for {\latexml}} +% +% \begin{macrocode} +%<*package> +%<@@=stex_sproof> + +%%%%%%%%%%%%% sproof.dtx %%%%%%%%%%%%% + +% \end{macrocode} +% +% +% \subsection{Proofs}\label{sec:impl:proofs} +% +% We first define some keys for the |proof| environment. +% \begin{macrocode} +\keys_define:nn { stex / spf } { + id .str_set_x:N = \spfid, + for .clist_set:N = \l_@@_spf_for_clist , + from .tl_set:N = \l_@@_spf_from_tl , + proofend .tl_set:N = \l_@@_spf_proofend_tl, + type .str_set_x:N = \spftype, + title .tl_set:N = \spftitle, + continues .tl_set:N = \l_@@_spf_continues_tl, + functions .tl_set:N = \l_@@_spf_functions_tl, + method .tl_set:N = \l_@@_spf_method_tl +} +\cs_new_protected:Nn \_@@_spf_args:n { + \str_clear:N \spfid + \tl_clear:N \l_@@_spf_for_tl + \tl_clear:N \l_@@_spf_from_tl + \tl_set:Nn \l_@@_spf_proofend_tl {\sproof@box} + \str_clear:N \spftype + \tl_clear:N \spftitle + \tl_clear:N \l_@@_spf_continues_tl + \tl_clear:N \l_@@_spf_functions_tl + \tl_clear:N \l_@@_spf_method_tl + \bool_set_false:N \l_@@_inc_counter_bool + \keys_set:nn { stex / spf }{ #1 } +} +% \end{macrocode} +% +% \begin{macro}{\c_@@_flow_str} +% We define this macro, so that we can test whether the |display| key has the value |flow| +% \begin{macrocode} +\str_set:Nn\c_@@_flow_str{inline} +% \end{macrocode} +% \end{macro} +% +% For proofs, we will have to have deeply nested structures of enumerated list-like +% environments. However, {\LaTeX} only allows |enumerate| environments up to nesting depth +% 4 and general list environments up to listing depth 6. This is not enough for us. +% Therefore we have decided to go along the route proposed by Leslie Lamport to use a +% single top-level list with dotted sequences of numbers to identify the position in the +% proof tree. Unfortunately, we could not use his |pf.sty| package directly, since it does +% not do automatic numbering, and we have to add keyword arguments all over the place, to +% accomodate semantic information. +% +% \begin{environment}{pst@with@label} +% This environment manages\footnote{This gets the labeling right but only works 8 levels +% deep} the path labeling of the proof steps in the description environment of the +% outermost |proof| environment. The argument is the label prefix up to now; which we +% cache in |\pst@label| (we need evaluate it first, since are in the right place +% now!). Then we increment the proof depth which is stored in |\count10| (lower counters +% are used by {\TeX} for page numbering) and initialize the next level counter +% |\count\count10| with 1. In the end call for this environment, we just decrease the +% proof depth counter by 1 again. +% \begin{macrocode} +\intarray_new:Nn\l_@@_counter_intarray{50} +\cs_new_protected:Npn \sproofnumber { + \int_set:Nn \l_tmpa_int {1} + \bool_while_do:nn { + \int_compare_p:nNn { + \intarray_item:Nn \l_@@_counter_intarray \l_tmpa_int + } > 0 + }{ + \intarray_item:Nn \l_@@_counter_intarray \l_tmpa_int . + \int_incr:N \l_tmpa_int + } +} +\cs_new_protected:Npn \_@@_inc_counter: { + \int_set:Nn \l_tmpa_int {1} + \bool_while_do:nn { + \int_compare_p:nNn { + \intarray_item:Nn \l_@@_counter_intarray \l_tmpa_int + } > 0 + }{ + \int_incr:N \l_tmpa_int + } + \int_compare:nNnF \l_tmpa_int = 1 { + \int_decr:N \l_tmpa_int + } + \intarray_gset:Nnn \l_@@_counter_intarray \l_tmpa_int { + \intarray_item:Nn \l_@@_counter_intarray \l_tmpa_int + 1 + } +} + +\cs_new_protected:Npn \_@@_add_counter: { + \int_set:Nn \l_tmpa_int {1} + \bool_while_do:nn { + \int_compare_p:nNn { + \intarray_item:Nn \l_@@_counter_intarray \l_tmpa_int + } > 0 + }{ + \int_incr:N \l_tmpa_int + } + \intarray_gset:Nnn \l_@@_counter_intarray \l_tmpa_int { 1 } +} + +\cs_new_protected:Npn \_@@_remove_counter: { + \int_set:Nn \l_tmpa_int {1} + \bool_while_do:nn { + \int_compare_p:nNn { + \intarray_item:Nn \l_@@_counter_intarray \l_tmpa_int + } > 0 + }{ + \int_incr:N \l_tmpa_int + } + \int_decr:N \l_tmpa_int + \intarray_gset:Nnn \l_@@_counter_intarray \l_tmpa_int { 0 } +} +% \end{macrocode} +% \end{environment} +% +% +%\begin{macro}{\sproofend} +% This macro places a little box at the end of the line if there is space, or at the +% end of the next line if there isn't +% \begin{macrocode} +\def\sproof@box{ + \hbox{\vrule\vbox{\hrule width 6 pt\vskip 6pt\hrule}\vrule} +} +\def\sproofend{ + \tl_if_empty:NF \l_@@_spf_proofend_tl { + \hfil\null\nobreak\hfill\l_@@_spf_proofend_tl\par\smallskip + } +} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{spf@*@kw} +% \begin{macrocode} +\def\spf@proofsketch@kw{Proof~Sketch} +\def\spf@proof@kw{Proof} +\def\spf@step@kw{Step} +% \end{macrocode} +% \end{macro} +% +% For the other languages, we set up triggers +% \begin{macrocode} +\AddToHook{begindocument}{ + \ltx@ifpackageloaded{babel}{ + \makeatletter + \clist_set:Nx \l_tmpa_clist {\bbl@loaded} + \clist_if_in:NnT \l_tmpa_clist {ngerman}{ + \input{sproof-ngerman.ldf} + } + \clist_if_in:NnT \l_tmpa_clist {finnish}{ + \input{sproof-finnish.ldf} + } + \clist_if_in:NnT \l_tmpa_clist {french}{ + \input{sproof-french.ldf} + } + \clist_if_in:NnT \l_tmpa_clist {russian}{ + \input{sproof-russian.ldf} + } + \makeatother + }{} +} +% \end{macrocode} +% +% \begin{macro}{spfsketch} +% \begin{macrocode} +\newcommand\spfsketch[2][]{ + \begingroup + \let \premise \stex_proof_premise: + \_@@_spf_args:n{#1} + \stex_if_smsmode:TF { + \str_if_empty:NF \spfid { + \stex_ref_new_doc_target:n \spfid + } + }{ + \seq_clear:N \l_tmpa_seq + \clist_map_inline:Nn \l_@@_spf_for_clist { + \tl_if_empty:nF{ ##1 }{ + \stex_get_symbol:n { ##1 } + \exp_args:NNo \seq_put_right:Nn \l_tmpa_seq { + \l_stex_get_symbol_uri_str + } + } + } + \exp_args:Nnx + \stex_annotate:nnn{proofsketch}{\seq_use:Nn \l_tmpa_seq {,}}{ + \str_if_empty:NF \spftype { + \stex_annotate_invisible:nnn{type}{\spftype}{} + } + \clist_set:No \l_tmpa_clist \spftype + \tl_set:Nn \l_tmpa_tl { + \titleemph{ + \tl_if_empty:NTF \spftitle { + \spf@proofsketch@kw + }{ + \spftitle + } + }:~ + } + \clist_map_inline:Nn \l_tmpa_clist { + \exp_args:No \str_if_eq:nnT \c_@@_flow_str {##1} { + \tl_clear:N \l_tmpa_tl + } + } + \str_if_empty:NF \spfid { + \stex_ref_new_doc_target:n \spfid + } + \l_tmpa_tl #2 \sproofend + } + } + \endgroup + \stex_smsmode_do: +} + +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{spfeq} +% This is very similar to |\spfsketch|, but uses a computation array\ednote{This should +% really be more like a tabular with an ensuremath in it. or invoke text on the last +% column}\ednote{document above} +% \begin{macrocode} +\newenvironment{spfeq}[2][]{ + \_@@_spf_args:n{#1} + \let \premise \stex_proof_premise: + \stex_if_smsmode:TF { + \str_if_empty:NF \spfid { + \stex_ref_new_doc_target:n \spfid + } + }{ + \seq_clear:N \l_tmpa_seq + \clist_map_inline:Nn \l_@@_spf_for_clist { + \tl_if_empty:nF{ ##1 }{ + \stex_get_symbol:n { ##1 } + \exp_args:NNo \seq_put_right:Nn \l_tmpa_seq { + \l_stex_get_symbol_uri_str + } + } + } + \exp_args:Nnnx + \begin{stex_annotate_env}{spfeq}{\seq_use:Nn \l_tmpa_seq {,}} + \str_if_empty:NF \spftype { + \stex_annotate_invisible:nnn{type}{\spftype}{} + } + + \clist_set:No \l_tmpa_clist \spftype + \tl_clear:N \l_tmpa_tl + \clist_map_inline:Nn \l_tmpa_clist { + \tl_if_exist:cT {_@@_spfeq_##1_start:}{ + \tl_set:Nn \l_tmpa_tl {\use:c{_@@_spfeq_##1_start:}} + } + \exp_args:No \str_if_eq:nnT \c_@@_flow_str {##1} { + \tl_set:Nn \l_tmpa_tl {\use:n{}} + } + } + \tl_if_empty:NTF \l_tmpa_tl { + \_@@_spfeq_start: + }{ + \l_tmpa_tl + }{~#2} + \str_if_empty:NF \spfid { + \stex_ref_new_doc_target:n \spfid + } + \begin{displaymath}\begin{array}{rcll} + } + \stex_smsmode_do: +}{ + \stex_if_smsmode:F { + \end{array}\end{displaymath} + \clist_set:No \l_tmpa_clist \spftype + \tl_clear:N \l_tmpa_tl + \clist_map_inline:Nn \l_tmpa_clist { + \tl_if_exist:cT {_@@_spfeq_##1_end:}{ + \tl_set:Nn \l_tmpa_tl {\use:c{_@@_spfeq_##1_end:}} + } + } + \tl_if_empty:NTF \l_tmpa_tl { + \_@@_spfeq_end: + }{ + \l_tmpa_tl + } + \end{stex_annotate_env} + } +} + +\cs_new_protected:Nn \_@@_spfeq_start: { + \titleemph{ + \tl_if_empty:NTF \spftitle { + \spf@proof@kw + }{ + \spftitle + } + }: +} +\cs_new_protected:Nn \_@@_spfeq_end: {\sproofend} + +\newcommand\stexpatchspfeq[3][] { + \str_set:Nx \l_tmpa_str{ #1 } + \str_if_empty:NTF \l_tmpa_str { + \tl_set:Nn \_@@_spfeq_start: { #2 } + \tl_set:Nn \_@@_spfeq_end: { #3 } + }{ + \exp_after:wN \tl_set:Nn \csname _@@_spfeq_#1_start:\endcsname{ #2 } + \exp_after:wN \tl_set:Nn \csname _@@_spfeq_#1_end:\endcsname{ #3 } + } +} + +% \end{macrocode} +% \end{macro} +% +% \begin{environment}{sproof} +% In this environment, we initialize the proof depth counter |\count10| to 10, and set +% up the description environment that will take the proof steps. At the end of the +% proof, we position the proof end into the last line. +% \begin{macrocode} +\newenvironment{sproof}[2][]{ + \let \premise \stex_proof_premise: + \intarray_gzero:N \l_@@_counter_intarray + \intarray_gset:Nnn \l_@@_counter_intarray 1 1 + \_@@_spf_args:n{#1} + \stex_if_smsmode:TF { + \str_if_empty:NF \spfid { + \stex_ref_new_doc_target:n \spfid + } + }{ + \seq_clear:N \l_tmpa_seq + \clist_map_inline:Nn \l_@@_spf_for_clist { + \tl_if_empty:nF{ ##1 }{ + \stex_get_symbol:n { ##1 } + \exp_args:NNo \seq_put_right:Nn \l_tmpa_seq { + \l_stex_get_symbol_uri_str + } + } + } + \exp_args:Nnnx + \begin{stex_annotate_env}{sproof}{\seq_use:Nn \l_tmpa_seq {,}} + \str_if_empty:NF \spftype { + \stex_annotate_invisible:nnn{type}{\spftype}{} + } + + \clist_set:No \l_tmpa_clist \spftype + \tl_clear:N \l_tmpa_tl + \clist_map_inline:Nn \l_tmpa_clist { + \tl_if_exist:cT {_@@_sproof_##1_start:}{ + \tl_set:Nn \l_tmpa_tl {\use:c{_@@_sproof_##1_start:}} + } + \exp_args:No \str_if_eq:nnT \c_@@_flow_str {##1} { + \tl_set:Nn \l_tmpa_tl {\use:n{}} + } + } + \tl_if_empty:NTF \l_tmpa_tl { + \_@@_sproof_start: + }{ + \l_tmpa_tl + }{~#2} + \str_if_empty:NF \spfid { + \stex_ref_new_doc_target:n \spfid + } + \begin{description} + } + \stex_smsmode_do: +}{ + \stex_if_smsmode:F{ + \end{description} + \clist_set:No \l_tmpa_clist \spftype + \tl_clear:N \l_tmpa_tl + \clist_map_inline:Nn \l_tmpa_clist { + \tl_if_exist:cT {_@@_sproof_##1_end:}{ + \tl_set:Nn \l_tmpa_tl {\use:c{_@@_sproof_##1_end:}} + } + } + \tl_if_empty:NTF \l_tmpa_tl { + \_@@_sproof_end: + }{ + \l_tmpa_tl + } + \end{stex_annotate_env} + } +} + +\cs_new_protected:Nn \_@@_sproof_start: { + \par\noindent\titleemph{ + \tl_if_empty:NTF \spftype { + \spf@proof@kw + }{ + \spftype + } + }: +} +\cs_new_protected:Nn \_@@_sproof_end: {\sproofend} + +\newcommand\stexpatchsproof[3][] { + \str_set:Nx \l_tmpa_str{ #1 } + \str_if_empty:NTF \l_tmpa_str { + \tl_set:Nn \_@@_sproof_start: { #2 } + \tl_set:Nn \_@@_sproof_end: { #3 } + }{ + \exp_after:wN \tl_set:Nn \csname _@@_sproof_#1_start:\endcsname{ #2 } + \exp_after:wN \tl_set:Nn \csname _@@_sproof_#1_end:\endcsname{ #3 } + } +} +% \end{macrocode} +% \end{environment} +% +% \begin{macro}{\spfidea} +% \begin{macrocode} +\newcommand\spfidea[2][]{ + \_@@_spf_args:n{#1} + \titleemph{ + \tl_if_empty:NTF \spftype {Proof~Idea}{ + \spftype + }: + }~#2 + \sproofend +} +% \end{macrocode} +% \end{macro} +% +% The next two environments (proof steps) and comments, are mostly semantical, they take +% |KeyVal| arguments that specify their semantic role. In draft mode, they read these +% values and show them. If the surrounding proof had |display=flow|, then no new |\item| is +% generated, otherwise it is. In any case, the proof step number (at the current level) is +% incremented. +% \begin{environment}{spfstep} +% \begin{macrocode} +\newenvironment{spfstep}[1][]{ + \_@@_spf_args:n{#1} + \stex_if_smsmode:TF { + \str_if_empty:NF \spfid { + \stex_ref_new_doc_target:n \spfid + } + }{ + \@in@omtexttrue + \seq_clear:N \l_tmpa_seq + \clist_map_inline:Nn \l_@@_spf_for_clist { + \tl_if_empty:nF{ ##1 }{ + \stex_get_symbol:n { ##1 } + \exp_args:NNo \seq_put_right:Nn \l_tmpa_seq { + \l_stex_get_symbol_uri_str + } + } + } + \exp_args:Nnnx + \begin{stex_annotate_env}{spfstep}{\seq_use:Nn \l_tmpa_seq {,}} + \str_if_empty:NF \spftype { + \stex_annotate_invisible:nnn{type}{\spftype}{} + } + \clist_set:No \l_tmpa_clist \spftype + \tl_set:Nn \l_tmpa_tl { + \item[\sproofnumber] + \bool_set_true:N \l_@@_inc_counter_bool + } + \clist_map_inline:Nn \l_tmpa_clist { + \exp_args:No \str_if_eq:nnT \c_@@_flow_str {##1} { + \tl_clear:N \l_tmpa_tl + } + } + \l_tmpa_tl + \tl_if_empty:NF \spftitle { + {(\titleemph{\spftitle})\enspace} + } + \str_if_empty:NF \spfid { + \stex_ref_new_doc_target:n \spfid + } + } + \stex_smsmode_do: + \ignorespacesandpars +}{ + \bool_if:NT \l_@@_inc_counter_bool { + \_@@_inc_counter: + } + \stex_if_smsmode:F { + \end{stex_annotate_env} + } +} +% \end{macrocode} +% \end{environment} +% +% \begin{environment}{sproofcomment} +% \begin{macrocode} +\newenvironment{sproofcomment}[1][]{ + \_@@_spf_args:n{#1} + \clist_set:No \l_tmpa_clist \spftype + \tl_set:Nn \l_tmpa_tl { + \item[\sproofnumber] + \bool_set_true:N \l_@@_inc_counter_bool + } + \clist_map_inline:Nn \l_tmpa_clist { + \exp_args:No \str_if_eq:nnT \c_@@_flow_str {##1} { + \tl_clear:N \l_tmpa_tl + } + } + \l_tmpa_tl +}{ + \bool_if:NT \l_@@_inc_counter_bool { + \_@@_inc_counter: + } +} +% \end{macrocode} +% \end{environment} +% +% The next two environments also take a |KeyVal| argument, but also a regular one, which +% contains a start text. Both environments start a new numbered proof level. +% +% \begin{environment}{subproof} +% In the |subproof| environment, a new (lower-level) proproofof environment is started. +% \begin{macrocode} +\newenvironment{subproof}[2][]{ + \_@@_spf_args:n{#1} + \stex_if_smsmode:TF{ + \str_if_empty:NF \spfid { + \stex_ref_new_doc_target:n \spfid + } + }{ + \seq_clear:N \l_tmpa_seq + \clist_map_inline:Nn \l_@@_spf_for_clist { + \tl_if_empty:nF{ ##1 }{ + \stex_get_symbol:n { ##1 } + \exp_args:NNo \seq_put_right:Nn \l_tmpa_seq { + \l_stex_get_symbol_uri_str + } + } + } + \exp_args:Nnnx + \begin{stex_annotate_env}{subproof}{\seq_use:Nn \l_tmpa_seq {,}} + \str_if_empty:NF \spftype { + \stex_annotate_invisible:nnn{type}{\spftype}{} + } + + \clist_set:No \l_tmpa_clist \spftype + \tl_set:Nn \l_tmpa_tl { + \item[\sproofnumber] + \bool_set_true:N \l_@@_inc_counter_bool + } + \clist_map_inline:Nn \l_tmpa_clist { + \exp_args:No \str_if_eq:nnT \c_@@_flow_str {##1} { + \tl_clear:N \l_tmpa_tl + } + } + \l_tmpa_tl + \tl_if_empty:NF \spftitle { + {(\titleemph{\spftitle})\enspace} + } + {~#2} + \str_if_empty:NF \spfid { + \stex_ref_new_doc_target:n \spfid + } + } + \_@@_add_counter: + \stex_smsmode_do: +}{ + \_@@_remove_counter: + \bool_if:NT \l_@@_inc_counter_bool { + \_@@_inc_counter: + } + \stex_if_smsmode:F{ + \end{stex_annotate_env} + } +} +% \end{macrocode} +% \end{environment} +% +% \begin{environment}{spfcases} +% In the |pfcases| environment, the start text is displayed as the first comment of the +% proof. +% \begin{macrocode} +\newenvironment{spfcases}[2][]{ + \tl_if_empty:nTF{#1}{ + \begin{subproof}[method=by-cases]{#2} + }{ + \begin{subproof}[#1,method=by-cases]{#2} + } +}{ + \end{subproof} +} +% \end{macrocode} +% \end{environment} +% +% \begin{environment}{spfcase} +% In the |pfcase| environment, the start text is displayed specification of the case +% after the |\item| +% \begin{macrocode} +\newenvironment{spfcase}[2][]{ + \_@@_spf_args:n{#1} + \stex_if_smsmode:TF { + \str_if_empty:NF \spfid { + \stex_ref_new_doc_target:n \spfid + } + }{ + \seq_clear:N \l_tmpa_seq + \clist_map_inline:Nn \l_@@_spf_for_clist { + \tl_if_empty:nF{ ##1 }{ + \stex_get_symbol:n { ##1 } + \exp_args:NNo \seq_put_right:Nn \l_tmpa_seq { + \l_stex_get_symbol_uri_str + } + } + } + \exp_args:Nnnx + \begin{stex_annotate_env}{spfcase}{\seq_use:Nn \l_tmpa_seq {,}} + \str_if_empty:NF \spftype { + \stex_annotate_invisible:nnn{type}{\spftype}{} + } + \clist_set:No \l_tmpa_clist \spftype + \tl_set:Nn \l_tmpa_tl { + \item[\sproofnumber] + \bool_set_true:N \l_@@_inc_counter_bool + } + \clist_map_inline:Nn \l_tmpa_clist { + \exp_args:No \str_if_eq:nnT \c_@@_flow_str {##1} { + \tl_clear:N \l_tmpa_tl + } + } + \l_tmpa_tl + \tl_if_empty:nF{#2}{ + \titleemph{#2}:~ + } + } + \_@@_add_counter: + \stex_smsmode_do: +}{ + \_@@_remove_counter: + \bool_if:NT \l_@@_inc_counter_bool { + \_@@_inc_counter: + } + \stex_if_smsmode:F{ + \clist_set:No \l_tmpa_clist \spftype + \tl_set:Nn \l_tmpa_tl{\sproofend} + \clist_map_inline:Nn \l_tmpa_clist { + \exp_args:No \str_if_eq:nnT \c_@@_flow_str {##1} { + \tl_clear:N \l_tmpa_tl + } + } + \l_tmpa_tl + \end{stex_annotate_env} + } +} +% \end{macrocode} +% \end{environment} +% +% \begin{environment}{spfcase} +% similar to |spfcase|, takes a third argument. +% \begin{macrocode} +\newcommand\spfcasesketch[3][]{ + \begin{spfcase}[#1]{#2}#3\end{spfcase} +} +% \end{macrocode} +% \end{environment} +% +% \subsection{Justifications} +% +% We define the actions that are undertaken, when the keys for justifications are +% encountered. Here this is very simple, we just define an internal macro with the value, +% so that we can use it later. +% \begin{macrocode} +\keys_define:nn { stex / just }{ + id .str_set_x:N = \l_@@_just_id_str, + method .tl_set:N = \l_@@_just_method_tl, + premises .tl_set:N = \l_@@_just_premises_tl, + args .tl_set:N = \l_@@_just_args_tl +} +% \end{macrocode} +% +% The next three environments and macros are purely semantic, so we ignore the keyval +% arguments for now and only display the content.\ednote{need to do something about the +% premise in draft mode.} +% +% \begin{environment}{justification} +% \begin{macrocode} +\newenvironment{justification}[1][]{}{} +% \end{macrocode} +% \end{environment} +% +% \begin{macro}{\premise} +% \begin{macrocode} +\newcommand\stex_proof_premise:[2][]{#2} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\justarg} +% the |\justarg| macro is purely semantic, so we ignore the keyval arguments for now and +% only display the content. +% \begin{macrocode} +\newcommand\justarg[2][]{#2} +%</package> +% \end{macrocode} +% \end{macro} +% \end{implementation} +% \Finale +\endinput +%%% Local Variables: +%%% mode: doctex +%%% TeX-master: t +%%% End: +% LocalWords: GPL structuresharing STR sproof dtx CPERL keyval methodfalse env +% LocalWords: methodtrue envtrue medhodtrue DefKeyVal Semiverbatim omdoc args +% LocalWords: DefEnvironment OptionalKeyVals KeyVal omtext DefConstructor str +% LocalWords: proofidea KeyVal pfstep DefCMPEnvironment KeyVal proofcomment eq +% LocalWords: KeyVal pfcases KeyVal pfcase KeyVal extractBodyText unlist elsif +% LocalWords: foreach getBody toString str str str LookupValue LastSeenCMP Thu +% LocalWords: appendText getValue undef openElement closeElement DefMacro omd +% LocalWords: afterClose nodeType childNodes firstCMP localname hasChildNodes +% LocalWords: firstChild textContent removeChild iffalse kohlhase sref scsys +% LocalWords: sproofs.sty sc sc mathml openmath latexml cmathml activemath geq +% LocalWords: twintoo atwin atwintoo texttt fileversion maketitle stex newpage +% LocalWords: tableofcontents newpage exfig scriptsize vspace ednote spfidea +% LocalWords: spfidea spfsketch spfsketch spfstep justarg spfcases spfcase rhs +% LocalWords: sproofcomment ind-hyp splitit arith byindhyp sproofend proofend +% LocalWords: printbibliography textsf langle textsf langle ltxml ctancite spf +% LocalWords: srefaddidkey pf.sty newenvironment hbox vrule vbox ifx showmeta +% LocalWords: hrule vskip hrule vrule hfil nobreak hfill smallskip newcommand +% LocalWords: stDMemph newcount endsproof xref doctex showmeta hline lec ldots +% LocalWords: textbackslash makeatletter sketchproof compactenum tracissue +% LocalWords: metakeys addmetakey metasetkeys stylable pstlabelstyle pstlabel +% LocalWords: pstlabelstyle pstlabelstyle ldots ldots ensuremath inparaenum +% LocalWords: nameuse prooflistenv spfcasesketch spfcasesketch spfeq rcll +% LocalWords: displaymath noindent ignorespaces diff --git a/macros/latex/contrib/stex/source/stex/statements.dtx b/macros/latex/contrib/stex/source/stex/statements.dtx new file mode 100644 index 0000000000..3ddeca0dbd --- /dev/null +++ b/macros/latex/contrib/stex/source/stex/statements.dtx @@ -0,0 +1,908 @@ +% \iffalse meta-comment +% An Infrastructure for Semantic Macros and Module Scoping +% Copyright (c) 2019 Michael Kohlhase, all rights reserved +% this file is released under the +% LaTeX Project Public License (LPPL) +% +% The original of this file is in the public repository at +% http://github.com/sLaTeX/sTeX/ +% +% TODO update copyright +% +%<*driver> +\providecommand\bibfolder{../../lib/bib} +\input{../../doc/docheader} + +\begin{document} + \DocInput{\jobname.dtx} +\end{document} +%</driver> +% \fi +% +% \title{ \sTeX-Statements +% \thanks{Version {\fileversion} (last revised {\filedate})} +% } +% +% \author{Michael Kohlhase, Dennis Müller\\ +% FAU Erlangen-Nürnberg\\ +% \url{http://kwarc.info/} +% } +% +% \maketitle +% +%\ifinfulldoc\else +% This is the documentation for the \pkg{stex-statements} package. +% For a more high-level introduction, +% see \href{\basedocurl/manual.pdf}{the \sTeX Manual} or the +% \href{\basedocurl/stex.pdf}{full \sTeX documentation}. +% +% \input{../../doc/packages/statements} +% \fi +% +% \begin{documentation}\label{pkg:statements:doc} +% +% Code related to statements, e.g. definitions, theorems +% +% \section{Macros and Environments}\label{pkg:statements:doc:macros} +% +% \begin{environment}{symboldoc} +% \begin{syntax} \cs{begin}\Arg{symboldoc}\Arg{symbols} \meta{text} \cs{end}\Arg{symboldoc} \end{syntax} +% Declares \meta{text} to be a (natural language, encyclopaedic) description +% of \Arg{symbols} (a comma separated list of symbol identifiers). +% \end{environment} +% +% \end{documentation} +% +% \begin{implementation}\label{pkg:statements:impl} +% +% \section{\sTeX-Statements Implementation} +% +% \begin{macrocode} +%<*package> + +%%%%%%%%%%%%% features.dtx %%%%%%%%%%%%% + +%<@@=stex_statements> +% \end{macrocode} +% +% Warnings and error messages +% +% \begin{macrocode} + +% \end{macrocode} +% \begin{macro}{\titleemph} +% \begin{macrocode} +\def\titleemph#1{\textbf{#1}} +% \end{macrocode} +% \end{macro} +% +% \subsection{Definitions} +% +% \begin{macro}{definiendum} +% \begin{macrocode} +\keys_define:nn {stex / definiendum }{ + pre .tl_set:N = \l_@@_definiendum_pre_tl, + post .tl_set:N = \l_@@_definiendum_post_tl, + root .str_set_x:N = \l_@@_definiendum_root_str, + gfa .str_set_x:N = \l_@@_definiendum_gfa_str +} +\cs_new_protected:Nn \_@@_definiendum_args:n { + \str_clear:N \l_@@_definiendum_root_str + \tl_clear:N \l_@@_definiendum_post_tl + \str_clear:N \l_@@_definiendum_gfa_str + \keys_set:nn { stex / definiendum }{ #1 } +} +\NewDocumentCommand \definiendum { O{} m m} { + \_@@_definiendum_args:n { #1 } + \stex_get_symbol:n { #2 } + \stex_ref_new_sym_target:n \l_stex_get_symbol_uri_str + \str_if_empty:NTF \l_@@_definiendum_root_str { + \tl_if_empty:NTF \l_@@_definiendum_post_tl { + \tl_set:Nn \l_tmpa_tl { #3 } + } { + \str_set:Nx \l_@@_definiendum_root_str { #3 } + \tl_set:Nn \l_tmpa_tl { + \l_@@_definiendum_pre_tl\l_@@_definiendum_root_str\l_@@_definiendum_post_tl + } + } + } { + \tl_set:Nn \l_tmpa_tl { #3 } + } + + % TODO root + \rustex_if:TF { + \stex_annotate:nnn { definiendum } { \l_stex_get_symbol_uri_str } { \l_tmpa_tl } + } { + \exp_args:Nnx \defemph@uri { \l_tmpa_tl } { \l_stex_get_symbol_uri_str } + } +} +\stex_deactivate_macro:Nn \definiendum {definition~environments} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{definame} +% \begin{macrocode} + +\NewDocumentCommand \definame { O{} m } { + \_@@_definiendum_args:n { #1 } + % TODO: root + \stex_get_symbol:n { #2 } + \stex_ref_new_sym_target:n \l_stex_get_symbol_uri_str + \str_set:Nx \l_tmpa_str { + \prop_item:cn { l_stex_symdecl_ \l_stex_get_symbol_uri_str _prop } { name } + } + \exp_args:NNno \str_replace_all:Nnn \l_tmpa_str {-} {~} + \rustex_if:TF { + \stex_annotate:nnn { definiendum } { \l_stex_get_symbol_uri_str } { + \l_tmpa_str\l_@@_definiendum_post_tl + } + } { + \defemph@uri { + \l_tmpa_str\l_@@_definiendum_post_tl + } { \l_stex_get_symbol_uri_str } + } +} +\stex_deactivate_macro:Nn \definame {definition~environments} + +\NewDocumentCommand \Definame { O{} m } { + \_@@_definiendum_args:n { #1 } + \stex_get_symbol:n { #2 } + \str_set:Nx \l_tmpa_str { + \prop_item:cn { l_stex_symdecl_ \l_stex_get_symbol_uri_str _prop } { name } + } + \exp_args:NNno \str_replace_all:Nnn \l_tmpa_str {-} {~} + \stex_ref_new_sym_target:n \l_stex_get_symbol_uri_str + \rustex_if:TF { + \stex_annotate:nnn { definiendum } { \l_stex_get_symbol_uri_str } { + \l_tmpa_str\l__stex_statements_definiendum_post_tl + } + } { + \defemph@uri { + \exp_after:wN \stex_capitalize:n \l_tmpa_str\l__stex_statements_definiendum_post_tl + } { \l_stex_get_symbol_uri_str } + } +} +\stex_deactivate_macro:Nn \Definame {definition~environments} + +\NewDocumentCommand \premise { m }{ + \stex_annotate:nnn{ premise }{}{ #1 } +} +\NewDocumentCommand \conclusion { m }{ + \stex_annotate:nnn{ conclusion }{}{ #1 } +} +\NewDocumentCommand \definiens { m }{ + \stex_annotate:nnn{ definiens }{}{ #1 } +} + +\stex_deactivate_macro:Nn \premise {definition,~example~or~assertion~environments} +\stex_deactivate_macro:Nn \conclusion {example~or~assertion~environments} +\stex_deactivate_macro:Nn \definiens {definition~environments} + +% \end{macrocode} +% \end{macro} +% +% \begin{environment}{sdefinition} +% \begin{macrocode} + +\keys_define:nn {stex / sdefinition }{ + type .str_set_x:N = \sdefinitiontype, + id .str_set_x:N = \sdefinitionid, + name .str_set_x:N = \sdefinitionname, + for .clist_set:N = \l_@@_sdefinition_for_clist , + title .tl_set:N = \sdefinitiontitle +} +\cs_new_protected:Nn \_@@_sdefinition_args:n { + \str_clear:N \sdefinitiontype + \str_clear:N \sdefinitionid + \str_clear:N \sdefinitionname + \clist_clear:N \l_@@_sdefinition_for_clist + \tl_clear:N \sdefinitiontitle + \keys_set:nn { stex / sdefinition }{ #1 } +} + +\NewDocumentEnvironment{sdefinition}{O{}}{ + \_@@_sdefinition_args:n{ #1 } + \stex_reactivate_macro:N \definiendum + \stex_reactivate_macro:N \definame + \stex_reactivate_macro:N \Definame + \stex_reactivate_macro:N \premise + \stex_reactivate_macro:N \definiens + \stex_if_smsmode:F{ + \seq_clear:N \l_tmpa_seq + \clist_map_inline:Nn \l_@@_sdefinition_for_clist { + \tl_if_empty:nF{ ##1 }{ + \stex_get_symbol:n { ##1 } + \exp_args:NNo \seq_put_right:Nn \l_tmpa_seq { + \l_stex_get_symbol_uri_str + } + } + } + \exp_args:Nnnx + \begin{stex_annotate_env}{definition}{\seq_use:Nn \l_tmpa_seq {,}} + \str_if_empty:NF \sdefinitiontype { + \stex_annotate_invisible:nnn{type}{\sdefinitiontype}{} + } + \clist_set:No \l_tmpa_clist \sdefinitiontype + \tl_clear:N \l_tmpa_tl + \clist_map_inline:Nn \l_tmpa_clist { + \tl_if_exist:cT {_@@_sdefinition_##1_start:}{ + \tl_set:Nn \l_tmpa_tl {\use:c{_@@_sdefinition_##1_start:}} + } + } + \tl_if_empty:NTF \l_tmpa_tl { + \_@@_sdefinition_start: + }{ + \l_tmpa_tl + } + } + \stex_ref_new_doc_target:n \sdefinitionid + \stex_smsmode_do: +}{ + \str_if_empty:NF \sdefinitionname { \stex_symdecl_do:nn{}{\sdefinitionname} } + \stex_if_smsmode:F { + \clist_set:No \l_tmpa_clist \sdefinitiontype + \tl_clear:N \l_tmpa_tl + \clist_map_inline:Nn \l_tmpa_clist { + \tl_if_exist:cT {_@@_sdefinition_##1_end:}{ + \tl_set:Nn \l_tmpa_tl {\use:c{_@@_sdefinition_##1_end:}} + } + } + \tl_if_empty:NTF \l_tmpa_tl { + \_@@_sdefinition_end: + }{ + \l_tmpa_tl + } + \end{stex_annotate_env} + } +} +% \end{macrocode} +% \end{environment} +% +% \begin{macro}{\stexpatchdefinition} +% \begin{macrocode} +\cs_new_protected:Nn \_@@_sdefinition_start: { + \par\noindent\titleemph{Definition\tl_if_empty:NF \sdefinitiontitle { + ~(\sdefinitiontitle) + }~} +} +\cs_new_protected:Nn \_@@_sdefinition_end: {\par\medskip} + +\newcommand\stexpatchdefinition[3][] { + \str_set:Nx \l_tmpa_str{ #1 } + \str_if_empty:NTF \l_tmpa_str { + \tl_set:Nn \_@@_sdefinition_start: { #2 } + \tl_set:Nn \_@@_sdefinition_end: { #3 } + }{ + \exp_after:wN \tl_set:Nn \csname _@@_sdefinition_#1_start:\endcsname{ #2 } + \exp_after:wN \tl_set:Nn \csname _@@_sdefinition_#1_end:\endcsname{ #3 } + } +} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\inlinedef} +% inline: +% \begin{macrocode} +\keys_define:nn {stex / inlinedef }{ + type .str_set_x:N = \sdefinitiontype, + id .str_set_x:N = \sdefinitionid, + for .clist_set:N = \l_@@_sdefinition_for_clist , + name .str_set_x:N = \sdefinitionname +} +\cs_new_protected:Nn \_@@_inlinedef_args:n { + \str_clear:N \sdefinitiontype + \str_clear:N \sdefinitionid + \str_clear:N \sdefinitionname + \clist_clear:N \l_@@_sdefinition_for_clist + \keys_set:nn { stex / inlinedef }{ #1 } +} +\NewDocumentCommand \inlinedef { O{} m } { + \begingroup + \_@@_inlinedef_args:n{ #1 } + \stex_reactivate_macro:N \definiendum + \stex_reactivate_macro:N \definame + \stex_reactivate_macro:N \Definame + \stex_reactivate_macro:N \premise + \stex_reactivate_macro:N \definiens + \stex_ref_new_doc_target:n \sdefinitionid + \stex_if_smsmode:TF{ + \str_if_empty:NF \sdefinitionname { \stex_symdecl_do:nn{}{\sdefinitionname} } + }{ + \seq_clear:N \l_tmpa_seq + \clist_map_inline:Nn \l_@@_sdefinition_for_clist { + \tl_if_empty:nF{ ##1 }{ + \stex_get_symbol:n { ##1 } + \exp_args:NNo \seq_put_right:Nn \l_tmpa_seq { + \l_stex_get_symbol_uri_str + } + } + } + \exp_args:Nnx + \stex_annotate:nnn{definition}{\seq_use:Nn \l_tmpa_seq {,}}{ + \str_if_empty:NF \sdefinitiontype { + \stex_annotate_invisible:nnn{type}{\sdefinitiontype}{} + } + #2 + \str_if_empty:NF \sdefinitionname { \stex_symdecl_do:nn{}{\sdefinitionname} } + } + } + \endgroup + \stex_smsmode_do: +} +% \end{macrocode} +% \end{macro} +% +% \subsection{Assertions} +% +% \begin{environment}{sassertion} +% \begin{macrocode} + +\keys_define:nn {stex / sassertion }{ + type .str_set_x:N = \sassertiontype, + id .str_set_x:N = \sassertionid, + title .tl_set:N = \sassertiontitle , + for .clist_set:N = \l_@@_sassertion_for_clist , + name .str_set_x:N = \sassertionname +} +\cs_new_protected:Nn \_@@_sassertion_args:n { + \str_clear:N \sassertiontype + \str_clear:N \sassertionid + \str_clear:N \sassertionname + \clist_clear:N \l_@@_sassertion_for_clist + \tl_clear:N \sassertiontitle + \keys_set:nn { stex / sassertion }{ #1 } +} + +%\tl_new:N \g_@@_aftergroup_tl + +\NewDocumentEnvironment{sassertion}{O{}}{ + \_@@_sassertion_args:n{ #1 } + \stex_reactivate_macro:N \premise + \stex_reactivate_macro:N \conclusion + \stex_if_smsmode:F { + \seq_clear:N \l_tmpa_seq + \clist_map_inline:Nn \l_@@_sassertion_for_clist { + \tl_if_empty:nF{ ##1 }{ + \stex_get_symbol:n { ##1 } + \exp_args:NNo \seq_put_right:Nn \l_tmpa_seq { + \l_stex_get_symbol_uri_str + } + } + } + \exp_args:Nnnx + \begin{stex_annotate_env}{assertion}{\seq_use:Nn \l_tmpa_seq {,}} + \str_if_empty:NF \sassertiontype { + \stex_annotate_invisible:nnn{type}{\sassertiontype}{} + } + \clist_set:No \l_tmpa_clist \sassertiontype + \tl_clear:N \l_tmpa_tl + \clist_map_inline:Nn \l_tmpa_clist { + \tl_if_exist:cT {_@@_sassertion_##1_start:}{ + \tl_set:Nn \l_tmpa_tl {\use:c{_@@_sassertion_##1_start:}} + } + } + \tl_if_empty:NTF \l_tmpa_tl { + \_@@_sassertion_start: + }{ + \l_tmpa_tl + } + } + \str_if_empty:NTF \sassertionid { + \str_if_empty:NF \sassertionname { + \stex_ref_new_doc_target:n {} + } + } { + \stex_ref_new_doc_target:n \sassertionid + } + \stex_smsmode_do: +}{ + \str_if_empty:NF \sassertionname { + \stex_symdecl_do:nn{}{\sassertionname} + \stex_ref_new_sym_target:n {\l_stex_current_module_str ? \sassertionname} + } + \stex_if_smsmode:F { + \clist_set:No \l_tmpa_clist \sassertiontype + \tl_clear:N \l_tmpa_tl + \clist_map_inline:Nn \l_tmpa_clist { + \tl_if_exist:cT {_@@_sassertion_##1_end:}{ + \tl_set:Nn \l_tmpa_tl {\use:c{_@@_sassertion_##1_end:}} + } + } + \tl_if_empty:NTF \l_tmpa_tl { + \_@@_sassertion_end: + }{ + \l_tmpa_tl + } + \end{stex_annotate_env} + } +} +% \end{macrocode} +% \end{environment} +% +% \begin{macro}{\stexpatchassertion} +% \begin{macrocode} + +\cs_new_protected:Nn \_@@_sassertion_start: { + \par\noindent\titleemph{Assertion~\tl_if_empty:NF \sassertiontitle { + (\sassertiontitle) + }~} +} +\cs_new_protected:Nn \_@@_sassertion_end: {\par\medskip} + +\newcommand\stexpatchassertion[3][] { + \str_set:Nx \l_tmpa_str{ #1 } + \str_if_empty:NTF \l_tmpa_str { + \tl_set:Nn \_@@_sassertion_start: { #2 } + \tl_set:Nn \_@@_sassertion_end: { #3 } + }{ + \exp_after:wN \tl_set:Nn \csname _@@_sassertion_#1_start:\endcsname{ #2 } + \exp_after:wN \tl_set:Nn \csname _@@_sassertion_#1_end:\endcsname{ #3 } + } +} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\inlineass} +% inline: +% \begin{macrocode} +\keys_define:nn {stex / inlineass }{ + type .str_set_x:N = \sassertiontype, + id .str_set_x:N = \sassertionid, + for .clist_set:N = \l_@@_sassertion_for_clist , + name .str_set_x:N = \sassertionname +} +\cs_new_protected:Nn \_@@_inlineass_args:n { + \str_clear:N \sassertiontype + \str_clear:N \sassertionid + \str_clear:N \sassertionname + \clist_clear:N \l_@@_sassertion_for_clist + \keys_set:nn { stex / inlineass }{ #1 } +} +\NewDocumentCommand \inlineass { O{} m } { + \begingroup + \stex_reactivate_macro:N \premise + \stex_reactivate_macro:N \conclusion + \_@@_inlineass_args:n{ #1 } + \str_if_empty:NTF \sassertionid { + \str_if_empty:NF \sassertionname { + \stex_ref_new_doc_target:n {} + } + } { + \stex_ref_new_doc_target:n \sassertionid + } + + \stex_if_smsmode:TF{ + \str_if_empty:NF \sassertionname { + \stex_symdecl_do:nn{}{\sassertionname} + \stex_ref_new_sym_target:n {\l_stex_current_module_str ? \sassertionname} + } + }{ + \seq_clear:N \l_tmpa_seq + \clist_map_inline:Nn \l_@@_sassertion_for_clist { + \tl_if_empty:nF{ ##1 }{ + \stex_get_symbol:n { ##1 } + \exp_args:NNo \seq_put_right:Nn \l_tmpa_seq { + \l_stex_get_symbol_uri_str + } + } + } + \exp_args:Nnx + \stex_annotate:nnn{assertion}{\seq_use:Nn \l_tmpa_seq {,}}{ + \str_if_empty:NF \sassertiontype { + \stex_annotate_invisible:nnn{type}{\sassertiontype}{} + } + #2 + \str_if_empty:NF \sassertionname { + \stex_symdecl_do:nn{}{\sassertionname} + \stex_ref_new_sym_target:n {\l_stex_current_module_str ? \sassertionname} + } + } + } + \endgroup + \stex_smsmode_do: +} +% \end{macrocode} +% \end{macro} +% +% \subsection{Examples} +% +% \begin{environment}{sexample} +% \begin{macrocode} + +\keys_define:nn {stex / sexample }{ + type .str_set_x:N = \exampletype, + id .str_set_x:N = \sexampleid, + title .tl_set:N = \sexampletitle, + for .clist_set:N = \l_@@_sexample_for_clist, +} +\cs_new_protected:Nn \_@@_sexample_args:n { + \str_clear:N \sexampletype + \str_clear:N \sexampleid + \tl_clear:N \sexampletitle + \clist_clear:N \l_@@_sexample_for_clist + \keys_set:nn { stex / sexample }{ #1 } +} + +\NewDocumentEnvironment{sexample}{O{}}{ + \_@@_sexample_args:n{ #1 } + \stex_reactivate_macro:N \premise + \stex_reactivate_macro:N \conclusion + \stex_if_smsmode:F { + \seq_clear:N \l_tmpa_seq + \clist_map_inline:Nn \l_@@_sexample_for_clist { + \tl_if_empty:nF{ ##1 }{ + \stex_get_symbol:n { ##1 } + \exp_args:NNo \seq_put_right:Nn \l_tmpa_seq { + \l_stex_get_symbol_uri_str + } + } + } + \exp_args:Nnnx + \begin{stex_annotate_env}{example}{\seq_use:Nn \l_tmpa_seq {,}} + \str_if_empty:NF \sexampletype { + \stex_annotate_invisible:nnn{type}{\sexampletype}{} + } + \clist_set:No \l_tmpa_clist \sexampletype + \tl_clear:N \l_tmpa_tl + \clist_map_inline:Nn \l_tmpa_clist { + \tl_if_exist:cT {_@@_sexample_##1_start:}{ + \tl_set:Nn \l_tmpa_tl {\use:c{_@@_sexample_##1_start:}} + } + } + \tl_if_empty:NTF \l_tmpa_tl { + \_@@_sexample_start: + }{ + \l_tmpa_tl + } + } + \str_if_empty:NF \sexampleid { + \stex_ref_new_doc_target:n \sexampleid + } + \stex_smsmode_do: +}{ + \str_if_empty:NF \sexamplename { \stex_symdecl_do:nn{}{\sexamplename} } + \stex_if_smsmode:F { + \clist_set:No \l_tmpa_clist \sexampletype + \tl_clear:N \l_tmpa_tl + \clist_map_inline:Nn \l_tmpa_clist { + \tl_if_exist:cT {_@@_sexample_##1_end:}{ + \tl_set:Nn \l_tmpa_tl {\use:c{_@@_sexample_##1_end:}} + } + } + \tl_if_empty:NTF \l_tmpa_tl { + \_@@_sexample_end: + }{ + \l_tmpa_tl + } + \end{stex_annotate_env} + } +} +% \end{macrocode} +% \end{environment} +% +% \begin{macro}{\stexpatchexample} +% \begin{macrocode} + +\cs_new_protected:Nn \_@@_sexample_start: { + \par\noindent\titleemph{Example~\tl_if_empty:NF \sexampletitle { + (\sexampletitle) + }~} +} +\cs_new_protected:Nn \_@@_sexample_end: {\par\medskip} + +\newcommand\stexpatchexample[3][] { + \str_set:Nx \l_tmpa_str{ #1 } + \str_if_empty:NTF \l_tmpa_str { + \tl_set:Nn \_@@_sexample_start: { #2 } + \tl_set:Nn \_@@_sexample_end: { #3 } + }{ + \exp_after:wN \tl_set:Nn \csname _@@_sexample_#1_start:\endcsname{ #2 } + \exp_after:wN \tl_set:Nn \csname _@@_sexample_#1_end:\endcsname{ #3 } + } +} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\inlineex} +% inline: +% \begin{macrocode} +\keys_define:nn {stex / inlineex }{ + type .str_set_x:N = \sexampletype, + id .str_set_x:N = \sexampleid, + for .clist_set:N = \l_@@_sexample_for_clist , + name .str_set_x:N = \sexamplename +} +\cs_new_protected:Nn \_@@_inlineex_args:n { + \str_clear:N \sexampletype + \str_clear:N \sexampleid + \str_clear:N \sexamplename + \clist_clear:N \l_@@_sexample_for_clist + \keys_set:nn { stex / inlineex }{ #1 } +} +\NewDocumentCommand \inlineex { O{} m } { + \begingroup + \stex_reactivate_macro:N \premise + \stex_reactivate_macro:N \conclusion + \_@@_inlineex_args:n{ #1 } + \str_if_empty:NF \sexampleid { + \stex_ref_new_doc_target:n \sexampleid + } + \stex_if_smsmode:TF{ + \str_if_empty:NF \sexamplename { \stex_symdecl_do:nn{}{\examplename} } + }{ + \seq_clear:N \l_tmpa_seq + \clist_map_inline:Nn \l_@@_sexample_for_clist { + \tl_if_empty:nF{ ##1 }{ + \stex_get_symbol:n { ##1 } + \exp_args:NNo \seq_put_right:Nn \l_tmpa_seq { + \l_stex_get_symbol_uri_str + } + } + } + \exp_args:Nnx + \stex_annotate:nnn{example}{\seq_use:Nn \l_tmpa_seq {,}}{ + \str_if_empty:NF \sexampletype { + \stex_annotate_invisible:nnn{type}{\sexampletype}{} + } + #2 + \str_if_empty:NF \sexamplename { \stex_symdecl_do:nn{}{\sexamplename} } + } + } + \endgroup + \stex_smsmode_do: +} +% \end{macrocode} +% \end{macro} +% +% \subsection{Logical Paragraphs} +% +% \begin{environment}{sparagraph} +% \begin{macrocode} +\keys_define:nn { stex / sparagraph} { + id .str_set_x:N = \sparagraphid , + title .tl_set:N = \l_stex_sparagraph_title_tl , + type .str_set_x:N = \sparagraphtype , + for .clist_set:N = \l_@@_sparagraph_for_clist , + from .tl_set:N = \sparagraphfrom , + to .tl_set:N = \sparagraphto , + start .tl_set:N = \l_stex_sparagraph_start_tl , + name .str_set:N = \sparagraphname +} + +\cs_new_protected:Nn \stex_sparagraph_args:n { + \tl_clear:N \l_stex_sparagraph_title_tl + \tl_clear:N \sparagraphfrom + \tl_clear:N \sparagraphto + \tl_clear:N \l_stex_sparagraph_start_tl + \str_clear:N \sparagraphid + \str_clear:N \sparagraphtype + \clist_clear:N \l_@@_sparagraph_for_clist + \str_clear:N \sparagraphname + \keys_set:nn { stex / sparagraph }{ #1 } +} +\newif\if@in@omtext\@in@omtextfalse + +\NewDocumentEnvironment {sparagraph} { O{} } { + \stex_sparagraph_args:n { #1 } + \tl_if_empty:NTF \l_stex_sparagraph_start_tl { + \tl_set_eq:NN \sparagraphtitle \l_stex_sparagraph_title_tl + }{ + \tl_set_eq:NN \sparagraphtitle \l_stex_sparagraph_start_tl + } + \@in@omtexttrue + \stex_if_smsmode:F { + \seq_clear:N \l_tmpa_seq + \clist_map_inline:Nn \l_@@_sparagraph_for_clist { + \tl_if_empty:nF{ ##1 }{ + \stex_get_symbol:n { ##1 } + \exp_args:NNo \seq_put_right:Nn \l_tmpa_seq { + \l_stex_get_symbol_uri_str + } + } + } + \exp_args:Nnnx + \begin{stex_annotate_env}{paragraph}{\seq_use:Nn \l_tmpa_seq {,}} + \str_if_empty:NF \sparagraphtype { + \stex_annotate_invisible:nnn{type}{\sparagraphtype}{} + } + \str_if_empty:NF \sparagraphfrom { + \stex_annotate_invisible:nnn{from}{\sparagraphfrom}{} + } + \str_if_empty:NF \sparagraphto { + \stex_annotate_invisible:nnn{to}{\sparagraphto}{} + } + \clist_set:No \l_tmpa_clist \sparagraphtype + \tl_clear:N \l_tmpa_tl + \clist_map_inline:Nn \sparagraphtype { + \tl_if_exist:cT {_@@_sparagraph_##1_start:}{ + \tl_set:Nn \l_tmpa_tl {\use:c{_@@_sparagraph_##1_start:}} + } + } + \tl_if_empty:NTF \l_tmpa_tl { + \_@@_sparagraph_start: + }{ + \l_tmpa_tl + } + } + \clist_set:No \l_tmpa_clist \sparagraphtype + \str_if_empty:NTF \sparagraphid { + \str_if_empty:NTF \sparagraphname { + \exp_args:NNx \clist_if_in:NnT \l_tmpa_clist {\tl_to_str:n{symdoc}}{ + \stex_ref_new_doc_target:n {} + } + } { + \stex_ref_new_doc_target:n {} + } + } { + \stex_ref_new_doc_target:n \sparagraphid + } + \exp_args:NNx + \clist_if_in:NnT \l_tmpa_clist {\tl_to_str:n{symdoc}}{ + \clist_map_inline:Nn \l_@@_sparagraph_for_clist { + \tl_if_empty:nF{ ##1 }{ + \stex_get_symbol:n { ##1 } + \stex_ref_new_sym_target:n \l_stex_get_symbol_uri_str + } + } + } + \stex_smsmode_do: + \ignorespacesandpars +}{ + \str_if_empty:NF \sparagraphname { + \stex_symdecl_do:nn{}{\sparagraphname} + \stex_ref_new_sym_target:n {\l_stex_current_module_str ? \sparagraphname} + } + \stex_if_smsmode:F { + \clist_set:No \l_tmpa_clist \sparagraphtype + \tl_clear:N \l_tmpa_tl + \clist_map_inline:Nn \l_tmpa_clist { + \tl_if_exist:cT {_@@_sparagraph_##1_end:}{ + \tl_set:Nn \l_tmpa_tl {\use:c{_@@_sparagraph_##1_end:}} + } + } + \tl_if_empty:NTF \l_tmpa_tl { + \_@@_sparagraph_end: + }{ + \l_tmpa_tl + } + \end{stex_annotate_env} + } +} +% \end{macrocode} +% \end{environment} +% +% \begin{macro}{\stexpatchparagraph} +% \begin{macrocode} + +\cs_new_protected:Nn \_@@_sparagraph_start: { + \par\noindent\tl_if_empty:NTF \l_stex_sparagraph_start_tl { + \tl_if_empty:NF \l_stex_sparagraph_title_tl { + \titleemph{\l_stex_sparagraph_title_tl}:~ + } + }{ + \titleemph{\l_stex_sparagraph_start_tl}~ + } +} +\cs_new_protected:Nn \_@@_sparagraph_end: {\par\medskip} + +\newcommand\stexpatchparagraph[3][] { + \str_set:Nx \l_tmpa_str{ #1 } + \str_if_empty:NTF \l_tmpa_str { + \tl_set:Nn \_@@_sparagraph_start: { #2 } + \tl_set:Nn \_@@_sparagraph_end: { #3 } + }{ + \exp_after:wN \tl_set:Nn \csname _@@_sparagraph_#1_start:\endcsname{ #2 } + \exp_after:wN \tl_set:Nn \csname _@@_sparagraph_#1_end:\endcsname{ #3 } + } +} + +\keys_define:nn { stex / inlinepara} { + id .str_set_x:N = \sparagraphid , + type .str_set_x:N = \sparagraphtype , + for .clist_set:N = \l_@@_sparagraph_for_clist , + from .tl_set:N = \sparagraphfrom , + to .tl_set:N = \sparagraphto , + name .str_set:N = \sparagraphname +} +\cs_new_protected:Nn \_@@_inlinepara_args:n { + \tl_clear:N \sparagraphfrom + \tl_clear:N \sparagraphto + \str_clear:N \sparagraphid + \str_clear:N \sparagraphtype + \clist_clear:N \l_@@_sparagraph_for_clist + \str_clear:N \sparagraphname + \keys_set:nn { stex / inlinepara }{ #1 } +} +\NewDocumentCommand \inlinepara { O{} m } { + \begingroup + \_@@_inlinepara_args:n{ #1 } + \clist_set:No \l_tmpa_clist \sparagraphtype + \str_if_empty:NTF \sparagraphid { + \str_if_empty:NTF \sparagraphname { + \exp_args:NNx \clist_if_in:NnT \l_tmpa_clist {\tl_to_str:n{symdoc}}{ + \stex_ref_new_doc_target:n {} + } + } { + \stex_ref_new_doc_target:n {} + } + } { + \stex_ref_new_doc_target:n \sparagraphid + } + \stex_if_smsmode:TF{ + \str_if_empty:NF \sparagraphname { + \stex_symdecl_do:nn{}{\sparagraphname} + \stex_ref_new_sym_target:n {\l_stex_current_module_str ? \sparagraphname} + } + }{ + \seq_clear:N \l_tmpa_seq + \clist_map_inline:Nn \l_@@_sparagraph_for_clist { + \tl_if_empty:nF{ ##1 }{ + \stex_get_symbol:n { ##1 } + \exp_args:NNo \seq_put_right:Nn \l_tmpa_seq { + \l_stex_get_symbol_uri_str + } + } + } + \exp_args:Nnx + \stex_annotate:nnn{paragraph}{\seq_use:Nn \l_tmpa_seq {,}}{ + \str_if_empty:NF \sparagraphtype { + \stex_annotate_invisible:nnn{type}{\sparagraphtype}{} + } + \str_if_empty:NF \sparagraphfrom { + \stex_annotate_invisible:nnn{from}{\sparagraphfrom}{} + } + \str_if_empty:NF \sparagraphto { + \stex_annotate_invisible:nnn{to}{\sparagraphto}{} + } + \str_if_empty:NF \sparagraphname { + \stex_symdecl_do:nn{}{\sparagraphname} + \stex_ref_new_sym_target:n {\l_stex_current_module_str ? \sparagraphname} + } + \exp_args:NNx \clist_if_in:NnT \l_tmpa_clist {\tl_to_str:n{symdoc}}{ + \clist_map_inline:Nn \l_tmpa_seq { + \stex_ref_new_sym_target:n {##1} + } + } + #2 + } + } + \endgroup + \stex_smsmode_do: +} + +% \end{macrocode} +% \end{macro} +% +% +% +% +% +% +% +% +% +% +% +% +% +% +% +% +% +% +% +% +% +% \begin{macrocode} +%</package> +% \end{macrocode} +% +% \end{implementation} +% +% \PrintIndex + +% \endinput +% Local Variables: +% mode: doctex +% TeX-master: t +% End: diff --git a/macros/latex/contrib/stex/source/stex/stex.ins b/macros/latex/contrib/stex/source/stex/stex.ins new file mode 100644 index 0000000000..95ff248c0d --- /dev/null +++ b/macros/latex/contrib/stex/source/stex/stex.ins @@ -0,0 +1,46 @@ + %% +%% This file generates files required to use the ed package. +%% At your command prompt write +%% +%% latex stex.ins +%% +%% Copyright (c) 2021 Michael Kohlhase +%% +%% This file is distributed under the terms of the LaTeX Project Public +%% License from CTAN archives in directory macros/latex/base/lppl.txt. +%% Either version 1.0 or, at your option, any later version. +%% +\input docstrip +\preamble +\endpreamble + +\keepsilent +\askforoverwritefalse + +\generate{ + \file{stex.cls}{\from{basics.dtx}{cls}} + \file{stex.sty}{ + \from{basics.dtx}{package} + \from{mathhub.dtx}{package} + \from{references.dtx}{package} + \from{modules.dtx}{package} + \from{inheritance.dtx}{package} + \from{symbols.dtx}{package} + \from{terms.dtx}{package} + \from{features.dtx}{package} + \from{statements.dtx}{package} + \from{sproof.dtx}{package} + % ... + \from{others.dtx}{package} + \from{metatheory.dtx}{package} + } +} + +\Msg{*} +\Msg{* You probably need to move the generated style files into a directory searched by TeX.} +\Msg{*} +\Msg{* And don't forget to refresh your filename database} +\Msg{* if your TeX distribution uses such a database.} +\Msg{*} + +\endbatchfile diff --git a/macros/latex/contrib/stex/source/stex/symbols.dtx b/macros/latex/contrib/stex/source/stex/symbols.dtx new file mode 100644 index 0000000000..da633e1be3 --- /dev/null +++ b/macros/latex/contrib/stex/source/stex/symbols.dtx @@ -0,0 +1,1263 @@ +% \iffalse meta-comment +% An Infrastructure for Semantic Macros and Module Scoping +% Copyright (c) 2019 Michael Kohlhase, all rights reserved +% this file is released under the +% LaTeX Project Public License (LPPL) +% +% The original of this file is in the public repository at +% http://github.com/sLaTeX/sTeX/ +% +% TODO update copyright +% +%<*driver> +\providecommand\bibfolder{../../lib/bib} +\input{../../doc/docheader} + +\begin{document} + \DocInput{\jobname.dtx} +\end{document} +%</driver> +% \fi +% +% \title{ \sTeX-Symbols +% \thanks{Version {\fileversion} (last revised {\filedate})} +% } +% +% \author{Michael Kohlhase, Dennis Müller\\ +% FAU Erlangen-Nürnberg\\ +% \url{http://kwarc.info/} +% } +% +% \maketitle +% +%\ifinfulldoc\else +% This is the documentation for the \pkg{stex-symbols} package. +% For a more high-level introduction, +% see \href{\basedocurl/manual.pdf}{the \sTeX Manual} or the +% \href{\basedocurl/stex.pdf}{full \sTeX documentation}. +% +% \input{../../doc/packages/symbols} +% \fi +% +% \begin{documentation}\label{pkg:symbols:doc} +% +% Code related to symbol declarations and notations +% +% \section{Macros and Environments}\label{pkg:symbols:doc:macros} +% +% \begin{function}{\symdecl} +% \begin{syntax} \cs{symdecl}\Arg{macroname}|[|\meta{args}|]| \end{syntax} +% Declares a new symbol with semantic macro \cs{macroname}. Optional +% arguments are: +% \begin{itemize} +% \item |name|: An (\omdoc) name. By default equal to \meta{macroname}. +% \item |type|: An (ideally semantic) term. Not used by \sTeX, but +% passed on to \mmt for semantic services. +% \item |local|: A boolean (by default false). If set, this declaration +% will not be added to the module content, i.e. importing +% the current module will not make this declaration available. +% \item |args|: Specifies the ``signature'' of the semantic macro. +% Can be either an integer $0 \leq n \leq 9$, or a (more precise) +% sequence of the following characters: +% \begin{itemize} +% \item[|i|] a ``normal'' argument, e.g. +% |\symdecl{plus}[args=ii]| allows for |\plus{2}{2}|. +% \item[|a|] an \emph{associative} argument; i.e. a sequence of +% arbitrarily many arguments provided as a comma-separated list, +% e.g. +% |\symdecl{plus}[args=a]| allows for |\plus{2,2,2}|. +% \item[|b|] a \emph{variable} argument. Is treated by \sTeX +% like an |i|-argument, but an application is turned into +% an |OMBind| in \omdoc, binding the provided variable +% in the subsequent arguments of the operator; e.g. +% |\symdecl{forall}[args=bi]| allows for |\forall{x\in\Nat}{x\geq0}|. +% \end{itemize} +% \end{itemize} +% \end{function} +% +% \begin{function}{\stex_symdecl_do:n} +% Implements the core functionality of \cs{symdecl}, and is +% called by \cs{symdecl} and \cs{symdef}. +% +% Ultimately stores the symbol \meta{URI} in the property +% list |\l_stex_symdecl_|\meta{URI}|_prop| with fields: +% \begin{itemize} +% \item |name| (string), +% \item |module| (string), +% \item |notations| (sequence of strings; initially empty), +% \item |local| (boolean), +% \item |type| (token list), +% \item |args| (string of |i|s, |a|s and |b|s), +% \item |arity| (integer string), +% \item |assocs| (integer string; number of associative arguments), +% \end{itemize} +% \end{function} +% +% \begin{function}{\stex_all_symbols:n} +% Iterates over all currently available symbols. +% Requires two |\seq_map_break:| to break fully. +% \end{function} +% +% \begin{function}{\stex_get_symbol:n} +% Computes the full URI of a symbol from a macro argument, e.g. +% the macro name, the macro itself, the full URI... +% \end{function} +% +% \begin{function}{\notation} +% \begin{syntax} \cs{notation}|[|\meta{args}|]|\Arg{symbol}\Arg{notations$^+$} \end{syntax} +% Introduces a new notation for \meta{symbol}, see \cs{stex_notation_do:nn} +% \end{function} +% +% \begin{function}{\stex_notation_do:nn} +% \begin{syntax} \cs{stex_notation_do:nn}\Arg{URI}\Arg{notations$^+$}\end{syntax} +% +% Implements the core functionality of \cs{notation}, and is +% called by \cs{notation} and \cs{symdef}. +% +% Ultimately stores the notation in the property +% list\\ |\g_stex_notation_|\meta{URI}|#|\meta{variant}|#|^^A +% \meta{lang}|_prop| with fields: +% \begin{itemize} +% \item |symbol| (URI string), +% \item |language| (string), +% \item |variant| (string), +% \item |opprec| (integer string), +% \item |argprecs| (sequence of integer strings) +% \end{itemize} +% \end{function} +% +% \begin{function}{\symdef} +% \begin{syntax} \cs{symdef}|[|\meta{args}|]|\Arg{symbol}\Arg{notations$^+$} \end{syntax} +% Combines \cs{symdecl} and \cs{notation} by introducing a new +% symbol and assigning a new notation for it. +% \end{function} +% +% \end{documentation} +% +% \begin{implementation}\label{pkg:symbols:impl} +% +% \section{\sTeX-Symbols Implementation} +% +% \begin{macrocode} +%<*package> + +%%%%%%%%%%%%% symbols.dtx %%%%%%%%%%%%% + +% \end{macrocode} +% +% Warnings and error messages +% +% \begin{macrocode} +\msg_new:nnn{stex}{error/wrongargs}{ + args~value~in~symbol~declaration~for~#1~ + needs~to~be~i,~a,~b~or~B,~but~#2~given +} +% \end{macrocode} +% +% \subsection{Symbol Declarations} +% \begin{macrocode} +%<@@=stex_symdecl> +% \end{macrocode} +% +% \begin{macro}{\stex_all_symbols:n} +% Map over all available symbols +% \begin{macrocode} +\cs_new_protected:Nn \stex_all_symbols:n { + \def \_@@_all_symbols_cs ##1 {#1} + \seq_map_inline:Nn \l_stex_all_modules_seq { + \seq_map_inline:cn{c_stex_module_##1_constants}{ + \_@@_all_symbols_cs{##1?####1} + } + } +} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\STEXsymbol} +% \begin{macrocode} +\NewDocumentCommand \STEXsymbol { m } { + \stex_get_symbol:n { #1 } + \exp_args:No + \stex_invoke_symbol:n { \l_stex_get_symbol_uri_str } +} +% \end{macrocode} +% \end{macro} +% +% |symdecl| arguments: +% +% \begin{macrocode} +\keys_define:nn { stex / symdecl } { + name .str_set_x:N = \l_stex_symdecl_name_str , + local .bool_set:N = \l_stex_symdecl_local_bool , + args .str_set_x:N = \l_stex_symdecl_args_str , + type .tl_set:N = \l_stex_symdecl_type_tl , + deprecate .str_set_x:N = \l_stex_symdecl_deprecate_str , + align .str_set:N = \l_stex_symdecl_align_str , % TODO(?) + gfc .str_set:N = \l_stex_symdecl_gfc_str , % TODO(?) + specializes .str_set:N = \l_stex_symdecl_specializes_str , % TODO(?) + def .tl_set:N = \l_stex_symdecl_definiens_tl , + assoc .choices:nn = + {bin,binl,binr,pre,conj,pwconj} + {\str_set:Nx \l_stex_symdecl_assoctype_str {\l_keys_choice_tl}} +} + +\bool_new:N \l_stex_symdecl_make_macro_bool + +\cs_new_protected:Nn \_@@_args:n { + \str_clear:N \l_stex_symdecl_name_str + \str_clear:N \l_stex_symdecl_args_str + \str_clear:N \l_stex_symdecl_deprecate_str + \str_clear:N \l_stex_symdecl_assoctype_str + \bool_set_false:N \l_stex_symdecl_local_bool + \tl_clear:N \l_stex_symdecl_type_tl + \tl_clear:N \l_stex_symdecl_definiens_tl + + \keys_set:nn { stex / symdecl } { #1 } +} +% \end{macrocode} +% +% \begin{macro}{\symdecl} +% +% Parses the optional arguments and passes them on to +% \cs{stex_symdecl_do:} (so that \cs{symdef} +% can do the same) +% +% \begin{macrocode} + +\NewDocumentCommand \symdecl { s m O{}} { + \_@@_args:n { #3 } + \IfBooleanTF #1 { + \bool_set_false:N \l_stex_symdecl_make_macro_bool + } { + \bool_set_true:N \l_stex_symdecl_make_macro_bool + } + \stex_symdecl_do:n { #2 } + \stex_smsmode_do: +} + +\cs_new_protected:Nn \stex_symdecl_do:nn { + \_@@_args:n{#1} + \bool_set_false:N \l_stex_symdecl_make_macro_bool + \stex_symdecl_do:n{#2} +} + +\stex_deactivate_macro:Nn \symdecl {module~environments} +% \end{macrocode} +% \end{macro} +% +% +% \begin{macro}{\stex_symdecl_do:n} +% \begin{macrocode} +\cs_new_protected:Nn \stex_symdecl_do:n { + \stex_if_in_module:F { + % TODO throw error? some default namespace? + } + + \str_if_empty:NT \l_stex_symdecl_name_str { + \str_set:Nx \l_stex_symdecl_name_str { #1 } + } + + \prop_if_exist:cT { l_stex_symdecl_ + \l_stex_current_module_str ? + \l_stex_symdecl_name_str + _prop + }{ + % TODO throw error (beware of circular dependencies) + } + + \prop_clear:N \l_tmpa_prop + \prop_put:Nnx \l_tmpa_prop { module } { \l_stex_current_module_str } + \seq_clear:N \l_tmpa_seq + \prop_put:Nno \l_tmpa_prop { name } \l_stex_symdecl_name_str + \prop_put:Nno \l_tmpa_prop { type } \l_stex_symdecl_type_tl + + \str_if_empty:NT \l_stex_symdecl_deprecate_str { + \str_if_empty:NF \l_stex_module_deprecate_str { + \str_set_eq:NN \l_stex_symdecl_deprecate_str \l_stex_module_deprecate_str + } + } + \prop_put:Nno \l_tmpa_prop { deprecate } \l_stex_symdecl_deprecate_str + + \exp_args:No \stex_add_constant_to_current_module:n { + \l_stex_symdecl_name_str + } + + % arity/args + \int_zero:N \l_tmpb_int + + \bool_set_true:N \l_tmpa_bool + \str_map_inline:Nn \l_stex_symdecl_args_str { + \token_case_meaning:NnF ##1 { + 0 {} 1 {} 2 {} 3 {} 4 {} 5 {} 6 {} 7 {} 8 {} 9 {} + {\tl_to_str:n i} { \bool_set_false:N \l_tmpa_bool } + {\tl_to_str:n b} { \bool_set_false:N \l_tmpa_bool } + {\tl_to_str:n a} { + \bool_set_false:N \l_tmpa_bool + \int_incr:N \l_tmpb_int + } + {\tl_to_str:n B} { + \bool_set_false:N \l_tmpa_bool + \int_incr:N \l_tmpb_int + } + }{ + \msg_error:nnxx{stex}{error/wrongargs}{ + \l_stex_current_module_str ? + \l_stex_symdecl_name_str + }{##1} + } + } + \bool_if:NTF \l_tmpa_bool { + % possibly numeric + \str_if_empty:NTF \l_stex_symdecl_args_str { + \prop_put:Nnn \l_tmpa_prop { args } {} + \prop_put:Nnn \l_tmpa_prop { arity } { 0 } + }{ + \int_set:Nn \l_tmpa_int { \l_stex_symdecl_args_str } + \prop_put:Nnx \l_tmpa_prop { arity } { \int_use:N \l_tmpa_int } + \str_clear:N \l_tmpa_str + \int_step_inline:nn \l_tmpa_int { + \str_put_right:Nn \l_tmpa_str i + } + \prop_put:Nnx \l_tmpa_prop { args } { \l_tmpa_str } + } + } { + \prop_put:Nnx \l_tmpa_prop { args } { \l_stex_symdecl_args_str } + \prop_put:Nnx \l_tmpa_prop { arity } + { \str_count:N \l_stex_symdecl_args_str } + } + \prop_put:Nnx \l_tmpa_prop { assocs } { \int_use:N \l_tmpb_int } + + + % semantic macro + + \bool_if:NT \l_stex_symdecl_make_macro_bool { + \exp_args:Nx \stex_do_up_to_module:n { + \tl_set:cn { #1 } { \stex_invoke_symbol:n { + \l_stex_current_module_str ? \l_stex_symdecl_name_str + }} + } + + \bool_if:NF \l_stex_symdecl_local_bool { + \exp_args:Nx \stex_add_to_current_module:n { + \tl_set:cn { #1 } { \stex_invoke_symbol:n { + \l_stex_current_module_str ? \l_stex_symdecl_name_str + } } + } + } + } + + \stex_debug:nn{symbols}{New~symbol:~ + \l_stex_current_module_str ? \l_stex_symdecl_name_str^^J + Type:~\exp_not:o { \l_stex_symdecl_type_tl }^^J + Args:~\prop_item:Nn \l_tmpa_prop { args } + } + + % circular dependencies require this: + + \prop_if_exist:cF { + l_stex_symdecl_ + \l_stex_current_module_str ? \l_stex_symdecl_name_str + _prop + } { + \prop_set_eq:cN { + l_stex_symdecl_ + \l_stex_current_module_str ? \l_stex_symdecl_name_str + _prop + } \l_tmpa_prop + } + + \seq_clear:c { + l_stex_symdecl_ + \l_stex_current_module_str ? \l_stex_symdecl_name_str + _notations + } + + \bool_if:NF \l_stex_symdecl_local_bool { + \exp_args:Nx + \stex_add_to_current_module:n { + \seq_clear:c { + l_stex_symdecl_ + \l_stex_current_module_str ? \l_stex_symdecl_name_str + _notations + } + \prop_set_from_keyval:cn { + l_stex_symdecl_ + \l_stex_current_module_str ? \l_stex_symdecl_name_str + _prop + } { + name = \prop_item:Nn \l_tmpa_prop { name } , + module = \prop_item:Nn \l_tmpa_prop { module } , + type = \prop_item:Nn \l_tmpa_prop { type } , + args = \prop_item:Nn \l_tmpa_prop { args } , + arity = \prop_item:Nn \l_tmpa_prop { arity } , + assocs = \prop_item:Nn \l_tmpa_prop { assocs } + } + } + } + + \stex_if_smsmode:F { +% \exp_args:Nx \stex_do_up_to_module:n { +% \seq_put_right:Nn \exp_not:N \l_stex_all_symbols_seq { +% \l_stex_current_module_str ? \l_stex_symdecl_name_str +% } +% } + \stex_if_do_html:T { + \stex_annotate_invisible:nnn {symdecl} { + \l_stex_current_module_str ? \l_stex_symdecl_name_str + } { + \tl_if_empty:NF \l_stex_symdecl_type_tl {\stex_annotate_invisible:nnn{type}{}{$\l_stex_symdecl_type_tl$}} + \stex_annotate_invisible:nnn{args}{}{ + \prop_item:Nn \l_tmpa_prop { args } + } + \stex_annotate_invisible:nnn{macroname}{#1}{} + \tl_if_empty:NF \l_stex_symdecl_definiens_tl { + \stex_annotate_invisible:nnn{definiens}{} + {$\l_stex_symdecl_definiens_tl$} + } + \str_if_empty:NF \l_stex_symdecl_assoctype_str { + \stex_annotate_invisible:nnn{assoctype}{\l_stex_symdecl_assoctype_str}{} + } + } + } + } +} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\stex_get_symbol:n} +% +% \begin{macrocode} +\str_new:N \l_stex_get_symbol_uri_str + +\cs_new_protected:Nn \stex_get_symbol:n { + \tl_if_head_eq_catcode:nNTF { #1 } \relax { + \_@@_get_symbol_from_cs:n { #1 } + }{ + % argument is a string + % is it a command name? + \cs_if_exist:cTF { #1 }{ + \cs_set_eq:Nc \l_tmpa_tl { #1 } + \str_set:Nx \l_tmpa_str { \cs_argument_spec:N \l_tmpa_tl } + \str_if_empty:NTF \l_tmpa_str { + \exp_args:Nx \cs_if_eq:NNTF { + \tl_head:N \l_tmpa_tl + } \stex_invoke_symbol:n { + \exp_args:No \_@@_get_symbol_from_cs:n { \use:c { #1 } } + }{ + \_@@_get_symbol_from_string:n { #1 } + } + } { + \_@@_get_symbol_from_string:n { #1 } + } + }{ + % argument is not a command name + \_@@_get_symbol_from_string:n { #1 } + % \l_stex_all_symbols_seq + } + } + \str_if_eq:eeF { + \prop_item:cn { + l_stex_symdecl_\l_stex_get_symbol_uri_str _prop + }{ deprecate } + }{}{ + \msg_warning:nnxx{stex}{warning/deprecated}{ + Symbol~\l_stex_get_symbol_uri_str + }{ + \prop_item:cn {l_stex_symdecl_\l_stex_get_symbol_uri_str _prop}{ deprecate } + } + } +} + +\cs_new_protected:Nn \_@@_get_symbol_from_string:n { + \tl_set:Nn \l_tmpa_tl { + \msg_set:nnn{stex}{error/unknownsymbol}{ + No~symbol~#1~found! + } + \msg_error:nn{stex}{error/unknownsymbol} + } + \str_set:Nn \l_tmpa_str { #1 } + \int_set:Nn \l_tmpa_int { \str_count:N \l_tmpa_str } + + \stex_all_symbols:n { + \str_if_eq:eeT { \l_tmpa_str }{ \str_range:nnn {##1}{-\l_tmpa_int}{-1}}{ + \seq_map_break:n{\seq_map_break:n{ + \tl_set:Nn \l_tmpa_tl { + \str_set:Nn \l_stex_get_symbol_uri_str { ##1 } + } + }} + } + } + + \l_tmpa_tl +} + +\cs_new_protected:Nn \_@@_get_symbol_from_cs:n { + \exp_args:NNx \tl_set:Nn \l_tmpa_tl + { \tl_tail:N \l_tmpa_tl } + \tl_if_single:NTF \l_tmpa_tl { + \exp_args:No \tl_if_head_is_group:nTF \l_tmpa_tl { + \exp_after:wN \str_set:Nn \exp_after:wN + \l_stex_get_symbol_uri_str \l_tmpa_tl + }{ + % TODO + % tail is not a single group + } + }{ + % TODO + % tail is not a single group + } +} +% \end{macrocode} +% \end{macro} +% +% \subsection{Notations} +% \begin{macrocode} +%<@@=stex_notation> +% \end{macrocode} +% +% |notation| arguments: +% +% \begin{macrocode} +\keys_define:nn { stex / notation } { + lang .tl_set_x:N = \l_@@_lang_str , + variant .tl_set_x:N = \l_@@_variant_str , + prec .str_set_x:N = \l_@@_prec_str , + op .tl_set:N = \l_@@_op_tl , + primary .bool_set:N = \l_@@_primary_bool , + primary .default:n = {true} , + unknown .code:n = \str_set:Nx + \l_@@_variant_str \l_keys_key_str +} + +\cs_new_protected:Nn \_stex_notation_args:n { + \str_clear:N \l_@@_lang_str + \str_clear:N \l_@@_variant_str + \str_clear:N \l_@@_prec_str + \tl_clear:N \l_@@_op_tl + \bool_set_false:N \l_@@_primary_bool + + \keys_set:nn { stex / notation } { #1 } +} +% \end{macrocode} +% +% +% +% \begin{macro}{\notation} +% \begin{macrocode} +\NewDocumentCommand \notation { s m O{}} { + \_stex_notation_args:n { #3 } + \tl_clear:N \l_stex_symdecl_definiens_tl + \stex_get_symbol:n { #2 } + \tl_set:Nn \l_stex_notation_after_do_tl { + \_@@_final: + \IfBooleanTF#1{ + \stex_setnotation:n {\l_stex_get_symbol_uri_str} + }{} + \stex_smsmode_do: + } + \stex_notation_do:nnnn + { \prop_item:cn {l_stex_symdecl_\l_stex_get_symbol_uri_str _prop } { args } } + { \prop_item:cn { l_stex_symdecl_\l_stex_get_symbol_uri_str _prop } { arity } } + { \l_@@_variant_str \c_hash_str \l_@@_lang_str } +} +\stex_deactivate_macro:Nn \notation {module~environments} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\stex_notation_do:nnnn} +% \begin{macrocode} +\seq_new:N \l_@@_precedences_seq +\tl_new:N \l_@@_opprec_tl +\int_new:N \l_@@_currarg_int +\tl_new:N \stex_symbol_after_invocation_tl + +\cs_new_protected:Nn \stex_notation_do:nnnn { + \let\l_stex_current_symbol_str\relax + \seq_clear:N \l_@@_precedences_seq + \tl_clear:N \l_@@_opprec_tl + \str_set:Nx \l_@@_args_str { #1 } + \str_set:Nx \l_@@_arity_str { #2 } + \str_set:Nx \_@@_suffix_str { #3 } + + % precedences + \str_if_empty:NTF \l_@@_prec_str { + \int_compare:nNnTF \l_@@_arity_str = 0 { + \tl_set:No \l_@@_opprec_tl { \neginfprec } + }{ + \tl_set:Nn \l_@@_opprec_tl { 0 } + } + } { + \str_if_eq:onTF \l_@@_prec_str {nobrackets}{ + \tl_set:No \l_@@_opprec_tl { \neginfprec } + \int_step_inline:nn { \l_@@_arity_str } { + \exp_args:NNo + \seq_put_right:Nn \l_@@_precedences_seq { \infprec } + } + }{ + \seq_set_split:NnV \l_tmpa_seq ; \l_@@_prec_str + \seq_pop_left:NNTF \l_tmpa_seq \l_tmpa_str { + \tl_set:No \l_@@_opprec_tl { \l_tmpa_str } + \seq_pop_left:NNT \l_tmpa_seq \l_tmpa_str { + \exp_args:NNNo \exp_args:NNno \seq_set_split:Nnn + \l_tmpa_seq {\tl_to_str:n{x} } { \l_tmpa_str } + \seq_map_inline:Nn \l_tmpa_seq { + \seq_put_right:Nn \l_tmpb_seq { ##1 } + } + } + }{ + \int_compare:nNnTF \l_@@_arity_str = 0 { + \tl_set:No \l_@@_opprec_tl { \infprec } + }{ + \tl_set:No \l_@@_opprec_tl { 0 } + } + } + } + } + + \seq_set_eq:NN \l_tmpa_seq \l_@@_precedences_seq + \int_step_inline:nn { \l_@@_arity_str } { + \seq_pop_left:NNF \l_tmpa_seq \l_tmpb_str { + \exp_args:NNo + \seq_put_right:No \l_@@_precedences_seq { + \l_@@_opprec_tl + } + } + } + \tl_clear:N \l_stex_notation_dummyargs_tl + + \int_compare:nNnTF \l_@@_arity_str = 0 { + \exp_args:NNe + \cs_set:Npn \l_stex_notation_macrocode_cs { + \_stex_term_math_oms:nnnn { \l_stex_current_symbol_str } + { \_@@_suffix_str } + { \l_@@_opprec_tl } + { \exp_not:n { #4 } } + } + \l_stex_notation_after_do_tl + }{ + \str_if_in:NnTF \l_@@_args_str b { + \exp_args:Nne \use:nn + { + \cs_generate_from_arg_count:NNnn \l_stex_notation_macrocode_cs + \cs_set:Npn \l_@@_arity_str } { { + \_stex_term_math_omb:nnnn { \l_stex_current_symbol_str } + { \_@@_suffix_str } + { \l_@@_opprec_tl } + { \exp_not:n { #4 } } + }} + }{ + \str_if_in:NnTF \l_@@_args_str B { + \exp_args:Nne \use:nn + { + \cs_generate_from_arg_count:NNnn \l_stex_notation_macrocode_cs + \cs_set:Npn \l_@@_arity_str } { { + \_stex_term_math_omb:nnnn { \l_stex_current_symbol_str } + { \_@@_suffix_str } + { \l_@@_opprec_tl } + { \exp_not:n { #4 } } + } } + }{ + \exp_args:Nne \use:nn + { + \cs_generate_from_arg_count:NNnn \l_stex_notation_macrocode_cs + \cs_set:Npn \l_@@_arity_str } { { + \_stex_term_math_oma:nnnn { \l_stex_current_symbol_str } + { \_@@_suffix_str } + { \l_@@_opprec_tl } + { \exp_not:n { #4 } } + } } + } + } + + \str_set_eq:NN \l_@@_remaining_args_str \l_@@_args_str + \int_zero:N \l_@@_currarg_int + \seq_set_eq:NN \l_@@_remaining_precs_seq \l_@@_precedences_seq + \_@@_arguments: + } +} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\_@@_arguments:} +% +% Takes care of annotating the arguments in a +% notation macro +% +% \begin{macrocode} +\cs_new_protected:Nn \_@@_arguments: { + \int_incr:N \l_@@_currarg_int + \str_if_empty:NTF \l_@@_remaining_args_str { + \l_stex_notation_after_do_tl + }{ + \str_set:Nx \l_tmpa_str { \str_head:N \l_@@_remaining_args_str } + \str_set:Nx \l_@@_remaining_args_str { \str_tail:N \l_@@_remaining_args_str } + \str_if_eq:VnTF \l_tmpa_str a { + \_@@_argument_assoc:n + }{ + \str_if_eq:VnTF \l_tmpa_str B { + \_@@_argument_assoc:n + }{ + \seq_pop_left:NN \l_@@_remaining_precs_seq \l_tmpa_str + \tl_put_right:Nx \l_stex_notation_dummyargs_tl { + { \_stex_term_math_arg:nnn + { \int_use:N \l_@@_currarg_int } + { \l_tmpa_str } + { ####\int_use:N \l_@@_currarg_int } + } + } + \_@@_arguments: + } + } + } +} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\_@@_argument_assoc:n} +% \begin{macrocode} +\cs_new_protected:Nn \_@@_argument_assoc:n { + + \cs_generate_from_arg_count:NNnn \l_tmpa_cs \cs_set:Npn + {\l_@@_arity_str}{ + #1 + } + \int_zero:N \l_tmpa_int + \tl_clear:N \l_tmpa_tl + \str_map_inline:Nn \l_@@_args_str { + \int_incr:N \l_tmpa_int + \tl_put_right:Nx \l_tmpa_tl { + \str_if_eq:nnTF {##1}{a}{ {} }{ + \str_if_eq:nnTF {##1}{B}{ {} }{ + {\_stex_term_arg:nn{\int_use:N \l_tmpa_int}{################ \int_use:N \l_tmpa_int}} + } + } + } + } + \exp_after:wN\exp_after:wN\exp_after:wN \def + \exp_after:wN\exp_after:wN\exp_after:wN \l_tmpa_cs + \exp_after:wN\exp_after:wN\exp_after:wN ## + \exp_after:wN\exp_after:wN\exp_after:wN 1 + \exp_after:wN\exp_after:wN\exp_after:wN ## + \exp_after:wN\exp_after:wN\exp_after:wN 2 + \exp_after:wN\exp_after:wN\exp_after:wN { + \exp_after:wN \exp_after:wN \exp_after:wN + \exp_not:n \exp_after:wN \exp_after:wN \exp_after:wN { + \exp_after:wN \l_tmpa_cs \l_tmpa_tl + } + } + + \seq_pop_left:NN \l_@@_remaining_precs_seq \l_tmpa_str + \tl_put_right:Nx \l_stex_notation_dummyargs_tl { { + \_stex_term_math_assoc_arg:nnnn + { \int_use:N \l_@@_currarg_int } + { \l_tmpa_str } + { ####\int_use:N \l_@@_currarg_int } + { \l_tmpa_cs {####1} {####2} } + } } + \_@@_arguments: +} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\_@@_final:} +% +% Called after processing all notation arguments +% +% \begin{macrocode} +\cs_new_protected:Nn \_@@_final: { + \exp_args:Nne \use:nn + { + \cs_generate_from_arg_count:cNnn { + stex_notation_ \l_stex_get_symbol_uri_str \c_hash_str + \_@@_suffix_str + _cs + } + \cs_set:Npn \l_@@_arity_str } { { + \exp_after:wN \exp_after:wN \exp_after:wN + \exp_not:n \exp_after:wN \exp_after:wN \exp_after:wN + { \exp_after:wN \l_stex_notation_macrocode_cs \l_stex_notation_dummyargs_tl \stex_symbol_after_invocation_tl} + } } + + \tl_if_empty:NF \l_@@_op_tl { + \cs_set:cpx { + stex_op_notation_ \l_stex_get_symbol_uri_str \c_hash_str + \_@@_suffix_str + _cs + } { + \_stex_term_oms:nnn { + \l_stex_get_symbol_uri_str \c_hash_str \_@@_suffix_str + }{ + \l_stex_get_symbol_uri_str + }{ \comp{ \exp_args:No \exp_not:n { \l_@@_op_tl } } } + } + } + + \exp_args:Ne + \stex_add_to_current_module:n { + \cs_generate_from_arg_count:cNnn { + stex_notation_ \l_stex_get_symbol_uri_str \c_hash_str + \_@@_suffix_str + _cs + } \cs_set:Npn {\l_@@_arity_str} { + \exp_after:wN \exp_after:wN \exp_after:wN + \exp_not:n \exp_after:wN \exp_after:wN \exp_after:wN + { \exp_after:wN \l_stex_notation_macrocode_cs \l_stex_notation_dummyargs_tl \stex_symbol_after_invocation_tl} + } + \tl_if_empty:NF \l_@@_op_tl { + \cs_set:cpn { + stex_op_notation_\l_stex_get_symbol_uri_str \c_hash_str + \_@@_suffix_str + _cs + } { + \_stex_term_oms:nnn { + \l_stex_get_symbol_uri_str\c_hash_str \_@@_suffix_str + }{ + \l_stex_get_symbol_uri_str + }{ \comp{ \exp_args:No \exp_not:n { \l_@@_op_tl } } } + } + } + } + %\exp_args:Nx + % \stex_do_up_to_module:n { + \seq_put_right:cx { + l_stex_symdecl_ \l_stex_get_symbol_uri_str + _notations + } { + \_@@_suffix_str + } + % } + + \stex_debug:nn{symbols}{ + Notation~\_@@_suffix_str + ~for~\l_stex_get_symbol_uri_str^^J + Operator~precedence:~\l_@@_opprec_tl^^J + Argument~precedences:~ + \seq_use:Nn \l_@@_precedences_seq {,~}^^J + Notation: \cs_meaning:c { + stex_notation_ \l_stex_get_symbol_uri_str \c_hash_str + \_@@_suffix_str + _cs + } + } + + \exp_args:Ne + \stex_add_to_current_module:n { + \seq_put_right:cn { + l_stex_symdecl_\l_stex_get_symbol_uri_str + _notations + } { \_@@_suffix_str } + } + + \stex_if_smsmode:F { + + % HTML annotations + \stex_if_do_html:T { + \stex_annotate_invisible:nnn { notation } + { \l_stex_get_symbol_uri_str } { + \stex_annotate_invisible:nnn { notationfragment } + { \_@@_suffix_str }{} + \stex_annotate_invisible:nnn { precedence } + { \l_@@_prec_str }{} + + \int_zero:N \l_tmpa_int + \str_set_eq:NN \l_@@_remaining_args_str \l_@@_args_str + \tl_clear:N \l_tmpa_tl + \int_step_inline:nn { \l_@@_arity_str }{ + \int_incr:N \l_tmpa_int + \str_set:Nx \l_tmpb_str { \str_head:N \l_@@_remaining_args_str } + \str_set:Nx \l_@@_remaining_args_str { \str_tail:N \l_@@_remaining_args_str } + \str_if_eq:VnTF \l_tmpb_str a { + \tl_set:Nx \l_tmpa_tl { \l_tmpa_tl { + \c_hash_str \c_hash_str \int_use:N \l_tmpa_int a , + \c_hash_str \c_hash_str \int_use:N \l_tmpa_int b + } } + }{ + \str_if_eq:VnTF \l_tmpb_str B { + \tl_set:Nx \l_tmpa_tl { \l_tmpa_tl { + \c_hash_str \c_hash_str \int_use:N \l_tmpa_int a , + \c_hash_str \c_hash_str \int_use:N \l_tmpa_int b + } } + }{ + \tl_set:Nx \l_tmpa_tl { \l_tmpa_tl { + \c_hash_str \c_hash_str \int_use:N \l_tmpa_int + } } + } + } + } + \stex_annotate_invisible:nnn { notationcomp }{}{ + \str_set:Nx \l_stex_current_symbol_str {\l_stex_get_symbol_uri_str } + $ \exp_args:Nno \use:nn { \use:c { + stex_notation_ \l_stex_current_symbol_str + \c_hash_str \_@@_suffix_str _cs + } } { \l_tmpa_tl } $ + } + } + } + } +} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\setnotation} +% \begin{macrocode} +\keys_define:nn { stex / setnotation } { + lang .tl_set_x:N = \l_@@_lang_str , + variant .tl_set_x:N = \l_@@_variant_str , + unknown .code:n = \str_set:Nx + \l_@@_variant_str \l_keys_key_str +} + +\cs_new_protected:Nn \_stex_setnotation_args:n { + \str_clear:N \l_@@_lang_str + \str_clear:N \l_@@_variant_str + \keys_set:nn { stex / setnotation } { #1 } +} + +\cs_new_protected:Nn \stex_setnotation:n { + \exp_args:Nnx \seq_if_in:cnTF { l_stex_symdecl_#1 _notations } + { \l_@@_variant_str \c_hash_str \l_@@_lang_str }{ + \exp_args:Nnx \seq_remove_all:cn { l_stex_symdecl_#1 _notations } + { \l_@@_variant_str \c_hash_str \l_@@_lang_str } + \exp_args:Nnx \seq_remove_all:cn { l_stex_symdecl_#1 _notations } + { \c_hash_str } + \exp_args:Nnx \seq_put_left:cn { l_stex_symdecl_#1 _notations } + { \l_@@_variant_str \c_hash_str \l_@@_lang_str } + \exp_args:Nx \stex_add_to_current_module:n { + \exp_args:Nnx \seq_remove_all:cn { l_stex_symdecl_#1 _notations } + { \l_@@_variant_str \c_hash_str \l_@@_lang_str } + \exp_args:Nnx \seq_put_left:cn { l_stex_symdecl_#1 _notations } + { \l_@@_variant_str \c_hash_str \l_@@_lang_str } + \exp_args:Nnx \seq_remove_all:cn { l_stex_symdecl_#1 _notations } + { \c_hash_str } + } + \stex_debug:nn {notations}{ + Setting~default~notation~ + {\l_@@_variant_str \c_hash_str \l_@@_lang_str}~for~ + #1 \\ + \expandafter\meaning\csname + l_stex_symdecl_#1 _notations\endcsname + } + }{ + % todo throw error + } +} + +\NewDocumentCommand \setnotation {m m} { + \stex_get_symbol:n { #1 } + \_stex_setnotation_args:n { #2 } + \stex_setnotation:n{\l_stex_get_symbol_uri_str} + \stex_smsmode_do: +} + +\cs_new_protected:Nn \stex_copy_notations:nn { + \stex_debug:nn {notations}{ + Copying~notations~from~#2~to~#1\\ + \seq_use:cn{l_stex_symdecl_#2_notations}{,~} + } + \tl_clear:N \l_tmpa_tl + \int_step_inline:nn { \prop_item:cn {l_stex_symdecl_#2_prop}{ arity } } { + \tl_put_right:Nn \l_tmpa_tl { {## ##1} } + } + \seq_map_inline:cn {l_stex_symdecl_#2_notations}{ + \cs_set_eq:Nc \l_tmpa_cs { stex_notation_ #2 \c_hash_str ##1 _cs } + \edef \l_tmpa_tl { + \exp_after:wN\exp_after:wN\exp_after:wN \exp_not:n + \exp_after:wN\exp_after:wN\exp_after:wN { + \exp_after:wN \l_tmpa_cs \l_tmpa_tl + } + } + \exp_args:Nx + \stex_do_up_to_module:n { + \seq_put_right:cn{l_stex_symdecl_#1_notations}{##1} + \cs_generate_from_arg_count:cNnn { + stex_notation_ #1 \c_hash_str ##1 _cs + } \cs_set:Npn { \prop_item:cn {l_stex_symdecl_#2_prop}{ arity } }{ + \exp_after:wN\exp_not:n\exp_after:wN{\l_tmpa_tl} + } + } + } +} + +\NewDocumentCommand \copynotation {m m} { + \stex_get_symbol:n { #1 } + \str_set_eq:NN \l_tmpa_str \l_stex_get_symbol_uri_str + \stex_get_symbol:n { #2 } + \exp_args:Noo + \stex_copy_notations:nn \l_tmpa_str \l_stex_get_symbol_uri_str + \exp_args:Nx \stex_add_import_to_current_module:n{ + \stex_copy_notations:nn {\l_tmpa_str} {\l_stex_get_symbol_uri_str} + } + \stex_smsmode_do: +} + +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\symdef} +% \begin{macrocode} +\keys_define:nn { stex / symdef } { + name .str_set_x:N = \l_stex_symdecl_name_str , + local .bool_set:N = \l_stex_symdecl_local_bool , + args .str_set_x:N = \l_stex_symdecl_args_str , + type .tl_set:N = \l_stex_symdecl_type_tl , + def .tl_set:N = \l_stex_symdecl_definiens_tl , + op .tl_set:N = \l_@@_op_tl , + lang .str_set_x:N = \l_@@_lang_str , + variant .str_set_x:N = \l_@@_variant_str , + prec .str_set_x:N = \l_@@_prec_str , + assoc .choices:nn = + {bin,binl,binr,pre,conj,pwconj} + {\str_set:Nx \l_stex_symdecl_assoctype_str {\l_keys_choice_tl}}, + unknown .code:n = \str_set:Nx + \l_@@_variant_str \l_keys_key_str +} + +\cs_new_protected:Nn \_@@_symdef_args:n { + \str_clear:N \l_stex_symdecl_name_str + \str_clear:N \l_stex_symdecl_args_str + \str_clear:N \l_stex_symdecl_assoctype_str + \bool_set_false:N \l_stex_symdecl_local_bool + \tl_clear:N \l_stex_symdecl_type_tl + \tl_clear:N \l_stex_symdecl_definiens_tl + \str_clear:N \l_@@_lang_str + \str_clear:N \l_@@_variant_str + \str_clear:N \l_@@_prec_str + \tl_clear:N \l_@@_op_tl + + \keys_set:nn { stex / symdef } { #1 } +} + +\NewDocumentCommand \symdef { m O{} } { + \_@@_symdef_args:n { #2 } + \bool_set_true:N \l_stex_symdecl_make_macro_bool + \stex_symdecl_do:n { #1 } + \tl_set:Nn \l_stex_notation_after_do_tl { + \_@@_final: + \stex_smsmode_do: + } + \str_set:Nx \l_stex_get_symbol_uri_str { + \l_stex_current_module_str ? \l_stex_symdecl_name_str + } + \exp_args:Nx \stex_notation_do:nnnn + { \prop_item:cn {l_stex_symdecl_\l_stex_get_symbol_uri_str _prop } { args } } + { \prop_item:cn { l_stex_symdecl_\l_stex_get_symbol_uri_str _prop } { arity } } + { \l_@@_variant_str \c_hash_str \l_@@_lang_str } +} +\stex_deactivate_macro:Nn \symdef {module~environments} +% \end{macrocode} +% \end{macro} +% +% \subsection{Variables} +% +% \begin{macrocode} +%<@@=stex_variables> + +\keys_define:nn { stex / vardef } { + name .str_set_x:N = \l_@@_name_str , + args .str_set_x:N = \l_@@_args_str , + type .tl_set:N = \l_@@_type_tl , + def .tl_set:N = \l_@@_def_tl , + op .tl_set:N = \l_@@_op_tl , + prec .str_set_x:N = \l_@@_prec_str , + assoc .choices:nn = + {bin,binl,binr,pre,conj,pwconj} + {\str_set:Nx \l_@@_assoctype_str {\l_keys_choice_tl}}, + bind .choices:nn = + {forall,exists} + {\str_set:Nx \l_@@_bind_str {\l_keys_choice_tl}} +} + +\cs_new_protected:Nn \_@@_args:n { + \str_clear:N \l_@@_name_str + \str_clear:N \l_@@_args_str + \str_clear:N \l_@@_prec_str + \str_clear:N \l_@@_assoctype_str + \str_clear:N \l_@@_bind_str + \tl_clear:N \l_@@_type_tl + \tl_clear:N \l_@@_def_tl + \tl_clear:N \l_@@_op_tl + + \keys_set:nn { stex / vardef } { #1 } +} + +\NewDocumentCommand \_@@_do_simple:nnn { m O{}} { + \_@@_args:n {#2} + \str_if_empty:NT \l_@@_name_str { + \str_set:Nx \l_@@_name_str { #1 } + } + \prop_clear:N \l_tmpa_prop + \prop_put:Nno \l_tmpa_prop { name } \l_@@_name_str + + \int_zero:N \l_tmpb_int + \bool_set_true:N \l_tmpa_bool + \str_map_inline:Nn \l_@@_args_str { + \token_case_meaning:NnF ##1 { + 0 {} 1 {} 2 {} 3 {} 4 {} 5 {} 6 {} 7 {} 8 {} 9 {} + {\tl_to_str:n i} { \bool_set_false:N \l_tmpa_bool } + {\tl_to_str:n b} { \bool_set_false:N \l_tmpa_bool } + {\tl_to_str:n a} { + \bool_set_false:N \l_tmpa_bool + \int_incr:N \l_tmpb_int + } + {\tl_to_str:n B} { + \bool_set_false:N \l_tmpa_bool + \int_incr:N \l_tmpb_int + } + }{ + \msg_error:nnxx{stex}{error/wrongargs}{ + variable~\l_@@_name_str + }{##1} + } + } + \bool_if:NTF \l_tmpa_bool { + % possibly numeric + \str_if_empty:NTF \l_@@_args_str { + \prop_put:Nnn \l_tmpa_prop { args } {} + \prop_put:Nnn \l_tmpa_prop { arity } { 0 } + }{ + \int_set:Nn \l_tmpa_int { \l_@@_args_str } + \prop_put:Nnx \l_tmpa_prop { arity } { \int_use:N \l_tmpa_int } + \str_clear:N \l_tmpa_str + \int_step_inline:nn \l_tmpa_int { + \str_put_right:Nn \l_tmpa_str i + } + \str_set_eq:NN \l_@@_args_str \l_tmpa_str + \prop_put:Nnx \l_tmpa_prop { args } { \l_@@_args_str } + } + } { + \prop_put:Nnx \l_tmpa_prop { args } { \l_@@_args_str } + \prop_put:Nnx \l_tmpa_prop { arity } + { \str_count:N \l_@@_args_str } + } + \prop_put:Nnx \l_tmpa_prop { assocs } { \int_use:N \l_tmpb_int } + \tl_set:cx { #1 }{ \stex_invoke_variable:n { \l_@@_name_str } } + + \prop_set_eq:cN { l_stex_variable_\l_@@_name_str _prop} \l_tmpa_prop + + \tl_if_empty:NF \l_@@_op_tl { + \cs_set:cpx { + stex_var_op_notation_ \l_@@_name_str _cs + } { + \_stex_term_omv:nn { + var://\l_@@_name_str + }{ \comp{ \exp_args:No \exp_not:n { \l_@@_op_tl } } } + } + } + + \tl_set:Nn \l_stex_notation_after_do_tl { + \exp_args:Nne \use:nn { + \cs_generate_from_arg_count:cNnn { stex_var_notation_\l_@@_name_str _cs } + \cs_set:Npn { \prop_item:Nn \l_tmpa_prop { arity } } + } {{ + \exp_after:wN \exp_after:wN \exp_after:wN + \exp_not:n \exp_after:wN \exp_after:wN \exp_after:wN + { \exp_after:wN \l_stex_notation_macrocode_cs \l_stex_notation_dummyargs_tl \stex_symbol_after_invocation_tl} + }} + \stex_if_do_html:T { + \stex_annotate_invisible:nnn {vardecl}{\l_@@_name_str}{ + \stex_annotate_invisible:nnn { precedence } + { \l_@@_prec_str }{} + \tl_if_empty:NF \l_@@_type_tl {\stex_annotate_invisible:nnn{type}{}{$\l_@@_type_tl$}} + \stex_annotate_invisible:nnn{args}{}{ \l_@@_args_str } + \stex_annotate_invisible:nnn{macroname}{#1}{} + \tl_if_empty:NF \l_@@_def_tl { + \stex_annotate_invisible:nnn{definiens}{} + {$\l_@@_def_tl$} + } + \str_if_empty:NF \l_@@_assoctype_str { + \stex_annotate_invisible:nnn{assoctype}{\l_@@_assoctype_str}{} + } + \int_zero:N \l_tmpa_int + \str_set_eq:NN \l_@@_remaining_args_str \l_@@_args_str + \tl_clear:N \l_tmpa_tl + \int_step_inline:nn { \prop_item:Nn \l_tmpa_prop { arity } }{ + \int_incr:N \l_tmpa_int + \str_set:Nx \l_tmpb_str { \str_head:N \l_@@_remaining_args_str } + \str_set:Nx \l_@@_remaining_args_str { \str_tail:N \l_@@_remaining_args_str } + \str_if_eq:VnTF \l_tmpb_str a { + \tl_set:Nx \l_tmpa_tl { \l_tmpa_tl { + \c_hash_str \c_hash_str \int_use:N \l_tmpa_int a , + \c_hash_str \c_hash_str \int_use:N \l_tmpa_int b + } } + }{ + \str_if_eq:VnTF \l_tmpb_str B { + \tl_set:Nx \l_tmpa_tl { \l_tmpa_tl { + \c_hash_str \c_hash_str \int_use:N \l_tmpa_int a , + \c_hash_str \c_hash_str \int_use:N \l_tmpa_int b + } } + }{ + \tl_set:Nx \l_tmpa_tl { \l_tmpa_tl { + \c_hash_str \c_hash_str \int_use:N \l_tmpa_int + } } + } + } + } + \stex_annotate_invisible:nnn { notationcomp }{}{ + \str_set:Nx \l_stex_current_symbol_str {var://\l_@@_name_str } + $ \exp_args:Nno \use:nn { \use:c { + stex_var_notation_\l_@@_name_str _cs + } } { \l_tmpa_tl } $ + } + } + } + } + + \stex_notation_do:nnnn { \l_@@_args_str } { \prop_item:Nn \l_tmpa_prop { arity } } {} +} + +\cs_new:Nn \_@@_reset:N { + \tl_if_exist:NTF #1 { + \def \exp_not:N #1 { \exp_args:No \exp_not:n #1 } + }{ + \let \exp_not:N #1 \exp_not:N \undefined + } +} + +\NewDocumentCommand \_@@_do_complex:nn { m m }{ + \clist_set:Nx \l_@@_names { \tl_to_str:n {#1} } + \exp_args:Nnx \use:nn { + % TODO + \stex_annotate_invisible:nnn {vardecls}{\clist_use:Nn\l_@@_names,}{ + #2 + } + }{ + \_@@_reset:N \varnot + \_@@_reset:N \vartype + \_@@_reset:N \vardefi + } +} + +\NewDocumentCommand \vardef { s } { + \IfBooleanTF#1 { + \_@@_do_complex:nn + }{ + \_@@_do_simple:nnn + } +} + +\NewDocumentCommand \svar { O{} m }{ + \tl_if_empty:nTF {#1}{ + \str_set:Nn \l_tmpa_str { #2 } + }{ + \str_set:Nn \l_tmpa_str { #1 } + } + \_stex_term_omv:nn { + var://\l_tmpa_str + }{ \comp{ #2 } } +} + +% \end{macrocode} +% +% \begin{macrocode} +%</package> +% \end{macrocode} +% +% \end{implementation} +% +% \PrintIndex + +% \endinput +% Local Variables: +% mode: doctex +% TeX-master: t +% End: diff --git a/macros/latex/contrib/stex/source/stex/terms.dtx b/macros/latex/contrib/stex/source/stex/terms.dtx new file mode 100644 index 0000000000..94a71d0208 --- /dev/null +++ b/macros/latex/contrib/stex/source/stex/terms.dtx @@ -0,0 +1,1037 @@ +% \iffalse meta-comment +% An Infrastructure for Semantic Macros and Module Scoping +% Copyright (c) 2019 Michael Kohlhase, all rights reserved +% this file is released under the +% LaTeX Project Public License (LPPL) +% +% The original of this file is in the public repository at +% http://github.com/sLaTeX/sTeX/ +% +% TODO update copyright +% +%<*driver> +\providecommand\bibfolder{../../lib/bib} +\input{../../doc/docheader} + +\begin{document} + \DocInput{\jobname.dtx} +\end{document} +%</driver> +% \fi +% +% \title{ \sTeX-Terms +% \thanks{Version {\fileversion} (last revised {\filedate})} +% } +% +% \author{Michael Kohlhase, Dennis Müller\\ +% FAU Erlangen-Nürnberg\\ +% \url{http://kwarc.info/} +% } +% +% \maketitle +% +%\ifinfulldoc\else +% This is the documentation for the \pkg{stex-terms} package. +% For a more high-level introduction, +% see \href{\basedocurl/manual.pdf}{the \sTeX Manual} or the +% \href{\basedocurl/stex.pdf}{full \sTeX documentation}. +% +% \input{../../doc/packages/terms} +% \fi +% +% \begin{documentation}\label{pkg:terms:doc} +% +% Code related to symbolic expressions, typesetting notations, +% notation components, etc. +% +% \section{Macros and Environments}\label{pkg:terms:doc:macros} +% +% \begin{function}{\STEXsymbol} +% Uses \cs{stex_get_symbol:n} to find the symbol denoted by +% the first argument and passes the result on to +% \cs{stex_invoke_symbol:n} +% \end{function} +% +% \begin{function}{\symref} +% \begin{syntax} \cs{symref}\Arg{symbol}\Arg{text} \end{syntax} +% shortcut for \cs{STEXsymbol}\Arg{symbol}|![|\meta{text}|]| +% \end{function} +% +% \begin{function}{\stex_invoke_symbol:n} +% Executes a semantic macro. Outside of math mode or if followed by |*|, +% it continues to \cs{stex_term_custom:nn}. In math mode, +% it uses the default or optionally provided notation of +% the associated symbol. +% +% If followed by |!|, it will invoke the symbol \emph{itself} +% rather than its application (and continue to +% \cs{stex_term_custom:nn}), i.e. it allows to refer to +% |\plus![addition]| as an operation, rather than +% |\plus[addition of]{some}{terms}|. +% \end{function} +% +% \begin{function}{\_stex_term_math_oms:nnnn,\_stex_term_math_oma:nnnn,\_stex_term_math_omb:nnnn} +% \begin{syntax} \meta{URI}\meta{fragment}\meta{precedence}\meta{body} \end{syntax} +% +% Annotates \meta{body} as an \omdoc-term (|OMID|, |OMA| or |OMBIND|, respectively) +% with head symbol \meta{URI}, generated +% by the specific notation \meta{fragment} with (upwards) operator precedence +% \meta{precedence}. Inserts parentheses according to +% the current downwards precedence and operator precedence. +% \end{function} +% +% \begin{function}{\_stex_term_math_arg:nnn} +% \begin{syntax} \cs{stex_term_arg:nnn}\meta{int}\meta{prec}\meta{body} \end{syntax} +% Annotates \meta{body} as the \meta{int}th argument of the current |OMA| or |OMBIND|, +% with (downwards) argument precedence \meta{prec}. +% \end{function} +% +% \begin{function}{\_stex_term_math_assoc_arg:nnnn} +% \begin{syntax} \cs{stex_term_arg:nnn}\meta{int}\meta{prec}\meta{notation}\meta{body} \end{syntax} +% Annotates \meta{body} as the \meta{int}th (associative) \emph{sequence} argument +% (as comma-separated list of terms) of the current |OMA| or |OMBIND|, +% with (downwards) argument precedence \meta{prec} and associative +% notation \meta{notation}. +% +% \end{function} +% +% \begin{variable}{\infprec, \neginfprec} +% Maximal and minimal notation precedences. +% \end{variable} +% +% \begin{function}{\dobrackets} +% \begin{syntax} \cs{dobrackets} \Arg{body} \end{syntax} +% Puts \meta{body} in parentheses; scaled if in display mode +% unscaled otherwise. Uses the current \sTeX brackets (by default |(| and |)|), +% which can be changed temporarily using \cs{withbrackets}. +% \end{function} +% +% \begin{function}{\withbrackets} +% \begin{syntax} \cs{withbrackets} \meta{left} \meta{right} \Arg{body} \end{syntax} +% Temporarily (i.e. within \meta{body}) sets the brackets used by \sTeX for automated +% bracketing (by default |(| and |)|) to \meta{left} and \meta{right}. +% +% Note that \meta{left} and \meta{right} need to be allowed +% after \cs{left} and \cs{right} in displaymode. +% \end{function} +% +% \begin{function}{\stex_term_custom:nn} +% \begin{syntax} \cs{stex_term_custom:nn}\Arg{URI}\Arg{args}\end{syntax} +% Implements custom one-time notation. +% Invoked by \cs{stex_invoke_symbol:n} in text mode, or if +% followed by |*| in math mode, or whenever followed by |!|. +% \end{function} +% +% \begin{function}{\stex_highlight_term:nn} +% \begin{syntax} \cs{stex_highlight_term:nn}\Arg{URI}\Arg{args}\end{syntax} +% Establishes a context for \cs{comp}. Stores the URI in a variable +% so that \cs{comp} knows which symbol governs the current notation. +% \end{function} +% +% \begin{function}{\comp, \compemph,\compemph@uri, \defemph, \defemph@uri, \symrefemph,\symrefemph@uri} +% \begin{syntax} \cs{comp}\Arg{args}\end{syntax} +% Marks \meta{args} as a notation component of the current symbol for +% highlighting, linking, etc. +% +% The precise behavior is governed by \cs{@comp}, which takes as +% additional argument the URI of the current symbol. By default, +% \cs{@comp} adds the URI as a PDF tooltip and colors the highlighted part +% in blue. +% +% \cs{@defemph} behaves like \cs{@comp}, and can be similarly redefined, +% but marks an expression as \emph{definiendum} (used by \cs{definiendum}) +% \end{function} +% +% \begin{function}{\STEXinvisible} +% Exports its argument as \omdoc (invisible), but does +% not produce PDF output. Useful e.g. for semantic macros +% that take arguments that are not part of the symbolic +% notation. +% \end{function} +% +% \begin{function}{\ellipses} +% TODO +% \end{function} +% +% \end{documentation} +% +% \begin{implementation}\label{pkg:terms:impl} +% +% \section{\sTeX-Terms Implementation} +% +% \begin{macrocode} +%<*package> + +%%%%%%%%%%%%% terms.dtx %%%%%%%%%%%%% + +%<@@=stex_terms> +% \end{macrocode} +% +% Warnings and error messages +% +% \begin{macrocode} +\msg_new:nnn{stex}{error/nonotation}{ + Symbol~#1~invoked,~but~has~no~notation#2! +} +\msg_new:nnn{stex}{error/notationarg}{ + Error~in~parsing~notation~#1 +} +\msg_new:nnn{stex}{error/noop}{ + Symbol~#1~has~no~operator~notation~for~notation~#2 +} +\msg_new:nnn{stex}{error/notallowed}{ + Symbol~invocation~#1~not~allowed~in~notation~component~of~#2 +} + +% \end{macrocode} +% \subsection{Symbol Invocations} +% +% +% \begin{macro}{\stex_invoke_symbol:n} +% +% Invokes a semantic macro +% +% \begin{macrocode} +\keys_define:nn { stex / terms } { + lang .tl_set_x:N = \l_@@_lang_str , + variant .tl_set_x:N = \l_@@_variant_str , + unknown .code:n = \str_set:Nx + \l_@@_variant_str \l_keys_key_str +} + +\cs_new_protected:Nn \_@@_args:n { + \str_clear:N \l_@@_lang_str + \str_clear:N \l_@@_variant_str + + \keys_set:nn { stex / terms } { #1 } +} + +\cs_new:Nn \_@@_reset:N { + \tl_if_exist:NTF #1 { + \def \exp_not:N #1 { \exp_args:No \exp_not:n #1 } + }{ + \let \exp_not:N #1 \exp_not:N \undefined + } +} + +\bool_new:N \l_@@_allow_semantic_bool +\bool_set_true:N \l_@@_allow_semantic_bool + +\cs_new_protected:Nn \stex_invoke_symbol:n { + \bool_if:NTF \l_@@_allow_semantic_bool { + \str_if_eq:eeF { + \prop_item:cn { + l_stex_symdecl_#1_prop + }{ deprecate } + }{}{ + \msg_warning:nnxx{stex}{warning/deprecated}{ + Symbol~#1 + }{ + \prop_item:cn {l_stex_symdecl_#1_prop}{ deprecate } + } + } + \if_mode_math: + \exp_after:wN \_@@_invoke_math:n + \else: + \exp_after:wN \_@@_invoke_text:n + \fi: { #1 } + }{ + \msg_error:nnxx{stex}{error/notallowed}{#1}{\l_stex_current_symbol_str} + } +} + +\cs_new_protected:Nn \_@@_invoke_text:n { + \peek_charcode_remove:NTF ! { + \_@@_invoke_op_custom:nn {#1} + }{ + \_@@_invoke_custom:nn {#1} + } +} + +\cs_new_protected:Nn \_@@_invoke_math:n { + \peek_charcode_remove:NTF ! { + % operator + \peek_charcode_remove:NTF * { + % custom op + \_@@_invoke_op_custom:nn {#1} + }{ + % op notation + \peek_charcode:NTF [ { + \_@@_invoke_op_notation:nw {#1} + }{ + \_@@_invoke_op_notation:nw {#1}[] + } + } + }{ + \peek_charcode_remove:NTF * { + \_@@_invoke_custom:nn {#1} + % custom + }{ + % normal + \peek_charcode:NTF [ { + \_@@_invoke_notation:nw {#1} + }{ + \_@@_invoke_notation:nw {#1}[] + } + } + } +} + + +\cs_new_protected:Nn \_@@_invoke_op_custom:nn { + \exp_args:Nnx \use:nn { + \str_set:Nn \l_stex_current_symbol_str { #1 } + \bool_set_false:N \l_@@_allow_semantic_bool + \_stex_term_oms:nnn {#1 \c_hash_str\c_hash_str}{#1}{ + \comp{ #2 } + } + }{ + \_@@_reset:N \l_stex_current_symbol_str + \bool_set_true:N \l_@@_allow_semantic_bool + } +} + +\cs_new_protected:Nn \_@@_find_notation:nn { + \str_set:Nn \l_stex_current_symbol_str { #1 } + \_@@_args:n { #2 } + \seq_if_empty:cTF { + l_stex_symdecl_ #1 _notations + } { + \msg_error:nnxx{stex}{error/nonotation}{#1}{s} + } { + \bool_lazy_all:nTF { + {\str_if_empty_p:N \l_@@_variant_str} + {\str_if_empty_p:N \l_@@_lang_str} + }{ + \seq_get_left:cN {l_stex_symdecl_#1_notations}\l_@@_variant_str + }{ + \seq_if_in:cxTF {l_stex_symdecl_#1_notations}{ + \l_@@_variant_str \c_hash_str \l_@@_lang_str + }{ + \str_set:Nx \l_@@_variant_str { \l_@@_variant_str \c_hash_str \l_@@_lang_str } + }{ + \msg_error:nnxx{stex}{error/nonotation}{#1}{ + ~\l_@@_variant_str \c_hash_str \l_@@_lang_str + } + } + } + } +} + +\cs_new_protected:Npn \_@@_invoke_op_notation:nw #1 [#2] { + \_@@_find_notation:nn { #1 }{ #2 } + \bool_set_false:N \l_@@_allow_semantic_bool + \cs_if_exist:cTF { + stex_op_notation_ #1 \c_hash_str \l_@@_variant_str _cs + }{ + \use:c{stex_op_notation_ #1 \c_hash_str \l_@@_variant_str _cs} + }{ + \msg_error:nnxx{stex}{error/noop}{#1}{\l_@@_variant_str} + } + \bool_set_true:N \l_@@_allow_semantic_bool +} + +\cs_new_protected:Npn \_@@_invoke_notation:nw #1 [#2] { + \_@@_find_notation:nn { #1 }{ #2 } + \cs_if_exist:cTF { + stex_notation_ #1 \c_hash_str \l_@@_variant_str _cs + }{ + \tl_set:Nx \stex_symbol_after_invocation_tl { + \_@@_reset:N \stex_symbol_after_invocation_tl + \_@@_reset:N \l_stex_current_symbol_str + \bool_set_true:N \l_@@_allow_semantic_bool + } + \bool_set_false:N \l_@@_allow_semantic_bool + \use:c{stex_notation_ #1 \c_hash_str \l_@@_variant_str _cs} + }{ + \msg_error:nnxx{stex}{error/nonotation}{#1}{ + ~\l_@@_variant_str + } + } +} + +\prop_new:N \l_@@_custom_args_prop + +\cs_new_protected:Nn \_@@_invoke_custom:nn { + \exp_args:Nnx \use:nn { + \bool_set_false:N \l_@@_allow_semantic_bool + \str_set:Nn \l_stex_current_symbol_str { #1 } + \prop_clear:N \l_@@_custom_args_prop + \prop_put:Nnn \l_@@_custom_args_prop {currnum} {1} + \prop_get:cnN { + l_stex_symdecl_#1 _prop + }{ args } \l_tmpa_str + \prop_put:Nno \l_@@_custom_args_prop {args} \l_tmpa_str + \tl_set:Nn \arg { \_@@_arg: } + \str_if_empty:NTF \l_tmpa_str { + \_stex_term_oms:nnn {#1}{#1}{#2} + }{ + \str_if_in:NnTF \l_tmpa_str b { + \_stex_term_ombind:nnn {#1}{#1}{#2} + }{ + \str_if_in:NnTF \l_tmpa_str B { + \_stex_term_ombind:nnn {#1}{#1}{#2} + }{ + \_stex_term_oma:nnn {#1}{#1}{#2} + } + } + } + % TODO check that all arguments exist + }{ + \_@@_reset:N \l_stex_current_symbol_str + \_@@_reset:N \arg + \_@@_reset:N \l_@@_custom_args_prop + \bool_set_true:N \l_@@_allow_semantic_bool + } +} + +\NewDocumentCommand \_@@_arg: { s O{} m}{ + \tl_if_empty:nTF {#2}{ + \int_set:Nn \l_tmpa_int {\prop_item:Nn \l_@@_custom_args_prop {currnum}} + \bool_set_true:N \l_tmpa_bool + \bool_do_while:Nn \l_tmpa_bool { + \exp_args:NNx \prop_if_in:NnTF \l_@@_custom_args_prop {\int_use:N \l_tmpa_int} { + \int_incr:N \l_tmpa_int + }{ + \bool_set_false:N \l_tmpa_bool + } + } + }{ + \int_set:Nn \l_tmpa_int { #2 } + \exp_args:NNx \prop_if_in:NnT \l_@@_custom_args_prop {\int_use:N \l_tmpa_int} { + % TODO throw error + } + } + \str_set:Nx \l_tmpa_str {\prop_item:Nn \l_@@_custom_args_prop {args} } + \int_compare:nNnT \l_tmpa_int > {\str_count:N \l_tmpa_str} { + % TODO throw error + } + \IfBooleanTF#1{ + \stex_annotate_invisible:n { + \exp_args:No \_stex_term_arg:nn {\l_stex_current_symbol_str}{#3} + } + }{ + \exp_args:No \_stex_term_arg:nn {\l_stex_current_symbol_str}{#3} + } +} + + +\cs_new_protected:Nn \_stex_term_arg:nn { + \exp_args:Nnx \use:nn { + \bool_set_true:N \l_@@_allow_semantic_bool + \stex_annotate:nnn{ arg }{ #1 }{ #2 } + }{ + \bool_set_false:N \l_@@_allow_semantic_bool + } +} + +\cs_new_protected:Nn \_stex_term_math_arg:nnn { + \exp_args:Nnx \use:nn + { \int_set:Nn \l_@@_downprec { #2 } + \_stex_term_arg:nn { #1 }{ #3 } + } + { \int_set:Nn \exp_not:N \l_@@_downprec { \int_use:N \l_@@_downprec } } +} + + +% \end{macrocode} +% \end{macro} +% +% \subsection{Terms} +% +% Precedences: +% \begin{variable}{\infprec, \neginfprec, \l_@@_downprec} +% \begin{macrocode} +\tl_const:Nx \infprec {\int_use:N \c_max_int} +\tl_const:Nx \neginfprec {-\int_use:N \c_max_int} +\int_new:N \l_@@_downprec +\int_set_eq:NN \l_@@_downprec \infprec +% \end{macrocode} +% \end{variable} +% +% Bracketing: +% +% \begin{variable}{\l_@@_left_bracket_str, \l_@@_right_bracket_str} +% \begin{macrocode} +\tl_set:Nn \l_@@_left_bracket_str ( +\tl_set:Nn \l_@@_right_bracket_str ) +% \end{macrocode} +% \end{variable} +% +% \begin{macro}{\_@@_maybe_brackets:nn} +% +% Compares precedences and insert brackets accordingly +% +% \begin{macrocode} +\cs_new_protected:Nn \_@@_maybe_brackets:nn { + \bool_if:NTF \l_@@_brackets_done_bool { + \bool_set_false:N \l_@@_brackets_done_bool + #2 + } { + \int_compare:nNnTF { #1 } > \l_@@_downprec { + \bool_if:NTF \l_stex_inparray_bool { #2 }{ + \stex_debug:nn{dobrackets}{\number#1 > \number\l_@@_downprec; \detokenize{#2}} + \dobrackets { #2 } + } + }{ #2 } + } +} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\dobrackets} +% \begin{macrocode} +\bool_new:N \l_@@_brackets_done_bool +%\RequirePackage{scalerel} +\cs_new_protected:Npn \dobrackets #1 { + %\ThisStyle{\if D\m@switch + % \exp_args:Nnx \use:nn + % { \exp_after:wN \left\l_@@_left_bracket_str #1 } + % { \exp_not:N\right\l_@@_right_bracket_str } + % \else + \exp_args:Nnx \use:nn + { + \bool_set_true:N \l_@@_brackets_done_bool + \int_set:Nn \l_@@_downprec \infprec + \l_@@_left_bracket_str + #1 + } + { + \bool_set_false:N \l_@@_brackets_done_bool + \l_@@_right_bracket_str + \int_set:Nn \l_@@_downprec { \int_use:N \l_@@_downprec } + } + %\fi} +} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\withbrackets} +% \begin{macrocode} +\cs_new_protected:Npn \withbrackets #1 #2 #3 { + \exp_args:Nnx \use:nn + { + \tl_set:Nx \l_@@_left_bracket_str { #1 } + \tl_set:Nx \l_@@_right_bracket_str { #2 } + #3 + } + { + \tl_set:Nn \exp_not:N \l_@@_left_bracket_str + {\l_@@_left_bracket_str} + \tl_set:Nn \exp_not:N \l_@@_right_bracket_str + {\l_@@_right_bracket_str} + } +} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\STEXinvisible} +% \begin{macrocode} +\cs_new_protected:Npn \STEXinvisible #1 { + \stex_annotate_invisible:n { #1 } +} +% \end{macrocode} +% \end{macro} +% +% \omdoc terms: +% +% \begin{macro}{\_stex_term_math_oms:nnnn} +% \begin{macrocode} +\cs_new_protected:Nn \_stex_term_oms:nnn { + \stex_annotate:nnn{ OMID }{ #2 }{ + \stex_highlight_term:nn { #1 } { #3 } + } +} + +\cs_new_protected:Nn \_stex_term_math_oms:nnnn { + \_@@_maybe_brackets:nn { #3 }{ + \_stex_term_oms:nnn { #1 } { #1\c_hash_str#2 } { #4 } + } +} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\_stex_term_math_omv:nn} +% \begin{macrocode} +\cs_new_protected:Nn \_stex_term_omv:nn { + \stex_annotate:nnn{ OMID }{ #1 }{ + \stex_highlight_term:nn { #1 } { #2 } + } +} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\_stex_term_math_oma:nnnn} +% \begin{macrocode} +\cs_new_protected:Nn \_stex_term_oma:nnn { + \stex_annotate:nnn{ OMA }{ #2 }{ + \stex_highlight_term:nn { #1 } { #3 } + } +} + +\cs_new_protected:Nn \_stex_term_math_oma:nnnn { + \_@@_maybe_brackets:nn { #3 }{ + \_stex_term_oma:nnn { #1 } { #1\c_hash_str#2 } { #4 } + } +} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\_stex_term_math_omb:nnnn} +% \begin{macrocode} +\cs_new_protected:Nn \_stex_term_ombind:nnn { + \stex_annotate:nnn{ OMBIND }{ #2 }{ + \stex_highlight_term:nn { #1 } { #3 } + } +} + +\cs_new_protected:Nn \_stex_term_math_omb:nnnn { + \_@@_maybe_brackets:nn { #3 }{ + \_stex_term_ombind:nnn { #1 } { #1\c_hash_str#2 } { #4 } + } +} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\_stex_term_math_assoc_arg:nnnn} +% \begin{macrocode} +\cs_new_protected:Nn \_stex_term_math_assoc_arg:nnnn { + % TODO sequences + \clist_set:Nn \l_tmpa_clist{ #3 } + \int_compare:nNnTF { \clist_count:N \l_tmpa_clist } < 2 { + \tl_set:Nn \l_tmpa_tl { #3 } + }{ + \cs_set:Npn \l_tmpa_cs ##1 ##2 { #4 } + \clist_reverse:N \l_tmpa_clist + \clist_pop:NN \l_tmpa_clist \l_tmpa_tl + + \clist_map_inline:Nn \l_tmpa_clist { + \exp_args:NNNo \exp_args:NNo \tl_set:No \l_tmpa_tl { + \exp_args:Nno + \l_tmpa_cs { ##1 } \l_tmpa_tl + } + } + } + \exp_args:Nnno + \_stex_term_math_arg:nnn{#1}{#2}\l_tmpa_tl +} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\stex_term_custom:nn} +% \begin{macrocode} +\cs_new_protected:Nn \stex_term_custom:nn { + \str_set:Nn \l_@@_custom_uri { #1 } + \str_set:Nn \l_tmpa_str { #2 } + \tl_clear:N \l_tmpa_tl + \int_zero:N \l_tmpa_int + \int_set:Nn \l_tmpb_int { \str_count:N \l_tmpa_str } + \_@@_custom_loop: +} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\_@@_custom_loop:} +% \begin{macrocode} +\cs_new_protected:Nn \_@@_custom_loop: { + \bool_set_false:N \l_tmpa_bool + \bool_while_do:nn { + \str_if_eq_p:ee X { + \str_item:Nn \l_tmpa_str { \l_tmpa_int + 1 } + } + }{ + \int_incr:N \l_tmpa_int + } + + \peek_charcode:NTF [ { + % notation/text component + \_@@_custom_component:w + } { + \int_compare:nNnTF \l_tmpa_int = \l_tmpb_int { + % all arguments read => finish + \_@@_custom_final: + } { + % arguments missing + \peek_charcode_remove:NTF * { + % invisible, specific argument position or both + \peek_charcode:NTF [ { + % visible specific argument position + \_@@_custom_arg:wn + } { + % invisible + \peek_charcode_remove:NTF * { + % invisible specific argument position + \_@@_custom_arg_inv:wn + } { + % invisible next argument + \_@@_custom_arg_inv:wn [ \l_tmpa_int + 1 ] + } + } + } { + % next normal argument + \_@@_custom_arg:wn [ \l_tmpa_int + 1 ] + } + } + } +} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\_@@_custom_arg_inv:wn} +% \begin{macrocode} +\cs_new_protected:Npn \_@@_custom_arg_inv:wn [ #1 ] #2 { + \bool_set_true:N \l_tmpa_bool + \_@@_custom_arg:wn [ #1 ] { #2 } +} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\_@@_custom_arg:wn} +% \begin{macrocode} +\cs_new_protected:Npn \_@@_custom_arg:wn [ #1 ] #2 { + \str_set:Nx \l_tmpb_str { + \str_item:Nn \l_tmpa_str { #1 } + } + \str_case:VnTF \l_tmpb_str { + { X } { + \msg_error:nnx{stex}{error/notationarg}{\l_@@_custom_uri} + } + { i } { \_@@_custom_set_X:n { #1 } } + { b } { \_@@_custom_set_X:n { #1 } } + { a } { \_@@_custom_set_X:n { #1 } } % TODO ? + { B } { \_@@_custom_set_X:n { #1 } } % TODO ? + }{}{ + \msg_error:nnx{stex}{error/notationarg}{\l_@@_custom_uri} + } + + \bool_if:nTF \l_tmpa_bool { + \tl_put_right:Nx \l_tmpa_tl { + \stex_annotate_invisible:n { + \_stex_term_arg:nn { \int_eval:n { #1 } } + \exp_not:n { { #2 } } + } + } + } { + \tl_put_right:Nx \l_tmpa_tl { + \_stex_term_arg:nn { \int_eval:n { #1 } } + \exp_not:n { { #2 } } + } + } + + \_@@_custom_loop: +} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\_@@_custom_set_X:n} +% \begin{macrocode} +\cs_new_protected:Nn \_@@_custom_set_X:n { + \str_set:Nx \l_tmpa_str { + \str_range:Nnn \l_tmpa_str 1 { #1 - 1 } + X + \str_range:Nnn \l_tmpa_str { #1 + 1 } { -1 } + } +} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\_@@_custom_component:} +% \begin{macrocode} +\cs_new_protected:Npn \_@@_custom_component:w [ #1 ] { + \tl_put_right:Nn \l_tmpa_tl { \comp{ #1 } } + \_@@_custom_loop: +} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\_@@_custom_final:} +% \begin{macrocode} +\cs_new_protected:Nn \_@@_custom_final: { + \int_compare:nNnTF \l_tmpb_int = 0 { + \exp_args:Nnno \_stex_term_oms:nnn + }{ + \str_if_in:NnTF \l_tmpa_str {b} { + \exp_args:Nnno \_stex_term_ombind:nnn + } { + \exp_args:Nnno \_stex_term_oma:nnn + } + } + { \l_@@_custom_uri } { \l_@@_custom_uri } { \l_tmpa_tl } +} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\symref,\symname} +% \begin{macrocode} +\cs_new:Nn \stex_capitalize:n { \uppercase{#1} } + +\keys_define:nn { stex / symname } { + pre .tl_set_x:N = \l_@@_pre_tl , + post .tl_set_x:N = \l_@@_post_tl , + root .tl_set_x:N = \l_@@_root_tl +} + +\cs_new_protected:Nn \stex_symname_args:n { + \tl_clear:N \l_@@_post_tl + \tl_clear:N \l_@@_pre_tl + \tl_clear:N \l_@@_root_str + \keys_set:nn { stex / symname } { #1 } +} + +\NewDocumentCommand \symref { m m }{ + \let\compemph_uri_prev:\compemph@uri + \let\compemph@uri\symrefemph@uri + \STEXsymbol{#1}!{ #2 } + \let\compemph@uri\compemph_uri_prev: +} + +\NewDocumentCommand \synonym { O{} m m}{ + \stex_symname_args:n { #1 } + \let\compemph_uri_prev:\compemph@uri + \let\compemph@uri\symrefemph@uri + % TODO + \STEXsymbol{#2}!{\l_@@_pre_tl #3 \l_@@_post_tl} + \let\compemph@uri\compemph_uri_prev: +} + +\NewDocumentCommand \symname { O{} m }{ + \stex_symname_args:n { #1 } + \stex_get_symbol:n { #2 } + \str_set:Nx \l_tmpa_str { + \prop_item:cn { l_stex_symdecl_ \l_stex_get_symbol_uri_str _prop } { name } + } + \exp_args:NNno \str_replace_all:Nnn \l_tmpa_str {-} {~} + + \let\compemph_uri_prev:\compemph@uri + \let\compemph@uri\symrefemph@uri + \exp_args:NNx \use:nn + \stex_invoke_symbol:n { { \l_stex_get_symbol_uri_str }!{ + \l_@@_pre_tl \l_tmpa_str \l_@@_post_tl + } } + \let\compemph@uri\compemph_uri_prev: +} + +\NewDocumentCommand \Symname { O{} m }{ + \stex_symname_args:n { #1 } + \stex_get_symbol:n { #2 } + \str_set:Nx \l_tmpa_str { + \prop_item:cn { l_stex_symdecl_ \l_stex_get_symbol_uri_str _prop } { name } + } + \exp_args:NNno \str_replace_all:Nnn \l_tmpa_str {-} {~} + \let\compemph_uri_prev:\compemph@uri + \let\compemph@uri\symrefemph@uri + \exp_args:NNx \use:nn + \stex_invoke_symbol:n { { \l_stex_get_symbol_uri_str }!{ + \exp_after:wN \stex_capitalize:n \l_tmpa_str + \l_@@_post_tl + } } + \let\compemph@uri\compemph_uri_prev: +} +% \end{macrocode} +% \end{macro} +% +% +% \subsection{Notation Components} +% \begin{macrocode} +%<@@=stex_notationcomps> +% \end{macrocode} +% +% +% \begin{macro}{\stex_highlight_term:nn} +% \begin{macrocode} + +\str_new:N \l_stex_current_symbol_str +\cs_new_protected:Nn \stex_highlight_term:nn { + \exp_args:Nnx + \use:nn { + \str_set:Nx \l_stex_current_symbol_str { #1 } + #2 + } { + \str_set:Nx \exp_not:N \l_stex_current_symbol_str + { \l_stex_current_symbol_str } + } +} + +\cs_new_protected:Nn \stex_unhighlight_term:n { +% \latexml_if:TF { +% #1 +% } { +% \rustex_if:TF { +% #1 +% } { + #1 %\iffalse{{\fi}} #1 {{\iffalse}}\fi +% } +% } +} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\comp,\compemph@uri,\compemph,\defemph,\defemph@uri,\symrefemph,\symrefemph@uri} +% \begin{macrocode} +\cs_new_protected:Npn \comp #1 { + \str_if_empty:NF \l_stex_current_symbol_str { + \rustex_if:TF { + \stex_annotate:nnn { comp }{ \l_stex_current_symbol_str }{ #1 } + }{ + \exp_args:Nnx \compemph@uri { #1 } { \l_stex_current_symbol_str } + } + } +} + +\cs_new_protected:Npn \compemph@uri #1 #2 { + \compemph{ #1 } +} + + +\cs_new_protected:Npn \compemph #1 { + #1 +} + +\cs_new_protected:Npn \defemph@uri #1 #2 { + \defemph{#1} +} + +\cs_new_protected:Npn \defemph #1 { + \textbf{#1} +} + +\cs_new_protected:Npn \symrefemph@uri #1 #2 { + \symrefemph{#1} +} + +\cs_new_protected:Npn \symrefemph #1 { + \textbf{#1} +} +% \end{macrocode} +% \end{macro} +% +% +% \begin{macro}{\ellipses} +% \begin{macrocode} +\NewDocumentCommand \ellipses {} { \ldots } +% \end{macrocode} +% \end{macro} +% +% +% \begin{macro}{\parray,\prmatrix,\parrayline,\parraylineh,\parraycell} +% \begin{macrocode} +\bool_new:N \l_stex_inparray_bool +\bool_set_false:N \l_stex_inparray_bool +\NewDocumentCommand \parray { m m } { + \begingroup + \bool_set_true:N \l_stex_inparray_bool + \begin{array}{#1} + #2 + \end{array} + \endgroup +} + +\NewDocumentCommand \prmatrix { m } { + \begingroup + \bool_set_true:N \l_stex_inparray_bool + \begin{matrix} + #1 + \end{matrix} + \endgroup +} + +\def \maybephline { + \bool_if:NT \l_stex_inparray_bool {\hline} +} + +\def \parrayline #1 #2 { + #1 #2 \bool_if:NT \l_stex_inparray_bool {\\} +} + +\def \pmrow #1 { \parrayline{}{ #1 } } + +\def \parraylineh #1 #2 { + #1 #2 \bool_if:NT \l_stex_inparray_bool {\\\hline} +} + +\def \parraycell #1 { + #1 \bool_if:NT \l_stex_inparray_bool {&} +} +% \end{macrocode} +% \end{macro} +% +% \subsection{Variables} +% \begin{macrocode} +%<@@=stex_variables> +% \end{macrocode} +% +% \begin{macro}{\stex_invoke_variable:n} +% +% Invokes a variable +% +% \begin{macrocode} +\cs_new_protected:Nn \stex_invoke_variable:n { + \if_mode_math: + \exp_after:wN \_@@_invoke_math:n + \else: + \exp_after:wN \_@@_invoke_text:n + \fi: {#1} +} + +\cs_new_protected:Nn \_@@_invoke_text:n { + %TODO +} + + +\cs_new_protected:Nn \_@@_invoke_math:n { + \peek_charcode_remove:NTF ! { + \peek_charcode_remove:NTF ! { + \peek_charcode:NTF [ { + \_@@_invoke_op_custom:nw + }{ + % TODO throw error + } + }{ + \_@@_invoke_op:n { #1 } + } + }{ + \peek_charcode_remove:NTF * { + \_@@_invoke_text:n { #1 } + }{ + \_@@_invoke_math_ii:n { #1 } + } + } +} + +\cs_new_protected:Nn \_@@_invoke_op:n { + \cs_if_exist:cTF { + stex_var_op_notation_ #1 _cs + }{ + \use:c{stex_var_op_notation_ #1 _cs } + }{ + \msg_error:nnxx{stex}{error/noop}{variable~#1}{} + } +} + +\cs_new_protected:Npn \_@@_invoke_math_ii:n #1 { + \cs_if_exist:cTF { + stex_var_notation_#1_cs + }{ + \str_set:Nn \l_stex_current_symbol_str { #1 } + \use:c{stex_var_notation_#1_cs} + }{ + \msg_error:nnxx{stex}{error/nonotation}{variable~#1}{s} + } +} +% \end{macrocode} +% \end{macro} +% +% +% \begin{macrocode} +%</package> +% \end{macrocode} +% +% \end{implementation} +% +% \PrintIndex + +% \endinput +% Local Variables: +% mode: doctex +% TeX-master: t +% End: |