% \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>
\def\libfolder#1{../../lib/#1}
\input{../../doc/stex-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/stex-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/09/14}{3.2.0}{sTeX document class}

\DeclareOption*{\PassOptionsToPackage{\CurrentOption}{stex}}
\ProcessOptions

\bool_set_true:N \c_stex_document_class_bool

\RequirePackage{stex}

\stex_html_backend:TF {
  \LoadClass{article}
}{
  \LoadClass[border=1px,varwidth,crop=false]{standalone}
  \setlength\textwidth{15cm}
}
\RequirePackage{standalone}


\clist_if_empty:NT \c_stex_languages_clist {
  \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
  \exp_args:No \str_if_eq:nnF \l_tmpa_str {tex} {
    \exp_args:No \str_if_eq:nnF \l_tmpa_str {dtx} {
      \exp_args:NNo \seq_put_right:Nn \l_tmpa_seq \l_tmpa_str
    }
  }
  \seq_pop_left:NN \l_tmpa_seq \l_tmpa_str % <filename>
  \seq_if_empty:NF \l_tmpa_seq { %remaining element should be [<something>.]language
    \seq_pop_right:NN \l_tmpa_seq \l_tmpa_str
    \prop_if_in:NoT \c_stex_languages_prop \l_tmpa_str {
      \stex_debug:nn{language} {Language~\l_tmpa_str~
        inferred~from~file~name}
      \exp_args:NNo \stex_set_language:Nn \l_tmpa_str \l_tmpa_str
    }
  }
}
%</cls>
%    \end{macrocode}
%
% \subsection{Preliminaries}
%
%    \begin{macrocode}
%<*package>

%%%%%%%%%%%%%   basics.dtx   %%%%%%%%%%%%%

\RequirePackage{expl3,l3keys2e,ltxcmds}
\ProvidesExplPackage{stex}{2022/09/14}{3.2.0}{sTeX package}

\bool_if_exist:NF \c_stex_document_class_bool {
  \bool_set_false:N \c_stex_document_class_bool
  \RequirePackage{standalone}
}

\message{^^J*~This~is~sTeX~version~3.2.0~*^^J}

%\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 ,
  usesms    .bool_set:N   = \c_stex_persist_mode_bool ,
  writesms  .bool_set:N   = \c_stex_persist_write_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}
\RequirePackage{stex-logo} % externalized for backwards-compatibility reasons
%    \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 } {
    \msg_set:nnn{stex}{debug / #1}{
      \\Debug~#1:~#2\\
    }
    \msg_none:nn{stex}{debug / #1}
  }{
    \clist_if_in:NnT \c_stex_debug_clist { #1 } {
      \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>
%    \end{macrocode}
%
%    \begin{macrocode}
%    \end{macrocode}
%
% \begin{variable}{\l_stex_html_arg_tl, \c_stex_html_emptyarg_tl}
%
% Used by annotation macros to ensure that the HTML output to annotate
% is not empty.
%
%    \begin{macrocode}
\tl_new:N \l_stex_html_arg_tl
%    \end{macrocode}
% \end{variable}
%
% \begin{macro}{\_stex_html_checkempty:n}
%    \begin{macrocode}
\cs_new_protected:Nn \_stex_html_checkempty:n {
  \tl_set:Nn \l_stex_html_arg_tl { #1 }
  \tl_if_empty:NT \l_stex_html_arg_tl {
    \tl_set_eq:NN \l_stex_html_arg_tl \c_stex_html_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}
\ifcsname if@rustex\endcsname\else
  \expandafter\newif\csname if@rustex\endcsname
  \@rustexfalse
\fi
\ifcsname if@latexml\endcsname\else
  \expandafter\newif\csname if@latexml\endcsname
  \@latexmlfalse
\fi
\tl_if_exist:NF\stex@backend{
  \if@rustex
    \def\stex@backend{rustex}
  \else
    \if@latexml
      \def\stex@backend{latexml}
    \else
      \cs_if_exist:NTF\HCode{
        \def\stex@backend{tex4ht}
      }{
        \def\stex@backend{pdflatex}
      }
    \fi
  \fi
}
\input{stex-backend-\stex@backend.cfg}

\newif\ifstexhtml
\stex_html_backend:TF\stexhtmltrue\stexhtmlfalse

%    \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}
\exp_args:NNx \prop_const_from_keyval:Nn \c_stex_languages_prop { \tl_to_str:n {
  en = english ,
  de = ngerman ,
  ar = arabic ,
  bg = bulgarian ,
  ru = russian ,
  fi = finnish ,
  ro = romanian ,
  tr = turkish ,
  fr = french
}}

\exp_args:NNx \prop_const_from_keyval:Nn \c_stex_language_abbrevs_prop { \tl_to_str:n {
  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}
\cs_new_protected:Nn \stex_set_language:Nn {
  \str_set:Nx \l_tmpa_str {#2}
  \prop_get:NoNT \c_stex_languages_prop \l_tmpa_str #1 {
    \ifx\@onlypreamble\@notprerr 
      \ltx@ifpackageloaded{babel}{
        \exp_args:No \selectlanguage #1
      }{}
    \else
      \exp_args:No \str_if_eq:nnTF #1 {turkish} {
        \RequirePackage[#1,shorthands=:!]{babel}
      }{
        \RequirePackage[#1]{babel}
      }
    \fi
  }
}

\clist_if_empty:NF \c_stex_languages_clist {
  \bool_set_false:N \l_tmpa_bool
  \clist_clear:N \l_tmpa_clist
  \clist_map_inline:Nn \c_stex_languages_clist {
    \str_set:Nx \l_tmpa_str {#1}
    \str_if_eq:nnT {#1}{tr}{
      \bool_set_true:N \l_tmpa_bool
    }
    \prop_get:NoNTF \c_stex_languages_prop \l_tmpa_str \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 {,~} }
  \bool_if:NTF \l_tmpa_bool {
    \RequirePackage[\clist_use:Nn \l_tmpa_clist,,shorthands=:!]{babel}
  }{
    \RequirePackage[\clist_use:Nn \l_tmpa_clist,]{babel}
  }
}

\AtBeginDocument{
  \stex_html_backend:T {
    \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
      \seq_pop_right:NN \l_tmpa_seq \l_tmpa_str
      \stex_debug:nn{basics} {Language~\l_tmpa_str~
        inferred~from~file~name}
      \stex_annotate_invisible:nnn{language}{ \l_tmpa_str }{}
    }
  }
}

%    \end{macrocode}
%
% \subsection{Persistence}
%
%    \begin{macrocode}
%<@@=stex_persist>
\bool_if:NTF \c_stex_persist_mode_bool {
  \def \stex_persist:n #1 {}
  \def \stex_persist:x #1 {}
}{
  \bool_if:NTF \c_stex_persist_write_mode_bool {
  \iow_new:N \c_@@_iow
  \iow_open:Nn \c_@@_iow{\jobname.sms}
  \AtEndDocument{
    \iow_close:N \c_@@_iow
  }
  \cs_new_protected:Nn \stex_persist:n {
    \tl_set:Nn \l_tmpa_tl { #1 }
    \regex_replace_all:nnN { \cP\# } { \cO\# } \l_tmpa_tl
    \regex_replace_all:nnN { \  } { \~ } \l_tmpa_tl
    \exp_args:NNo \iow_now:Nn \c_@@_iow \l_tmpa_tl
  }
  \cs_generate_variant:Nn \stex_persist:n {x}
  }{
    \def \stex_persist:n #1 {}
    \def \stex_persist:x #1 {}
  }
}
%    \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}{\detokenize{#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
  }
}

\cs_new_protected:Nn \stex_copy_control_sequence:NNN {
  \tl_set:Nx \_tmp_args_tl {\cs_argument_spec:N #2}
  \exp_args:NNo \tl_remove_all:Nn \_tmp_args_tl \c_hash_str
  \int_set:Nn \l_tmpa_int {\tl_count:N \_tmp_args_tl}

  \tl_clear:N \_tmp_args_tl
  \int_step_inline:nn \l_tmpa_int {
    \tl_put_right:Nx \_tmp_args_tl {{\exp_not:n{####}\exp_not:n{##1}}}
  }

  \tl_set:Nn #3 {\cs_generate_from_arg_count:NNnn #1 \cs_set:Npn}
  \tl_put_right:Nx #3 { {\int_use:N \l_tmpa_int}{
      \exp_after:wN\exp_after:wN\exp_after:wN \exp_not:n 
      \exp_after:wN\exp_after:wN\exp_after:wN {
        \exp_after:wN #2 \_tmp_args_tl
      }
  }}
}
\cs_generate_variant:Nn \stex_copy_control_sequence:NNN {cNN}
\cs_generate_variant:Nn \stex_copy_control_sequence:NNN {NcN}
\cs_generate_variant:Nn \stex_copy_control_sequence:NNN {ccN}

\cs_new_protected:Nn \stex_copy_control_sequence_ii:NNN {
  \tl_set:Nx \_tmp_args_tl {\cs_argument_spec:N #2}
  \exp_args:NNo \tl_remove_all:Nn \_tmp_args_tl \c_hash_str
  \int_set:Nn \l_tmpa_int {\tl_count:N \_tmp_args_tl}

  \tl_clear:N \_tmp_args_tl
  \int_step_inline:nn \l_tmpa_int {
    \tl_put_right:Nx \_tmp_args_tl {{\exp_not:n{########}\exp_not:n{##1}}}
  }

  \edef \_tmp_args_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 #2 \_tmp_args_tl
    }
  }
  
  \exp_after:wN \def \exp_after:wN \_tmp_args_tl
  \exp_after:wN ##\exp_after:wN 1 \exp_after:wN ##\exp_after:wN 2
  \exp_after:wN  { \_tmp_args_tl }

  \edef \_tmp_args_tl {
    \exp_after:wN \exp_not:n \exp_after:wN {
      \_tmp_args_tl {####1}{####2}
    }
  }

  \tl_set:Nn #3 {\cs_generate_from_arg_count:NNnn #1 \cs_set:Npn}
  \tl_put_right:Nx #3 { {\int_use:N \l_tmpa_int}{
    \exp_after:wN\exp_not:n\exp_after:wN{\_tmp_args_tl}
  }}
}

\cs_generate_variant:Nn \stex_copy_control_sequence_ii:NNN {cNN}
\cs_generate_variant:Nn \stex_copy_control_sequence_ii:NNN {NcN}
\cs_generate_variant:Nn \stex_copy_control_sequence_ii:NNN {ccN}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\MMTrule}
%    \begin{macrocode}
\NewDocumentCommand \MMTrule {m m}{
  \seq_set_split:Nnn \l_tmpa_seq , {#2}
  \int_zero:N \l_tmpa_int
  \stex_annotate_invisible:nnn{mmtrule}{scala://#1}{
    \seq_if_empty:NF \l_tmpa_seq {
      $\seq_map_inline:Nn \l_tmpa_seq {
        \int_incr:N \l_tmpa_int
        \stex_annotate:nnn{arg}{i\int_use:N \l_tmpa_int}{##1}
      }$
    }
  }
}

\NewDocumentCommand \MMTinclude {m}{
  \stex_annotate_invisible:nnn{import}{#1}{}
}

\tl_new:N \g_stex_document_title
\cs_new_protected:Npn \STEXtitle #1 {
  \tl_if_empty:NT \g_stex_document_title {
    \tl_gset:Nn \g_stex_document_title { #1 }
  }
}
\cs_new_protected:Nn \stex_document_title:n {
  \tl_if_empty:NT \g_stex_document_title {
    \tl_gset:Nn \g_stex_document_title { #1 }
    \stex_annotate_invisible:n{\noindent
      \stex_annotate:nnn{doctitle}{}{ #1 }
    \par}
  }
}
\AtBeginDocument {
  \let \STEXtitle \stex_document_title:n
  \tl_if_empty:NF \g_stex_document_title {
    \stex_annotate_invisible:n{\noindent
      \stex_annotate:nnn{doctitle}{}{ \g_stex_document_title }
    \par}
  }
  \let\_stex_maketitle:\maketitle
  \def\maketitle{
    \tl_if_empty:NF \@title {
      \exp_args:No \stex_document_title:n \@title
    }
    \_stex_maketitle:
  }
}

\cs_new_protected:Nn \stex_par: {
  \mode_if_vertical:F{
    \if@minipage\else\if@nobreak\else\par\fi\fi
  }
}

%</package>
%    \end{macrocode}
% \end{macro}
%
% \end{implementation}
% \ifinfulldoc\else\printbibliography\fi
%
% \PrintIndex
