diff options
author | Karl Berry <karl@freefriends.org> | 2010-07-20 22:30:22 +0000 |
---|---|---|
committer | Karl Berry <karl@freefriends.org> | 2010-07-20 22:30:22 +0000 |
commit | cdfe96a3444a4d0664b9702c4ff6fe6622257834 (patch) | |
tree | 577232accd4bf41d7480fae7c177ceef147c8fea /Master/texmf-dist/source | |
parent | 47e2d96a8faed88dfedd17ca5352227d585a6710 (diff) |
stex update once more
git-svn-id: svn://tug.org/texlive/trunk@19548 c570f23f-e606-0410-a88d-b1316a301751
Diffstat (limited to 'Master/texmf-dist/source')
15 files changed, 9080 insertions, 8 deletions
diff --git a/Master/texmf-dist/source/latex/stex/assignment/assignment.dtx b/Master/texmf-dist/source/latex/stex/assignment/assignment.dtx index bed15998630..b2cc124ff7a 100644 --- a/Master/texmf-dist/source/latex/stex/assignment/assignment.dtx +++ b/Master/texmf-dist/source/latex/stex/assignment/assignment.dtx @@ -25,6 +25,8 @@ \begin{document}\DocInput{assignment.dtx}\end{document} %</driver> % \fi +%\CheckSum{323} +% % \changes{v0.9}{2006/09/18}{First Version with Documentation} % % \GetFileInfo{assignment.sty} diff --git a/Master/texmf-dist/source/latex/stex/cmathml/cmathml.dtx b/Master/texmf-dist/source/latex/stex/cmathml/cmathml.dtx index dfd1c52bd18..6e6645d5164 100644 --- a/Master/texmf-dist/source/latex/stex/cmathml/cmathml.dtx +++ b/Master/texmf-dist/source/latex/stex/cmathml/cmathml.dtx @@ -22,7 +22,7 @@ \usepackage{../ctansvn} \usepackage{hyperref} \usepackage[eso-foot,today]{svninfo} -\svnInfo $Id: cmathml.dtx 1483 2010-07-19 07:11:16Z kohlhase $ +\svnInfo $Id: cmathml.dtx 1502 2010-07-20 08:17:00Z kohlhase $ \svnKeyword $HeadURL: https://svn.kwarc.info/repos/stex/trunk/sty/cmathml/cmathml.dtx $ \makeindex \floatstyle{boxed} @@ -32,7 +32,7 @@ %</driver> % \fi % -%\CheckSum{1} +%\CheckSum{1586} % % \changes{v0.1}{2006/01/10}{Initial Version} % \changes{v0.2}{2006/01/16}{Added big operators} @@ -2334,7 +2334,7 @@ DefConstructor('\Couterproduct [] {}{}', . "<ltx:XMTok meaning='outerproduct' role='OPFUNCTION' ?#1(definitionURL='#1')()/>" . "<ltx:XMArg>#2</ltx:XMArg>" . "<ltx:XMArg>#3</ltx:XMArg>" - . "</ltx:XMApp>"); + . "</ltx:XMApp>");#$ %</ltxml> % \end{macrocode} % @@ -2432,7 +2432,6 @@ DefConstructor('\Ccomplement [] {}', % \end{macrocode} % \Finale \endinput - % \iffalse %%% Local Variables: %%% mode: doctex diff --git a/Master/texmf-dist/source/latex/stex/cnx/cnx.dtx b/Master/texmf-dist/source/latex/stex/cnx/cnx.dtx index 4a83a3702de..f851073fead 100644 --- a/Master/texmf-dist/source/latex/stex/cnx/cnx.dtx +++ b/Master/texmf-dist/source/latex/stex/cnx/cnx.dtx @@ -20,7 +20,7 @@ \bibliography{kwarc} \usepackage{ctansvn} \usepackage[eso-foot,today]{svninfo} -\svnInfo $Id: cnx.dtx 1483 2010-07-19 07:11:16Z kohlhase $ +\svnInfo $Id: cnx.dtx 1502 2010-07-20 08:17:00Z kohlhase $ \svnKeyword $HeadURL: https://svn.kwarc.info/repos/stex/trunk/sty/cnx/cnx.dtx $ \makeindex \floatstyle{boxed} @@ -30,7 +30,7 @@ %</driver> % \fi % -%\CheckSum{1} +%\CheckSum{432} % % \changes{v0.1}{2005/12/06}{Initial Version} % \changes{v0.2}{2006/01/11}{Namespaces now work} diff --git a/Master/texmf-dist/source/latex/stex/dcm/dcm.dtx b/Master/texmf-dist/source/latex/stex/dcm/dcm.dtx new file mode 100644 index 00000000000..c78aeb8566f --- /dev/null +++ b/Master/texmf-dist/source/latex/stex/dcm/dcm.dtx @@ -0,0 +1,1029 @@ +% \iffalse meta-comment +% An Infrastructure for marking up Dublin Core Metadata in LaTeX documents +% $URL: https://svn.kwarc.info/repos/stex/trunk/sty/dcm/dcm.dtx $ +% $Rev: 1502 $; last modified by $Author: kohlhase $ +% $Date: 2010-07-20 10:17:00 +0200 (Tue, 20 Jul 2010) $ +% Copyright (c) 2007 Michael Kohlhase, all rights reserved +% this file is released under the +% LaTeX Project Public License (LPPL) +% \fi +% +% \iffalse +%<*package> +\NeedsTeXFormat{LaTeX2e}[1999/12/01] +\ProvidesPackage{dcm}[2010/06/25 v0.3 Dublin Core Metadata] +%</package> +%<*driver> +\documentclass{ltxdoc} +\usepackage{dcm,sref,url,array,float} +\usepackage[show]{ed} +\usepackage[hyperref=auto,style=alphabetic]{biblatex} +\bibliography{kwarc} +\usepackage{../ctansvn} +\usepackage{hyperref} +\usepackage[eso-foot,today]{svninfo} +\svnInfo $Id: dcm.dtx 1502 2010-07-20 08:17:00Z kohlhase $ +\svnKeyword $HeadURL: https://svn.kwarc.info/repos/stex/trunk/sty/dcm/dcm.dtx $ +\makeindex +\floatstyle{boxed} +\newfloat{exfig}{thp}{lop} +\floatname{exfig}{Example} +\DCMperson[id=jdoe,affiliation={DFKI Bremen}, + url=http://dfki.de/jdoe]{John Doe} +\DCMperson[id=miko,affiliation={Jacobs University, Bremen}, + url=http://kwarc.info/kohlhase]{Michael Kohlhase} +\begin{document}\DocInput{dcm.dtx}\end{document} +%</driver> +% \fi +% +%\CheckSum{667} +% +% \changes{v0.1}{2007/01/02}{First Hack for OMDoc spec} +% \changes{v0.2}{2008/06/17}{First Version with Documentation} +% \changes{v0.2}{2008/07/02}{Renamed to dcm} +% \changes{v0.3}{2009/09/21}{much more documentation of the user interface} +% \changes{v0.3}{2009/09/21}{Adding sref support and made generated headings configurable} +% \changes{v0.3}{2010/01/11}{Eliminating stub author index that never worked anyways} +% +% \GetFileInfo{dcm.sty} +% +% \MakeShortVerb{\|} +% \def\scsys#1{{{\sc #1}}\index{#1@{\sc #1}}} +% \def\latexml{\scsys{LaTeXML}} +% +% \begin{DCmetadata}[maketitle] +% \DCMtitle{{\texttt{dcm.sty}}: An Infrastructure for marking up Dublin Core Metadata in {\LaTeX} +% documents\thanks{Version {\fileversion} (last revised {\filedate})}} +% \DCMcreators{miko,jdoe} +% \DCMabstract{The |dcm| package allows mark up Dublin +% Core Metadata in {\LaTeX} documents that can be harvested by automated tools or +% exported to PDF, while at the same time generating conventional title information.} +% \end{DCmetadata} +% +% \setcounter{tocdepth}{2}\tableofcontents\newpage +% +%\DCMsection[id=intro,creators={miko}]{Introduction} +% +% The |dcm| packge allows mark up Dublin Core Metadata~\cite{DCMI:dmt03} in {\LaTeX} +% documents so that it can be harvested by automated tools or exported to PDF\ednote{This +% still needs to be implemented, see \texttt{http://www.wlug.org.nz/PdfLatexNotes} for +% details}. This package allows to attribute authorship to arbitrary text +% fragments.\ednote{continue} +% +% \DCMsection[id=user,creators={miko,jdoe}]{The User Interface} +% +% \DCMsubsection{Persons} +% +% The |dcm| package recognizes that from a metadata perspective, persons are complex +% entities. In particular, specifying metadata is a tedious and repetitive task that leads +% to embarrassing errors. Therefore the |dcm| package takes a hint from bibTeX and allows +% to specify personal metadata in a database and use it by a database key. +% \begin{exfig}[ht] +% \begin{verbatim} +% \DCMperson[id=jdoe,affiliation={DFKI Bremen}, +% url=http://dfki.de/jdoe]{John Doe} +% \DCMperson[id=miko,affiliation={Jacobs University, Bremen}, +% url=http://kwarc.info/kohlhase]{Michael Kohlhase} +% \end{verbatim} +% \caption{A small database of Persons} +% \label{fig:persons} +% \end{exfig} +% The \DescribeMacro{\DCMperson}|\DCMperson| macro allows to specify personal metadata\ednote{This +% should be synchronized with the FOAF specification~\cite{FOAF:spec}} with the following +% keys: +% \begin{center} +% \begin{tabular}{|l|l|}\hline +% key & comment\\\hline\hline +% id & identifier of this person\\\hline +% birthdate & birthdate \\\hline +% email & the primary e-mail address\\\hline +% url & the URI of the primary home page \\\hline +% affiliation & the primary professional affiliation\\\hline +% personaltitle & the personal title e.g. {\texttt{King}}\\\hline +% academictitle & the academic title e.g. {\texttt{Prof. Dr.}}\\\hline +% department & the department specified in the work address\\\hline +% workaddress & the work address \\\hline +% privaddress & the private address \\\hline +% worktel & work telephone number \\\hline +% privtel & private telephone number\\\hline +% workfax & work fax number \\\hline +% privfax & private fax number \\\hline +% worktelfax & if the phone and fax share a prefix, give this as well \\\hline +% privtelfax & dito\\\hline +% \end{tabular} +% \end{center} +% In Figure~\ref{fig:persons} we have specified (minimal) metadata for the authors of the +% |dcm| package. The metadata can be accessed by specifying the identifiers (given by the +% |id| key) in the |dcm| macros defined below, see for instance the |\DCMcreators| macro +% in Figure~\ref{fig:dcmblock}, which leads to the title block of this note. +% +% Like in bibTeX~\cite{Patashnik:b88}, it is a good idea to collect the metadata in a separate +% file that is input in the document. In practice it may be possible to generate these +% files from conventional address databases. +% +% \DCMsubsection[id=user.dcm.mdblock]{The DC Metadata Block} +% +% \DescribeEnv{DCmetadata} The |dcm| provides the environment |DCmetadata| for Dublin Core +% Metadata Blocks. |DCmetadata| defines local macros for the specifying the relevant +% Dublin Core metadata fields and takes an optional argument that specifies the +% presentation of the metadata block, see Figure~\ref{fig:dcmblock} for an example which +% would generate the title block for the |dcm| package. Let us now come to the macros themselves +% +% \DescribeMacro{\DCMcreators}\DescribeMacro{\DCMcontributors} The |\DCMcreators| and +% |\DCMcontributors| macros are used to specify the authors and contributors to a text +% fragments. These macros take one argument, the authorship of a document specified in +% terms of |id|s of persons specified via |\DCMperson| before. They can occur multiply in +% a metadata block. +% +% \DescribeMacro{\DCMtitle} The |\DCMtitle| macro takes one argument, the +% +% \DescribeMacro{\DCMshorttitle} The |\DCMshorttitle| macro takes one argument, the +% +% \DescribeMacro{\DCMsubject} The |\DCMsubject| macro takes one argument, the +% +% \DescribeMacro{\DCMdescription} The |\DCMdescription| macro takes one argument, the +% +% \DescribeMacro{\DCMpublisher} The |\DCMpublisher| macro takes one argument, the +% +% \DescribeMacro{\DCMdate} The |\DCMdate| macro takes one argument, the +% +% \DescribeMacro{\DCMtype} The |\DCMtype| macro takes one argument, the +% +% \DescribeMacro{\DCMidentifier} The |\DCMidentifier| macro takes two arguments, the first one +% is the identification system, and the second one the identifier string itself. +% +% \DescribeMacro{\DCMsource} The |\DCMsource| macro takes one argument, the +% +% \DescribeMacro{\DCMlanguage} The |\DCMlanguage| macro takes one argument, the +% +% \DescribeMacro{\DCMrelation} The |\DCMrelation| macro takes one argument, the +% +% \DescribeMacro{\DCMrights} The |\DCMrights| macro takes one argument, the +% +% \DescribeMacro{\DCMlicense} The |\DCMlicense| macro takes one argument, the +% +% \DescribeMacro{\DCMabstract} The |\DCMabstract| macro takes one argument, the +% +% \DescribeMacro{\DCMlicensenotice} The |\DCMlicensenotice| macro takes one argument, the +% +% \DescribeMacro{\DCMcopyrightnotice} The |\DCMcopyrightnotice| macro takes one argument, the +% +% \DescribeMacro{\DCMcclicense} The |\DCMcclicense| macro +% +% \DescribeMacro{\attribution} +% +% \DescribeMacro{\noncommercial} +% +% \DescribeMacro{\sharealike} +% +% \DescribeMacro{\noderivativeworks} +% +% \begin{exfig}[ht] +% \begin{verbatim} +% \begin{DCmetadata}[maketitle] +% \DCMtitle{An Infrastructure for marking up Dublin Core Metadata in +% {\LaTeX} documents\thanks{Version {\fileversion} +% (last revised {\filedate})}} +% \DCMcreators{miko,jdoe} +% \DCMdate{\today} +% \DCMcopyrightnotice{2008}{Michael Kohlhase} +% \DCMlicensenotice{Copyright (c) 2008 Michael Kohlhase, all rights +% reserved. This file is released under the LaTeX Project Public +% License (LPPL)} +% \DCMabstract{The {\texttt{dcm}} packge allows mark up Dublin +% Core Metadata in {\LaTeX} documents that can be harvested by +% automated tools or exported to PDF, while at the same time +% generating conventional title information.} +% \end{DCmetadata} +% \end{verbatim} +% \caption{The DC Metadata block for the {\texttt{dcm}} package documentation} +% \label{fig:dcmblock} +% \end{exfig} +% +% \DCMsubsection[creators=jdoe,id=user.blockstyles]{DCM Metadata Block Styles} +% +% The |DCmetadata| environment takes an optional argument that specifies the style the +% metadata block is rendered in. The |dcm| package supplies two styles: +% \DescribeMacro{maketitle}|maketitle| and \DescribeMacro{titlepage}|titlepage|. The +% former uses the |\maketitle| macro from the calling class to assemble a title, whereas +% the latter builds a title page from scratch. The title block of this documentation has +% been created by the |maketitle| style. +% +% To add a further metadata block style \meta{sty}, we simply have to supply a +% \DescribeMacro{\dcm@*@block}|\dcm@|\meta{sty}|@block| macro that expands to the intended +% presentation. This macro does not take any arguments, but can use the internal token +% registers defined by the |DCmetadata| environment. Generally, for any of the metadata +% commands |\DCM|\meta{md} defined in {\sref{user.dcm.mdblock}} there is a token register +% |\dcm@|\meta{md} that contains the value specified in the key. +% +% \DCMsubsection{Augmented Sectioning Macros} +% +% The |dcm| package supplies sectioning commands customized for metadata handling: The +% \DescribeMacro{\DCMchapter}|\DCMchatper| \DescribeMacro{\DCMsection}|\DCMsection| +% \DescribeMacro{\DCMsubsection}|\DCMsubsection|, and +% \DescribeMacro{\DCMsubsubsection}|\DCMsubsubsection| macros behave like their regular +% {\LaTeX} counterpart, except that the optional argument, which is used to specify a +% short title there, is now a KeyVal argument. The |short| key takes over the role of +% specifying a short title in |\DCM|\meta{sect}. The |id| key allows to specify an +% identifier, which can be used for {\LaTeX}-style referencing (use +% |\ref{|\meta{sect}|.|\meta{id}|}|) or |sref|-style referencing~\ctancite{Kohlhase:sref} +% (use |\sref{|\meta{id}|}|). Finally, the keys |creators| and |contributors| can be used +% to specify the authors (creators in Dublin Core speak~\cite{DCMI:dmt03}) and +% contributors. For instance the following line was used to specify the heading of +% {\sref{user}}. +% \begin{verbatim} +% \DCMsection[id=user,creators={miko,jdoe}]{The User Interface} +% \end{verbatim} +% Finally, the |style| key can be used to specify a style. +% +% \DCMsubsection[id=user.conig]{Configuration} +% +% The |dcm| package provides a set of macros that customize (e.g. for multiple languages) +% the generated +% content. +% \DescribeMacro{\dcm@abstract@heading} +% \DescribeMacro{\dcm@creators@heading} +% \DescribeMacro{\dcm@contributors@connector} +% \DescribeMacro{\dcm@chapter@heading} +% \DescribeMacro{\dcm@section@heading} +% \DescribeMacro{\dcm@subsection@heading} +% \DescribeMacro{\dcm@subsubsection@heading} +% \begin{center}\makeatletter +% \begin{tabular}{|l|l|}\hline +% Macro & Default\\\hline\hline +% |\dcm@abstract@heading| & \dcm@abstract@heading \\\hline +% |\dcm@creators@heading| & \dcm@creators@heading \\\hline +% |\dcm@contributors@connector| & \dcm@contributors@connector \\\hline\hline +% |\dcm@chapter@heading| & \dcm@chapter@heading \\\hline +% |\dcm@section@heading| & \dcm@section@heading \\\hline +% |\dcm@subsection@heading| & \dcm@subsection@heading \\\hline +% |\dcm@subsubsection@heading| & \dcm@subsubsection@heading \\\hline +% \end{tabular} +% \end{center} +% +% \StopEventually{\printbibliography} +% +% \DCMsection[creators=jdoe,id=impl]{The Implementation} +% +% The first measure is to ensure that the |KeyVal| package is loaded (in the right +% version). For {\latexml} we also initialize the package inclusions. +% \begin{macrocode} +%<*package> +\RequirePackage{sref} +%</package> +%<*ltxml> +# -*- CPERL -*- +package LaTeXML::Package::Pool; +use strict; +use LaTeXML::Global; +use LaTeXML::Package; +RequirePackage('sref'); +%</ltxml> +% \end{macrocode} +% +% \DCMsubsection{Persons} +% +% To implement the |\DCMperson| macro, we need to implement its keywords first and also +% the |\dcm@person@clear@keys| macro that clears them. \ednote{need some DCM stuff here} +% +% \begin{macrocode} +%<*package> +\omdaddkey{dcm@person}{id} +\omdaddkey{dcm@person}{birthdate} +\omdaddkey{dcm@person}{email} +\omdaddkey{dcm@person}{url} +\omdaddkey{dcm@person}{affiliation} +\omdaddkey{dcm@person}{personaltitle} +\omdaddkey{dcm@person}{academictitle} +\omdaddkey{dcm@person}{department} +\omdaddkey{dcm@person}{workaddress} +\omdaddkey{dcm@person}{privaddress} +\omdaddkey{dcm@person}{worktel} +\omdaddkey{dcm@person}{privtel} +\omdaddkey{dcm@person}{workfax} +\omdaddkey{dcm@person}{privfax} +\omdaddkey{dcm@person}{worktelfax} +\omdaddkey{dcm@person}{privtelfax} +%</package> +% \end{macrocode} +% +% The next macro is an auxiliary one that puts the value into an appropriate token +% register. At the {\latexml} side we have a function |ExportMetadata| that does a similar +% job, fishing out the metadata keys from the keyval arguments and storing them in a safe +% place so they can be accessed later. +% +% \begin{macrocode} +%<*package> +\def\dcm@pers@def#1#2{\expandafter\xdef\csname dcm@person@\dcm@person@id @#1\endcsname{#2}} +\def\dcm@pers@ref#1#2{\csname dcm@person@#1@#2\endcsname} +\let\dcm@persons=\relax +%</package> +%<*ltxml> + sub getKeyValue_noDelim { + my ($keyval,$key)=@_; + my $valuelist = ToString($keyval->getValue($key)); + $valuelist =~ s/^{(.*)}$/$1/g if $valuelist; + return $valuelist; +} +sub ExportMetadata { + my $keys = shift; + my($id, $email,$affill,$address,$url,$name)=$keys + && map(getKeyValue_noDelim($keys,$_),qw(id email affiliation address url name)); + if ($id) { + AssignValue('DCM_'.$id.'_email',$email,'global') if $email; + AssignValue('DCM_'.$id.'_affiliation',$affill,'global') if $affill; + AssignValue('DCM_'.$id.'_address',$email,'global') if $email; + AssignValue('DCM_'.$id.'_url',$url,'global') if $url; + AssignValue('DCM_'.$id.'_name',$name,'global') if $name; + } else {print STDERR "Warning: key 'id' undefined in \\DCMperson\n"}; + return;} +%</ltxml> +% \end{macrocode} +% +% With this we can define the |\DCMperson| macro, it just clears the keys, sets them +% again, and stores them in token registers. If course only if a |id| attribute is given, +% else we raise an error. +% +% \begin{macro}{DCMPerson} +% \begin{macrocode} +%<*package> +\newcommand{\DCMperson}[2][]{\omdsetkeys{dcm@person}{#1} +\ifx\dcm@person@id\@empty\@latex@warning{key 'id' undefined in DCMperson}\else +\dcm@pers@def{name}{#2} +\dcm@pers@def{email}{\dcm@person@email} +\dcm@pers@def{birthdate}{\dcm@person@birthdate} +\dcm@pers@def{url}{\dcm@person@url} +\dcm@pers@def{affiliation}{\dcm@person@affiliation} +\dcm@pers@def{workaddress}{\dcm@person@workaddress} +\dcm@pers@def{privaddress}{\dcm@person@privaddress} +\dcm@pers@def{personaltitle}{\dcm@person@personaltitle} +\dcm@pers@def{academictitle}{\dcm@person@academictitle} +\dcm@pers@def{department}{\dcm@person@department} +\dcm@pers@def{workaddress}{\dcm@person@workaddress} +\dcm@pers@def{privaddress}{\dcm@person@privaddress} +\dcm@pers@def{worktel}{\dcm@person@worktel} +\dcm@pers@def{privtel}{\dcm@person@privtel} +\dcm@pers@def{workfax}{\dcm@person@workfax} +\dcm@pers@def{privfax}{\dcm@person@privfax} +\dcm@pers@def{worktelfax}{\dcm@person@worktelfax} +\dcm@pers@def{privtelfax}{\dcm@person@privtelfax} +\@ifundefined{dcm@persons}{\xdef\dcm@persons{\dcm@person@id}}{\xdef\dcm@persons{\dcm@persons,\dcm@person@id}} +\fi} +%</package> +%<*ltxml> +DefKeyVal('dcm@person','id','Semiverbatim'); +DefKeyVal('dcm@person','birthdate','Semiverbatim'); +DefKeyVal('dcm@person','email','Semiverbatim'); +DefKeyVal('dcm@person','url','Semiverbatim'); +DefKeyVal('dcm@person','affiliation','Semiverbatim'); +DefKeyVal('dcm@person','personaltitle','Semiverbatim'); +DefKeyVal('dcm@person','academictitle','Semiverbatim'); +DefKeyVal('dcm@person','department','Semiverbatim'); +DefKeyVal('dcm@person','workaddress','Semiverbatim'); +DefKeyVal('dcm@person','privaddress','Semiverbatim'); +DefKeyVal('dcm@person','worktel','Semiverbatim'); +DefKeyVal('dcm@person','privtel','Semiverbatim'); +DefKeyVal('dcm@person','workfax','Semiverbatim'); +DefKeyVal('dcm@person','privfax','Semiverbatim'); +DefKeyVal('dcm@person','worktelfax','Semiverbatim'); +DefKeyVal('dcm@person','privtelfax','Semiverbatim'); + +DefConstructor('\DCMperson OptionalKeyVals:dcm@person {}','', +beforeDigest=> sub { AssignValue(inPreamble=>0); }, +afterDigest=>sub { + my ($stomach,$whatsit)=@_; + my $keys=$whatsit->getArg(1); + my $name=ToString($whatsit->getArg(2)); + $keys->setValue('name',$name); + ExportMetadata($keys); + return; +});#$ +%</ltxml> +% \end{macrocode} +% \end{macro} +% +% Furthermore, we need a couple of helper functions for the +% +% \begin{macrocode} +%<*ltxml> +sub FishOutMetadata { + my ($document,$keyvals)=@_; + foreach my $role(qw(creators contributors)) { + my $idlist_string=getKeyValue_noDelim($keyvals,$role); + my @ids = split(/,\s*/, $idlist_string); + foreach my $id(@ids) { + my $name = LookupValue('DCM_'.$id.'_name'); + if ($name) { + my $prop_role = $role; + chop $prop_role if $prop_role; + $document->insertElement("dc:$prop_role",$name) if $role; + } else {print STDERR "Warning: no $role with 'id' $id !\n";} + } + } + return;}#$ +%</ltxml> +% \end{macrocode} +% +% \DCMsubsection{The DC Metadata Block} +% +% Then we make an environment for defining the metadata. Note that since we have defined +% the |omdoc:metadata| element to auto-open and auto-close, we do not have to (and should +% not for that matter) supply it in the |DCmetadata| element. +% +% \begin{environment}{DCmetadata} +% \begin{macrocode} +%<*package> +\newenvironment{DCmetadata}[1][]% +{\def\@style{#1}} % to set the way things are presented. +{\@ifundefined{dcm@\@style @block}{\message{style {\@style} not defined}}{\csname dcm@\@style @block\endcsname}} +%</package> +%<*ltxml> +DefEnvironment('{DCmetadata}[]', "<omdoc:metadata>#body</omdoc:metadata>"); +%</ltxml> +% \end{macrocode} +% \end{environment} +% +% Now some auxiliary macros to make author blocks. \ednote{use and document them!} +% +% \begin{macrocode} +%<*package> +\def\dc@mtabline#1#2{\xdef\tab@line{}% +\@for\@p:={#1}\do{\xdef\tab@line{\tab@line&\dcm@pers@ref\@p{#2}}} +\tab@line} +\def\dcm@atabline#1#2#3{\xdef\tab@line{}% +\@for\@p:={#1}\do{\xdef\tab@line{\tab@line: \dcm@pers@ref\@p{#3}}} +\tab@line} +\def\dcm@bitabline#1#2#3#4{\xdef\tab@line{}% +\@for\@p:={#1}\do{\xdef\tab@line{\tab@line&\dcm@pers@ref\@p{#2} #3 \dcm@pers@ref\@p{#4}}} +\tab@line} +%</package> +% \end{macrocode} +% Here come the constructors, most of them are relatively straightforward +% \begin{macro}{\DCMcreators} +% the |\DCMcreators| macro checks whether all ids are defined. +% \begin{macrocode} +%<*package> +\def\DCMcreators#1{\@for\@I:=#1\do{% +\ifx\csname dcm@person@\@I @id\endcsname\@empty% undefined \dcm@person@id +\PackageError{dcm}{reference to undefined DCMperson \@I}% +{you must define a person with id=\@I\MessageBreak% +via the macro \protect\DCMperson, before you can use it in \protect\DCMcreators}\fi}% +\def\dcm@creators{#1}} +%</package> +%<*ltxml> +DefConstructor('\DCMcreators{}',sub{ + my ($document,$args,%properties) = @_; + my $keyval = LaTeXML::KeyVals->new('dcm@person',T_BEGIN,T_END,('creators'=>$args)); + FishOutMetadata($document,$keyval); + return;}); +%</ltxml> +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\DCMcontributors} +% the |\DCMcontributors| macro also checks whether all ids are defined. +% \begin{macrocode} +%<*package> +\def\DCMcontributors#1{\@for\@I:=#1\do{% +\ifx\csname dcm@person@\@I @id\endcsname\@empty% undefined \dcm@person@id +\PackageError{dcm}{reference to undefined DCMperson \@I}% +{you must define a person with id=\@I\MessageBreak% +via the macro \protect\DCMperson, before you can use it in \protect\DCMcontributors}}% +\else% all \dcm@person@id in the list are defined +\def\dcm@contributors{#1}\fi} +%</package> +%<*ltxml> +DefConstructor('\DCMcontributors{}',sub{ + my ($document,$args,%properties) = @_; + my $keyval = LaTeXML::KeyVals->new('dcm@person',T_BEGIN,T_END,('contributors'=>$args)); + FishOutMetadata($document,$keyval); + return;}); +%</ltxml> +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\DCMtitle} +% \begin{macrocode} +%<*package> +\def\DCMtitle#1{\def\dcm@title{#1}\providecommand{\dcm@shorttitle}{#1}} +%</package> +%<*ltxml> +DefConstructor('\DCMtitle{}',"<dc:title>#1</dc:title>"); +%</ltxml> +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\DCMsubtitle} +% \begin{macrocode} +%<*package> +\def\dcm@subtitle{} +\def\DCMsubtitle#1{\def\dcm@subtitle{#1}} +%</package> +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\DCMshorttitle} +% \begin{macrocode} +%<*package> +\def\dcm@shorttitle{} +\def\DCMshorttitle#1{\def\dcm@shorttitle{#1}} +%</package> +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\DCMsubject} +% \begin{macrocode} +%<*package> +\def\DCMsubject#1{\def\dcm@subject{#1}} +%</package> +%<*ltxml> +DefConstructor('\DCMsubject{}',"<dc:subject>#1</dc:subject>"); +%</ltxml> +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\DCMdescription} +% \begin{macrocode} +%<*package> +\long\def\DCMdescription#1{\long\def\dcm@description{#1}} +%</package> +%<*ltxml> +DefConstructor('\DCMdescription{}',"<dc:description>#1</dc:description>"); +%</ltxml> +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\DCMpublisher} +% \begin{macrocode} +%<*package> +\def\DCMpublisher#1{\def\dcm@publisher{#1}} +%</package> +%<*ltxml> +DefConstructor('\DCMpublisher{}',"<dc:publisher>#1</dc:publisher>"); +%</ltxml> +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\DCMdate} +% the |\DCMdate| uses |\today| as a default\ednote{@DEYAN: do that in latexml} +% \begin{macrocode} +%<*package> +\def\dcm@date{\today} +\def\DCMdate#1{\def\dcm@date{#1}} +%</package> +%<*ltxml> +DefConstructor('\DCMdate{}',"<dc:date>#1</dc:date>"); +%</ltxml> +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\DCMtype} +% \begin{macrocode} +%<*package> +\def\DCMtype#1{\def\dcm@type{#1}} +%</package> +%<*ltxml> +DefConstructor('\DCMtype{}',"<dc:type>#1</dc:type>"); +%</ltxml> +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\DCMidentifier} +% \begin{macrocode} +%<*package> +\def\DCMidentifier#1#2{\def\dcm@scheme{#1}\def\dcm@identifier{#2}} +%</package> +%<*ltxml> +DefConstructor('\DCMidentifier{}{}',"<dc:identifier scheme='#1'>#2</dc:identifier>"); +%</ltxml> +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\DCMsource} +% \begin{macrocode} +%<*package> +\def\DCMsource#1{\def\dcm@source{#1}} +%</package> +%<*ltxml> +DefConstructor('\DCMsource{}',"<dc:source>#1</dc:source>"); +%</ltxml> +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\DCMlanguage} +% \begin{macrocode} +%<*package> +\def\DCMlanguage#1{\def\dcm@language{#1}} +%</package> +%<*ltxml> +DefConstructor('\DCMlanguage{}',"<dc:language>#1</dc:language>"); +%</ltxml> +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\DCMrelation} +% \begin{macrocode} +%<*package> +\def\DCMrelation#1{\def\dcm@relation{#1}} +%</package> +%<*ltxml> +DefConstructor('\DCMrelation{}',"<dc:relation>#1</dc:relation>"); +%</ltxml> +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\DCMrights} +% \begin{macrocode} +%<*package> +\def\DCMrights#1{\long\def\dcm@rights{#1}} +%</package> +%<*ltxml> +DefConstructor('\DCMrights{}',"<dc:rights>#1</dc:rights>"); +%</ltxml> +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\DCMlicense} +% \begin{macrocode} +%<*package> +\def\DCMlicense#1{\def\dcm@license{#1}} +%</package> +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\DCMlicensenotice} +% here we have a default +% \begin{macrocode} +%<*package> +\def\dcm@license{All rights reserved} +\def\DCMlicensenotice#1{\long\def\dcm@license{\\[1ex]License: #1}} +%</package> +%<*ltxml> +DefMacro('\DCMlicensenotice{}','\DCMrights{#1}'); +%</ltxml> +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\DCMcopyrightnotice} +% \begin{macrocode} +%<*package> +\def\DCMcopyrightnotice#1#2{\DCMrights{Copyright {\copyright} #1: #2}} +%</package> +%<*ltxml> +DefMacro('\DCMcopyrightnotice{}{}','\DCMrights{Copyright {\copyright} #1: #2}'); +%</ltxml> +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\cclicense} +% \begin{macrocode} +%<*package> +\def\cclicense#1{\def\attribution{\def\dcm@by{yes}} + \def\noncommercial{\def\dcm@nc{yes}} + \def\sharealike{\defdcm@sharealike{yes}} + \def\noderivativeworks{\def\dcm@derivatives{no}}} +%</package> +%<*ltxml> +DefConstructor('\cclicense{}',"<cc:license>#1</cc:license>"); +DefConstructor('\attribution',"<cc:attribution/>"); +DefConstructor('\noncommercial',"<cc:noncommercial/>"); +DefConstructor('\sharealike',"<cc:sharealike/>"); +DefConstructor('\noderivativeworks',"<cc:noderivativeworks>"); +%</ltxml> +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\DCMabstract} +% \begin{macrocode} +%<*package> +\long\def\DCMabstract#1{\long\def\dcm@abstract{#1}} +%</package> +%<*ltxml> +DefConstructor('\DCMabstract{}',"<dc:description>#1</dc:description>"); +%</ltxml> +% \end{macrocode} +% \end{macro} +% +% \DCMsubsection[creators=jdoe,id=impl.blockstyles]{DCM Block Styles} +% +% We now define various commonly used styles. +% +% \begin{macro}{\dcm@authorblock} +% This internal macro builds an author block from a list of |\DCMperson| labels in +% |\dcm@creators|. +% \begin{macrocode} +%<*package> +\def\dcm@authorblock{\newcounter{authors}\stepcounter{authors} +{\let\tabularnewline\relax + \@for\@I:=\dcm@creators\do{\stepcounter{authors}} + \def\@authors{}\def\@affs{}\def\@urls{} + \@for\@I:=\dcm@creators\do + {\xdef\@authors{\@authors&\csname dcm@person@\@I @name\endcsname} + \xdef\@affs{\@affs&\csname dcm@person@\@I @affiliation\endcsname} + \xdef\@urls{\@urls&\csname dcm@person@\@I @url\endcsname}} + \message{authors: \@authors}} + \begin{tabular}[t]{l*{\theauthors}{c}}\@authors\\\@affs\\\@urls\end{tabular}} +%</package> +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\dcm@titlepage@block} +% This style builds up a title page from scratch +% \begin{macrocode} +%<*package> +\def\dcm@titlepage@block{\begin{titlepage} + \null\vfil\vskip 60\p@ + \begin{center} + \ifx\dcm@title\@empty + \PackageWarning{dcm}{No title specified}{\LARGE Add title here\par} + \else\LARGE \dcm@title \par\fi + \ifx\dcm@subtitle\@empty + \vskip 3em\Large \dcm@subtitle \par\vskip 3em + \else\large\lineskip .75em\dcm@authorblock\vskip 1.5em\fi + \ifx\dcm@date\@empty + \PackageWarning{dcm}{No date specified}{\large\today\par} + \else{\large\dcm@date\par}\vskip 2em\fi + \end{center}\vskip2em + \ifx\dcm@abstract\@empty + \PackageWarning{dcm}{No Abstract specified}\else + \begin{quote}\textbf\dcm@abstract@heading:\dcm@abstract\end{quote}\fi + \vskip 2em\par\vfil\noindent + {\small\noindent\dcm@rights\dcm@license} + \end{titlepage}} +%</package> +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\dcm@maketitle@block} +% This style makes use of the title facility of the document class. +% \begin{macrocode} +%<*package> +\def\dcm@maketitle@block{\def\@title{\dcm@title\ifx\dcm@subtitle\empty\else\newline\dcm@subtitle\fi} +\def\@author{\dcm@authorblock}\def\@date{\dcm@date}\maketitle} +%</package> +% \end{macrocode} +% \end{macro} +% +% \DCMsubsection{Augmented Sectioning Macros} +% +% \begin{macro}{\dcm@sect@clear@keys} +% We first define the sectioning keys with the infrastructure from the |omd| package~\ctancite{Kohlhase:omd} +% \begin{macrocode} +%<*package> +\srefaddidkey{dcm@sect} +\omdaddkey{dcm@sect}{short} +\omdaddkey{dcm@sect}{creators} +\omdaddkey{dcm@sect}{contributors} +%</package> +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\dcm@section} +% The next step is to define an auxiliary macro that does all the +% work. |\dcm@section{|\meta{type}|}{|\meta{title}|}{|\meta{keys}|}| delegates the +% presentation of the \meta{title} and the metadata in \meta{keys} to the +% |\dcm@section@*@style| macro specified \meta{style}. +% \begin{macrocode} +%<*package> +\def\dcm@section#1#2#3{\def\dcm@sect@type{#1}\omdsetkeys{dcm@sect}{#3}\sref@target% +\ifx\dcm@sect@short\@empty\csname #1\endcsname{#2}% +\else\csname #1\endcsname[\dcm@sect@short]{#2}\fi~% +\@ifundefined{sect@style} % +{\dcm@section@default@style{#1}}% +{\csname dcm@section@\sect@style @style\endcsname{#1}}} +%</package> +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\dcm@section@default@style} +% This is the default style for sectional metadata +% \begin{macrocode} +%<*package> +\def\dcm@section@default@style#1{% +\ifx\dcm@sect@creators\@empty\else% +\textbf{\dcm@creators@heading}:% +\@for\@I:=\dcm@sect@creators\do{~\csname dcm@person@\@I @name\endcsname}\fi% +\ifx\dcm@sect@contributors\@empty\else% there are contributors +\dcm@contributors@connector% +\@for\@I:=\dcm@sect@contributors\do{~\csname dcm@person@\@I @name\endcsname}\\\fi} +%</package> +% \end{macrocode} +% \end{macro} +% +% Armed with these, the rest is very simple +% +% \begin{macro}{\DCMchapter} +% \begin{macrocode} +%<*package> +\newcommand{\DCMchapter}[2][]% +{\dcm@section{chapter}{#2}{#1}\sref@label@id{\dcm@chapter@heading\ \thechapter}} +%</package> +% \end{macrocode} +% For the {\latexml} bindings we have to be a bit more creative. We only open the +% |omgroup| element (and declare it to autoclose)\ednote{@DEYAN, we need to document more +% here; and we should also close the metadata element just to be more tidy.} +% \begin{macrocode} +%<*ltxml> +Tag('omdoc:omgroup', autoClose=>1); +DefConstructor('\DCMchapter OptionalKeyVals:omgroup {}',sub { + my ($document,$keyvals,$title,%properties) = @_; + my $id=$keyvals->getValue('id')||""; + $document->openElement('omdoc:chapter',('xml:id'=>$id)); + $document->openElement('omdoc:metadata'); + $document->insertElement('dc:title',$title); + FishOutMetadata($document,$keyvals); + return;}); +%</ltxml> +% \end{macrocode} +% \end{macro} +% \ednote{@DEYAN: I guess since they all do the same as {\texttt{DCMchapter}}, we may +% actually get away with \texttt{Let(DCMsection,DCMchapter);} here.} +% \begin{macro}{\DCMsection} +% \begin{macrocode} +%<*package> +\newcommand{\DCMsection}[2][]% +{\dcm@section{section}{#2}{#1}\sref@label@id{\dcm@section@heading\ \thesection}} +%</package> +%<*ltxml> +DefConstructor('\DCMsection OptionalKeyVals:omgroup {}',sub{ + my ($document,$keyvals,$title,%properties) = @_; + my $id=$keyvals->getValue('id')||""; + $document->openElement('omdoc:section',('xml:id'=>$id)); + $document->openElement('omdoc:metadata'); + $document->insertElement('dc:title',$title); + FishOutMetadata($document,$keyvals); + return;}); +%</ltxml> +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\DCMsubsection} +% \begin{macrocode} +%<*package> +\newcommand{\DCMsubsection}[2][]% +{\dcm@section{subsection}{#2}{#1}\sref@label@id{\dcm@subsection@heading\ \thesubsection}} +%</package> +%<*ltxml> +DefConstructor('\DCMsubsection OptionalKeyVals:omgroup {}',sub{ + my ($document,$keyvals,$title,%properties) = @_; + my $id=$keyvals->getValue('id')||""; + $document->openElement('omdoc:subsection',('xml:id'=>$id)); + $document->openElement('omdoc:metadata'); + $document->insertElement('dc:title',$title); + FishOutMetadata($document,$keyvals); + return;}); +%</ltxml> +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\DCMsubsubsection} +% \begin{macrocode} +%<*package> +\newcommand{\DCMsubsubsection}[2][]% +{\dcm@section{subsubsection}{#2}{#1}\sref@label@id{\dcm@subsubsection@heading\ \thesubsubsection}} +%</package> +%<*ltxml> +DefConstructor('\DCMsubsubsection OptionalKeyVals:omgroup {}',sub{ + my ($document,$keyvals,$title,%properties) = @_; + my $id=$keyvals->getValue('id')||""; + $document->openElement('omdoc:subsubsection',('xml:id'=>$id)); + $document->openElement('omdoc:metadata'); + $document->insertElement('dc:title',$title); + FishOutMetadata($document,$keyvals); + return;}); +%</ltxml> +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\DCMparagraph} +% \begin{macrocode} +%<*package> +\newcommand{\DCMparagraph}[2][]% +{\dcm@section{paragraph}{#2}{#1}\sref@label@id{this \dcm@paragraph@heading}} +%</package> +%<*ltxml> +DefConstructor('\DCMparagraph OptionalKeyVals:omgroup {}',sub{ + my ($document,$keyvals,$title,%properties) = @_; + my $id=$keyvals->getValue('id')||""; + $document->openElement('omdoc:paragraph',('xml:id'=>$id)); + $document->openElement('omdoc:metadata'); + $document->insertElement('dc:title',$title); + FishOutMetadata($document,$keyvals); + return;}); +%</ltxml> +% \end{macrocode} +% \end{macro} +% +% We have to make sure that the DCM sectioning and metadata commands have IDs, so that we doc not get +% duplicates. +% +% \begin{macrocode} +%<*ltxml> +Tag('omdoc:chapter',afterOpen=>\&numberIt,afterClose=>\&locateIt,autoClose=>1); +Tag('omdoc:section',afterOpen=>\&numberIt,afterClose=>\&locateIt,autoClose=>1); +Tag('omdoc:subsection',afterOpen=>\&numberIt,afterClose=>\&locateIt,autoClose=>1); +Tag('omdoc:subsubsection',afterOpen=>\&numberIt,afterClose=>\&locateIt,autoClose=>1); +Tag('omdoc:paragraph',afterOpen=>\&numberIt,afterClose=>\&locateIt,autoClose=>1); +Tag('omdoc:subparagraph',afterOpen=>\&numberIt,afterClose=>\&locateIt,autoClose=>1); +Tag('dc:description',afterOpen=>\&numberIt,afterClose=>\&locateIt,autoClose=>1); +Tag('dc:date',afterOpen=>\&numberIt,afterClose=>\&locateIt,autoClose=>1); +Tag('dc:creator',afterOpen=>\&numberIt,afterClose=>\&locateIt,autoClose=>1); +Tag('dc:contributor',afterOpen=>\&numberIt,afterClose=>\&locateIt,autoClose=>1); +Tag('dc:title',afterOpen=>\&numberIt,afterClose=>\&locateIt,autoClose=>1); +Tag('dc:subject',afterOpen=>\&numberIt,afterClose=>\&locateIt,autoClose=>1); +Tag('dc:publisher',afterOpen=>\&numberIt,afterClose=>\&locateIt,autoClose=>1); +Tag('dc:type',afterOpen=>\&numberIt,afterClose=>\&locateIt,autoClose=>1); +Tag('dc:identifier',afterOpen=>\&numberIt,afterClose=>\&locateIt,autoClose=>1); +Tag('dc:language',afterOpen=>\&numberIt,afterClose=>\&locateIt,autoClose=>1); +Tag('dc:rights',afterOpen=>\&numberIt,afterClose=>\&locateIt,autoClose=>1); +%</ltxml> +% \end{macrocode} +% +% \DCMsubsection{Dealing with ISO Dates} +% +% The first step is to build a macro for making ISO dates.\ednote{make better ltxml} +% +% \begin{macrocode} +%<*package> +\def\ISOtimestamp{\count1=\time\divide\count1 by 60 % hours +\count2=\count1\multiply\count2 by 60% minutes in \count1 hours +\count3=\time\advance\count3 by -\count2 % minutes +\the\year -\ifnum\month>9\else0\fi\the\month-\ifnum\day>9\else0\fi\the\day +T\ifnum\count1>9\else0\fi\the\count1:\ifnum\count3>9\else0\fi\the\count3:00Z} +%</package> +%<*ltxml> +RawTeX('\def\ISOtimestamp{\count1=\time\divide\count1 by 60 % hours +\count2=\count1\multiply\count2 by 60% minutes in \count1 hours +\count3=\time\advance\count3 by -\count2 % minutes +\the\year -\the\month-\the\day T\the\count1:\the\count3:00Z}'); +%</ltxml> +% \end{macrocode} +% +%\DCMsubsection{Configuration} +% +% \begin{macrocode} +%<*package> +\def\dcm@abstract@heading{Abstract} +\def\dcm@creators@heading{Author(s)} +\def\dcm@contributors@connector{with contributions from} +\def\dcm@chapter@heading{Chapter} +\def\dcm@section@heading{Section} +\def\dcm@subsection@heading{Subsection} +\def\dcm@subsubsection@heading{Subsubsection} +%</package> +% \end{macrocode} +% +% \DCMsubsection[id=sec:impl:ids]{Providing IDs for {\omdoc} Elements} +% +% To provide default identifiers, we tag all {\omdoc} elements that allow |xml:id| +% attributes by executing the |numberIt| procedure below. +% +% \begin{macrocode} +%<*ltxml> +Tag('dc:title',afterOpen=>\&numberIt,afterClose=>\&locateIt); +%</ltxml> +% \end{macrocode} +% +%\DCMsubsection{Finale} +% +% Finally, we need to terminate the file with a success mark for perl. +% \begin{macrocode} +%<ltxml>1; +% \end{macrocode} +% \Finale +\endinput +% \iffalse +% LocalWords: GPL structuresharing STR LaTeX dcm dtx keyval sref CPERL url qw +%%% Local Variables: +%%% mode: doctex +%%% TeX-master: t +%%% End: +% \fi + +% LocalWords: RequirePackage birthdate personaltitle academictitle workaddress +% LocalWords: privaddress worktel privtel workfax privfax worktelfax noDelim +% LocalWords: privtelfax getKeyValue valuelist ToString getValue affill STDERR +% LocalWords: ExportMetadata AssignValue DCMperson DefConstructor afterDigest +% LocalWords: getArg setValue FishOutMetadata keyvals foreach idlist tabline +% LocalWords: LookupValue insertElement atabline bitabline shorttitle nc args +% LocalWords: sharealike noderivativeworks DefMacro authorblock subsubsection +% LocalWords: contribs OptionalKeyVals omgroup omdoc srcref locator xml RawTeX +% LocalWords: openElement iffalse kohlhase Thu scsys sc sc latexml DCmetadata +% LocalWords: maketitle DCMtitle texttt fileversion DCMcreators miko jdoe impl +% LocalWords: DCMabstract setcounter tocdepth tableofcontents newpage dmt03 +% LocalWords: DCMsection ednote DCMsubsection exfig hline dcmblock Patashnik +% LocalWords: DescribeEnv DCMcontributors DCMshorttitle DCMshorttitle DCMdate +% LocalWords: DCMsubject DCMsubject DCMdescription DCMdescription DCMpublisher +% LocalWords: DCMpublisher DCMdate DCMtype DCMtype DCMidentifier DCMidentifier +% LocalWords: DCMsource DCMsource DCMlanguage DCMlanguage DCMrelation ctancite +% LocalWords: DCMrelation DCMrights DCMrights DCMlicense DCMlicense titlepage +% LocalWords: DCMlicensenotice DCMlicensenotice DCMcopyrightnotice titlepage +% LocalWords: DCMcopyrightnotice DCMcclicense DCMcclicense user.blockstyles +% LocalWords: DCMchapter DCMchatper DCMsubsubsection DCMsubsubsection ltxml +% LocalWords: user.conig makeatletter printbibliography omdaddkey expandafter +% LocalWords: xdef csname endcsname newcommand omdsetkeys ifx ifundefined affs +% LocalWords: Semiverbatim whatsit newenvironment mtabline providecommand vfil +% LocalWords: DCMsubtitle cclicense defdcm impl.blockstyles newcounter vskip +% LocalWords: stepcounter tabularnewline theauthors lineskip textbf noindent +% LocalWords: omd omd srefaddidkey thechapter autoclose thesection ifnum ifnum +% LocalWords: thesubsection thesubsubsection DCMparagraph ISOtimestamp doctex diff --git a/Master/texmf-dist/source/latex/stex/mikoslides.dtx b/Master/texmf-dist/source/latex/stex/mikoslides/mikoslides.dtx index 2ed715feb0f..3840ff87e4e 100644 --- a/Master/texmf-dist/source/latex/stex/mikoslides.dtx +++ b/Master/texmf-dist/source/latex/stex/mikoslides/mikoslides.dtx @@ -24,7 +24,7 @@ %</driver> % \fi % -% \CheckSum{1} +% \CheckSum{317} % % \changes{v0.1}{2005/12/06}{Initial Version} % \changes{v0.2}{2006/01/11}{course notes back on seminar} diff --git a/Master/texmf-dist/source/latex/stex/modules/modules.dtx b/Master/texmf-dist/source/latex/stex/modules/modules.dtx new file mode 100644 index 00000000000..d68258bcdf6 --- /dev/null +++ b/Master/texmf-dist/source/latex/stex/modules/modules.dtx @@ -0,0 +1,1853 @@ +% \iffalse meta-comment +% An Infrastructure for Semantic Macros and Module Scoping +% Copyright (C) 2004-2010 Michael Kohlhase, all rights reserved +% this file is released under the +% LaTeX Project Public License (LPPL) +% +% The development version of this file can be found at +% $HeadURL: https://svn.kwarc.info/repos/stex/trunk/sty/modules/modules.dtx $ +% \fi +% +% \iffalse +%<package>\NeedsTeXFormat{LaTeX2e}[1999/12/01] +%<package>\ProvidesPackage{modules}[2010/06/25 v1.0 Semantic Markup] +% +%<*driver> +\documentclass{ltxdoc} +\usepackage{stex-logo,modules} +\usepackage{url,array,float,textcomp} +\usepackage[show]{ed} +\usepackage[hyperref=auto,style=alphabetic]{biblatex} +\usepackage{listings} +\usepackage{amsfonts} +\bibliography{kwarc} +\usepackage[eso-foot,today]{svninfo} +\svnInfo $Id: modules.dtx 1502 2010-07-20 08:17:00Z kohlhase $ +\svnKeyword $HeadURL: https://svn.kwarc.info/repos/stex/trunk/sty/modules/modules.dtx $ +\usepackage{../ctansvn} +\usepackage{hyperref} +\makeindex +\floatstyle{boxed} +\newfloat{exfig}{thp}{lop} +\floatname{exfig}{Example} +\begin{document}\DocInput{modules.dtx}\end{document} +%</driver> +% \fi +% +% \CheckSum{779} +% +% \changes{v0.9}{2005/06/14}{First Version with Documentation} +% \changes{v0.9a}{2005/07/01}{Completed Documentation} +% \changes{v0.9b}{2005/08/06}{Complete functionality and Updated Documentation} +% \changes{v0.9c}{2006/01/13}{more packaging} +% \changes{v0.9d}{2007/12/12}{fixing double loading of .tex and .sms} +% \changes{v0.9e}{2008/06/17}{fixing LaTeXML} +% \changes{v0.9f}{2008/06/17}{remove unused options uses and usesqualified} +% \changes{v0.9g}{2009/05/02}{adding resymdef functionality} +% \changes{v0.9g}{2009/08/12}{adding importOMDocmodule} +% \changes{v0.9h}{2010/01/19}{using {\texttt{\textbackslash mod@newcommand}} instead of +% {\texttt{\textbackslash providecommand}} for more intuitive inheritance.} +% \changes{v0.9h}{2010/03/05}{adding {\texttt{\textbackslash metalanguage}}} +% \changes{v1.0}{2010/06/18}{minor fixes} +% +% \GetFileInfo{modules.sty} +% +% \MakeShortVerb{\|} +%\def\scsys#1{{{\sc #1}}\index{#1@{\sc #1}}} +% \def\xml{\scsys{Xml}} +% \def\mathml{\scsys{MathML}} +% \def\omdoc{\scsys{OMDoc}} +% \def\openmath{\scsys{OpenMath}} +% \def\latexml{\scsys{LaTeXML}} +% \def\perl{\scsys{Perl}} +% \def\cmathml{Content-{\sc MathML}\index{Content {\sc MathML}}\index{MathML@{\sc MathML}!content}} +% \def\activemath{\scsys{ActiveMath}} +% \def\twin#1#2{\index{#1!#2}\index{#2!#1}} +% \def\twintoo#1#2{{#1 #2}\twin{#1}{#2}} +% \def\atwin#1#2#3{\index{#1!#2!#3}\index{#3!#2 (#1)}} +% \def\atwintoo#1#2#3{{#1 #2 #3}\atwin{#1}{#2}{#3}} +% \def\cT{\mathcal{T}}\def\cD{\mathcal{D}} +% \title{{\texttt{modules.sty}}: Semantic Macros and Module Scoping in {\stex}\thanks{Version {\fileversion} (last revised +% {\filedate})}} +% \author{Michael Kohlhase \& Deyan Ginev \& Rares Ambrus\\ +% Jacobs University, Bremen\\ +% \url{http://kwarc.info/kohlhase}} +% \maketitle +% +% \begin{abstract} +% The |modules| package is a central 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 a definition mechanism for semantic macros and a non-standard +% scoping construct for them, which is oriented at the semantic dependency relation +% rather than the document structure. This structure can be used by MKM systems for +% added-value services, either directly from the {\sTeX} sources, or after translation. +% \end{abstract} +% +% \newpage\setcounter{tocdepth}{2}\tableofcontents\newpage +% +% \section{Introduction}\label{sec:intro} +% +% Following general practice in the {\TeX/\LaTeX} community, we use the term ``semantic +% macro'' for a macro whose expansion stands for a mathematical object, and whose name +% (the command sequence) is inspired by the name of the mathematical object. This can +% range from simple definitions like |\def\Reals{\mathbb{R}}| for individual mathematical +% objects to more complex (functional) ones object constructors like +% |\def\SmoothFunctionsOn#1{\mathcal{C}^\infty(#1,#1)}|. Semantic macros are traditionally +% used to make {\TeX/\LaTeX} code more portable. However, the {\TeX/\LaTeX} scoping model +% (macro definitions are scoped either in the local group or until the rest of the +% document), does not mirror mathematical practice, where notations are scoped by +% mathematical environments like statements, theories, or such. For an in-depth discussion +% of semantic macros and scoping we refer the reader~\cite{Kohlhase:ulsmf08}. +% +% The |modules| package provides a {\LaTeX}-based markup infrastructure for defining +% module-scoped semantic macros and {\latexml} bindings~\cite{Miller:latexml:online} to +% create {\omdoc}~\cite{Kohlhase:omdoc1.2} from {\stex} documents. In the {\stex} world +% semantic macros have a special status, since they allow the transformation of +% {\TeX/\LaTeX} formulae into a content-oriented markup format like +% {\openmath}~\cite{BusCapCar:2oms04} and (strict) content +% {\mathml}~\cite{CarlisleEd:MathML3}; see Figure~\ref{fig:omsemmac} for an example, where +% the semantic macros above have been defined by the |\symdef| macros (see +% Section~\ref{sec:symdef}) in the scope of a |\begin{module}[id=calculus]| (see +% Section~\ref{sec:modules}). +% +% \begin{exfig}\lstset{basicstyle=\scriptsize,aboveskip=-.5em,belowskip=-1.5em} +% \begin{tabular}{l|p{9.7cm}} +% \LaTeX & \verb|\SmoothFunctionsOn\Reals| \\\hline +% PDF/DVI & ${\mathcal{C}^\infty(\mathbb{R},\mathbb{R})}$\\\hline +% {\openmath} & \lstset{morekeywords={OMA,OMS}} +% \begin{lstlisting} +% <OMA> +% <OMS cd="calculus" name="SmoothFunctionsOn"/> +% <OMS cd="calculus" name="Reals"/> +% </OMA>\end{lstlisting}\\\hline +% {\mathml} & \lstset{morekeywords={apply,csymbol}} +% \begin{lstlisting} +% <apply> +% <csymbol cd="calculus">SmoothFunctionsOn</csymbol> +% <csymbol cd="calculus">Reals</csymbol> +% </apply>\end{lstlisting}\\ +% \end{tabular} +% \caption{{\openmath} and {\mathml} generated from Semantic Macros}\label{fig:omsemmac} +% \end{exfig} +% +% \section{The User Interface} +% +% The main contributions of the |modules| package are the |module| environment, which +% allows for lexical scoping of semantic macros with inheritance and the |\symdef| macro +% for declaration of semantic macros that underly the |module| scoping. +% +% \subsection{Package Options}\label{sec:options} +% +% The |modules| package takes two options: If we set \DescribeMacro{showviews}|showviews|, +% then the views (see Section~\ref{sec:user:views}) are shown. If we set the +% \DescribeMacro{qualifiedimports}|qualifiedimports| option, then qualified imports are +% enabled. Qualified imports give more flexibility in module inheritance, but consume more +% internal memory. As qualified imports are not fully implemented at the moment, they are +% turned off by default see Limitation~\ref{sec:limitations:qualified-imports}. +% +% \subsection{Modules and Inheritance}\label{sec:modules} +% +% \DescribeEnv{module} The |module| environment takes an optional |KeyVal| +% argument. Currently, only the |id| key is supported for specifying the identifier of a +% module (also called the {\twintoo{module}{name}}). A module introduced by +% |\begin{module}[id=foo]| restricts the scope the semantic macros (see +% Section~\ref{sec:symdef}) defined by the |\symdef| form to the end of this module +% given by the corresponding |\end{module}|, and to any other |module| environments that +% import them by a |\importmodule{foo}| directive. If the module |foo| contains +% |\importmodule| directives of its own, these are also exported to the importing module. +% +% Thus the \DescribeMacro{\importmodule}|\importmodule| declarations induce the +% {\atwintoo{semantic}{inheritance}{relation}}. Figure~\ref{exf:importmodule} shows a +% module that imports the semantic macros from three others. In the simplest form, +% |\importmodule{|\meta{mod}|}| will activate the semantic macros and concepts declared by +% |\symdef| and |\termdef| in module \meta{mod} in the current module\footnote{Actually, +% in the current {\TeX} group, therefore \texttt{\textbackslash importmodule} should be +% placed directly after the \texttt{\textbackslash begin\{module\}}.}. To understand the +% mechanics of this, we need to understand a bit of the internals. The |module| +% environment sets up an internal macro pool, to which all the macros defined by the +% |\symdef| and |\termdef| declarations are added; |\importmodule| only activates this +% macro pool. Therefore |\importmodule{|\meta{mod}|}| can only work, if the {\TeX} parser +% --- which linearly goes through the {\sTeX} sources --- already came across the module +% \meta{mod}. In many situations, this is not obtainable; e.g. for ``semantic forward +% references'', where symbols or concepts are previewed or motivated to knowledgeable +% readers before they are formally introduced or for modularizations of documents into +% multiple files. To enable situations like these, the |module| package uses auxiliary +% files called {\textbf{\sTeX module signatures}}. For any file, \meta{file}|.tex|, we +% generate a corresponding \sTeX module signature \meta{file}|.sms| with the |sms| utility +% (see also Limitation~\ref{sec:limitations:sms}), which contains (copies of) all +% |\begin|/|\end{module}|, |\importmodule|, |\symdef|, and |\termdef| invocations in +% \meta{file}|.tex|. The value of an \sTeX module signature is that it can be loaded +% instead its corresponding \sTeX document, if we are only interested in the semantic +% macros. So |\importmodule[|\meta{filepath}|]{|\meta{mod}|}| will load the \sTeX module +% signature \meta{filepath}|.sms| (if it exists and has not been loaded before) and +% activate the semantic macros from module \meta{mod} (which was supposedly defined in +% \meta{filepath}|.tex|). Note that since \meta{filepath}|.sms| contains all +% |\importmodule| statements that \meta{filepath}|.tex| does, an |\importmodule| +% recursively loads all necessary files to supply the semantic macros inherited by the +% current module. +% +% The \DescribeMacro{\metalanguage} |metalanguage| macro is a variant of +% \lstinline|importmodule| that imports the meta language, i.e. the language in which the +% meaning of the new symbols is expressed. For mathematics this is often first-order logic +% with some set theory; see~\cite{RabKoh:WSMSML10} for discussion. +% +% \subsection{Semantic Macros and Module Scoping}\label{sec:symdef} +% +% The \DescribeMacro{\symdef} is the main constructor for semantic macros in {\sTeX}. A +% call to the |\symdef| macro has the general form +% \begin{quote} +% |\symdef[|\meta{keys}|]{|\meta{cseq}|}[|\meta{args}|]{|\meta{definiens}|}| +% \end{quote} +% where {\meta{cseq}} is a control sequence (the name of the semantic macro) {\meta{args}} +% is a number between 0 and 9 for the number of arguments {\meta{definiens}} is the token +% sequence used in macro expansion for {\meta{cseq}}. Finally {\meta{keys}} is a keyword +% list that further specifies the semantic status of the defined macro. +% +% The two semantic macros in Figure~\ref{fig:omsemmac} would have been declared by +% invocations of the |\symdef| macro of the form: +% \begin{verbatim} +% \symdef{Reals}{\mathbb{R}} +% \symdef{SmoothFunctionsOn}[1]{\mathcal{C}^\infty(#1,#1)} +% \end{verbatim} +% +% Note that both semantic macros correspond to {\openmath} or {\mathml} ``symbols'', +% i.e. named representations of mathematical concepts (the real numbers and the +% constructor for the space of smooth functions over a set); we call these names the +% {\textbf{symbol name}} of a semantic macro. Normally, the symbol name of a semantic +% macro declared by a |\symdef| directive is just \meta{cseq}. The key-value pair +% \DescribeMacro{name}|name=|\meta{symname} can be used to override this behavior and +% specify a differing name. There are two main use cases for this. +% +% The first one is shown in Example~\ref{fig:resymdef}, where we define semantic macros +% for the ``exclusive or'' operator. Note that we define two semantic macros: |\xorOp| and +% |\xor| for the applied form and the operator. As both relate to the same mathematical +% concept, their symbol names should be the same, so we specify |name=xor| on the +% definition of |\xorOp|. +% +% A key \DescribeMacro{local}|local| can be added to {\meta{keys}} to specify that the +% symbol is local to the module and is invisible outside. Note that even though |\symdef| +% has no advantage over |\def| for defining local semantic macros, it is still considered +% good style to use |\symdef| and |\abbrdef|, if only to make switching between local and +% exported semantic macros easier. +% +% \DescribeMacro{\abbrdef}The |\abbrdef| macro is a variant of |\symdef| that is only +% different in semantics, not in presentation. An abbreviative macro is like a semantic +% macro, and underlies the same scoping and inheritance rules, but it is just an +% abbreviation that is meant to be expanded, it does not stand for an atomic mathematical +% object. +% +% We will use a simple module for natural number arithmetics as a running example. It +% defines exponentiation and summation as new concepts while drawing on the basic +% operations like $+$ and $-$ from {\LaTeX}. In our example, we will define a semantic +% macro for summation |\Sumfromto|, which will allow us to express an expression like +% $\sum{i=1}^nx^i$ as |\Sumfromto{i}1n{2i-1}| (see Example~\ref{fig:semmodule} for an +% example). In this example we have also made use of a local semantic symbol for $n$, +% which is treated as an arbitrary (but fixed) symbol. +% +%\begin{exfig} +% \begin{verbatim} +% \begin{module}[id=arith] +% \symdef{Sumfromto}[4]{\sum_{#1=#2}^{#3}{#4}} +% \symdef[local]{arbitraryn}{n} +% What is the sum of the first $\arbitraryn$ odd numbers, i.e. +% $\Sumfromto{i}1\arbitraryn{2i-1}?$ +% \end{module} +% \end{verbatim} +% \vspace*{-3.5ex}\hrule\vspace*{1ex} +% \begin{module}[id=arith] +% \symdef{Sumfromto}[4]{\sum_{#1=#2}^{#3}{#4}} +% \symdef[local]{arbitraryn}{n} +% What is the sum of the first $\arbitraryn$ odd numbers, i.e. +% $\Sumfromto{i}1\arbitraryn{2i-1}?$ +% \end{module} +% \caption{Semantic Markup in a {\texttt{module}} Context}\label{fig:semmodule} +% \end{exfig} +% +% To locally change the presentation of a semantic macro, we can use the +% \DescribeMacro{\resymdef}|\resymdef| macro\footnote{For some reason, this does not +% interact very well with the {\texttt{beamer}} class, if used in side a {\texttt{frame}} +% environment, the option {\texttt{[fragile]}} should be given of {\texttt{frame}}.}. It +% takes the same arguments as the |\symdef| macro described above, but locally redefines +% the presentation. Consider for instance the situation in Figure~\ref{fig:resymdef} +% +%\begin{exfig} +% \begin{verbatim} +% \begin{module}[id=xbool] +% \symdef[name=xor]{xorOp}{\oplus} +% \symdef{xor}[2]{#1\xorOp #2} +% \termdef[name=xor]{xdisjunction}{exclusive disjunction} +% \captitalize\xdisjunction is commutative: $\xor{p}q=\xor{q}p$\\ +% \resymdef[name=xor]{xorOp}{\underline{\vee}} +% Some authors also write exclusive or with the $\xorOp$ operator, +% then the formula above is $\xor{p}q=\xor{q}p$ +% \end{module} +% \end{verbatim} +% \vspace*{-3.5ex}\hrule\vspace*{1ex} +% \begin{module}[id=xbool] +% \symdef[name=xor]{xorOp}{\oplus} +% \symdef{xor}[2]{#1\oplus#2} +% \termdef[name=xor]{xdisjunction}{exclusive disjunction} +% \capitalize\xdisjunction is communtative: $\xor{p}q=\xor{q}p$\\ +% \resymdef[name=xor]{xorOp}{\underline{\vee}} +% Some authors also write exclusive or with the $\xorOp$ operator, +% then the formula above is $\xor{p}q=\xor{q}p$ +% \end{module} +% \caption{Redefining the Presentation of a Semantic Macro}\label{fig:resymdef} +% \end{exfig} +% +% \subsection{Symbol and Concept Names}\label{sec:user:termdef} +% +% Just as the |\symdef| declarations define semantic macros for mathematical symbols, the +% |modules| package provides an infrastructure for {\emph{mathematical concepts}} that are +% expressed in mathematical vernacular. The key observation here is that concept names +% like ``finite symplectic group'' follow the same scoping rules as mathematical symbols, +% i.e. they are module-scoped. The \DescribeMacro{\termdef}|\termdef| macro is an analogue +% to |\symdef| that supports this: use +% |\termdef[|\meta{keys}|]{|\meta{cseq}|}{|\meta{concept}|}| to declare the macro +% |\|\meta{cseq} that expands to \meta{concept}. See Figure~\ref{fig:resymdef} for an +% example, where we use the \DescribeMacro{\capitalize}|\captitalize| macro to adapt +% \meta{concept} to the sentence beginning.\ednote{continue, describe \meta{keys}, they +% will have to to with plurals,\ldots once implemented}. The main use of the +% |\termdef|-defined concepts lies in automatic cross-referencing facilities via the +% \DescribeMacro{\termref}|\termref| and \DescribeMacro{\symref}|\symref| macros provided +% by the |statements| package~\ctancite{Kohlhase:smms}. Together with the |hyperref| +% package~\cite{RahObe:hmlmh10}, this provide cross-referencing to the definitions of the +% symbols and concepts. As discussed in section~\ref{sec:limitations:crossref}, the +% |\symdef| and |\termdef| declarations must be on top-level in a module, so the +% infrastructure provided in the |modules| package alone cannot be used to locate the +% definitions, so we use the infrastructure for mathematical statements for that. +% +% \subsection{Dealing with multiple Files}\label{sec:user:multiple} +% +% The infrastructure presented above works well if we are dealing with small files or +% small collections of modules. In reality, collections of modules tend to grow, get +% re-used, etc, making it much more difficult to keep everything in one file. This general +% trend towards increasing entropy is aggravated by the fact that modules are very +% self-contained objects that are ideal for re-used. Therefore in the absence of a +% content management system for {\LaTeX} document (fragments), module collections tend to +% develop towards the ``one module one file'' rule, which leads to situations with lots +% and lots of little files. +% +% Moreover, most mathematical documents are not self-contained, i.e. they do not build up +% the theory from scratch, but pre-suppose the knowledge (and notation) from other +% documents. In this case we want to make use of the semantic macros from these +% prerequisite documents without including their text into the current document. One way +% to do this would be to have {\LaTeX} read the prerequisite documents without producing +% output. For efficiency reasons, {\stex} chooses a different route. It comes with a +% utility |sms| (see Section~\ref{sec:utilities}) that exports the modules and macros +% defined inside them from a particular document and stores them inside |.sms| files. This +% way we can avoid overloading LaTeX with useless information, while retaining the +% important information which can then be imported in a more efficient way. +% +% \DescribeMacro{\importmodule} For such situations, the |\importmodule| macro can be +% given an optional first argument that is a path to a file that contains a path to the +% module file, whose module definition (the |.sms| file) is read. Note that the +% |\importmodule| macro can be used to make module files truly self-contained. To arrive +% at a file-based content management system, it is good practice to reuse the module +% identifiers as module names and to prefix module files with corresponding +% |\importmodule| statements that pre-load the corresponding module files. +% +%\begin{exfig} +% \begin{verbatim} +% \begin{module}[id=foo] +% \importmodule[../other/bar]{bar} +% \importmodule[../mycolleaguesmodules]{baz} +% \importmodule[../other/bar]{foobar} +% ... +% \end{module} +% \end{verbatim} +% \vspace{-1.7em} +% \caption{Self-contained Modules via {\texttt{importmodule}}}\label{exf:importmodule} +% \end{exfig} +% +% In Example~\ref{exf:importmodule}, we have shown the typical setup of a module +% file. The |\importmodule| macro takes great care that files are only read once, as +% {\sTeX} allows multiple inheritance and this setup would lead to an exponential (in the +% module inheritance depth) number of file loads. +% +% Sometimes we want to import an existing {\omdoc} theory\footnote{{\omdoc} theories are +% the counterpart of {\stex} modules.} $\widehat\cT$ into (the {\omdoc} document +% $\widehat\cD$ generated from) a {\stex} document $\cD$. Naturally, we have to provide an +% {\stex} stub module $\cT$ that provides |\symdef| declarations for all symbols we use in +% $\cD$. In this situation, we use\DescribeMacro{\importOMDocmodule} +% |\importOMDocmodule[|\meta{spath}|]{|\meta{OURI}|}{|\meta{name}|}|, where \meta{spath} +% is the file system path to $\cT$ (as in |\importmodule|, this argument must not contain +% the file extension), \meta{OURI} is the URI to the {\omdoc} module (this time with +% extension), and \meta{name} is the name of the theory $\widehat\cT$ and the module in +% $\cT$ (they have to be identical for this to work). Note that since the \meta{spath} +% argument is optional, we can make ``local imports'', where the stub $\cT$ is in $\cD$ +% and only contains the |\symdef|s needed there. +% +% Note that the recursive (depth-first) nature of the file loads induced by this setup is +% very natural, but can lead to problems with the depth of the file stack in the {\TeX} +% formatter (it is usually set to something like 15\footnote{If you have sufficient rights +% to change your {\TeX} installation, you can also increase the variable +% {\texttt{max\_in\_open}} in the relevant {\texttt{texmf.cnf}} file.}). Therefore, it +% may be necessary to circumvent the recursive load pattern providing (logically spurious) +% |\importmodule| commands. Consider for instance module |bar| in +%Example~\ref{exf:importmodule}, say that |bar| already has load depth 15, then we cannot +% naively import it in this way. If module |bar| depended say on a module |base| on the +% critical load path, then we could add a statement \DescribeMacro{\requiremodules} +% |\requiremodules{../base}| in the second line. This would load the modules from +% |../base.sms| in advance (uncritical, since it has load depth 10), so that it would not +% have to be re-loaded in the critical path of the module |foo|. Solving the load depth +% problem. +% +% \DescribeMacro{\sinput} In all of the above, we do not want to load an |sms| file, if +% the corresponding file has already been loaded, since the semantic macros are already in +% memory. Therefore the |modules| package supplies a semantic variant of the |\input| +% macro, which records in an internal register that the modules in the file have already +% been loaded. Thus if we consistently use |\sinput| instead of |\input| or |\include| for +% files that contain modules\footnote{files without modules should be treated by the +% regular {\LaTeX} input mechanism, since they do not need to be registered.}, we can +% prevent double loading of files and therefore gain efficiency. The +% \DescribeMacro{\sinputref} |\sinputref| macro behaves just like |\sinput| in the +% {\LaTeX} workflow, but in the {\latexml} conversion process creates a reference to the +% transformed version of the input file instead. +% +% Finally, the separation of documents into multiple modules often profits from a symbolic +% management of file paths. To simplify this, the |modules| package supplies the +% \DescribeMacro{\defpath}|\defpath| macro: |\defpath{|\meta{cname}|}{|\meta{path}|}| +% defines a command, so that |\|\meta{csname}|{|\meta{name}|}| expands to +% \meta{path}|/|\meta{name}. So we could have used +% \begin{lstlisting} +% \defpath{OPaths}{../other} +% \importmodule[\OPhats{bar}]{bar} +% \end{lstlisting} +% instead of the second line in Example~\ref{exf:importmodule}. The variant |\OPaths| has +% the big advantage that we can get around the fact that {\TeX/\LaTeX} does not set the +% current directory in |\input|, so that we can use systematically deployed +% |\defpath|-defined path macros to make modules relocatable by defining the path macros +% locally. +% +% \subsection{Including Externally Defined Semantic Macros } +% +% In some cases, we use an existing {\LaTeX} macro package for typesetting objects that +% have a conventionalized mathematical meaning. In this case, the macros are ``semantic'' +% even though they have not been defined by a |\symdef|. This is no problem, if we are +% only interested in the {\LaTeX} workflow. But if we want to e.g. transform them to +% {\omdoc} via {\latexml}, the {\latexml} bindings will need to contain references to an +% {\omdoc} theory that semantically corresponds to the {\LaTeX} package. In particular, +% this theory will have to be imported in the generated {\omdoc} file to make it +% {\omdoc}-valid. +% +% \DescribeMacro{\requirepackage} To deal with this situation, the |modules| package +% provides the |\requirepackage| macro. It takes two arguments: a package name, and a URI +% of the corresponding {\omdoc} theory. In the {\LaTeX} workflow this macro behaves like a +% |\usepackage| on the first argument, except that it can --- and should --- be used +% outside the {\LaTeX} preamble. In the {\latexml} workflow, this loads the {\latexml} +% bindings of the package specified in the first argument and generates an appropriate +% |imports| element using the URI in the second argument. +% +% \subsection{Views}\label{sec:user:views} +% +% \ednote{Document and make Examples} +% +% \section{Limitations \& Extensions}\label{sec:limitations} +% +% In this section we will discuss limitations and possible extensions of the |modules| +% package. Any contributions and extension ideas are welcome; please discuss ideas, +% requests, fixes, etc on the {\sTeX} TRAC~\cite{sTeX:online}. +% +% \subsection{Perl Utility \texttt{sms}}\label{sec:limitations:sms} +% +% Currently we have to use an external perl utility |sms| to extract \sTeX module +% signatures from \sTeX files. This considerably adds to the complexity of the \sTeX +% installation and workflow. If we can solve security setting problems that allows us to +% write to \sTeX module signatures outside the current directory, writing them from \sTeX +% may be an avenue of future development see~\cite[issue \#1522]{sTeX:online} for a +% discussion. +% +% \subsection{Qualified Imports}\label{sec:limitations:qualified-imports} +% +% In an earlier version of the \texttt{modules} package we used the \texttt{usesqualified} +% for importing macros with a disambiguating prefix (this is used whenever we have +% conflicting names for macros inherited from different modules). This is not accessible +% from the current interface. We need something like a |\importqualified| macro for this; +% see~\cite[issue \#1505]{sTeX:online}. Until this is implemented the infrastructure is +% turned off by default, but we have already introduced the +% \DescribeMacro{qualifiedimports}|qualifiedimports| option for the future. +% +% \subsection{Error Messages}\label{sec:limitations:errormsg} +% +% The error messages generated by the |modules| package are still quite bad. For instance +% if |thyA| does note exists we get the cryptic error message +% \begin{verbatim} +% ! Undefined control sequence. +% \module@defs@thyA ...hy +% \expandafter \mod@newcomma... +% l.490 ...ortmodule{thyA} +% \end{verbatim} +% This should definitely be improved. +% +% \subsection{Crossreferencing}\label{sec:limitations:crossref} +% +% Note that the macros defined by |\symdef| are still subject to the normal {\TeX} scoping +% rules. Thus they have to be at the top level of a module to be visible throughout the +% module as intended. As a consequence, the location of the |\symdef| elements cannot be +% used as targets for crossreferencing, which is currently supplied by the |statement| +% package~\ctancite{Kohlhase:smms}. A way around this limitation would be to import +% the current module from the \sTeX module signature (see Section~\ref{sec:modules}) via +% the |\importmodule| declaration. +% +% \section{Tips and Tricks}\label{sec:tipstricks} +% +% \subsection{Forward References}\label{sec:limitations:forward-references} +% +% It is a inherent limitation of {\sTeX} that we cannot have simple forward references in +% the same file (|\importmodules{|\meta{thy}|}|, where \meta{thy} is in the same file +% after the occurrence of |\importmodule|). In this case, we need to use +% |\importmodule[|\meta{jobname}|]{|\meta{thy}|}|, where \meta{jobname} is the name of the +% file or (if it is the top-level file {\LaTeX} is called with) even |\jobname|. +% +% \StopEventually{\newpage\PrintIndex\newpage\PrintChanges\newpage\printbibliography}\newpage +% +% \section{The Implementation} +% +% The |modules| package generates to files: the {\LaTeX} package (all the code between +% {\textlangle\textsf{*package}\textrangle} and {\textsf{\textlangle/package\textrangle}}) and the +% {\latexml} bindings (between {\textsf{\textlangle*ltxml\textrangle}} and +% {\textsf{\textlangle/ltxml\textrangle}}). We keep the corresponding code fragments together, +% since the documentation applies to both of them and to prevent them from getting out of +% sync. +% +% \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). +% \begin{macrocode} +%<*package> +\newif\ifmod@show\mod@showfalse +\DeclareOption{show}{\mod@showtrue} +\newif\ifmod@qualified\mod@qualifiedfalse +\DeclareOption{qualifiedimports}{\mod@qualifiedtrue} +% \end{macrocode} +% Finally, we need to declare the end of the option declaration section to {\LaTeX}. +% \begin{macrocode} +\ProcessOptions +%</package> +% \end{macrocode} +% +% {\latexml} does not support module options yet, so we do not have to do anything here +% for the {\latexml} bindings. We only set up the {\perl} packages (and tell {\texttt{emacs}} +% about the appropriate mode for convenience +% +% The next measure is to ensure that the |sref| and |xcomment| packages are loaded (in the +% right version). For {\latexml}, we also initialize the package inclusions. +% \begin{macrocode} +%<*package> +\RequirePackage{sref} +\RequirePackage{xspace} +\RequirePackage{xcomment} +%</package> +%<*ltxml> +# -*- CPERL -*- +package LaTeXML::Package::Pool; +use strict; +use LaTeXML::Global; +use LaTeXML::Package; +%</ltxml> +% \end{macrocode} +% +% \subsection{Modules and Inheritance}\label{sec:impl:modules} +% +% We define the keys for the |module| environment and the actions that are undertaken, +% when the keys are encountered. +% +% \begin{macro}{module:cd} +% This |KeyVal| key is only needed for {\latexml} at the moment; use this to specify a +% content dictionary name that is different from the module name. +% \begin{macrocode} +%<*package> +\define@key{module}{cd}{} +%</package> +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{module:id} +% For a module with |[id=|\meta{name}|]|, we have a macro |\module@defs@|\meta{name} +% that acts as a repository for semantic macros of the current module. I will be called +% by |\importmodule| to activate them. We will add the internal forms of the semantic +% macros whenever |\symdef| is invoked. To do this, we will need an unexpended form +% |\this@module| that expands to |\module@defs@|\meta{name}; we define it first and then +% initialize |\module@defs@|\meta{name} as empty. Then we do the same for qualified +% imports as well (if the |qualifiedimports| option was specified). Furthermore, we save +% the module name in |\mod@id| and the module path in |\|\meta{name}|@cd@file@base| +% which we add to |\module@defs@|\meta{name}, so that we can use it in the importing +% module. +% \begin{macrocode} +%<*package> +\define@key{module}{id}{% +\edef\this@module{\expandafter\noexpand\csname module@defs@#1\endcsname}% +\global\@namedef{module@defs@#1}{}% +\ifmod@qualified +\edef\this@qualified@module{\expandafter\noexpand\csname module@defs@qualified@#1\endcsname}% +\global\@namedef{module@defs@qualified@#1}{}% +\fi +\def\mod@id{#1}% +\expandafter\edef\csname #1@cd@file@base\endcsname{\mod@path}% +\expandafter\g@addto@macro\csname module@defs@#1\expandafter\endcsname\expandafter% +{\expandafter\def\csname #1@cd@file@base\expandafter\endcsname\expandafter{\mod@path}}} +%</package> +% \end{macrocode} +% \end{macro} +% +% \begin{environment}{module} +% finally, we define the begin module command for the module environment. All the work +% has already been done in the keyval bindings, so this is very simple. +% \begin{macrocode} +%<*package> +\newenvironment{module}[1][]{\setkeys{module}{#1}}{} +%</package> +% \end{macrocode} +% for the {\latexml} bindings, we have to do the work all at once. +% \begin{macrocode} +%<*ltxml> +DefEnvironment('{module} OptionalKeyVals:Module', + "?#excluded()(<omdoc:theory " + . "?&defined(&KeyVal(#1,'id'))(xml:id='&KeyVal(#1,'id')')(xml:id='#id')>#body</omdoc:theory>)", +# beforeDigest=>\&useTheoryItemizations, + afterDigestBegin=>sub { + my($stomach, $whatsit)=@_; + $whatsit->setProperty(excluded=>LookupValue('excluding_modules')); + + my $keys = $whatsit->getArg(1); + my($id, $cd)=$keys + && map(ToString($keys->getValue($_)),qw(id cd)); + #make sure we have an id or give a stub one otherwise: + if (not $id) { + #do magic to get a unique id for this theory + $whatsit->setProperties(beginItemize('theory')); + $id = ToString($whatsit->getProperty('id')); + } + $cd = $id unless $cd; + # update the catalog with paths for modules + my $module_paths = LookupValue('module_paths') || {}; + $module_paths->{$id} = LookupValue('last_module_path'); + AssignValue('module_paths', $module_paths, 'global'); + + #Update the current module position + AssignValue(current_module => $id); + AssignValue(module_cd => $cd) if $cd; + + #activate the module in our current scope + $STATE->activateScope("module:".$id); + + #Activate parent scope, if present + my $parentmod = LookupValue('parent_module'); + use_module($parentmod) if $parentmod; + #Update the current parent module + AssignValue("parent_of_$id"=>$parentmod,'global'); + AssignValue("parent_module" => $id); + return; }, + afterDigest => sub { + #Move a step up on the module ancestry + AssignValue("parent_module" => LookupValue("parent_of_".LookupValue("parent_module"))); + return; + }); +%</ltxml> +% \end{macrocode} +% \end{environment} +% +% +% \begin{macro}{usemodule} +% The |use_module| subroutine performs depth-first load of definitions of the used +% modules +% \begin{macrocode} +%<*ltxml> +sub use_module { + my($module,%ancestors)=@_; + $module = ToString($module); + if (defined $ancestors{$module}) { + Fatal(":module \"$module\" leads to import cycle!"); + } + $ancestors{$module}=1; + # Depth-first load definitions from used modules, disregarding cycles + foreach my $used_module (@{ LookupValue("module_${module}_uses") || []}){ + use_module($used_module,%ancestors); + } + # then load definitions for this module + $STATE->activateScope("module:$module"); }#$ +%</ltxml> +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\activate@defs} +% To activate the |\symdef|s from a given module xxx, we call the macro |\module@defs@xxx|. +% \begin{macrocode} +%<*package> +\def\activate@defs#1{\csname module@defs@#1\endcsname} +%</package> +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\export@defs} +% To export a the |\symdef|s from the current module, we all the macros +% |\module@defs@|\meta{mod} to |\module@defs@|\meta{mod} (if the current module has a +% name and it is \meta{mod}) +% \begin{macrocode} +%<*package> +\def\export@defs#1{\@ifundefined{mod@id}{}% +{\expandafter\expandafter\expandafter\g@addto@macro\expandafter% +\this@module\expandafter{\csname module@defs@#1\endcsname}}} +%</package> +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\importmodule} +% The |\importmodule[|\meta{file}|]{|\meta{mod}|}| macro is an interface macro that +% loads \meta{file} and activates and re-exports the |\symdef|s from module +% \meta{mod}. It also remembers the file name in |\mod@path|. +% \begin{macrocode} +%<*package> +\def\coolurion{} +\def\coolurioff{} +\newcommand{\importmodule}[2][]{{\def\mod@path{#1}% +\ifx\mod@path\@empty\else\requiremodules{#1}\fi}% +\activate@defs{#2}\export@defs{#2}} +%</package> +%<*ltxml> +DefMacro('\coolurion',sub {AssignValue('cooluri'=>1);}); +DefMacro('\coolurioff',sub {AssignValue('cooluri'=>0);}); +sub omext { + my ($mod)=@_; my $dest=''; + if (ToString($mod)) { + #We need a constellation of abs_path invocations + # to make sure that all symbolic links get resolved + my ($d,$f,$t) = pathname_split(abs_path(ToString($mod))); + $d = pathname_relative(abs_path($d),abs_path(cwd())); + $dest=$d."/".$f; + } + $dest.=".omdoc" if (ToString($mod) && !LookupValue('cooluri')); + return Tokenize($dest);} +sub importmoduleI { + my($stomach,$whatsit)=@_; + my $file = $whatsit->getArg(1); + my $omdocmod = $file.".omdoc" if $file; + my $module = $whatsit->getArg(2); + $module = ToString($module); + my $containing_module = LookupValue('current_module'); + #set the relation between the current module and the one to be imported + PushValue("module_".$containing_module."_uses"=>$module) if $containing_module; + #check if we've already loaded this module file or no file path given + if((!$file) || (LookupValue('file_'.$module.'_loaded'))) {use_module($module);} #if so activate it! + else { + #if not: + my $gullet = $stomach->getGullet; + #1) mark as loaded + AssignValue('file_'.$module.'_loaded' => 1, 'global'); + #open a group for its definitions so that they are localized + $stomach->bgroup; + #update the last module path + AssignValue('last_module_path', $file); + #queue the closing tag for this module in the gullet where it will be executed + #after all other definitions of the imported module have been taken care of + $gullet->unread(Invocation(T_CS('\end@requiredmodule'), T_OTHER($module))->unlist); + #we only need to load the sms definitions without generating any xml output, so we set the flag to 1 + AssignValue('excluding_modules' => 1); + #queue this module's sms file in the gullet so that its definitions are imported + $gullet->input($file,['sms']); + } + return;} +DefConstructor('\importmodule OptionalSemiverbatim {}', + "<omdoc:imports from='?#1(&omext(#1))\##2'/>", + afterDigest=>sub{ importmoduleI(@_)}); +%</ltxml> +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\importOMDocmodule} +% for the {\LaTeX} side we can just re-use |\importmodule|, for the {\latexml} side we +% have a full URI anyways. So things are easy. +% \begin{macrocode} +%<*package> +\newcommand{\importOMDocmodule}[3][]{\importmodule[#1]{#3}} +%</package> +%<*ltxml> +DefConstructor('\importOMDocmodule OptionalSemiverbatim {}{}',"<omdoc:imports from='#3\##2'/>", +afterDigest=>sub{ + #Same as \importmodule, just switch second and third argument. + my ($stomach,$whatsit) = @_; + my $path = $whatsit->getArg(1); + my $ouri = $whatsit->getArg(2); + my $module = $whatsit->getArg(3); + $whatsit->setArgs(($path, $module,$ouri)); + importmoduleI($stomach,$whatsit); + return; +}); +%</ltxml> +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\metalanguage} +% |\metalanguage| behaves exactly like |\importmodule| for formatting. For {\latexml}, +% we only add the |type| attribute. +% \begin{macrocode} +%<*package> +\let\metalanguage=\importmodule +%</package> +%<*ltxml> +DefConstructor('\metalanguage OptionalSemiverbatim {}', + "<omdoc:imports type='metalanguage' from='?#1(&omext(#1))\##2'/>", + afterDigest=>sub{ importmoduleI(@_)}); +%</ltxml> +% \end{macrocode} +% \end{macro} +% +% \subsection{Semantic Macros}\label{sec:impl:symdef} +% +% \begin{macro}{\mod@newcommand} +% We first hack the {\LaTeX} kernel macros to obtain a version of the |\newcommand| +% macro that does not check for definedness. This is just a copy of the code from +% |latex.ltx| where I have removed the |\@ifdefinable| check.\footnote{Someone must have +% done this before, I would be very happy to hear about a package that provides this.} +% \begin{macrocode} +%<*package> +\def\mod@newcommand{\@star@or@long\mod@new@command} +\def\mod@new@command#1{\@testopt{\@mod@newcommand#1}0} +\def\@mod@newcommand#1[#2]{\kernel@ifnextchar [{\mod@xargdef#1[#2]}{\mod@argdef#1[#2]}} +\long\def\mod@argdef#1[#2]#3{\@yargdef#1\@ne{#2}{#3}} +\long\def\mod@xargdef#1[#2][#3]#4{\expandafter\def\expandafter#1\expandafter{% +\expandafter\@protected@testopt\expandafter #1\csname\string#1\endcsname{#3}}% +\expandafter\@yargdef\csname\string#1\endcsname\tw@{#2}{#4}} +%</package> +% \end{macrocode} +% \end{macro} +% +% Now we define the optional KeyVal arguments for the |\symdef| form and the actions that +% are taken when they are encountered. +% +% \begin{macro}{symdef:keys} +% The optional argument local specifies the scope of the function to be defined. If +% local is not present as an optional argument then |\symdef| assumes the scope of the +% function is global and it will include it in the pool of macros of the current +% module. Otherwise, if local is present then the function will be defined only locally +% and it will not be added to the current module (i.e. we cannot inherit a local +% function). Note, the optional key local does not need a value: we write +% |\symdef[local]{somefunction}[0]{some expansion}|. The other keys are not used in the +% {\LaTeX} part. +% \begin{macrocode} +%<*package> +\define@key{symdef}{local}[true]{\@symdeflocaltrue} +\define@key{symdef}{name}{} +\define@key{symdef}{assocarg}{} +\define@key{symdef}{bvars}{} +\define@key{symdef}{bvar}{} +%</package> +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\symdef} +% The the |\symdef|, and |\@symdef| macros just handle optional arguments. +% \begin{macrocode} +%<*package> +\newif\if@symdeflocal +\def\symdef{\@ifnextchar[{\@symdef}{\@symdef[]}} +\def\@symdef[#1]#2{\@ifnextchar[{\@@symdef[#1]{#2}}{\@@symdef[#1]{#2}[0]}} +% \end{macrocode} +% next we locally abbreviate |\mod@newcommand| to make the argument passing simpler. +% \begin{macrocode} +\def\@mod@nc#1{\mod@newcommand{#1}[1]} +% \end{macrocode} +% now comes the real meat: the |\@@symdef| macro does two things, it adds the macro +% definition to the macro definition pool of the current module and also provides it. +% \begin{macrocode} +\def\@@symdef[#1]#2[#3]#4{% +% \end{macrocode} +% We use a switch to keep track of the local optional argument. We initialize the switch +% to false and check for the local keyword. Then we set all the keys that have been +% provided as arguments: |name|, |local|. First, using |\mod@newcommand| we initialize the +% intermediate function, the one that can be changed internally with |\resymdef| and then +% we link the actual function to it, again with |\mod@newcommand|. +% \begin{macrocode} +\@symdeflocalfalse\setkeys{symdef}{#1}% +\expandafter\mod@newcommand\csname modules@#2@pres\endcsname[#3]{#4}% +\expandafter\def\csname#2\endcsname{\csname modules@#2@pres\endcsname}% +\expandafter\@mod@nc\csname mod@symref@#2\expandafter\endcsname\expandafter% +{\expandafter\mod@termref\expandafter{\mod@id}{#2}{##1}}% +% \end{macrocode} +% We check if the switch for the local scope is set: if it is we are done, since this +% function has a local scope. Similarly, if we are not inside a module, which we could +% export from. Otherwise, we add two functions to the module's pool of defined macros +% using |\g@addto@macro|. We add both functions so that we can keep the link between the +% real and the intermediate function whenever we inherit the module. Finally we also add +% |\mod@symref@|\meta{sym} macro to the macro pool. +% \begin{macrocode} +\if@symdeflocal\else% +\@ifundefined{mod@id}{}{% +\expandafter\g@addto@macro\this@module% +{\expandafter\mod@newcommand\csname modules@#2@pres\endcsname[#3]{#4}}% +\expandafter\g@addto@macro\this@module% +{\expandafter\def\csname#2\endcsname{\csname modules@#2@pres\endcsname}}% +\expandafter\g@addto@macro\csname module@defs@\mod@id\expandafter\endcsname\expandafter% +{\expandafter\@mod@nc\csname mod@symref@#2\expandafter\endcsname\expandafter% +{\expandafter\mod@termref\expandafter{\mod@id}{#2}{##1}}}% +% \end{macrocode} +% Finally, using |\g@addto@macro| we add the two functions to the qualified version of the +% module if the |qualifiedimports| option was set. +% \begin{macrocode} +\ifmod@qualified% +\expandafter\g@addto@macro\this@qualified@module% +{\expandafter\mod@newcommand\csname modules@#2@pres@qualified\endcsname[#3]{#4}}% +\expandafter\g@addto@macro\this@qualified@module% +{\expandafter\def\csname#2atqualified\endcsname{\csname modules@#2@pres@qualified\endcsname}}% +\fi% +% \end{macrocode} +% So now we only need to close all brackets and the macro is done. +% \begin{macrocode} +}\fi} +%</package> +% \end{macrocode} +% In the {\latexml} bindings, we have a top-level macro that delegates the work to two +% internal macros: |\@symdef|, which defines the content macro and |\@symdef@pres|, which +% generates the {\omdoc} |symbol| and |presentation| elements (see +% Section~\ref{sec:impl:presentation}). +% \begin{macrocode} +%<*ltxml> +DefMacro('\DefMathOp OptionalKeyVals:symdef {}', + sub { + my($self,$keyval,$pres)=@_; + my $name = KeyVal($keyval,'name') if $keyval; + #Rewrite this token + my $scopes = $STATE->getActiveScopes; + DefMathRewrite(active=>$scopes,xpath=>'descendant-or-self::ltx:XMath',match=>ToString($pres),replace=>"\\".ToString($name)); + #Invoke symdef + (Invocation(T_CS('\symdef'),$keyval,$name,undef,undef,$pres)->unlist); + }); +DefMacro('\symdef OptionalKeyVals:symdef {}[][]{}', + sub { + my($self,@args)=@_; + ((Invocation(T_CS('\@symdef'),@args)->unlist), + (LookupValue('excluding_modules') ? () + : (Invocation(T_CS('\@symdef@pres'), @args)->unlist))); }); + +#Current list of recognized formatter command sequences: +our @PresFormatters = qw (infix prefix postfix assoc mixfixi mixfixa mixfixii mixfixia mixfixai mixfixaii mixfixiii); +DefPrimitive('\@symdef OptionalKeyVals:symdef {}[][]{}', sub { + my($stomach,$keys,$cs,$nargs,$opt,$presentation)=@_; + my($name,$cd,$role,$bvars,$bvar)=$keys + && map($_ && $_->toString,map($keys->getValue($_), qw(name cd role + bvars bvar))); + $cd = LookupValue('module_cd') unless $cd; + $name = $cs unless $name; + #Store for later lookup + AssignValue("symdef.".ToString($cs).".cd"=>ToString($cd),'global'); + AssignValue("symdef.".ToString($cs).".name"=>ToString($name),'global'); + $nargs = (ref $nargs ? $nargs->toString : $nargs || 0); + my $module = LookupValue('current_module'); + my $scope = (($keys && ($keys->getValue('local') || '' eq 'true')) ? 'module_local' : 'module').":".$module; + + #The DefConstructorI Factory is responsible for creating the \symbol command sequences as dictated by the \symdef + DefConstructorI("\\".$cs->toString,convertLaTeXArgs($nargs,$opt), sub { + my ($document,@args) = @_; + my @props = @args; + my $localpres = $presentation; + @args = splice(@props,0,$nargs); + my %prs = @props; + $prs{isbound} = "BINDER" if ($bvars || $bvar); + my $wrapped; + my $parent=$document->getNode; + if(! defined $parent->lookupNamespacePrefix("http://omdoc.org/ns")){ # namespace not already declared? + $document->getDocument->documentElement->setNamespace("http://omdoc.org/ns","omdoc",0); } + my $symdef_scope=$parent->exists('ancestor::omdoc:rendering'); #Are we in a \symdef rendering? + if (($localpres =~/^LaTeXML::Token/) && $symdef_scope) { + #Note: We should probably ask Bruce whether this maneuver makes sense + # We jump back to digestion, at a processing stage where it has been already completed + # Hence need to reinitialize all scopes and make a new group. This is probably expensive to do. + + my @toks = $localpres->unlist; + while(@toks && $toks[0]->equals(T_SPACE)){ shift(@toks); } # Remove leading space + my $formatters = join("|",@PresFormatters); + $formatters = qr/$formatters/; + $wrapped = (@toks && ($toks[0]->toString =~ /^\\($formatters)$/)); + $localpres = Invocation(T_CS('\@use'),$localpres) unless $wrapped; + # Plug in the provided arguments, doing a nasty reversion: + my @sargs = map (Tokens($_->revert), @args); + $localpres = Tokens(LaTeXML::Expandable::substituteTokens($localpres,@sargs)) if $nargs>0; + #Digest: + my $stomach = $STATE->getStomach; + $stomach->beginMode('inline-math'); + $STATE->activateScope($scope); + use_module($module); + use_module(LookupValue("parent_of_".$module)) if LookupValue("parent_of_".$module); + $localpres=$stomach->digest($localpres); + $stomach->endMode('inline-math'); + } + else { #Some are already digested to Whatsit, usually when dropped from a wrapping constructor + } + if ($nargs == 0) { + if (!$symdef_scope) { #Simple case - discourse flow, only a single XMTok + #Referencing XMTok when not in \symdefs: + $document->insertElement('ltx:XMTok',undef,(name=>$cs->toString, meaning=>$name,omcd=>$cd,role => $role,scriptpos=>$prs{'scriptpos'})); + } + else { + if ($symdef_scope && ($localpres =~/^LaTeXML::Whatsit/) && (!$wrapped)) {#1. Simple case: converts to a single token + $localpres->setProperties((name=>$cs->toString, meaning=>$name,omcd=>$cd,role => $role,scriptpos=>$prs{'scriptpos'})); + } + else { + #Experimental treatment - COMPLEXTOKEN + #$role=$role||'COMPLEXTOKEN'; + #$document->openElement('ltx:XMApp',role=>'COMPLEXTOKEN'); + #$document->insertElement('ltx:XMTok',undef,(name=>$cs->toString, meaning=>$name, omcd=>$cd, role=>$role, scriptpos=>$prs{'scriptpos'})); + #$document->openElement('ltx:XMWrap'); + #$document->absorb($localpres); + #$document->closeElement('ltx:XMWrap'); + #$document->closeElement('ltx:XMApp'); + } + #We need expanded presentation when invoked in \symdef scope: + + #Suppress errors from rendering attributes when absorbing. + #This is bad style, but we have no way around it due to the digestion acrobatics. + my $verbosity = $LaTeXML::Global::STATE->lookupValue('VERBOSITY'); + my $errors = $LaTeXML::Global::STATE->getStatus('error'); + $LaTeXML::Global::STATE->assignValue('VERBOSITY',-5); + + #Absorb presentation: + $document->absorb($localpres); + + #Return to original verbosity and error state: + $LaTeXML::Global::STATE->assignValue('VERBOSITY',$verbosity); + $LaTeXML::Global::STATE->setStatus('error',$errors); + + #Strip all/any <rendering><Math><XMath> wrappers: + #TODO: Ugly LibXML work, possibly do something smarter + my $parent = $document->getNode; + my @renderings=$parent->findnodes(".//omdoc:rendering"); + foreach my $render(@renderings) { + my $content=$render; + while ($content && $content->localname =~/^rendering|[X]?Math/) { + $content = $content->firstChild; + } + my $sibling = $content->parentNode->lastChild; + my $localp = $render->parentNode; + while ((defined $sibling) && (!$sibling->isSameNode($content))) { + my $clone = $sibling->cloneNode(1); + $localp->insertAfter($clone,$render); + $sibling = $sibling->previousSibling; + } + $render->replaceNode($content); + } + } + } + else {#2. Constructors with arguments + if (!$symdef_scope) { #2.1 Simple case, outside of \symdef declarations: + #Referencing XMTok when not in \symdefs: + $document->openElement('ltx:XMApp',scriptpos=>$prs{'scriptpos'},role=>$prs{'isbound'}); + $document->insertElement('ltx:XMTok',undef,(name=>$cs->toString, meaning=>$name, omcd=>$cd, role=>$role, scriptpos=>$prs{'operator_scriptpos'})); + foreach my $carg (@args) { + if ($carg =~/^LaTeXML::Token/) { + my $stomach = $STATE->getStomach; + $stomach->beginMode('inline-math'); + $carg=$stomach->digest($carg); + $stomach->endMode('inline-math'); + } + $document->openElement('ltx:XMArg'); + $document->absorb($carg); + $document->closeElement('ltx:XMArg'); + } + $document->closeElement('ltx:XMApp'); + } + else { #2.2 Complex case, inside a \symdef declaration + #We need expanded presentation when invoked in \symdef scope: + + #Suppress errors from rendering attributes when absorbing. + #This is bad style, but we have no way around it due to the digestion acrobatics. + my $verbosity = $LaTeXML::Global::STATE->lookupValue('VERBOSITY'); + my $errors = $LaTeXML::Global::STATE->getStatus('error'); + $LaTeXML::Global::STATE->assignValue('VERBOSITY',-5); + + #Absorb presentation: + $document->absorb($localpres); + + #Return to original verbosity and error state: + $LaTeXML::Global::STATE->assignValue('VERBOSITY',$verbosity); + $LaTeXML::Global::STATE->setStatus('error',$errors); + + #Strip all/any <rendering><Math><XMath> wrappers: + #TODO: Ugly LibXML work, possibly do something smarter? + my $parent = $document->getNode; + if(! defined $parent->lookupNamespacePrefix("http://omdoc.org/ns")){ # namespace not already declared? + $document->getDocument->documentElement->setNamespace("http://omdoc.org/ns","omdoc",0); } + my @renderings=$parent->findnodes(".//omdoc:rendering"); + foreach my $render(@renderings) { + my $content=$render; + while ($content && $content->localname =~/^rendering|[X]?Math/) { + $content = $content->firstChild; + } + my $sibling = $content->parentNode->lastChild; + my $localp = $render->parentNode; + while ((defined $sibling) && (!$sibling->isSameNode($content))) { + my $clone = $sibling->cloneNode(1); + $localp->insertAfter($clone,$render); + $sibling = $sibling->previousSibling; + } + $render->replaceNode($content); + } + } + }}, + properties => {name=>$cs->toString, meaning=>$name,omcd=>$cd,role => $role}, + scope=>$scope); + return; }); +%</ltxml> +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\resymdef} +% We can use this function to redefine our intermediate presentational function inside +% the modules\ednote{We have already prepared the argument parsing for an optional first +% argument, but this is not looked at yet. }\ednote{does not seem to have a {\latexml} +% counterpart yet!} +% \begin{macrocode} +%<*package> +\def\resymdef{\@ifnextchar[{\@resymdef}{\@resymdef[]}} +\def\@resymdef[#1]#2{\@ifnextchar[{\@@resymdef[#1]{#2}}{\@@resymdef[#1]{#2}[0]}} +\def\@@resymdef[#1]#2[#3]#4{\expandafter\renewcommand\csname modules@#2@pres\endcsname[#3]{#4}} +%</package> +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\abbrdef} +% The |\abbrdef| macro is a variant of |\symdef| that does the same on the {\LaTeX} +% level. +% \begin{macrocode} +%<*package> +\let\abbrdef\symdef +%</package> +%<*ltxml> +DefPrimitive('\abbrdef OptionalKeyVals:symdef {}[][]{}', sub { + my($stomach,$keys,$cs,$nargs,$opt,$presentation)=@_; + my $module = LookupValue('current_module'); + my $scope = (($keys && ($keys->getValue('local') || '' eq 'true')) ? 'module_local' : 'module').":$module"; + DefMacroI("\\".$cs->toString,convertLaTeXArgs($nargs,$opt),$presentation, + scope=>$scope); + return; }); +%</ltxml> +% \end{macrocode} +% \end{macro} +% +% \subsection{Symbol and Concept Names}\label{sec:impl:concepts} +% +% \begin{macro}{\mod@path} +% the |\mod@path| macro is used to remember the local path, so that the |module| +% environment can set it for later cross-referencing of the modules. If |\mod@path| is +% empty, then it signifies the local file. +% \begin{macrocode} +%<*package> +\def\mod@path{} +%</package> +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\termdef} +% \begin{macrocode} +%<*package> +\def\mod@true{true} +\omdaddkey[false]{termdef}{local} +\omdaddkey{termdef}{name} +\newcommand{\termdef}[3][]{\omdsetkeys{termdef}{#1}% +\expandafter\mod@newcommand\csname#2\endcsname[0]{#3\xspace} +\ifx\termdef@local\mod@true\else% +\@ifundefined{mod@id}{}{\expandafter\g@addto@macro\this@module% +{\expandafter\mod@newcommand\csname#2\endcsname[0]{#3\xspace}}} +\fi} +%</package> +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\capitalize} +% \begin{macrocode} +%<*package> +\def\@captitalize#1{\uppercase{#1}} +\newcommand\capitalize[1]{\expandafter\@captitalize #1} +%</package> +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\mod@termref} +% |\mod@termref{|\meta{module}|}{|\meta{name}|}{|\meta{nl}|}| determines whether the +% macro |\|\meta{module}|@cd@file@base| is defined. If it is, we make it the prefix of a +% URI reference in the local macro |\@uri|, which we compose to the hyper-reference, +% otherwise we give a warning. +% \begin{macrocode} +%<*package> +\def\mod@termref#1#2#3{\def\@test{#3} +\@ifundefined{#1@cd@file@base} + {\protect\G@refundefinedtrue + \@latex@warning{\protect\termref with unidentified cd "#1": the cd key must + reference an active module} + \def\@label{sref@#2 @target}} + {\def\@label{sref@#2@#1@target}}% +\expandafter\ifx\csname #1@cd@file@base\endcsname\@empty% local reference +\sref@hlink@ifh{\@label}{\ifx\@test\@empty #2\else #3\fi}\else% +\def\@uri{\csname #1@cd@file@base\endcsname.pdf\#\@label}% +\sref@href@ifh{\@uri}{\ifx\@test\@empty #2\else #3\fi}\fi} +%</package> +% \end{macrocode} +% \end{macro} +% +% \subsection{Dealing with Multiple Files}\label{sec:impl:multiple} +% +% Before we can come to the functionality we want to offer, we need some auxiliary +% functions that deal with path names. +% +% \subsubsection{Simplifying Path Names} +% +% The |\mod@simplify| macro is used for simplifying +% path names by removing \meta{xxx}|/..| from a string. eg: +% \meta{aaa}|/|\meta{bbb}|/../|\meta{ddd} goes to \meta{aaa}|/|\meta{ddd} unless +% \meta{bbb} is |..|. This is used to normalize relative path names below. +% +% \begin{macro}{\mod@simplify} +% The macro |\mod@simplify| recursively runs over the path collecting the result in the +% internal |\mod@savedprefix| macro. +% \begin{macrocode} +%<*package> +\def\mod@simplify#1{\expandafter\mod@simpl#1/\relax} +% \end{macrocode} +% It is based on the |\mod@simpl| macro\ednote{what does the mod@blaaa do?} +% \begin{macrocode} +\def\mod@simpl#1/#2\relax{\def\@second{#2}% +\ifx\mod@blaaaa\@empty\edef\mod@savedprefix{}\def\mod@blaaaa{aaa}\else\fi% +\ifx\@second\@empty\edef\mod@savedprefix{\mod@savedprefix#1}% +\else\mod@simplhelp#1/#2\relax\fi} +% \end{macrocode} +% which in turn is based on a helper macro +% \begin{macrocode} +\def\mod@updir{..} +\def\mod@simplhelp#1/#2/#3\relax{\def\@first{#1}\def\@second{#2}\def\@third{#3}% +%\message{mod@simplhelp: first=\@first, second=\@second, third=\@third, result=\mod@savedprefix.} +\ifx\@third\@empty% base case +\ifx\@second\mod@updir\else% +\ifx\mod@second\@empty\edef\mod@savedprefix{\mod@savedprefix#1}% +\else\edef\mod@savedprefix{\mod@savedprefix#1/#2}% +\fi% +\fi% +\else% +\ifx\@first\mod@updir% +\edef\mod@savedprefix{\mod@savedprefix#1/}\mod@simplhelp#2/#3\relax% +\else% +\ifx\@second\mod@updir\mod@simpl#3\relax% +\else\edef\mod@savedprefix{\mod@savedprefix#1/}\mod@simplhelp#2/#3\relax% +\fi% +\fi% +\fi}% +%</package> +% \end{macrocode} +% \end{macro} +% +% We directly test the simplification: \makeatletter +% \def\mod@simpl@test#1{\def\mod@savedprefix{}\mod@simplify{#1}\mod@savedprefix} +% \begin{center} +% \begin{tabular}{|l|l|l|}\hline +% source & result & should be \\\hline\hline +% ../../aaa & \mod@simpl@test{../../aaa} & ../../aaa\\\hline +% aaa/bbb & \mod@simpl@test{aaa/bbb} & aaa/bbb\\\hline +% aaa/.. & \mod@simpl@test{aaa/..} & \\\hline +% ../../aaa/bbb & \mod@simpl@test{../../aaa/bbb} & ../../aaa/bbb\\\hline +% ../aaa/../bbb & \mod@simpl@test{../aaa/../bbb} & ../bbb\\\hline +% ../aaa/bbb & \mod@simpl@test{../aaa/bbb} & ../aaa/bbb\\\hline +% aaa/bbb/../ddd & \mod@simpl@test{aaa/bbb/../ddd} & aaa/ddd\\\hline +% \end{tabular} +% \end{center} +% \makeatother +% +% \begin{macro}{\defpath} +% \begin{macrocode} +%<*package> +\newcommand{\defpath}[2]{\expandafter\newcommand\csname #1\endcsname[1]{#2/##1}} +%</package> +%<*ltxml> +DefMacro('\defpath{}{}', sub { + my ($gullet,$arg1,$arg2)=@_; + $arg1 = ToString($arg1); + $arg2 = ToString($arg2); + my $paths = LookupValue('defpath')||{}; + $$paths{"$arg1"}=$arg2; + AssignValue('defpath'=>$paths,'global'); + DefMacro('\\'.$arg1.' {}',$arg2."/#1"); + });#$ +%</ltxml> +% \end{macrocode} +% \end{macro} +% +% \subsection{Loading Module Signatures} +% +% We will need a switch\ednote{explain why?} +% \begin{macrocode} +%<*package> +\newif\ifmodules +% \end{macrocode} +% and a ``registry'' macro whose expansion represents the list of added macros (or files) +% \begin{macro}{\mod@reg} +% We initialize the |\mod@reg| macro with the empty string. +% \begin{macrocode} +\gdef\mod@reg{} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\mod@update} +% This macro provides special append functionality. It takes a string and appends it +% to the expansion of the |\mod@reg| macro in the following way: |string@\mod@reg|. +% \begin{macrocode} +\def\mod@update#1{\ifx\mod@reg\@empty\xdef\mod@reg{#1}\else\xdef\mod@reg{#1@\mod@reg}\fi} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\mod@check} +% The |\mod@check| takes as input a file path (arg 3), and searches the registry. If the +% file path is not in the registry it means it means it has not been already added, so +% we make |\ifmodules| true, otherwise make |\ifmodules| false. The macro |\mod@search| +% will look at |\ifmodules| and update the registry for |\modulestrue| or do nothing for +% |\modulesfalse|. +% \begin{macrocode} +\def\mod@check#1@#2///#3\relax{% +\def\mod@one{#1}\def\mod@two{#2}\def\mod@three{#3}% +% \end{macrocode} +% Define a few intermediate macros so that we can split the registry into separate file +% paths and compare to the new one +% \begin{macrocode} +\expandafter% +\ifx\mod@three\mod@one\modulestrue% +\else% +\ifx\mod@two\@empty\modulesfalse\else\mod@check#2///#3\relax\fi% +\fi} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\mod@search} +% Macro for updating the registry after the execution of |\mod@check| +% \begin{macrocode} +\def\mod@search#1{% +% \end{macrocode} +% We put the registry as the first argument for |\mod@check| and the other +% argument is the new file path. +% \begin{macrocode} +\modulesfalse\expandafter\mod@check\mod@reg @///#1\relax% +% \end{macrocode} +% We run |\mod@check| with these arguments and the check |\ifmodules| for +% the result +% \begin{macrocode} +\ifmodules\else\mod@update{#1}\fi} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\mod@reguse} +% The macro operates almost as the |mod@search| function, but it does not update the +% registry. Its purpose is to check whether some file is or not inside the registry but +% without updating it. Will be used before deciding on a new sms file +% \begin{macrocode} +\def\mod@reguse#1{\modulesfalse\expandafter\mod@check\mod@reg @///#1\relax} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\mod@prefix} +% This is a local macro for storing the path prefix, we initialize it as the empty +% string. +% \begin{macrocode} +\def\mod@prefix{} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\mod@updatedpre} +% This macro updates the path prefix |\mod@prefix| with the last word in the path given +% in its argument. +% \begin{macrocode} +\def\mod@updatedpre#1{% +\edef\mod@prefix{\mod@prefix\mod@pathprefix@check#1/\relax}} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\mod@pathprefix@check} +% |\mod@pathprefix@check| returns the last word in a string composed of words separated +% by slashes +% \begin{macrocode} +\def\mod@pathprefix@check#1/#2\relax{% +\ifx\\#2\\% no slash in string +\else\mod@ReturnAfterFi{#1/\mod@pathprefix@help#2\relax}% +\fi} +% \end{macrocode} +% It needs two helper macros: +% \begin{macrocode} +\def\mod@pathprefix@help#1/#2\relax{% +\ifx\\#2\\% end of recursion +\else\mod@ReturnAfterFi{#1/\mod@pathprefix@help#2\relax}% +\fi} +\long\def\mod@ReturnAfterFi#1\fi{\fi#1} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\mod@pathpostfix@check} +% |\mod@pathpostfix@check| takes a string composed of words separated by slashes and +% returns the part of the string until the last slash +% \begin{macrocode} +\def\mod@pathpostfix@check#1/#2\relax{% slash +\ifx\\#2\\%no slash in string +#1\else\mod@ReturnAfterFi{\mod@pathpostfix@help#2\relax}% +\fi} +% \end{macrocode} +% Helper function for the |\pathpostfix@check| macro defined above +% \begin{macrocode} +\def\mod@pathpostfix@help#1/#2\relax{% +\ifx\\#2\\% +#1\else\mod@ReturnAfterFi{\mod@pathpostfix@help#2\relax}% +\fi} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\mod@updatedpost} +% This macro updates |\mod@savedprefix| with leading path (all but the last word) in the path given +% in its argument. +% \begin{macrocode} +\def\mod@updatedpost#1{% +\edef\mod@savedprefix{\mod@savedprefix\mod@pathpostfix@check#1/\relax}} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\mod@updatedsms} +% Finally: A macro that will add a |.sms| extension to a path. Will be used when adding a |.sms| file +% \begin{macrocode} +\def\mod@updatesms{\edef\mod@savedprefix{\mod@savedprefix.sms}} +%</package> +% \end{macrocode} +% \end{macro} +% +% \subsubsection{Selective Inclusion} +% +% \begin{macro}{\requiremodules} +% \begin{macrocode} +%<*package> +\newcommand{\requiremodules}[1]{% +{\mod@updatedpre{#1}% add the new file to the already existing path +\let\mod@savedprefix\mod@prefix% add the path to the new file to the prefix +\mod@updatedpost{#1}% +\def\mod@blaaaa{}% macro used in the simplify function (remove .. from the prefix) +\mod@simplify{\mod@savedprefix}% remove |xxx/..| from the path (in case it exists) +\mod@reguse{\mod@savedprefix}% +\ifmodules\else% +\mod@updatesms% update the file to contain the .sms extension +\let\newreg\mod@reg% use to compare, in case the .sms file was loaded before +\mod@search{\mod@savedprefix}% update registry +\ifx\newreg\mod@reg\else\input{\mod@savedprefix}\fi% check if the registry was updated and load if necessary +\fi}} +%</package> +%<*ltxml> +DefPrimitive('\requiremodules{}', sub { + my($stomach,$module)=@_; + my $GULLET = $stomach->getGullet; + $module = Digest($module)->toString; + if(LookupValue('file_'.$module.'_loaded')) {} + else { + AssignValue('file_'.$module.'_loaded' => 1, 'global'); + $stomach->bgroup; + AssignValue('last_module_path', $module); + $GULLET->unread(T_CS('\end@requiredmodule')); + AssignValue('excluding_modules' => 1); + $GULLET->input($module,['sms']); + } + return;}); + +DefPrimitive('\end@requiredmodule{}',sub { + #close the group + $_[0]->egroup; + #print STDERR "END: ".ToString(Digest($_[1])->toString); + #Take care of any imported elements in this current module by activating it and all its dependencies + #print STDERR "Important: ".ToString(Digest($_[1])->toString)."\n"; + use_module(ToString(Digest($_[1])->toString)); + return; });#$ +%</ltxml> +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\sinput} +% \begin{macrocode} +%<*package> +\def\sinput#1{ +{\mod@updatedpre{#1}% add the new file to the already existing path +\let\mod@savedprefix\mod@prefix% add the path to the new file to the prefix +\mod@updatedpost{#1}% +\def\mod@blaaaa{}% macro used in the simplify function (remove .. from the prefix) +\mod@simplify{\mod@savedprefix}% remove |xxx/..| from the path (in case it exists) +\mod@reguse{\mod@savedprefix}% +\let\newreg\mod@reg% use to compare, in case the .sms file was loaded before +\mod@search{\mod@savedprefix}% update registry +\ifx\newreg\mod@reg%\message{This file has been previously introduced} +\else\input{\mod@savedprefix}% +\fi}} +%</package> +%<*ltxml> +DefPrimitive('\sinput Semiverbatim', sub { + my($stomach,$module)=@_; + my $GULLET = $stomach->getGullet; + $module = Digest($module)->toString; + AssignValue('file_'.$module.'_loaded' => 1, 'global'); + $stomach->bgroup; + AssignValue('last_module_path', $module); + $GULLET->unread(Invocation(T_CS('\end@requiredmodule'),T_OTHER($module))->unlist); + $GULLET->input($module,['tex']); + return;});#$ +%</ltxml> +% \end{macrocode} +% \end{macro} +% \ednote{the sinput macro is just faked, it should be more like requiremodules, except +% that the tex file is inputted; I wonder if this can be simplified.} +% +% \begin{macrocode} +%<*package> +\let\sinputref=\sinput +%</package> +%<*ltxml> +DefConstructor('\sinputref{}',"<omdoc:ref xref='#1.omdoc' type='include'/>"); +%</ltxml> +% \end{macrocode} +% +% \subsubsection{Generating {\texorpdfstring\omdoc{OMDoc}} Presentation Elements}\label{sec:impl:presentation} +% +% Additional bundle of code to generate presentation encodings. Redefined to an expandable +% (macro) so that we can add conversions. +% +% \begin{macrocode} +%<*ltxml> +DefMacro('\@symdef@pres OptionalKeyVals:symdef {}[][]{}', sub { + my($self,$keys, $cs,$nargs,$opt,$presentation)=@_; + + my($name,$cd,$role)=$keys + && map($_ && $_->toString,map($keys->getValue($_), qw(name cd role))); + $cd = LookupValue('module_cd') unless $cd; + $name = $cs unless $name; + AssignValue('module_name'=>$name) if $name; + $nargs = 0 unless ($nargs); + my $nargkey = ToString($name).'_args'; + AssignValue($nargkey=>ToString($nargs)) if $nargs; + $name=ToString($name); + + Invocation(T_CS('\@symdef@pres@aux'), + $cs, + ($nargs || Tokens(T_OTHER(0))), + symdef_presentation_pmml($cs,ToString($nargs)||0,$presentation), +# symdef_presentation_TeX($presentation), + (Tokens(T_OTHER($name))), + (Tokens(T_OTHER($cd))), + $keys)->unlist; });#$ +% \end{macrocode} +% Generate the expansion of a symdef's macro using special arguments. +% +% Note that the |symdef_presentation_pmml| subroutine is responsible for preserving the +% rendering structure of the original definition. Hence, we keep a +% collection of all known formatters in the |@PresFormatters| array, +% which should be updated whenever the list of allowed formatters has +% been altered. +% +% \begin{macrocode} +sub symdef_presentation_pmml { + my($cs,$nargs,$presentation)=@_; + my @toks = $presentation->unlist; + while(@toks && $toks[0]->equals(T_SPACE)){ shift(@toks); } # Remove leading space + $presentation = Tokens(@toks); + # Wrap with \@use, unless already has a recognized formatter. + my $formatters = join("|",@PresFormatters); + $formatters = qr/$formatters/; + $presentation = Invocation(T_CS('\@use'),$presentation) + unless (@toks && ($toks[0]->toString =~ /^\\($formatters)$/)); + # Low level substitution. + my @args = map(Invocation(T_CS('\@SYMBOL'),T_OTHER("arg:".($_))),1..$nargs); + $presentation = Tokens(LaTeXML::Expandable::substituteTokens($presentation,@args)); + $presentation; }#$ +% \end{macrocode} +% The |\@use| macro just generates the contents of the notation element +% \begin{macrocode} +sub getSymmdefProperties { + my $cd = LookupValue('module_cd'); + my $name = LookupValue('module_name'); + my $nargkey = ToString($name).'_args'; + my $nargs = LookupValue($nargkey); + $nargs = 0 unless ($nargs); + my %props = ('cd'=>$cd,'name'=>$name,'nargs'=>$nargs); + return %props;} +DefConstructor('\@use{}', sub{ + my ($document,$args,%properties) = @_; + #Notation created at \@symdef@pres@aux + #Create the rendering: + $document->openElement('omdoc:rendering'); + $document->openElement('ltx:Math'); + $document->openElement('ltx:XMath'); + if ($args->isMath) {$document->absorb($args);} + else { $document->insertElement('ltx:XMText',$args);} + $document->closeElement('ltx:XMath'); + $document->closeElement('ltx:Math'); + $document->closeElement('omdoc:rendering'); +}, +properties=>sub { getSymmdefProperties($_[1]);}, + mode=>'inline_math'); +% \end{macrocode} +% The |get_cd| procedure reads of the cd from our list of keys. +% \begin{macrocode} +sub get_cd { + my($name,$cd,$role)=@_; + return $cd;} +% \end{macrocode} +% The |\@symdef@pres@aux| creates the |symbol| element and the outer layer of the of the +% |notation| element. The content of the latter is generated by applying the {\latexml} to +% the definiens of the |\symdef| form. +% \begin{macrocode} +DefConstructor('\@symdef@pres@aux{}{}{}{}{} OptionalKeyVals:symdef', sub { + my ($document,$cs,$nargs,$pmml,$name,$cd,$keys)=@_; + my $assocarg = ToString($keys->getValue('assocarg')) if $keys; + $assocarg = $assocarg||"0"; + my $bvars = ToString($keys->getValue('bvars')) if $keys; + $bvars = $bvars||"0"; + my $bvar = ToString($keys->getValue('bvar')) if $keys; + $bvar = $bvar||"0"; + my $appElement = 'om:OMA'; $appElement = 'om:OMBIND' if ($bvars || $bvar); + + $document->insertElement("omdoc:symbol",undef,(name=>$cs,"xml:id"=>ToString($cs).".sym")); + $document->openElement("omdoc:notation",(name=>$name,cd=>$cd)); + #First, generate prototype: + $nargs = ToString($nargs)||0; + $document->openElement('omdoc:prototype'); + $document->openElement($appElement) if $nargs; + my $cr="fun" if $nargs; + $document->insertElement('om:OMS',undef, + (cd=>$cd, + name=>$name, + "cr"=>$cr)); + if ($bvar || $bvars) { + $document->openElement('om:OMBVAR'); + if ($bvar) { + $document->insertElement('omdoc:expr',undef,(name=>"arg$bvar")); + } else { + $document->openElement('omdoc:exprlist',(name=>"args")); + $document->insertElement('omdoc:expr',undef,(name=>"arg")); + $document->closeElement('omdoc:exprlist'); + } + $document->closeElement('om:OMBVAR'); + } + for my $id(1..$nargs) { + next if ($id==$bvars || $id==$bvar); + if ($id!=$assocarg) { + my $argname="arg$id"; + $document->insertElement('omdoc:expr',undef,(name=>"$argname")); + } + else { + $document->openElement('omdoc:exprlist',(name=>"args")); + $document->insertElement('omdoc:expr',undef,(name=>"arg")); + $document->closeElement('omdoc:exprlist'); + } + } + $document->closeElement($appElement) if $nargs; + $document->closeElement('omdoc:prototype'); + #Next, absorb rendering: + $document->absorb($pmml); + $document->closeElement("omdoc:notation"); + }, afterDigest=>sub { my ($stomach, $whatsit) = @_; + my $keys = $whatsit->getArg(6); + my $module = LookupValue('current_module'); + $whatsit->setProperties(for=>ToString($whatsit->getArg(1))); + $whatsit->setProperty(role=>($keys ? $keys->getValue('role') + : (ToString($whatsit->getArg(2)) ? 'applied' + : undef))); }); +% \end{macrocode} +% Convert a macro body (tokens with parameters |#1|,..) into a Presentation |style=TeX| form. +% walk through the tokens, breaking into chunks of neutralized (|T_OTHER|) tokens and +% parameter specs. +% \begin{macrocode} +sub symdef_presentation_TeX { + my($presentation)=@_; + my @tokens = $presentation->unlist; + my(@frag,@frags) = (); + while(my $tok = shift(@tokens)){ + if($tok->equals(T_PARAM)){ + push(@frags,Invocation(T_CS('\@symdef@pres@text'),Tokens(@frag))) if @frag; + @frag=(); + my $n = shift(@tokens)->getString; + push(@frags,Invocation(T_CS('\@symdef@pres@arg'),T_OTHER($n+1))); } + else { + push(@frag,T_OTHER($tok->getString)); }} # IMPORTANT! Neutralize the tokens! + push(@frags,Invocation(T_CS('\@symdef@pres@text'),Tokens(@frag))) if @frag; + Tokens(map($_->unlist,@frags)); } +DefConstructor('\@symdef@pres@arg{}', "<omdoc:recurse select='#select'/>", + afterDigest=>sub { my ($stomach, $whatsit) = @_; + my $select = $whatsit->getArg(1); + $select = ref $select ? $select->toString : ''; + $whatsit->setProperty(select=>"*[".$select."]"); }); +DefConstructor('\@symdef@pres@text{}', "<omdoc:text>#1</omdoc:text>"); +%</ltxml>#$ +% \end{macrocode} +% +% +% \subsection{Including Externally Defined Semantic Macros }\label{sec:impl:packages} +% +% \begin{macro}{\requirepackage} +% \begin{macrocode} +%<*package> +\def\requirepackage#1#2{\makeatletter\input{#1.sty}\makeatother} +%</package> +%<*ltxml> +DefConstructor('\requirepackage{} Semiverbatim',"<omdoc:imports from='#2'/>", + afterDigest=>sub { my ($stomach, $whatsit) = @_; + my $select = $whatsit->getArg(1); + RequirePackage($select->toString); });#$ +%</ltxml> +% \end{macrocode} +% \end{macro} +% +% \subsection{Views}\label{sec:impl:views} +% +% \begin{macrocode} +%<*package> +\srefaddidkey{view} +\omdaddkey{view}{from} +\omdaddkey{view}{to} +\omdaddkey{view}{title} +\ifmod@show +\newsavebox{\viewbox} +\newcounter{view}[section] +\def\view@heading{{\textbf{View} \thesection.\theview} + \sref@label@id{View \thesection.\theproblem} + \@ifundefined{view@title}{:\quad}{\quad(\view@title)\hfill\\}} +\newenvironment{view}[1][]{\omdsetkeys{view}{#1}\sref@target\stepcounter{view} +\begin{lrbox}{\viewbox}\begin{minipage}{.9\textwidth}\importmodule{\view@to}} +{\end{minipage}\end{lrbox} +\setbox0=\hbox{\begin{minipage}{.9\textwidth}% +\noindent\view@heading\rm% +\end{minipage}} +\smallskip\noindent\fbox{\vbox{\box0\vspace*{.2em}\usebox\viewbox}}\smallskip} +\else\newxcomment[]{view}\fi +\def\vassign#1#2{#1\ensuremath{\mapsto #2}} +%</package> +% \end{macrocode} +% +% \subsection{Deprecated Functionality}\label{sec:impl:deprecated} +% +% In this section we centralize old interfaces that are only partially supported any more. +% \begin{macro}{module:uses} +% For each the module name |xxx| specified in the |uses| key, we activate their symdefs +% and we export the local symdefs.\ednote{this issue is deprecated, it will be removed +% before 1.0.} +% \begin{macrocode} +%<*package> +\define@key{module}{uses}{% +\@for\module@tmp:=#1\do{\activate@defs\module@tmp\export@defs\module@tmp}} +%</package> +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{module:usesqualified} +% This option operates similarly to the module:uses option defined above. The only +% difference is that here we import modules with a prefix. This is useful when two +% modules provide a macro with the same name. +% \begin{macrocode} +%<*package> +\define@key{module}{usesqualified}{% +\@for\module@tmp:=#1\do{\activate@defs{qualified@\module@tmp}\export@defs\module@tmp}} +%</package> +% \end{macrocode} +% \end{macro} +% +% \subsection{Providing IDs for {\omdoc} Elements}\label{sec:impl:ids} +% +% To provide default identifiers, we tag all {\omdoc} elements that allow |xml:id| +% attributes by executing the |numberIt| procedure below. +% +% \begin{macrocode} +%<*ltxml> +Tag('omdoc:recurse',afterOpen=>\&numberIt,afterClose=>\&locateIt); +Tag('omdoc:imports',afterOpen=>\&numberIt,afterClose=>\&locateIt); +Tag('omdoc:theory',afterOpen=>\&numberIt,afterClose=>\&locateIt); +%</ltxml> +% \end{macrocode} +% +% \subsection{Experiments} +% In this section we develop experimental functionality. Currently support for complex +% expressions, see +% \url{https://svn.kwarc.info/repos/stex/doc/blue/comlex_semmacros/note.pdf} for details. +% +% \begin{macro}{\csymdef} +% For the {\LaTeX} we use |\symdef| and forget the last argument. The code here is just +% needed for parsing the (non-standard) argument structure. +% \begin{macrocode} +%<*package> +\def\csymdef{\@ifnextchar[{\@csymdef}{\@csymdef[]}} +\def\@csymdef[#1]#2{\@ifnextchar[{\@@csymdef[#1]{#2}}{\@@csymdef[#1]{#2}[0]}} +\def\@@csymdef[#1]#2[#3]#4#5{\@@symdef[#1]{#2}[#3]{#4}} +%</package> +%<*ltxml> +%</ltxml> +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\notationdef} +% For the {\LaTeX} side, we just make |\notationdef| invisible. +% \begin{macrocode} +%<*package> +\def\notationdef[#1]#2#3{} +%</package> +%<*ltxml> +%</ltxml> +% \end{macrocode} +% \end{macro} +% +% \subsection{Finale} +% +% Finally, we need to terminate the file with a success mark for perl. +% \begin{macrocode} +%<ltxml>1; +% \end{macrocode} +% +% \Finale +\endinput +%%% Local Variables: +%%% mode: doctex +%%% TeX-master: t +%%% End: +% LocalWords: GPL structuresharing STR dtx env envfalse idfalse displayfalse +% LocalWords: usesfalse usesqualified usesqualifiedfalse envtrue idtrue CPERL +% LocalWords: usestrue displaytrue usesqualifiedtrue RequirePackage keyval tmp +% LocalWords: defs foreach LookupValue activateScope DefEnvironment keyvals cd +% LocalWords: OptionalKeyVals getValue toString AssignValue openElement omdoc +% LocalWords: closeElement beforeDigest useTheoryItemizations afterDigestBegin +% LocalWords: whatsit setProperty getArg qw symdef iffalse importOMDocmodule +% LocalWords: DefKeyVal Semiverbatim symdeflocal atqualified DefMacro STDERR +% LocalWords: args unlist DefPrimitive nargs Stringify eq attr omcd ltx XMTok +% LocalWords: DefConstructorI convertLaTeXArgs scriptpos XMApp OMA XMArg simpl +% LocalWords: DefMacroI blaaaa savedprefix aaa simplhelp tust tist tost reguse +% LocalWords: updatedpre ReturnAfterFi updateall updatedpost updatesms bgroup +% LocalWords: texclude tinclude getGullet requiredmodule tex sms egroup pmml +% LocalWords: toks mixfixi mixfixa mixfixii mixfixia mixfixai mixfixiii arg cr +% LocalWords: DefConstructor afterDigest setProperties undef tok PARAM locator +% LocalWords: getString showfalse showtrue xcomment stex srcref KeyVal omext +% LocalWords: beginItemize getProperty introdcue afterOpen numberIt Tokenize +% LocalWords: OptionalSemiverbatim omdocmod PushValue assocarg getStomach prs +% LocalWords: begingroup beginMode endMode endgroup insertElement resymdef sym +% LocalWords: updir nargkey PresFormatters mixfixaii formatters argname expr +% LocalWords: getSymmdefProperties XMath mcdcr exprlist recurse texttt scsys +% LocalWords: textbackslash newcommand providecommand sc sc mathml openmath nx +% LocalWords: latexml cmathml activemath twintoo atwin atwintoo mathcal Deyan +% LocalWords: mathcal fileversion Ginev maketitle newpage infty ulsmf08 exfig +% LocalWords: omsemmac lstset basicstyle scriptsize aboveskip belowskip hline +% LocalWords: morekeywords lstlisting csymbol showviews showviews foo exf cseq +% LocalWords: qualifiedimports qualifiedimports termdef textbf filepath RabKoh +% LocalWords: symname varSmoothfunctionsOn ednote abbrdef Sumfromto semmodule +% LocalWords: vspace hrule vspace arith arbitraryn xbool oplus xdisjunction tw +% LocalWords: emph captitalize ldots termref termref symref symref ctancite nc +% LocalWords: smms hyperref RahObe hmlmh10 widehat texmf.cnf requiremodules cs +% LocalWords: sinput sinputref sinputref defpath defpath defpath cname csname +% LocalWords: OPhats usepackage importqualified Crossreferencing jobname ltxml +% LocalWords: jobname printbibliography textsf langle textsf langle textlangle +% LocalWords: textrangle textlangle newif ifmod qualifiedfalse qualifiedtrue +% LocalWords: sref xspace expandafter noexpand endcsname namedef setkeys ifx +% LocalWords: newenvironment parentmod usemodule ifundefined coolurion cooluri +% LocalWords: coolurioff cwd ouri ifdefinable testopt ifnextchar xargdef bvars +% LocalWords: argdef yargdef somefunction symdeflocaltrue bvar xpath assoc qr +% LocalWords: symdeflocalfalse localpres isbound symdefs COMPLEXTOKEN localp +% LocalWords: findnodes localname carg renewcommand omdaddkey omdsetkeys bbb +% LocalWords: refundefinedtrue subsubsection blaaa makeatletter makeatother rm +% LocalWords: ifmodules gdef xdef xdef modulestrue modulesfalse pathpostfix +% LocalWords: updatedsms newreg xref texorpdfstring srefaddidkey newsavebox +% LocalWords: viewbox newcounter thesection theview theproblem hfill lrbox +% LocalWords: stepcounter textwidth hbox noindent smallskip fbox vbox usebox +% LocalWords: smallskip newxcomment vassign ensuremath mapsto doctex tocdepth +% LocalWords: setcounter tableofcontents mathbb diff --git a/Master/texmf-dist/source/latex/stex/omd/omd.dtx b/Master/texmf-dist/source/latex/stex/omd/omd.dtx new file mode 100644 index 00000000000..ea175ed803a --- /dev/null +++ b/Master/texmf-dist/source/latex/stex/omd/omd.dtx @@ -0,0 +1,222 @@ +% \iffalse meta-comment +% An Infrastructure for marking up Metadata in LaTeX documents +% $URL: https://svn.kwarc.info/repos/stex/trunk/sty/omd/omd.dtx $ +% $Rev: 1502 $; last modified by $Author: kohlhase $ +% $Date: 2010-07-20 10:17:00 +0200 (Tue, 20 Jul 2010) $ +% Copyright (c) 2009 Michael Kohlhase, all rights reserved +% this file is released under the +% LaTeX Project Public License (LPPL) +% \fi +% +% \iffalse +%<*package> +\NeedsTeXFormat{LaTeX2e}[1999/12/01] +\ProvidesPackage{omd}[2010/06/25 v0.9 OMDoc Metadata Framework] +%</package> +%<*driver> +\documentclass{ltxdoc} +\usepackage{stex-logo,sref,url,array,float} +\usepackage[show]{ed} +\usepackage{../ctansvn} +\usepackage[eso-foot,today]{svninfo} +\usepackage[hyperref=auto,style=alphabetic]{biblatex} +\bibliography{kwarc} +\svnInfo $Id: omd.dtx 1502 2010-07-20 08:17:00Z kohlhase $ +\svnKeyword $HeadURL: https://svn.kwarc.info/repos/stex/trunk/sty/omd/omd.dtx $ +\usepackage{hyperref} +\makeindex +\floatstyle{boxed} +\newfloat{exfig}{thp}{lop} +\floatname{exfig}{Example} +\usepackage{omd} +\begin{document}\DocInput{omd.dtx}\end{document} +%</driver> +% \fi +% +%\CheckSum{58} +% +% \changes{v0.1}{2009/12/14}{First version} +% \changes{v0.9}{2010/06/18}{This is almost done} +% +% \GetFileInfo{omd.sty} +% +% \MakeShortVerb{\|} +% \def\scsys#1{{{\sc #1}}\index{#1@{\sc #1}}} +% \def\latexml{\scsys{LaTeXML}} +% \def\omdoc{OMDoc} +% \def\omdocv#1{\omdoc{#1}} +% +% \title{{\texttt{omd.sty}}: A generic framework for extensible Metadata in {\LaTeX}\thanks{Version {\fileversion} (last revised +% {\filedate})}} +% \author{Michael Kohlhase\\ +% Jacobs University, Bremen\\ +% \url{http://kwarc.info/kohlhase}} +% \maketitle +% \begin{abstract} +% The |omd| 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 the infrastructure for extending {\sTeX} macros with {\omdoc} +% metadata. This package is mainly intended for authors of {\sTeX} extension packages. +% \end{abstract} +% +% \setcounter{tocdepth}{2}\tableofcontents\newpage +% +%\section{Introduction} +% +% The |omd| package supplies the infrastructure for extending {\sTeX} macros with +% ontology-based metadata. The |omd| infrastructure is intended to support the new +% metadata infrastructure for the {\omdoc} format~\cite{Kohlhase:omdoc1.2} introduced in +% {\omdocv{1.3}}~\cite{Kohlhase:OMDoc1.3}\ednote{continue} +% +% \section{The User Interface}\label{sec:user} +% +% The \DescribeMacro{\omdaddkey}|\omdaddkey| command takes two arguments, a metadata group +% \meta{group} and a metadata keyword name \meta{key}. It registers \meta{key} in the +% metadata group \meta{group}. The keys registered for a metadata group can be used for +% defining macros with a key/value arguments via the +% \DescribeMacro{\omdsetkeys}|\omdsetkeys| macro, see for instance the the definition in +% Figure~\ref{fig:foo}. With these definitions in a used package\footnote{The \texttt\@ +% character is only allowed in packages.} |\foo[type=bar,id=f4711]| is formatted to +% \begin{quote} +% \omdaddkey{foo}{id}\omdaddkey{foo}{type}\makeatletter +% \newcommand\foo[1][]{\omdsetkeys{foo}{#1} I have seen a \emph{foo} of type \texttt{\foo@type} +% with identifier \texttt{\foo@id}!}\makeatother +% \foo[type=bar,id=f4711] +% \end{quote} +% +% \begin{exfig}[ht] +% \begin{verbatim} +% \omdaddkey{foo}{id} +% \omdaddkey{foo}{type} +% \newcommand\foo[1][]{\omdsetkeys{foo}{#1} +% I have seen a \emph{foo} of type \texttt{\foo@type} with identifier +% \texttt\foo@id!} +% \end{verbatim} +% \vspace*{-2em} +% \caption{Defining a macro with metadata} +% \label{fig:foo} +% \end{exfig} +% +% \StopEventually{\newpage\PrintIndex\newpage\PrintChanges\printbibliography} +% +% \section{The Implementation}\label{sec:impl} +% +% We build on the |keyval| package which we first need to load. +% \begin{macrocode} +%<*package> +\RequirePackage{keyval}[1997/11/10] +%<*ltxml> +%</ltxml> +% \end{macrocode} +% +% \begin{macro}{\omdaddkey} +% An invocation of |\omdaddkey{|\meta{group}|}{|\meta{key}|}| macro first extends the +% clearkeys macro and then defines the key \meta{key} with the |\define@key| macro from +% the |keyval| package. This stores the key value given in the local macro +% |\|\meta{group}|@|\meta{key}. +% \begin{macrocode} +%<*package> +\newcommand\omdaddkey[3][]{\omd@ext@clear@keys{#2}{#3}{#1}% +\define@key{#2}{#3}[#1]{\expandafter\gdef\csname #2@#3\endcsname{##1}}} +%</package> +%<*ltxml> +%</ltxml> +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\omdsetkeys} +% \begin{macrocode} +%<*package> +\newcommand\omdsetkeys[2]{\csname clear@#1@keys\endcsname\setkeys{#1}{#2}} +%</package> +%<*ltxml> +%</ltxml> +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\omd@ext@clear@keys} +% |\omd@ext@clear@keys{|\meta{group}|}{|\meta{key}|}{|\meta{default}|}| extends (or sets +% up if this is the first |\omdaddkey| for \meta{group}) the +% |\clear@|\meta{group}|@keys| macro to set the default value \meta{default} for +% \meta{key}. The |\clear@|\meta{group}|@keys| macro is used in the generic +% |\omdsetkeys| macro below. +% \begin{macrocode} +%<*package> +\newcommand\omd@ext@clear@keys[3]{\@omd@ext@clear@keys{#1}{#1@#2}{#3}} +\newcommand\@omd@ext@clear@keys[3]{\@ifundefined{clear@#1@keys}% +{\expandafter\def\csname clear@#1@keys\endcsname% +{\expandafter\gdef\csname #2\endcsname{#3}}}% +{\expandafter\g@addto@macro\csname clear@#1@keys\endcsname% +{\expandafter\gdef\csname #2\endcsname{#3}}}} +%</package> +%<*ltxml> +%</ltxml> +% \end{macrocode} +% \end{macro} +% +% \subsection{Using better defaults than empty} +% +% \begin{macro}{\omdaddkeynew} +% |\omdaddkeynew| is an experimental version of |\omdaddkey| which gives +% |\omd@unspecified| as an optional argument, so that it is used as the default value +% here and then test for it in |\omfidus|. But unfortunately, this does not work yet. +% \begin{macrocode} +%<*package> +\newcommand\omdaddkeynew[3][]{\omd@ext@clear@keys{#2}{#3}{#1}% +\define@key{#2}{#3}{\expandafter\gdef\csname #2@#3\endcsname{##1}}} +%</package> +%<*ltxml> +%</ltxml> +% \end{macrocode} +% \end{macro} +% +% +% \begin{macro}{\omd@unspecified} +% Ain internal macro for unspecified values. It is used to initialize keys.\ednote{MK: +% we could probably embed an package error or warning in here} +% \begin{macrocode} +%<*package> +\newcommand\omd@unspecified{an omd-defined key left unspecified} +%</package> +%<*ltxml> +%</ltxml> +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\omdifus} +% This just tests for equality of the first arg with |\omd@unspecified| +% \begin{macrocode} +%<*package> +\newcommand\omdifus[4]{\message{testing #1@#2=\csname#1@#2\endcsname}\expandafter\ifx\csname #1@#2\endcsname\omd@unspecified{#3}\else{#4}\fi} +%</package> +%<*ltxml> +%</ltxml> +% \end{macrocode} +% \end{macro} +% +% \subsection{Finale} +% +% Finally, we need to terminate the file with a success mark for perl. +% \begin{macrocode} +%<ltxml>1; +% \end{macrocode} +% \Finale +\endinput +% \iffalse +%%% Local Variables: +%%% mode: doctex +%%% TeX-master: t +%%% End: +% \fi + + +% LocalWords: iffalse kohlhase Thu omd omd.dtx scsys sc sc latexml omdoc foo +% LocalWords: omdocv texttt fileversion maketitle setcounter tocdepth newpage +% LocalWords: tableofcontents ednote omdaddkey omdaddkey omdsetkeys omdsetkeys +% LocalWords: makeatletter newcommand emph makeatother exfig vspace impl ltxml +% LocalWords: printbibliography keyval clearkeys expandafter gdef csname ifx +% LocalWords: endcsname setkeys ifundefined omdaddkeynew omfidus omdifus +% LocalWords: doctex diff --git a/Master/texmf-dist/source/latex/stex/omdoc/omdoc.dtx b/Master/texmf-dist/source/latex/stex/omdoc/omdoc.dtx new file mode 100644 index 00000000000..2503218bc51 --- /dev/null +++ b/Master/texmf-dist/source/latex/stex/omdoc/omdoc.dtx @@ -0,0 +1,695 @@ +% \iffalse meta-comment +% A LaTeX Class and Package for OMDoc Document Structures +% Copyright (c) 2009 Michael Kohlhase, all rights reserved +% this file is released under the +% LaTeX Project Public License (LPPL) +% +% The development version of this file can be found at +% $HeadURL: https://svn.kwarc.info/repos/stex/trunk/sty/omdoc/omdoc.dtx $ +% \fi +% +% \iffalse +%<package>\NeedsTeXFormat{LaTeX2e}[1999/12/01] +%<package>\ProvidesPackage{omdoc}[2010/06/25 v1.0 OMDoc document Structure] +%<cls>\NeedsTeXFormat{LaTeX2e}[1999/12/01] +%<cls>\ProvidesClass{omdoc}[2010/06/25 v1.0 OMDoc Documents] +% +%<*driver> +\documentclass{ltxdoc} +\usepackage{url,array,omdoc,omtext,float} +\usepackage[show]{ed} +\usepackage[hyperref=auto,style=alphabetic]{biblatex} +\bibliography{kwarc} +\usepackage[eso-foot,today]{svninfo} +\svnInfo $Id: omdoc.dtx 1502 2010-07-20 08:17:00Z kohlhase $ +\svnKeyword $HeadURL: https://svn.kwarc.info/repos/stex/trunk/sty/omdoc/omdoc.dtx $ +\usepackage{stex-logo} +\usepackage{../ctansvn} +\usepackage{hyperref} +\makeindex +\floatstyle{boxed} +\newfloat{exfig}{thp}{lop} +\floatname{exfig}{Example} +\begin{document}\DocInput{omdoc.dtx}\end{document} +%</driver> +% \fi +% +%\CheckSum{275} +% +% \changes{v0.1}{2006/1/17}{First Version} +% \changes{v0.2}{2006/7/11}{added OMDoc class} +% \changes{v0.3}{2007/09/09}{moved omtext and friends here from the statements package} +% \changes{v0.4}{2008/09/06}{added quotes} +% \changes{v0.5}{2008/03/28}{more package/class options} +% \changes{v0.7}{2009/11/24}{giving keyval arguments to the document environment} +% \changes{v1.0}{2010/05/25}{separated out \texttt{omtext.dtx}} +% +% +% \GetFileInfo{omdoc.sty} +% +% \MakeShortVerb{\|} +% +% \def\omdoc{OMDoc} +% \def\latexml{{\LaTeX}ML} +% \title{{\texttt{omdoc.sty/cls}}: Semantic Markup for Open Mathematical Documents in {\LaTeX}\thanks{Version {\fileversion} (last revised +% {\filedate})}} +% \author{Michael Kohlhase\\ +% Jacobs University, Bremen\\ +% \url{http://kwarc.info/kohlhase}} +% \maketitle +% +% \begin{abstract} +% The |omdoc| 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 an infrastructure for writing {\omdoc} documents in {\LaTeX}. +% This includes a simple structure sharing mechanism for {\sTeX} that allows to to move +% from a copy-and-paste document development model to a copy-and-reference model, which +% conserves space and simplifies document management. The augmented structure can be +% used by MKM systems for added-value services, either directly from the {\sTeX} +% sources, or after translation. +% \end{abstract} +% +%\newpage\tableofcontents\newpage +% +%\begin{omgroup}[id=sec:STR]{Introduction} +% +% The |omdoc| package supplies macros and environment that allow to label document +% fragments and to reference them later in the same document or in other documents. In +% essence, this enhances the document-as-trees model to +% documents-as-directed-acyclic-graphs (DAG) model. This structure can be used by MKM +% systems for added-value services, either directly from the {\sTeX} sources, or after +% translation. Currently, trans-document referencing provided by this package can only +% be used in the {\sTeX} collection. +% +% {\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). The package +% supports direct translation to the {\omdoc} format~\cite{Kohlhase:omdoc1.2} +% +% DAG models of documents allow to replace the ``Copy and Paste'' in the source document +% with a label-and-reference model where document are shared in the document source and +% the formatter does the copying during document formatting/presentation.\ednote{talk +% about the advantages and give an example.}\ednote{is there a way to load documents at +% URIs in LaTeX?}\ednote{integrate with latexml's XMRef in the Math mode.} +% \end{omgroup} +% +% \begin{omgroup}[id=sec:user]{The User Interface}\ +% +% The |omdoc| package generates four files: |omdoc.cls|, |omdoc.sty| and their {\latexml} +% bindings |omdoc.cls.ltxml| and |omdoc.sty.ltxml|. We keep the corresponding code +% fragments together, since the documentation applies to both of them and to prevent them +% from getting out of sync. The {\omdoc} class is a minimally changed variant of the +% standard |article| class that includes the functionality provided by |omdoc.sty|. Most +% importantly, |omdoc.cls| sets up the {\latexml} infrastructure and thus should be used +% if {\omdoc} is to be generated from the {\sTeX} sources. The rest of the documentation +% pertains to the functionality introduced by |omdoc.sty|. +% +% \begin{omgroup}[id=sec:user:options]{Package and Class Options} +% +% |omdoc.sty| has the \DescribeMacro{noindex}|noindex| package option, which allows to +% suppress the creation of index entries. The \DescribeMacro{extrefs} option can be set +% to activate multifile support, see~\ctancite{Kohlhase:sref} for details. +% +% |omdoc.cls| accepts all options of the |omdoc.sty| (see~\sref{sec:user:options}) and +% |article.cls| and just passes them on to these. \ednote{describe them} +% \end{omgroup} +% +% \begin{omgroup}[id=sec:user:struct]{Document Structure} +% +% The top-level \DescribeEnv{document}|document| environment is augmented with an +% optional key/value argument that can be used to give metadata about the document. For +% the moment only the \DescribeMacro{id}|id| key is used to give an identifier to the +% \texttt{omdoc} element resulting from the {\latexml} transformation. +% +% \DescribeEnv{omgroup} The structure of the document is given by the |omgroup| +% environment just like in {\omdoc}. In the {\LaTeX} route, the |omgroup| environment is +% flexibly mapped to sectioning commands, inducing the proper sectioning level from the +% nesting of |omgroup| environments. Correspondingly, the |omgroup| environment takes an +% optional key/value argument for metadata followed by a regular argument for the +% (section) title of the omgroup. The optional metadata argument has the keys +% \DescribeMacro{id}|id| for an identifier, \DescribeMacro{creators}|creators| and +% \DescribeMacro{contributors}|contributors| for the Dublin Core +% metadata~\cite{DCMI:dmt03}; see~\ctancite{Kohlhase:dcm} for details of the format. The +% \DescribeMacro{short}|short| allows to give a short title for the generated section. +% \end{omgroup} +% +% \begin{omgroup}[id=sec:user:omtext]{Mathematical Text} +% +% The \DescribeEnv{ignore}|ignore| environment can be used for hiding text parts from the +% document structure. The body of the environment is not PDF or DVI output unless the +% \DescribeMacro{showignores}|showignores| option is given to the |omdoc| class or +% |package|. But in the generated {\omdoc} result, the body is marked up with a |ignore| +% element. This is useful in two situations. For +% \begin{description} +% \item[editing] One may want to hide unfinished or obsolete parts of a document +% \item[narrative/content markup] In {\stex} we mark up narrative-structured documents. In +% the generated {\omdoc} documents we want to be able to cache content objects that are +% not directly visible. For instance in the |statements| +% package~\ctancite{Kohlhase:smms} we use the |\inlinedef| macro to mark up +% phrase-level definitions, which verbalize more formal definitions. The latter can be +% hidden by an ignore and referenced by the |verbalizes| key in |\inlinedef|. +% \end{description} +% +% \end{omgroup} +% +% \begin{omgroup}[id=sec:user:sharing]{Structure Sharing} +% +% \DescribeMacro{\STRlabel}\DescribeMacro{\STRcopy} The |\STRlabel| macro takes two +% arguments: a label and the content and stores the the content for later use by +% |\STRcopy{label}|, which expands to the previously stored content. +% +% \DescribeMacro{\STRsemantics} The |\STRlabel| macro has a variant |\STRsemantics|, where +% the label argument is optional, and which takes a third argument, which is ignored in +% {\LaTeX}. This allows to specify the meaning of the content (whatever that may mean) in +% cases, where the source document is not formatted for presentation, but is transformed +% into some content markup format. \ednote{make an example} +% \end{omgroup} +% +% \begin{omgroup}[id=sec:user:phrase]{Phrase-Level Markup} +% +% \DescribeEnv{phrase} The |phrase| environment allows to mark up phrases with semantic +% information. It takes an optional |KeyVal| argument with the keys\ednote{continue} +% +% \DescribeMacro{\sinlinequote} The |sinlinequote| macro allows to mark up quotes inline and +% attribute them. The quote itself is given as the argument, possibly preceded by the a +% specification of the source in a an optional argument. For instance, we would quote +% Hamlet with +% \begin{verbatim} +% \sinlinequote[Hamlet, \cite{Shak:1603:Hamlet}]{To be or not to be} +% \end{verbatim} +% which would appear as \sinlinequote[Hamlet, (Shakespeare 1603)]{To be or not to be} in +% the text. The style in which inline quotations appear in the text can be adapted by +% specializing the macros \DescribeMacro{\@sinlinequote}|\@sinlinequote| --- for quotations +% without source and \DescribeMacro{\@@sinlinequote}|\@@sinlinequote| --- for quotations with +% source. +% \end{omgroup} +% +% \begin{omgroup}[id=sec:user:colors]{Colors} +% +% For convenience, the |omdoc| package defines a couple of color macros for the |color| +% package: For instance \DescribeMacro{\blue}|\blue| abbreviates |\textcolor{blue}|, so +% that |\blue{|\meta{something}|}| writes \meta{something} in blue. The macros +% \DescribeMacro{\red}|\red| \DescribeMacro{\green}|\green| \DescribeMacro{\cyan}|\cyan| +% \DescribeMacro{\magenta}|\magenta| \DescribeMacro{\brown}|\brown| +% \DescribeMacro{\yellow}|\yellow|, and finally \DescribeMacro{\black}|\black| are +% analogous. +% \end{omgroup} +% \end{omgroup} +% +% \StopEventually{\newpage\PrintIndex\newpage\PrintChanges\printbibliography}\newpage +% +% \begin{omgroup}[id=sec:impl:cls]{Implementation: The OMDoc Class} +% +% The |omdoc| package generates four files: |omdoc.cls| (all the code between +% {\textsf{$\langle$*cls$\rangle$}} and {\textsf{$\langle$/cls$\rangle$}}), |omdoc.sty| +% (between {\textsf{$\langle$*package$\rangle$}} and +% {\textsf{$\langle$/package$\rangle$}}) and their {\latexml} bindings (between +% {\textsf{$\langle$*ltxml.cls$\rangle$}} and {\textsf{$\langle$/ltxml.cls$\rangle$}} and +% {\textsf{$\langle$*ltxml.sty$\rangle$}} and {\textsf{$\langle$/ltxml.sty$\rangle$ +% respetively}}). We keep the corresponding code fragments together, since the +% documentation applies to both of them and to prevent them from getting out of sync. +% +% We load |article.cls|, and the desired packages. For the {\latexml} bindings, we make +% sure the right packages are loaded. +% \begin{macrocode} +%<*cls> +\def\omdoc@class{article} +\DeclareOption{report}{\def\omdoc@class{report}\PassOptionsToPackage{\CurrentOption}{omdoc}} +\DeclareOption{book}{\def\omdoc@class{book}\PassOptionsToPackage{\CurrentOption}{omdoc}} +\DeclareOption{chapter}{\PassOptionsToPackage{\CurrentOption}{omdoc}} +\DeclareOption{part}{\PassOptionsToPackage{\CurrentOption}{omdoc}} +\DeclareOption{showignores}{\PassOptionsToPackage{\CurrentOption}{omdoc}} +\DeclareOption{extrefs}{\PassOptionsToPackage{\CurrentOption}{sref}} +\DeclareOption*{\PassOptionsToClass{\CurrentOption}{article}} +\ProcessOptions +\LoadClass{\omdoc@class} +\RequirePackage{omdoc} +%</cls> +%<*ltxml.cls> +# -*- CPERL -*- +package LaTeXML::Package::Pool; +use strict; +use LaTeXML::Package; +use LaTeXML::Util::Pathname; +use Cwd qw(cwd abs_path); +DeclareOption('report',sub {PassOptions('omdoc','sty',ToString(Digest(T_CS('\CurrentOption')))); }); +DeclareOption('book',sub {PassOptions('omdoc','sty',ToString(Digest(T_CS('\CurrentOption')))); }); +DeclareOption('chapter',sub {PassOptions('omdoc','sty',ToString(Digest(T_CS('\CurrentOption')))); }); +DeclareOption('part',sub {PassOptions('omdoc','sty',ToString(Digest(T_CS('\CurrentOption')))); }); +DeclareOption('showignores',sub {PassOptions('omdoc','sty',ToString(Digest(T_CS('\CurrentOption')))); }); +DeclareOption('extrefs',sub {PassOptions('sref','sty',ToString(Digest(T_CS('\CurrentOption')))); }); +DeclareOption(undef,sub {PassOptions('article','cls',ToString(Digest(T_CS('\CurrentOption')))); }); +ProcessOptions(); +LoadClass('article'); +RequirePackage('sref'); +%</ltxml.cls> +% \end{macrocode} +% Now, we also need to register the namespace prefixes for {\latexml} to use. +% \begin{macrocode} +%<*ltxml.cls> +RegisterNamespace('omdoc'=>"http://omdoc.org/ns"); +RegisterNamespace('om'=>"http://www.openmath.org/OpenMath"); +RegisterNamespace('m'=>"http://www.w3.org/1998/Math/MathML"); +RegisterNamespace('dc'=>"http://purl.org/dc/elements/1.1/"); +RegisterNamespace('cc'=>"http://creativecommons.org/ns"); +RegisterNamespace('stex'=>"http://kwarc.info/ns/sTeX"); +RegisterNamespace('ltx'=>"http://dlmf.nist.gov/LaTeXML"); +%</ltxml.cls> +% \end{macrocode} +% Since we are dealing with a class, we need to set up the document type in the {\latexml} +% bindings. +% \begin{macrocode} +%<*ltxml.cls> +RelaxNGSchema('omdoc+ltxml', + '#default'=>"http://omdoc.org/ns", + 'om'=>"http://www.openmath.org/OpenMath", + 'm'=>"http://www.w3.org/1998/Math/MathML", + 'dc'=>"http://purl.org/dc/elements/1.1/", + 'cc'=>"http://creativecommons.org/ns", + 'ltx'=>"http://dlmf.nist.gov/LaTeXML", + 'stex'=>"http://kwarc.info/ns/sTeX"); +%</ltxml.cls> +% \end{macrocode} +% Then we load the |omdoc| package, which we define separately in the next section so that +% it can be loaded separately\ednote{reword} +% \begin{macrocode} +%<*ltxml.cls> +RequirePackage('omdoc'); +%</ltxml.cls> +% \end{macrocode} +% +% Now, we will define the environments we need. The top-level one is the |document| +% environment, which we redefined so that we can provide keyval arguments. +% +% \begin{environment}{document} +% For the moment we do not use them on the {\LaTeX} level, but the document identifier +% is picked up by {\latexml}. +% \begin{macrocode} +%<*cls> +\let\orig@document=\document +\renewcommand{\document}[1][]{\orig@document} +%</cls> +%<*ltxml.cls> +sub xmlBase { + my $baseuri = LookupValue('baseuri'); + my $baselocal = LookupValue('baselocal'); + my $cdir = abs_path(cwd()); + $cdir =~ s/^$baselocal//; + my ($d,$f,$t) = pathname_split(LookupValue('SOURCEFILE')); + $t = '' if LookupValue('cooluri'); + Tokenize($baseuri.$cdir.'/'.$f.$t); } +DefEnvironment('{document} OptionalKeyVals:omdoc', + "<omdoc:omdoc " + . "?&KeyVal(#1,'id')(xml:id='&KeyVal(#1,'id')')" + . "(?&Tokenize(&LookupValue('SOURCEBASE'))" + . "(xml:id='&Tokenize(&LookupValue('SOURCEBASE')).omdoc')()) " + . "?&Tokenize(&LookupValue('baseuri'))" + . "(xml:base='&xmlBase()')() " + . "?#locator(stex:srcref='#locator')()>" + . "#body" + ."</omdoc:omdoc>", + beforeDigest=> sub { AssignValue(inPreamble=>0); }, + afterDigest=> sub { $_[0]->getGullet->flush; return; }); +%</ltxml.cls> +% \end{macrocode} +% \end{environment} +% \end{omgroup} +% +% \begin{omgroup}[id=sec:impl:sty]{Implementation: OMDoc Package} +% +% \begin{omgroup}[id=sec:impl:options]{Package Options} +% +% The initial setup for {\latexml}: +% +% \begin{macrocode} +%<*ltxml.sty> +package LaTeXML::Package::Pool; +use strict; +use LaTeXML::Package; +use Cwd qw(cwd abs_path); +%</ltxml.sty> +% \end{macrocode} +% +% 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> +\newif\if@chapter\@chapterfalse +\newif\if@part\@partfalse +\newcount\section@level\section@level=3 +\newif\ifshow@ignores\show@ignoresfalse +\def\omdoc@class{article} +\DeclareOption{report}{\def\omdoc@class{report}\section@level=2} +\DeclareOption{book}{\def\omdoc@class{book}\section@level=1} +\DeclareOption{chapter}{\section@level=2\@chaptertrue} +\DeclareOption{part}{\section@level=1\@chaptertrue\@parttrue} +\DeclareOption{showignores}{\show@ignorestrue} +\DeclareOption{extrefs}{\PassOptionsToPackage{\CurrentOption}{sref}} +\ProcessOptions +%</package> +%<*ltxml.sty> +DeclareOption('report',''); +DeclareOption('book',''); +DeclareOption('chapter',''); +DeclareOption('part',''); +DeclareOption('showignores',''); +DeclareOption('extrefs',''); +%</ltxml.sty> +% \end{macrocode} +% +% Then we need to set up the packages by requiring the |sref| package to be loaded. +% +% \begin{macrocode} +%<*package> +\RequirePackage{sref} +\RequirePackage{comment} +%</package> +%<*ltxml.sty> +RequirePackage('sref'); +RequirePackage('omtext'); +%</ltxml.sty> +% \end{macrocode} +% \end{omgroup} +% +% \begin{omgroup}[id=sec:impl:struct]{Document Structure} +% +% The structure of the document is given by the |omgroup| environment just like in +% OMDoc. The hierarchy is adjusted automatically\ednote{maybe define the toplevel +% according to a param, need to know how to detect that the chapter macro exists.} +% +% \begin{environment}{omgroup} +% \begin{macrocode} +%<*package> +\srefaddidkey{omgroup} +\omdaddkey{omgroup}{creators} +\omdaddkey{omgroup}{contributors} +\omdaddkey{omgroup}{type} +\omdaddkey{omgroup}{short} +\omdaddkey{omgroup}{display} +\newenvironment{omgroup}[2][]% title +{\bgroup\omdsetkeys{omgroup}{#1}\sref@target +\ifx\omgroup@display\st@flow\noindent{\Large\textbf{#2}\\[.3ex]\noindent\ignorespaces} +\else +\if@part\ifnum\section@level=1\part{#2}\sref@label@id{Part \thepart}\fi\fi +\if@chapter\ifnum\section@level=2\chapter{#2}\sref@label@id{Chapter \thechapter}\fi\fi +\ifnum\section@level=3\section{#2}\sref@label@id{Section \thesection}\fi +\ifnum\section@level=4\subsection{#2}\sref@label@id{Subsection \thesubsection}\fi +\ifnum\section@level=5\subsubsection{#2}\sref@label@id{Subsubsection \thesubsubsection}\fi +\ifnum\section@level=6\paragraph{#2}\sref@label@id{this paragraph}\fi +\ifnum\section@level=7\subparagraph{#2}\sref@label@id{this subparagraph}\fi +\advance\section@level by 1 +\fi}{\egroup} +%</package> +%<*ltxml.sty> +DefEnvironment('{omgroup} OptionalKeyVals:omgroup {}', + "<omdoc:omgroup layout='sectioning'" + . "?&KeyVal(#1,'id')(xml:id='&KeyVal(#1,'id')')()" + . "?&KeyVal(#1,'type')(type='&KeyVal(#1,'type')')()>\n" + . "<dc:title ?#locator(stex:srcref='#locator')()>#2</dc:title>\n" + . "#body\n" + . "</omdoc:omgroup>"); +%</ltxml.sty> +% \end{macrocode} +% \end{environment} +% +% the |itemize|, |description|, and |enumerate| environments originally introduced in the +% |omtext| package do double duty in OMDoc, outside a |CMP| they are transformed into a +% |<omgroup layout='itemize|description|enumerate'>|, where the text after the macros +% |\item| come to be the children. If that is only text, then it is enclosed in an +% |<omtext><CMP>|, otherwise it is left as it is. The optional argument of the |\item| +% is transformed into the |<metadata><dc:title>| of the generated |\item| element. +% \begin{macrocode} +%<*ltxml.sty> +DefParameterType('IfBeginFollows', sub { + my ($gullet) = @_; + $gullet->skipSpaces; + my $next = $gullet->readToken; + $gullet->unread($next); + $next = ToString($next); + #Hm, falling back to regexp handling, the $gullet->ifNext approach didn't work properly + return 1 unless ($next=~/^\\begin/); + return; + }, + reversion=>'', optional=>1);#$ +Let('\group@item@maybe@unwrap','\relax'); +DefMacro('\group@item[] IfBeginFollows', sub { + my($gullet,$tag,$needswrapper)=@_; + ( T_CS('\group@item@maybe@unwrap'), + ($needswrapper ? (Invocation(T_CS('\group@item@wrap'),$tag)->unlist) : ()) ); }); +DefConstructor('\group@item@wrap {}', + "<omdoc:omtext>" + . "?#1(<dc:title>#1</dc:title>)()" + . "<omdoc:CMP><omdoc:p>", + beforeDigest=>sub { + Let('\group@item@maybe@unwrap','\group@item@unwrap'); + #$_[0]->bgroup; + useCMPItemizations(); + return; }, + properties=>sub{ RefStepItemCounter(); }); +DefConstructor('\group@item@unwrap', + "", + beforeDigest=>sub { + # $_[0]->egroup;#$ + Let('\group@item@maybe@unwrap','\relax'); }, + beforeConstruct=>sub { + $_[0]->maybeCloseElement('omdoc:p'); + $_[0]->maybeCloseElement('omdoc:CMP'); + $_[0]->maybeCloseElement('omdoc:omtext'); + }); +Let('group@item@maybe@unwrap','\relax'); +Let('\itemize@item'=>'\group@item'); +Let('\enumerate@item'=>'\group@item'); +Let('\description@item'=>'\group@item'); +DefEnvironment('{itemize}', + "<omdoc:omgroup xml:id='#id' layout='itemize'>" + . "#body" + ."</omdoc:omgroup>", + properties=>sub { beginItemize('itemize'); }, + beforeDigestEnd=>sub { Digest(T_CS('\group@item@maybe@unwrap')); }); +DefEnvironment('{enumerate}', + "<omdoc:omgroup xml:id='#id' layout='enumerate'>#body</omdoc:omgroup>", + properties=>sub { beginItemize('enumerate'); }, + beforeDigestEnd=>sub { Digest(T_CS('\group@item@maybe@unwrap')); }); +DefEnvironment('{description}', + "<omdoc:omgroup xml:id='#id' layout='description'>" + . "#body" + ."</omdoc:omgroup>", + properties=>sub { beginItemize('description'); }, + beforeDigestEnd=>sub { Digest(T_CS('\group@item@maybe@unwrap')); }); +%</ltxml.sty> +% \end{macrocode} +% \end{omgroup} +% +% \begin{environment}{ignore} +% \begin{macrocode} +%<*package> +\ifshow@ignores +\omdaddkey{ignore}{type} +\omdaddkey{ignore}{comment} +\newenvironment{ignore}[1][] +{\omdsetkeys{ignore}{#1}\textless\ignore@type\textgreater\bgroup\itshape} +{\egroup\textless/\ignore@type\textgreater} +\renewenvironment{ignore}{}{}\else\excludecomment{ignore}\fi +%</package> +%<*ltxml.sty> +DefKeyVal('ignore','type','Semiverbatim'); +DefKeyVal('ignore','comment','Semiverbatim'); +DefEnvironment('{ignore} OptionalKeyVals:ignore', + "<omdoc:ignore %&KeyVals(#1)>#body</omdoc:ignore>"); +%</ltxml.sty> +% \end{macrocode} +% \end{environment} +% \end{omgroup} +% +% \begin{omgroup}[id=sec:impl:share]{Structure Sharing} +% +% \begin{macro}{\STRlabel} +% The main macro, it it used to attach a label to some text expansion. Later on, using the +% |\STRcopy| macro, the author can use this label to get the expansion originally assigned. +% \begin{macrocode} +%<*package> +\long\def\STRlabel#1#2{\STRlabeldef{#1}{#2}{#2}} +%</package> +%<*ltxml.sty> +DefConstructor('\STRlabel{}{}', sub { + my($document,$label,$object)=@_; + $document->absorb($object); + $document->addAttribute('xml:id'=>ToString($label)) if $label; }); +%</ltxml.sty> +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\STRcopy} +% The |\STRcopy| macro is used to call the expansion of a given label. In case the label is +% not defined it will issue a warning. +% \begin{macrocode} +%<*package> +\def\STRcopy#1{\expandafter\ifx\csname STR@#1\endcsname\relax +\message{STR warning: reference #1 undefined!} +\else\csname STR@#1\endcsname\fi} +%</package> +%<*ltxml.sty> +DefConstructor('\STRcopy{}',"<omdoc:ref xref='##1'/>"); +%</ltxml.sty> +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\STRsemantics} +% if we have a presentation form and a semantic form, then we can use +% \begin{macrocode} +%<*package> +\newcommand{\STRsemantics}[3][]{#2\def\@test{#1}\ifx\@test\@empty\STRlabeldef{#1}{#2}\fi} +%</package> +%<*ltxml.sty> +DefConstructor('\STRsemantics[]{}{}', sub { + my($document,$label,$ignore,$object)=@_; + $document->absorb($object); + $document->addAttribute('xml:id'=>ToString($label)) if $label; }); +%</ltxml.sty>#$ +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\STRlabeldef} +% This is the macro that does the actual labeling. Is it called inside |\STRlabel| +% \begin{macrocode} +%<*package> +\def\STRlabeldef#1{\expandafter\gdef\csname STR@#1\endcsname} +%</package> +%<*ltxml.sty> +DefMacro('\STRlabeldef{}{}', ""); +%</ltxml.sty> +% \end{macrocode} +% \end{macro} +% \end{omgroup} +% +% \begin{omgroup}[id=sec:impl:colors]{Colors} +% +% \begin{environment}{blue, red, green, magenta} +% We will use the following abbreviations for colors from |color.sty| +% \begin{macrocode} +%<*package> +\def\black#1{\textcolor{black}{#1}} +\def\blue#1{\textcolor{blue}{#1}} +\def\red#1{\textcolor{red}{#1}} +\def\green#1{\textcolor{green}{#1}} +\def\cyan#1{\textcolor{cyan}{#1}} +\def\magenta#1{\textcolor{magenta}{#1}} +\def\brown#1{\textcolor{brown}{#1}} +\def\yellow#1{\textcolor{yellow}{#1}} +\def\yellow#1{\textcolor{yellow}{#1}} +\def\orange#1{\textcolor{orange}{#1}} +%</package> +% \end{macrocode} +% For the {\latexml} bindings, we go a generic route, we replace |\blue{#1}| by +% |{\@omdoc@color{blue}\@omdoc@color@content{#1}}|. +% \begin{macrocode} +%<*ltxml.sty> +sub omdocColorMacro { + my ($color, @args) = @_; + my $tok_color = TokenizeInternal($color); + (T_BEGIN, T_CS('\@omdoc@color'), T_BEGIN, $tok_color->unlist, + T_END, T_CS('\@omdoc@color@content'), T_OTHER('['), $tok_color->unlist, T_OTHER(']'), + T_BEGIN, $args[1]->unlist, T_END, T_END); } +DefMacro('\@omdoc@color{}', sub { MergeFont(color=>$_[1]->toString); return; });#$ +%</ltxml.sty> +% \end{macrocode} +% Ideally, here we will remove the optional argument and have a conversion module +% add the attribute at the end (or maybe add it just for math?) +% or, we can take the attributes for style from the current font ? +% \begin{macrocode} +%<*ltxml.sty> +DefConstructor('\@omdoc@color@content[]{}', + "?#isMath(#2)(<omdoc:phrase ?#1(style='color:#1')()>#2</omdoc:phrase>)"); +foreach my $color(qw(blue red green magenta cyan brown yellow)) { + DefMacro("\\".$color.'{}', sub { omdocColorMacro($color, @_); }); }#$ +%</ltxml.sty> +% \end{macrocode} +% \end{environment} +% \end{omgroup} +% +% \begin{omgroup}{{\LaTeX} Commands we interpret differently} +% +% The reinterpretations are quite simple, we either disregard presentational markup or +% we re-interpret it in terms of {\omdoc}. +% \begin{macrocode} +%<*ltxml.sty> +DefConstructor('\newpage',''); +%</ltxml.sty> +% \end{macrocode} +% \end{omgroup} +% +% \begin{omgroup}[id=sec:impl:ids]{Providing IDs for {\omdoc} Elements} +% +% To provide default identifiers, we tag all {\omdoc} elements that allow |xml:id| +% attributes by executing the |numberIt| procedure below. +% +% \begin{macrocode} +%<*ltxml.sty> +Tag('omdoc:ignore',afterOpen=>\&numberIt,afterClose=>\&locateIt); +Tag('omdoc:ref',afterOpen=>\&numberIt,afterClose=>\&locateIt); +%</ltxml.sty> +% \end{macrocode} +% \end{omgroup} +% +% \begin{omgroup}{Leftovers} +% +% \begin{macrocode} +%<*package> +\newcommand{\baseURI}[2][]{} +%</package> +%<*ltxml.sty> +DefMacro('\baseURI []Semiverbatim', sub { + AssignValue('baselocal'=>abs_path(ToString(Expand($_[1])))); + AssignValue('baseuri'=>ToString(Expand($_[2])));}); +DefConstructor('\url Semiverbatim',"<omdoc:link href='#1'>#1</omdoc:link>"); +DefConstructor('\href Semiverbatim {}',"<omdoc:link href='#1'>#2</omdoc:link>"); +%</ltxml.sty> +% \end{macrocode} +% \ednote{this should be handled differently, omdoc.sty should include url and give a new +% macro for it, which we then use in omdoc} +% and finally, we need to terminate the file with a success mark for perl. +% \begin{macrocode} +%<ltxml.sty|ltxml.cls>1; +% \end{macrocode} +% \end{omgroup} +% \Finale +\endinput +% \iffalse +% LocalWords: GPL structuresharing STR omdoc dtx stex CPERL LoadClass url dc +%%% Local Variables: +%%% mode: doctex +%%% TeX-master: t +%%% End: +% \fi +% LocalWords: RequirePackage RegisterNamespace namespace xsl DocType ltxml dtd +% LocalWords: ltx DefEnvironment beforeDigest AssignValue inPreamble getGullet +% LocalWords: afterDigest keyval omgroup DefKeyVal Semiverbatim KeyVal locator +% LocalWords: OptionalKeyVals DefParameterType IfBeginFollows skipSpaces CMP +% LocalWords: ifNext DefMacro needwrapper unlist DefConstructor omtext bgroup +% LocalWords: useCMPItemizations RefStepItemCounter egroup beginItemize li di +% LocalWords: beforeDigestEnd dt autoclose ul ol dl env showignores srcref Cwd +% LocalWords: afterOpen LastSeenCMP autoClose DefCMPEnvironment proto ToString +% LocalWords: addAttribute nlex nlcex omdocColorMacro args tok MergeFont qw +% LocalWords: TokenizeInternal toString isMath foreach maybeCloseElement id'd +% LocalWords: autoOpen minipage footnotesize scriptsize numberIt whatsit href +% LocalWords: getAttribute setAttribute OMDoc RelaxNGSchema noindex xml lec +% LocalWords: Subsubsection useDefaultItemizations refundefinedtrue sblockquote +% LocalWords: DefCMPConstructor sinlinequote idx idt ide idp emph extrefs sref +% LocalWords: flushleft flushright DeclareOption PassOptions undef cls iffalse +% LocalWords: ProcessOptions subparagraph ignoresfalse ignorestrue texttt ttin +% LocalWords: texttt latexml fileversion maketitle newpage tableofcontents cwd +% LocalWords: newpage ednote ctancite dmt03 smms inlinedef STRlabel STRcopy +% LocalWords: STRlabel STRsemantics STRsemantics textcolor printbibliography +% LocalWords: textsf langle textsf langle respetively orig renewcommand cdir +% LocalWords: baseuri baseuri baselocal baselocal SOURCEFILE cooluri newif ifx +% LocalWords: SOURCEBASE chapterfalse partfalse newcount ifshow chaptertrue +% LocalWords: parttrue srefaddidkey omdaddkey newenvironment omdsetkeys textbf +% LocalWords: noindent noindent ignorespaces ifnum thepart thechapter regexp +% LocalWords: thesection thesubsection thesubsubsection needswrapper itshape +% LocalWords: textgreater renewenvironment excludecomment STRlabeldef csname +% LocalWords: expandafter endcsname xref newcommand gdef doctex diff --git a/Master/texmf-dist/source/latex/stex/omtext/omtext.dtx b/Master/texmf-dist/source/latex/stex/omtext/omtext.dtx new file mode 100644 index 00000000000..e12d7cf0743 --- /dev/null +++ b/Master/texmf-dist/source/latex/stex/omtext/omtext.dtx @@ -0,0 +1,799 @@ +% \iffalse meta-comment +% A LaTeX Class and Package for OMDoc Text Fragments +% Copyright (c) 2010 Michael Kohlhase, all rights reserved +% this file is released under the +% LaTeX Project Public License (LPPL) +% +% The development version of this file can be found at +% $HeadURL: https://svn.kwarc.info/repos/stex/trunk/sty/omtext/omtext.dtx $ +% \fi +% +% \iffalse +%<package>\NeedsTeXFormat{LaTeX2e}[1999/12/01] +%<package>\ProvidesPackage{omtext}[2010/06/25 v1.0 OMDoc Text Fragments] +% +%<*driver> +\documentclass{ltxdoc} +\usepackage{url,array,omdoc,float} +\usepackage{omtext} +\usepackage[show]{ed} +\usepackage[hyperref=auto,style=alphabetic]{biblatex} +\bibliography{kwarc} +\usepackage[eso-foot,today]{svninfo} +\svnInfo $Id: omtext.dtx 1502 2010-07-20 08:17:00Z kohlhase $ +\svnKeyword $HeadURL: https://svn.kwarc.info/repos/stex/trunk/sty/omtext/omtext.dtx $ +\usepackage{stex-logo} +\usepackage{../ctansvn} +\usepackage{hyperref} +\makeindex +\floatstyle{boxed} +\newfloat{exfig}{thp}{lop} +\floatname{exfig}{Example} +\begin{document}\DocInput{omtext.dtx}\end{document} +%</driver> +% \fi +% +%\CheckSum{333} +% +% \changes{v0.4}{2008/07/22}{added index markup} +% \changes{v0.4}{2008/09/29}{augmenting the index macros with optional values} +% \changes{v0.6}{2009/07/08}{removing {\texttt{ttin}} {\texttt{{emin}}} and friends, +% they were almost never used.} +% \changes{v0.6}{2009/07/08}{renmanig {\texttt{myindex}} to {\texttt{omdoc\@ index}}, +% {\texttt{twin}} to {\texttt{\@ twin}}, and {\texttt{atwin}} to {\texttt{\@ atwin}} to +% make them packge-local} +% \changes{v0.7}{2010/02/11}{changing blockquote to sblockquote and inlinequote similarly} +% \changes{v0.9}{2010/05/25}{separated out from \texttt{omdoc.dtx}} +% \changes{v1.0}{2010/06/18}{fixing typos} +% +% \GetFileInfo{omtext.sty} +% +% \MakeShortVerb{\|} +% +% \def\omdoc{OMDoc} +% \def\latexml{{\LaTeX}ML} +% \title{{\texttt{omtext}}: Semantic Markup for Mathematical Text Fragments in {\LaTeX}\thanks{Version {\fileversion} (last revised +% {\filedate})}} +% \author{Michael Kohlhase\\ +% Jacobs University, Bremen\\ +% \url{http://kwarc.info/kohlhase}} +% \maketitle +% +% \begin{abstract} +% The |omtext| 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 an infrastructure for writing {\omdoc} text fragments in +% {\LaTeX}. +% \end{abstract} +% +%\newpage\tableofcontents\newpage +% +%\begin{omgroup}[id=sec:STR]{Introduction} +% +% The |omtext| package supplies macros and environment that allow to mark up mathematical +% texts in {\sTeX}, 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). The +% package supports direct translation to the {\omdoc} format~\cite{Kohlhase:omdoc1.2} +% \end{omgroup} +% +% \begin{omgroup}[id=sec:user]{The User Interface}\ +% +% \DescribeEnv{omtext} The |omtext| environment is used for any text fragment that has a +% contribution to a text that needs to be marked up. It can have a title, which can be +% specified via the |title| key. Often it is also helpful to annotate the |type| +% key. The standard relations from rhetorical structure theory |abstract|, +% |introduction|, |conclusion|, |thesis|, |comment|, |antithesis|, |elaboration|, +% |motivation|, |evidence|, |transition|, | note|, |annote| are recommended. Note that +% some of them are unary relations like |introduction|, which calls for a target. In +% this case, a target using the |for| key should be specified. The |transition| relation +% is special in that it is binary (a ``transition between two statements''), so +% additionally, a source should be specified using the |from| key. +% \end{omgroup} +% +% \begin{omgroup}[id=sec:user:block]{Block-Level Markup} +% +% \DescribeEnv{sblockquote} The |sblockquote| environment is the big brother of the +% |\sinlinequote| macro. It also takes an optional argument to specify the source. Here +% the four internal macros \DescribeMacro{\begin@sblockquote}|\begin@sblockquote| to +% \DescribeMacro{\end@@sblockquote}|\end@@sblockquote| are used for styling and can be +% adapted by package integrators. Here a quote of Hamlet would marked up as +% \begin{verbatim} +% \begin{sblockquote}[Hamlet, \cite{Shak:1603:Hamlet}]\obeylines +% To be, or not to be: that is the question: +% Whether 'tis nobler in the mind to suffer +% \end{sblockquote} +% \end{verbatim} +% and would render as +% \begin{sblockquote}[Hamlet, (Shakespeare 1603)]\obeylines +% To be, or not to be: that is the question: +% Whether 'tis nobler in the mind to suffer +% \end{sblockquote} +% +% \DescribeMacro{\lec}The |\lec| macro takes one argument and sets it as a comment at the +% end of the line, making sure that if the content is too long it is pushed into a new +% line. We use it internally for placing the of source of the |sblockquote| environment +% above. The actual appearance of the line end comment is determined by the +% \DescribeMacro{\@@lec}|\@@lec| macro, which can be customized in the document class. +% \end{omgroup} +% +% \begin{omgroup}[id=sec:user:index]{Index Markup} +% +% The |omtext| package provides some extensions for the well-known indexing macros of +% {\LaTeX}. The main reason for introducing these macros is that index markup in +% {\omdoc} wraps the indexed terms rather than just marking the spot for +% cross-referencing. Furthermore the index commands only indexes words unless +% the\DescribeMacro{noindex} |noindex| option is set in the |\usepackage|. The |omtext| +% package and class make the usual |\index| macro undefined\ednote{implement this and +% issue the respective error message}. +% +% The \DescribeMacro{\indextoo}|\indextoo| macro renders a word and marks it for the +% index. Sometimes, we want to index a slightly different form of the word, e.g. for +% non-standard plurals: while |\indextoo{word}s| works fine, we cannot use this for the +% word ``datum'', which has the plural ``data''. For this we have the macro +% \DescribeMacro{\indexalt}|\indexalt|, which takes another argument for the displayed +% text, allowing us to use |\indexalt{data}{datum}|, which prints ``data'' but puts +% ``datum'' into the index. +% +% The second set of macros adds an infrastructure for two-word compounds. Take for +% instance the compound ``OMDoc document'', which we usually want to add into the index +% under ``OMDoc'' and ``document''. \DescribeMacro{\twintoo}|\twintoo{OMDoc}{document}| +% is a variant of |\indextoo| that will do just this. Again, we have a version that +% prints a variant: This is useful for situations like this the one in +% Figure~\ref{fig:index-markup}: +% \begin{exfig} +% \begin{verbatim} +% We call group \twinalt{Abelian}{Abelian}{group}, iff \ldots +% \end{verbatim} +% \vspace*{-1em}will result in the following +% \begin{quote} +% We call group \twinalt{Abelian}{Abelian}{group}, iff \ldots +% \end{quote} +% and put ``Abelian Group'' into the index. +% \caption{Index markup}\label{fig:index-markup} +% \end{exfig} +% +% The third set of macros does the same for two-word compounds with adjectives, +% e.g. ``wonderful OMDoc +% document''. \DescribeMacro{\atwintoo}|\atwin{wonderful}{OMdoc}{document}| will make the +% necessary index entries under ``wonderful'' and ``document''. Again, we have a variant +% \DescribeMacro{\atwinalt}|\atwinalt| whose first argument is the alternative text. +% +% All index macros take an optional first argument that is used for ordering the +% respective entries in the index. +% \end{omgroup} +% +% \StopEventually{\newpage\PrintIndex\newpage\PrintChanges\printbibliography}\newpage +% +% \begin{omgroup}[id=sec:impl]{Implementation} +% +% \begin{omgroup}[id=sec:impl:options]{Package Options} +% +% The initial setup for {\latexml}: +% +% \begin{macrocode} +%<*ltxml> +package LaTeXML::Package::Pool; +use strict; +use LaTeXML::Package; +use Cwd qw(cwd abs_path); +%</ltxml> +% \end{macrocode} +% +% 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> +\newif\ifindex\indextrue +\DeclareOption{noindex}{\indexfalse} +\ProcessOptions +\ifindex\makeindex\fi +%</package> +%<*ltxml> +DeclareOption('noindex',''); +%</ltxml> +% \end{macrocode} +% +% Then we need to set up the packages by requiring the |sref| package to be loaded. +% +% \begin{macrocode} +%<*package> +\RequirePackage{sref} +\RequirePackage{comment} +%</package> +%<*ltxml> +RequirePackage('sref'); +%</ltxml> +% \end{macrocode} +% \end{omgroup} +% +% \begin{omgroup}[id=sec:impl:metadata]{Metadata} +% +% All the {\omdoc} elements allow to specify metadata in them, which is modeled by the +% |omdoc:metadata| element. Since the content of this element is precisely controlled +% by the Schema, we can afford to auto-open and auto-close it. Thus metadata elements +% from various sources will just be included into one |omdoc:metadata| element, even if +% they are supplied by different {\sTeX} bindings. Also we add numbering and location +% facilities. +% +% \begin{macrocode} +%<*ltxml> +Tag('omdoc:metadata',afterOpen=>\&numberIt,afterClose=>\&locateIt,autoClose=>1,autoOpen=>1); +%</ltxml> +% \end{macrocode} +% \end{omgroup} +% +% the |itemize|, |description|, and |enumerate| environments generate |omdoc:li|, +% |omdoc:di| with |autoclose| inside a CMP. This behavior will be overwritten later, so we +% remember that we are in a |CMP| by assigning |_LastSeenCMP|. +% +% \begin{macrocode} +%<*ltxml> +DefConstructor('\CMP@itemize@item[]', + "<omdoc:li>?#1(<dc:title ?#locator(stex:srcref='#locator')()>#1</dc:title>)()", + properties=>sub{ RefStepItemCounter(); }); +DefConstructor('\CMP@enumerate@item[]', + "<omdoc:li>?#1(<dc:title ?#locator(stex:srcref='#locator')()>#1</dc:title>)()", + properties=>sub{ RefStepItemCounter(); }); +DefConstructor('\CMP@description@item[]', + "<omdoc:di>" + . "?#1(<omdoc:dt>#1</omdoc:dt>)()<omdoc:dd>", # trust di and dt to autoclose + properties=>sub{ RefStepItemCounter(); }); +DefEnvironment('{CMP@itemize}', + "<omdoc:ul>#body</omdoc:ul>", + properties=>sub { beginItemize('CMP@itemize'); }, + beforeDigest=>sub { Let(T_CS('\end{itemize}') =>T_CS('\end{CMP@itemize}')); }); +DefEnvironment('{CMP@enumerate}', + "<omdoc:ol xml:id='#id'>#body</omdoc:ol>", + properties=>sub { beginItemize('CMP@enumerate'); }, + beforeDigest=>sub { Let(T_CS('\end{enumerate}') =>T_CS('\end{CMP@enumerate}')); }); +DefEnvironment('{CMP@description}', + "<omdoc:dl xml:id='#id'>#body</omdoc:dl>", + properties=>sub { beginItemize('CMP@description'); }, + beforeDigest=>sub { Let(T_CS('\end{description}') =>T_CS('\end{CMP@description}'));}); +sub useCMPItemizations { + Let(T_CS('\begin{itemize}') =>T_CS('\begin{CMP@itemize}')); + Let(T_CS('\begin{enumerate}') =>T_CS('\begin{CMP@enumerate}')); + Let(T_CS('\begin{description}')=>T_CS('\begin{CMP@description}')); + return; } +sub declareFunctions{ + my ($stomach,$whatsit) = @_; + my $keyval = $whatsit->getArg(1); + my $funval = KeyVal($keyval,'functions') if KeyVal($keyval,'functions'); + my @funsymbs = ParseKeyValList($funval); + #Unread the function declarations at the Gullet + foreach (@funsymbs) { + $stomach->getGullet->unread(Tokenize('\lxDeclare[role=FUNCTION]{$'.$_.'$}')->unlist); + } + return; +} +Tag('omdoc:CMP', afterOpen => sub {AssignValue('_LastSeenCMP', $_[1], 'global');return;});#$ +Tag('omdoc:li', autoClose=>1); +Tag('omdoc:dd', autoClose=>1); +Tag('omdoc:di', autoClose=>1); +%</ltxml> +% \end{macrocode} +% \end{omgroup} +% +% \begin{omgroup}[id=sec:impl:mtxt]{Mathematical Text} +% +% We define the actions that are undertaken, when the keys are encountered. Here this is +% very simple, we just define an internal macro with the value, so that we can use it +% later. Note that we allow math in the |title| field, so we do not declare it to be +% |Semiverbatim| (indeed not at all, which allows it by default). +% +% \begin{macrocode} +%<*package> +\srefaddidkey{omtext} +\omdaddkey[]{omtext}{functions} +\omdaddkey{omtext}{display} +\omdaddkey{omtext}{for} +\omdaddkey{omtext}{from} +\omdaddkey{omtext}{type} +\omdaddkey{omtext}{title} +\omdaddkey{omtext}{theory} +\omdaddkey{omtext}{continues} +\omdaddkey{omtext}{verbalizes} +%</package> +%<*ltxml> +DefKeyVal('omtext','functions','Semiverbatim'); +DefKeyVal('omtext','display','Semiverbatim'); +DefKeyVal('omtext','for','Semiverbatim'); +DefKeyVal('omtext','from','Semiverbatim'); +DefKeyVal('omtext','type','Semiverbatim'); +DefKeyVal('omtext','title','Plain'); #Math mode in titles. +DefKeyVal('omtext','theory','Semiverbatim'); +DefKeyVal('omtext','continues','Semiverbatim'); +DefKeyVal('omtext','verbalizes','Semiverbatim'); +%</ltxml> +% \end{macrocode} +% +% \begin{macro}{\st@flow} +% We define this macro, so that we can test whether the |display| key has the value |flow| +% \begin{macrocode} +%<*package> +\def\st@flow{flow} +%</package> +% \end{macrocode} +% \end{macro} +% +% \begin{environment}{omtext} +% The |omtext| environment is different, it does not have a keyword that marks +% it. Instead, it can have a title, which is used in a similar way. We redefine the +% |\lec| macro so the trailing |\par| does not get into the way. +% \begin{macrocode} +%<*package> +\def\omtext@pre@skip{\smallskip} +\def\omtext@post@skip{} +\providecommand{\stDMemph}[1]{\textbf{#1}} +\newenvironment{omtext}[1][]{\bgroup\omdsetkeys{omtext}{#1}\sref@label@id{this paragraph}% +\def\lec##1{\@lec{##1}} +\ifx\omtext@display\st@flow\else\omtext@pre@skip\par\noindent% +\ifx\omtext@title\@empty\else\stDMemph{\omtext@title}: \fi\fi\ignorespaces} +{\egroup\omtext@post@skip} +%</package> +%<*ltxml> +DefCMPEnvironment('{omtext} OptionalKeyVals:omtext', + "<omdoc:omtext " + . "?&KeyVal(#1,'id')(xml:id='&KeyVal(#1,'id')')() " + . "?&KeyVal(#1,'type')(type='&KeyVal(#1,'type')')() " + . "?&KeyVal(#1,'for')(for='&KeyVal(#1,'for')')() " + . "?&KeyVal(#1,'from')(from='&KeyVal(#1,'from')')()>" + . "?&KeyVal(#1,'title')(<dc:title>&KeyVal(#1,'title')</dc:title>)()" + . "<omdoc:CMP>" + . "<omdoc:p>" + . "#body"); +%</ltxml> +% \end{macrocode} +% \end{environment} +% +% We also make our life easier If defining an environment that is +% turned into something that contains |<CMP>|\meta{body}|</CMP>|, use this method instead +% \begin{macrocode} +%<*ltxml> +sub DefCMPEnvironment { + my ($proto, $replacement, %options) = @_; + my @before = $options{beforeDigest} ? ($options{beforeDigest}) : (); + push(@before, \&useCMPItemizations); + $options{beforeDigest} = \@before; + my @after = $options{afterDigestBegin} ? ($options{afterDigestBegin}) : (); + push(@after, \&declareFunctions); + $options{afterDigestBegin} = \@after; + DefEnvironment($proto, $replacement, %options); +} +sub DefCMPConstructor { + my ($proto, $replacement, %options) = @_; + my @before = $options{beforeDigest} ? ($options{beforeDigest}) : (); + push(@before, \&useCMPItemizations); + $options{beforeDigest} = \@before; + DefConstructor($proto, $replacement, %options); +} +%</ltxml> +% \end{macrocode} +% +% \begin{omgroup}[id=sec:impl:phrase]{Phrase-level Markup} +% +% \begin{environment}{phrase} +% For the moment, we do disregard the most of the keys +% \begin{macrocode} +%<*package> +\srefaddidkey{phrase} +\omdaddkey{phrase}{style} +\omdaddkey{phrase}{class} +\omdaddkey{phrase}{index} +\omdaddkey{phrase}{verbalizes} +\omdaddkey{phrase}{type} +\newenvironment{phrase}[1][]{\omdsetkeys{phrase}{#1}}{} +%</package> +%<*ltxml> +DefKeyVal('phrase','id','Semiverbatim'); +DefKeyVal('phrase','style','Semiverbatim'); +DefKeyVal('phrase','class','Semiverbatim'); +DefKeyVal('phrase','index','Semiverbatim'); +DefKeyVal('phrase','verbalizes','Semiverbatim'); +DefKeyVal('phrase','type','Semiverbatim'); +DefConstructor('\phrase OptionalKeyVals:phrase {}', + "<omdoc:phrase %&KeyVals(#1)>#2</omdoc:phrase>"); +%</ltxml> +% \end{macrocode} +% \end{environment} +% +% \begin{environment}{nlex} +% For the moment, we do disregard the most of the keys +% \begin{macrocode} +%<*package> +\def\nlex#1{\green{\sl{#1}}} +\def\nlcex#1{*\green{\sl{#1}}} +%</package> +%<*ltxml> +DefConstructor('\nlex{}', + "<omdoc:phrase type='nlex'>#1</omdoc:phrase>"); +DefConstructor('\nlcex{}', + "<omdoc:phrase type='nlcex'>#1</omdoc:phrase>"); +%</ltxml> +% \end{macrocode} +% \end{environment} +% +% \begin{macro}{sinlinequote} +% \begin{macrocode} +%<*package> +\def\@sinlinequote#1{``{\sl{#1}}''} +\def\@@sinlinequote#1#2{\@sinlinequote{#2}~#1} +\newcommand{\sinlinequote}[2][] +{\def\@opt{#1}\ifx\@opt\@empty\@sinlinequote{#2}\else\@@sinlinequote\@opt{#2}\fi} +%</package> +%<*ltxml> +DefConstructor('\sinlinequote [] {}', + "<omdoc:phrase type='inlinequote'>" + . "?#1(<dc:source ?#locator(stex:srcref='#locator')()>#1</dc:source>\n)()" + . "#2" + . "</omdoc:phrase>"); +%</ltxml> +% \end{macrocode} +% \end{macro} +% \end{omgroup} +% +% \begin{omgroup}[id=sec:impl:block]{Block-Level Markup} +% +% \begin{environment}{sblockquote} +% \ednote{describe above} +% \begin{macrocode} +%<*package> +\def\begin@sblockquote{\begin{quote}\sl} +\def\end@sblockquote{\end{quote}} +\def\begin@@sblockquote#1{\begin@sblockquote} +\def\end@@sblockquote#1{\def\@@lec##1{{\rm ##1}}\@lec{#1}\end@sblockquote} +\newenvironment{sblockquote}[1][] + {\def\@opt{#1}\ifx\@opt\@empty\begin@sblockquote\else\begin@@sblockquote\@opt\fi} + {\ifx\@opt\@empty\end@sblockquote\else\end@@sblockquote\@opt\fi} +%</package> +%<*ltxml> +DefEnvironment('{sblockquote} []', + "<omdoc:omgroup type='quote'" + . "?#1(<dc:source>#1</dc:source>\n)()" + . "#body" + . "</omdoc:omgroup>"); +%</ltxml> +% \end{macrocode} +% \end{environment} +% +% The line end comment macro makes sure that it will not be forced on the next line unless +% necessary. +% \begin{macro}{\lec} +% The actual appearance of the line end comment is determined by the |\@@lec| macro, +% which can be customized in the document class. The basic one here is provided so that +% it is not missing. +% \begin{macrocode} +%<*package> +\providecommand{\@@lec}[1]{(#1)} +\def\@lec#1{\strut\hfil\strut\null\nobreak\hfill\hbox{\@@lec{#1}}} +\def\lec#1{\@lec{#1}\par} +%</package> +%<*ltxml> +DefConstructor('\lec{}', + "\n<omdoc:note type='line-end-comment'>#1</omdoc:note>"); +%</ltxml> +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\my*graphics} +% We set up a special treatment for including graphics to respect the intended {\omdoc} +% document structure. The main work is done in the transformation stylesheet though. +% +% \begin{macrocode} +%<ltxml>RawTeX(' +%<*ltxml|package> +\newcommand\mygraphics[2][]{\includegraphics[#1]{#2}} +\newcommand\mycgraphics[2][]{\begin{center}\includegraphics[#1]{#2}\end{center}} +\newcommand\mybgraphics[2][]{\fbox{\includegraphics[#1]{#2}\end{center}}} +%</ltxml|package> +%<ltxml>'); +% \end{macrocode} +% \end{macro} +% \end{omgroup} +% +% \begin{omgroup}[id=sec:impl:index]{Index Markup} +% +% \begin{macrocode} +%<*package> +\newcommand{\omdoc@index}[2][]{\def\@test{#1}% +\ifindex\ifx\@test\@empty\index{#2}\else\index{#1@#2}\fi\fi} +\newcommand{\indexalt}[3][]{{#2}\omdoc@index[#1]{#3}} % word in text and index +\newcommand{\indextoo}[2][]{{#2}\omdoc@index[#1]{#2}} % word in text and index +%</package> +% \end{macrocode} +% +% this puts two-compound words into the index in various permutations +% +% \begin{macrocode} +%<*package> +\newcommand{\@twin}[3][]{\def\@test{#1}% +\ifindex\ifx\@test\@empty\index{#2!#3}\else\index{#1@#2!#3}\fi\index{#3!#2}\fi} +\newcommand{\twinalt}[4][]{#2\@twin[#1]{#3}{#4}} +\newcommand{\twintoo}[3][]{{#2 #3}\@twin[#1]{#2}{#3}} % and use the word compound too +%</package> +% \end{macrocode} +% +% this puts adjectivized two-compound words into the index in various +% permutations\ednote{what to do with the optional argument here and below?} +% +% \begin{macrocode} +%<*package> +\newcommand{\@atwin}[4][]{\def\@test{#1}% +\ifindex\ifx\@test\@empty\index{#2!#3!#4}\else\index{#1@#2!#3!#4}\fi\index{#3!#2 (#1)}\fi} +\newcommand{\atwinalt}[5][]{#2\@atwin[#1]{#3}{#4}{#4}} +\newcommand{\atwintoo}[4][]{{#2 #3 #4}\@atwin[#1]{#2}{#3}{#4}} % and use it too +%</package> +%<*ltxml> +DefConstructor('\indextoo[]{}', + "<omdoc:idx>" + . "<omdoc:idt>#2</omdoc:idt>" + . "<omdoc:ide ?#1(sort-by='#1')()>" + . "<omdoc:idp>#2</omdoc:idp>" + . "</omdoc:ide>" + ."</omdoc:idx>"); +DefConstructor('\indexalt[]{}{}', + "<omdoc:idx>" + . "<omdoc:idt>#2</omdoc:idt>" + . "<omdoc:ide ?#1(sort-by='#1')()>" + . "<omdoc:idp>#3</omdoc:idp>" + . "</omdoc:ide>" + ."</omdoc:idx>"); +%</ltxml> +% \end{macrocode} +% +% \begin{macrocode} +%<*ltxml> +DefConstructor('\twintoo[]{}{}', + "<omdoc:idx>" + . "<omdoc:idt>#2 #3</omdoc:idt>" + . "<omdoc:ide ?#1(sort-by='#1')()>" + . "<omdoc:idp>#2</omdoc:idp>" + . "<omdoc:idp>#3</omdoc:idp>" + . "</omdoc:ide>" + ."</omdoc:idx>"); +DefConstructor('\twinalt[]{}{}{}', + "<omdoc:idx>" + . "<omdoc:idt>#2</omdoc:idt>" + . "<omdoc:ide ?#1(sort-by='#1')()>" + . "<omdoc:idp>#2</omdoc:idp>" + . "<omdoc:idp>#3</omdoc:idp>" + . "</omdoc:ide>" + ."</omdoc:idx>"); +%</ltxml> +% \end{macrocode} +% +% \begin{macrocode} +%<*ltxml> +DefConstructor('\atwintoo[]{}{}{}', + "<omdoc:idx>" + . "<omdoc:idt>#2 #3</omdoc:idt>" + . "<omdoc:ide ?#1(sort-by='#1')()>" + . "<omdoc:idp>#2</omdoc:idp>" + . "<omdoc:idp>#3</omdoc:idp>" + . "<omdoc:idp>#4</omdoc:idp>" + . "</omdoc:ide>" + ."</omdoc:idx>"); + +DefConstructor('\atwinalt[]{}{}{}{}', + "<omdoc:idx>" + . "<omdoc:idt>#2</omdoc:idt>" + . "<omdoc:ide ?#1(sort-by='#1')()>" + . "<omdoc:idp>#2</omdoc:idp>" + . "<omdoc:idp>#3</omdoc:idp>" + . "<omdoc:idp>#4</omdoc:idp>" + . "</omdoc:ide>" + ."</omdoc:idx>"); +%</ltxml> +% \end{macrocode} +% and finally we supply the |\printindex| command +% \begin{macrocode} +%<*package> +\def\printindex{\IfFileExists{\jobname.ind}{\input{\jobname.ind}}{}} +%</package> +%<*ltxml> +DefConstructor('\printindex','<omdoc:index/>'); +%</ltxml> +% \end{macrocode} +% \end{omgroup} +% +% \begin{omgroup}{{\LaTeX} Commands we interpret differently} +% +% The first think we have to take care of are the paragraphs, we want to generate {\omdoc} +% that uses the |omdoc:p| element for paragraphs inside |CMP|s. For that we have modified +% the DTD only to allowed |omdoc:p| elements in |omdoc:CMP| (in particular no text). Then +% we instruct the |\par| macro to close a |omdoc:p| element if possible. The next +% |omdoc:p| element is then opened automatically, since we make |omdoc:p| and |omdoc:CMP| +% autoclose and autoopen. +% +% \begin{macrocode} +%<*ltxml> +DefConstructor('\par',sub { $_[0]->maybeCloseElement('omdoc:p'); }, + alias=>"\\par\n"); +Tag('omdoc:p', autoClose=>1, autoOpen=>1); +Tag('omdoc:CMP', autoClose=>1, autoOpen=>1); +Tag('omdoc:omtext', autoClose=>1, autoOpen=>1); +%</ltxml>#$ +% \end{macrocode} +% the rest of the reinterpretations is quite simple, we either disregard presentational +% markup or we re-interpret it in terms of {\omdoc}. +% \begin{macrocode} +%<package>\def\omspace#1{\hspace*{#1}} +%<*ltxml> +DefConstructor('\omspace{}',''); +DefConstructor('\emph{}',"<omdoc:phrase class='emphasis'>#1</omdoc:phrase>"); +DefConstructor('\em',"<omdoc:phrase class='emphasis'>"); +DefConstructor('\texttt{}',"<omdoc:phrase class='code'>#1</omdoc:phrase>"); +DefConstructor('\textbf{}',"<omdoc:phrase class='bold'>#1</omdoc:phrase>"); +Tag('omdoc:phrase', autoClose=>1); +DefEnvironment('{center}','#body'); +DefEnvironment('{flushleft}','#body'); +DefEnvironment('{flushright}','#body'); +DefEnvironment('{minipage}[]{}','#body'); +DefEnvironment('{quote}', + "<omdoc:phrase type='quote' style='display:block'>" + . "#body" + ."</omdoc:phrase>"); +DefEnvironment('{quotation}', + "<omdoc:phrase type='quote' style='display:block'> + . "#body" + ."</omdoc:phrase>"); +DefEnvironment('{LARGE}','#body'); +DefEnvironment('{Large}','#body'); +DefEnvironment('{large}','#body'); +DefEnvironment('{small}','#body'); +DefEnvironment('{footnotesize}','#body'); +DefEnvironment('{tiny}','#body'); +DefEnvironment('{scriptsize}','#body'); +DefConstructor('\LARGE',''); +DefConstructor('\Large',''); +DefConstructor('\large',''); +DefConstructor('\small',''); +DefConstructor('\footnotesize',''); +DefConstructor('\scriptsize',''); +DefConstructor('\tiny',''); +DefConstructor('\fbox{}','#1'); +DefConstructor('\footnote[]{}', + "<omdoc:note class='foot' ?#1(mark='#1')>#2</omdoc:note>"); +DefConstructor('\footnotemark[]',""); +DefConstructor('\footnotetext[]{}', + "<omdoc:note class='foot' ?#1(mark='#1')>#2</omdoc:note>"); +DefConstructor('\sf', ''); +DefConstructor('\sc', ''); +%</ltxml> +% \end{macrocode} +% \end{omgroup} +% +% \begin{omgroup}[id=sec:impl:ids]{Providing IDs for {\omdoc} Elements} +% +% To provide default identifiers, we tag all {\omdoc} elements that allow |xml:id| +% attributes by executing the |numberIt| procedure below. +% +% \begin{macrocode} +%<*ltxml> +Tag('omdoc:p',afterOpen=>\&numberIt,afterClose=>\&locateIt); +Tag('omdoc:omtext',afterOpen=>\&numberIt,afterClose=>\&locateIt); +Tag('omdoc:omgroup',afterOpen=>\&numberIt,afterClose=>\&locateIt); +Tag('omdoc:CMP',afterOpen=>\&numberIt,afterClose=>\&locateIt); +Tag('omdoc:link',afterOpen=>\&numberIt,afterClose=>\&locateIt); +Tag('omdoc:meta',afterOpen=>\&numberIt,afterClose=>\&locateIt); +Tag('omdoc:resource',afterOpen=>\&numberIt,afterClose=>\&locateIt); +Tag('omdoc:ul',afterOpen=>\&numberIt,afterClose=>\&locateIt); +Tag('omdoc:li',afterOpen=>\&numberIt,afterClose=>\&locateIt); +Tag('omdoc:di',afterOpen=>\&numberIt,afterClose=>\&locateIt); +Tag('omdoc:dt',afterOpen=>\&numberIt,afterClose=>\&locateIt); +Tag('omdoc:dd',afterOpen=>\&numberIt,afterClose=>\&locateIt); +Tag('omdoc:ol',afterOpen=>\&numberIt,afterClose=>\&locateIt); +Tag('omdoc:dl',afterOpen=>\&numberIt,afterClose=>\&locateIt); +Tag('omdoc:idx',afterOpen=>\&numberIt,afterClose=>\&locateIt); +Tag('omdoc:phrase',afterOpen=>\&numberIt,afterClose=>\&locateIt); +Tag('omdoc:note',afterOpen=>\&numberIt,afterClose=>\&locateIt); +%</ltxml> +% \end{macrocode} +% We also have to number some {\latexml} tags, so that we do not get into trouble with the +% \omdoc tags inside them. +% \begin{macrocode} +%<*ltxml> +Tag('ltx:tabular',afterOpen=>\&numberIt,afterClose=>\&locateIt); +Tag('ltx:thead',afterOpen=>\&numberIt,afterClose=>\&locateIt); +Tag('ltx:td',afterOpen=>\&numberIt,afterClose=>\&locateIt); +Tag('ltx:tr',afterOpen=>\&numberIt,afterClose=>\&locateIt); +Tag('ltx:caption',afterOpen=>\&numberIt,afterClose=>\&locateIt); +%</ltxml> +% \end{macrocode} +% The |numberIt| procedure gets the prefix from first parent with an |xml:id| attribute and then +% extends it with a label that reflects the number of preceding siblings, provided that +% there is not already an identifier. Additionally, it estimates an XPointer position in the original document +% of the command sequence which produced the tag. +% The |locateIt| subroutine is a sibling of |numberIt| as it is required as an |afterClose| handle for tags +% produced by {\LaTeX} environments, as opposed to commands. |locateIt| estimates an XPointer end position of +% the LaTeX environment, allowing to meaningfully locate the entire environment at the source. +% \begin{macrocode} +%<*ltxml> +sub numberIt { + my($document,$node,$whatsit)=@_; + my(@parents)=$document->findnodes('ancestor::*[@xml:id]',$node); + my $prefix= (@parents ? $parents[$#parents]->getAttribute('xml:id')."." : ''); + my(@siblings)=$document->findnodes('preceding-sibling::*[@xml:id]',$node); + my $n = scalar(@siblings)+1; + my $id = ($node -> getAttribute('xml:id')); + $node->setAttribute('xml:id'=>$prefix."p$n") unless $id; + my $about = $node -> getAttribute('about'); + $node->setAttribute('about'=>'#'.$node->getAttribute('xml:id')) unless $about; + #Also, provide locators: + my $locator = $whatsit->getProperty('locator'); + #Need to inherit locators if missing: + $locator = (@parents ? $parents[$#parents]->getAttribute('stex:srcref') : '') unless $locator; + $node->setAttribute('stex:srcref'=>$locator) if $locator; } +sub locateIt { + my($document,$node,$whatsit)=@_; + #Estimate trailer locator: + my $trailer = $whatsit->getProperty('trailer'); + return unless $trailer; #Nothing we can do if the trailer isn't defined + $trailer = $trailer->getLocator; + return unless ($trailer && $trailer!~/^\s*$/); #Useless if broken + my $locator = $node->getAttribute('stex:srcref'); + if ($locator) { + $locator =~ /^(.+from=\d+;\d+)/; + my $from = $1; + $trailer =~ /(,to=\d+;\d+.+)$/; + my $to = $1; + $locator = $from.$to; + } else { + $locator = $trailer; #This should never happen + } + $node->setAttribute('stex:srcref' => $locator); +} +%</ltxml>#$ +% \end{macrocode} +% \end{omgroup} +% +% \begin{omgroup}{Finale} +% +% We need to terminate the file with a success mark for perl. +% \begin{macrocode} +%<ltxml>1; +% \end{macrocode} +% \end{omgroup} +% \end{omgroup} +% \Finale +\endinput +% \iffalse +% LocalWords: GPL structuresharing STR omdoc dtx stex CPERL LoadClass url dc +%%% Local Variables: +%%% mode: doctex +%%% TeX-master: t +%%% End: +% \fi +% LocalWords: RequirePackage RegisterNamespace namespace xsl DocType ltxml dtd +% LocalWords: ltx DefEnvironment beforeDigest AssignValue inPreamble getGullet +% LocalWords: afterDigest keyval omgroup DefKeyVal Semiverbatim KeyVal locator +% LocalWords: OptionalKeyVals DefParameterType IfBeginFollows skipSpaces CMP +% LocalWords: ifNext DefMacro needwrapper unlist DefConstructor omtext bgroup +% LocalWords: useCMPItemizations RefStepItemCounter egroup beginItemize li di +% LocalWords: beforeDigestEnd dt autoclose ul ol dl env showignores srcref def +% LocalWords: afterOpen LastSeenCMP autoClose DefCMPEnvironment proto ToString +% LocalWords: addAttribute nlex nlcex omdocColorMacro args tok MergeFont qw rm +% LocalWords: TokenizeInternal toString isMath foreach maybeCloseElement id'd +% LocalWords: autoOpen minipage footnotesize scriptsize numberIt whatsit href +% LocalWords: getAttribute setAttribute OMDoc RelaxNGSchema noindex xml lec sc +% LocalWords: Subsubsection useDefaultItemizations refundefinedtrue sblockquote +% LocalWords: DefCMPConstructor sinlinequote idx idt ide idp emph extrefs sref +% LocalWords: flushleft flushright DeclareOption PassOptions undef cls iffalse +% LocalWords: ProcessOptions subparagraph ignoresfalse ignorestrue raisebox tr +% LocalWords: texorpdfstring latexml texttt fileversion maketitle newpage iff +% LocalWords: tableofcontents newpage ednote obeylines usepackage indextoo Cwd +% LocalWords: indextoo twintoo twintoo exfig vspace twinalt ldots ttin emin +% LocalWords: renmanig myindex atwin atwin packge-local blockquote inlinequote +% LocalWords: atwintoo atwinalt atwinalt printbibliography impl cwd newif ifx +% LocalWords: ifindex indextrue indexfalse srefaddidkey omdaddkey smallskip +% LocalWords: providecommand stDMemph textbf newenvironment omdsetkeys hfil +% LocalWords: noindent ignorespaces newcommand nobreak hfill hbox mygraphics +% LocalWords: includegraphics mycgraphics mybgraphics fbox adjectivized hspace +% LocalWords: printindex jobname.ind jobname.ind omspace footnotemark thead +% LocalWords: footnotetext findnodes doctex diff --git a/Master/texmf-dist/source/latex/stex/presentation/presentation.dtx b/Master/texmf-dist/source/latex/stex/presentation/presentation.dtx new file mode 100644 index 00000000000..57e2352ede5 --- /dev/null +++ b/Master/texmf-dist/source/latex/stex/presentation/presentation.dtx @@ -0,0 +1,1368 @@ +% \iffalse meta-comment +% An Infrastructure for Presenting Semantic Macros in sTeX +% Copyright (C) 2004-2007 Michael Kohlhase, all rights reserved +% This file is released under the LaTeX Project Public License (LPPL) +% +% The development version of this file can be found at +% $HeadURL: https://svn.kwarc.info/repos/stex/trunk/sty/presentation/presentation.dtx $ +% \fi +% +% \iffalse +%<package>\NeedsTeXFormat{LaTeX2e}[1999/12/01] +%<package>\ProvidesPackage{presentation}[2010/06/25 v1.0 presentation for semantic macros] +% +%<*driver> +\documentclass{ltxdoc} +\usepackage{url,array,presentation,float,stex-logo} +\usepackage[show]{ed} +\usepackage[hyperref=auto,style=alphabetic]{biblatex} +\bibliography{kwarc} +\usepackage{../ctansvn} +\usepackage{hyperref} +\usepackage[eso-foot,today]{svninfo} +\svnInfo $Id: presentation.dtx 1502 2010-07-20 08:17:00Z kohlhase $ +\svnKeyword $HeadURL: https://svn.kwarc.info/repos/stex/trunk/sty/presentation/presentation.dtx $ +\makeindex +\floatstyle{boxed} +\newfloat{exfig}{thp}{lop} +\floatname{exfig}{Example} +\begin{document}\DocInput{presentation.dtx}\end{document} +%</driver> +% \fi +% +% \CheckSum{557} +% +% \changes{v0.9}{2005/06/14}{First Version with Documentation} +% \changes{v0.9a}{2005/07/01}{Completed Documentation} +% \changes{v0.9b}{2005/08/06}{Complete functionality and Updated Documentation} +% \changes{v0.9c}{2006/01/13}{more packaging} +% \changes{v0.9d}{2006/10/13}{adding mixfix declarations} +% \changes{v0.9d}{2006/10/13}{dealing with precedences in keyword arguments} +% \changes{v0.9e}{2007/09/03}{fixing argument precedences, adding LaTeXML bindings} +% \changes{v0.9f}{2007/12/09}{adding general elision} +% \changes{v0.9g}{2008/06/17}{getting the LaTeXML right} +% \changes{v0.9h}{2009/02/27}{turning the precedence order around to make this compatible +% with the latest OMDoc, change all precedences $n$ to $1000-n$} +% \changes{v0.9h}{2009/07/30}{adding brackets to the generated notation elements} +% \changes{v0.9h}{2010/06/18}{considering done now} +% \GetFileInfo{presentation.sty} +% +% \MakeShortVerb{\|} +%\def\scsys#1{{{\sc #1}}\index{#1@{\sc #1}}} +% \def\xml{\scsys{Xml}} +% \def\mathml{\scsys{MathML}} +% \def\omdoc{\scsys{OMDoc}} +% \def\openmath{\scsys{OpenMath}} +% \def\latexml{\scsys{LaTeXML}} +% \def\perl{\scsys{Perl}} +% \def\cmathml{Content-{\sc MathML}\index{Content {\sc MathML}}\index{MathML@{\sc MathML}!content}} +% \def\activemath{\scsys{ActiveMath}} +% \def\twin#1#2{\index{#1!#2}\index{#2!#1}} +% \def\twintoo#1#2{{#1 #2}\twin{#1}{#2}} +% \def\atwin#1#2#3{\index{#1!#2!#3}\index{#3!#2 (#1)}} +% \def\atwintoo#1#2#3{{#1 #2 #3}\atwin{#1}{#2}{#3}} +% \title{{\texttt{presentation.sty}}: An Infrastructure for Presenting Semantic +% Macros in {\stex}\thanks{Version {\fileversion} (last revised {\filedate})}} +% \author{Michael Kohlhase \& Deyan Ginev\\ +% Jacobs University, Bremen\\ +% \url{http://kwarc.info/kohlhase}} +% \date{\today} +% \maketitle +% +% \begin{abstract} +% The |presentation| package is a central 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 an infrastructure that allows to specify the presentation of +% semantic macros, including preference-based bracket elision. This allows to markup the +% functional structure of mathematical formulae without having to lose high-quality +% human-oriented presentation in {\LaTeX}. Moreover, the notation definitions can be +% used by MKM systems for added-value services, either directly from the {\sTeX} +% sources, or after translation. +% \end{abstract} +% +% \setcounter{tocdepth}{2}\tableofcontents\newpage +% +%\section{Introduction}\label{sec:presentation} +% +% The |presentation| package supplies an infrastructure that allows to specify the +% presentation of semantic macros, including preference-based bracket elision. This allows +% to markup the functional structure of mathematical formulae without having to lose +% high-quality human-oriented presentation in {\LaTeX}. Moreover, the notation definitions +% can be used by MKM systems for added-value services, either directly from the {\sTeX} +% sources, or after translation. +% +% {\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). +% +% The setup for semantic macros described in the {\stex} |modules| package works well for +% simple mathematical functions: we make use of the macro application syntax in {\TeX} to +% express function application. For a simple function called ``foo'', we would just +% declare |\symdef{foo}[1]{foo(#1)}| and have the concise and intuitive syntax |\foo{x}| +% for $foo(x)$. But mathematical notation is much more varied and interesting than just +% this. +% +% \section{The User Interface}\label{sec:user} +% +% In this package we will follow the {\sTeX} approach and assume that there are four basic +% types of mathematical expressions: symbols, variables, applications and +% binders. Presentation of the variables is relatively straightforward, so we will not +% concern ourselves with that. The application of functions in mathematics is mostly +% presented in the form $f(a_1,\ldots,a_n)$, where $f$ is the function and the $a_i$ are +% the arguments. However, many commonly-used functions from this presentational scheme: +% for instance binomial coefficients: $\bigl({n\atop k}\bigr)$, pairs: $\langle +% a,b\rangle$, sets: $\{x\in S\,\vert\, x^2\ne0\}$, or even simple addition: $3+5+7$. Note +% that in all these cases, the presentation is determined by the (functional) head of the +% expression, so we will bind the presentational infrastructure to the operator. +% +% \subsection{Prefix \& Postfix Notations}\label{sec:prepostfix} +% +% The default notation for an object that is obtained by applying a function $f$ to +% arguments $a_1$ to $a_n$ is $f(a_1,\ldots,a_n)$. The \DescribeMacro{\prefix}|\prefix| +% macro allows to specify a prefix presentation for a function (the usual presentation in +% mathematics). Note that it is better to specify |\symdef{uminus}[1]{\prefix{-}{#1}}| +% than just |\symdef{uminus}[1]{-#1}|, since we can specify the bracketing behavior in the +% former (see Section~\ref{sec:elision}). +% +% The \DescribeMacro{\postfix}|\postfix| macro is similar, only that the function is +% presented after the argument as for e.g. the factorial function: $5!$ stands for the +% result of applying the factorial function to the number 5. Note that the function is +% still the first argument to the |\postfix| macro: we would specify the presentation for +% the factorial function with |\symdef{factorial}[1]{\postfix{!}{#1}}|. +% +% |\prefix| and |\postfix| have $n$-ary variants \DescribeMacro{\prefixa}|\prefixa| and +% \DescribeMacro{\postfixa}|\postfixa| that take an arbitrary number of arguments +% (mathematically; syntactically grouped into one {\TeX} argument). These take an extra +% separator argument.\ednote{think of a good example!} +% +% \subsection{Mixfix Notations}\label{sec:mixfix} +% +% For the presentation of more complex operators, we will follow the approach used by the +% Isabelle theorem prover. There, the presentation of an $n$-ary function (i.e. one that +% takes $n$ arguments) is specified as +% \meta{pre}\meta{arg$_0$}\meta{mid$_1$}$\cdots$\meta{mid$_n$}\meta{arg$_n$}\meta{post}, +% where the \meta{arg$_i$} are the arguments and \meta{pre}, \meta{post}, and the +% \meta{mid$_i$} are presentational material. For instance, in infix operators like the +% binary subset operator, \meta{pre} and $\meta{post}$ are empty, and \meta{mid$_1$} is +% $\subseteq$. For the ternary conditional operator in a programming language, we might +% have the presentation pattern +% |if|\meta{arg$_1$}|then|\meta{arg$_2$}|else|\meta{arg$_3$}|fi| that utilizes all +% presentation positions. +% +% \DescribeMacro{\mixfix*}The |presentation| package provides mixfix declaration macros +% |\mixfixi|, |\mixfixii|, and |\mixfixiii| for unary, binary, and ternary functions. This +% covers most of the cases, larger arities would need a different argument +% pattern.\footnote{If you really need larger arities, contact the author!} The call +% pattern of these macros is just the presentation pattern above. In general, the mixfix +% declaration of arity $i$ has $2n+1$ arguments, where the even-numbered ones are for the +% arguments of the functions and the odd-numbered ones are for presentation material. For +% instance, to define a semantic macro for the subset relation and the conditional, we +% would use the markup in Figure~\ref{fig:mixfix}. +% \begin{exfig} +% \begin{verbatim} +% \symdef{sseteq}[2]{\mixfixii{}{#1}{\subseteq}{#2}{}} +% \symdef{sseteq}[2]{\infix\subseteq{#1}{#2}} +% \symdef{ite}[2]{\mixfixiii{{\tt{if}}\;}{#1} +% {\;{\tt{then}}\;}{#2} +% {\;{\tt{else}}\;}{#3}{\;{\tt{fi}}}} +% \end{verbatim} +% \vspace*{-1.5em} +% \begin{center} +% \begin{tabular}{|l|l|}\hline +% source & presentation \\\hline +% |\sseteq{S}T| & $(S\subseteq T)$\\\hline +% |\ite{x<0}{-x}x| & ${\tt{if}}\,x<0\,{\tt{then}}\,-x\,{\tt{else}}\,x\,{\tt{fi}}$\\\hline +% \end{tabular} +% \end{center} +% \caption{Declaration of mixfix operators}\label{fig:mixfix} +% \end{exfig} +% +% For certain common cases, the |presentation| package provides shortcuts for the mixfix +% declarations. For instance, we provide the \DescribeMacro{\infix}|\infix| macro for +% binary operators that are written between their arguments (see Figure~\ref{fig:mixfix}).\ednote{really?} +% +% \subsection{\texorpdfstring{$n$}{n}-ary Associative Operators}\label{sec:assoc} +% +% Take for instance the operator for set union: formally, it is a binary function on +% sets that is associative (i.e. $(S_1\cup S_2)\cup S_3=S_1\cup (S_2\cup S_3)$), therefore +% the brackets are often elided, and we write $S_1\cup S_2\cup S_3$ instead (once we have +% proven associativity). Some authors even go so far to introduce set union as a $n$-ary +% operator, i.e. a function that takes an arbitrary (positive) number of arguments. We will +% call such operators {\bf{$n$-ary +% associative}\atwin{n-ary}{associative}{operator}}. +% +% Specifying the presentation\ednote{introduce the notion of presentation above} of +% $n$-ary associative operators in |\symdef| forms is not straightforward, so we provide +% some infrastructure for that. As we cannot predict the number of arguments for $n$-ary +% operators, we have to give them all at once, if we want to maintain our use of {\TeX} +% macro application to specify function application. So a semantic macro for an $n$-ary +% operator will be applied as |\nunion{|\meta{$a_1$}|,|\ldots|,|\meta{$a_n$}|}|, where the +% sequence of $n$ logical arguments \meta{$a_i$} are supplied as one {\TeX} argument which +% contains a comma-separated list. We provide variants of the mixfix declarations +% presented in section~\ref{sec:mixfix} which deal with associative arguments. For +% instance, the variant \DescribeMacro{\mixfixa}|\mixfixa| allows to specify $n$-ary +% associative operators. +% |\mixfixa{|\meta{pre}|}{|\meta{arg}|}{|\meta{post}|}{|\meta{op}|}| specifies a +% presentation, where \meta{arg} is the associative argument and \meta{op} is the +% corresponding operator that is mapped over the argument list; as above, {\meta{pre}}, +% \meta{post}, are prefix and postfix presentational material. For instance, the finite +% set constructor could be constructed as +% \begin{verbatim} +% \newcommand{\fset}[1]{\mixfixa[p=1000]{\{}{#1}{\}}{,}} +% \end{verbatim} +% +% The \DescribeMacro{\assoc}|\assoc| macro is a convenient abbreviation of a |\mixfixa| +% that can be used in cases, where \meta{pre} and \meta{post} are empty (i.e. in the +% majority of cases). It takes two arguments: the presentation of a binary operator, and a +% comma-separated list of arguments, it replaces the commas in the second argument with +% the operator in the first one. For instance |\assoc\cup{S_1,S_2,S_3}| will be formatted +% to $S_1\cup S_2\cup S_3$. Thus we can use |\def\nunion#1{\assoc\cup{#1}}| or even +% |\def\nunion{\assoc\cup}|, to define the $n$-ary operator for set union in {\TeX}. For +% the definition of a semantic macro in {\stex}, we use the second form, since we are more +% conscious of the right number of arguments and would declare +% |\symdef{nunion}[1]{\assoc\cup{#1}}|.\ednote{think about big operators for ACI +% functions} +% +% The |\mixfixii| macro has variants \DescribeMacro{\mixfixia}|\mixfixia| and +% \DescribeMacro{\mixfixai}|\mixfixai| which allow to make one or two arguments in a +% binary function associative. A use case for the second macro is an nary function type +% operator |\fntype|, which can be defined via +% \begin{verbatim} +% \def\fntype#1#2{\mixfixai{}{#1}\rightarrow{#2}{}\times} +% \end{verbatim} +% \def\fntype#1#2{\mixfixai{}{#1}\rightarrow{#2}{}\times} +% and which will format |\fntype{\alpha,\beta,\gamma}\delta| as +% $\fntype{\alpha,\beta,\gamma}\delta$ +% +% Finally, the |\mixfixiii| macro has the variants |\mixfixaii|, |\mixfixiai|, and +% |\mixfixiia| as above\footnote{If you really need larger arities with associative +% arguments, contact the package author!}. For instance we can use the first variant for +% a typing judgment using +% \begin{verbatim} +% \def\typej#1#2#3{\mixfixaii{}{#1}{\vdash_{\Sigma}}{#2}\colon{#3}{}{,}} +% \end{verbatim} +% \def\typej#1#2#3{\mixfixaii{}{#1}{\vdash_{\Sigma}}{#2}\colon{#3}{}{,}} +% which formats |\typej{\Gamma,[x:\alpha],[y:\beta]}{f(x,y)}{\beta}| as +% \[\typej{\Gamma,[x:\alpha],[y:\beta]}{f(x,y)}{\beta}.\] +% +% \subsection{Precedence-Based Bracket Elision}\label{sec:elision} +% +% In the infrastructure discussed above, we have completely ignored the fact that we use +% brackets to disambiguate the formula structure. The general baseline rule here is that +% we enclose any presented subformula with (round) brackets to mark it as a logical unit. +% If we applied this to the following formula that combines set union and set intersection +% \begin{equation}\label{cupcap} +% |\nunion{\ninters{a,b},\ninters{c,d}}| +% \end{equation} +% this would yield $((a\cap b)\cup (c\cap d))$, and not $a\cap b\cup c\cap d$ as we are +% used to. In mathematics, brackets are elided, whenever the author anticipates that the +% reader can understand the formula without them, and would be overwhelmed with them. To +% achieve this, there are set of common conventions that govern bracket elision --- +% ``$\cap$ binds stronger than $\cup$'' in (\ref{cupcap}). The most common is to assign +% precedences to all operators, and elide brackets, if the {\index*{precedence}} of the +% operator is larger than that of the context it is presented in (or equivalently: we only +% write brackets, if the operator precedence is smaller or equal to the context +% precedence). Note that this is more selective that simply dropping outer brackets which +% would yield $a\cap b\cup c\cap d$ for (\ref{capcup}), where we would have liked $(a\cup +% b)\cap(c\cup d)$ +% \begin{equation}\label{capcup} +% |\ninters{\nunion{a,b},\nunion{c,d}}| +% \end{equation} +% In our example above, we would assign $\cap$ a larger precedence than $\cup$ (and both a +% larger precedence than the initial precedence to avoid outer brackets). To compute the +% presentation of (\ref{capcup}) we start out with the |\ninters|, elide its brackets +% (since the precedence $n$ of $\cup$ is larger than the initial precedence $i$), and set +% the context precedence for the arguments to $n$. When we present the arguments, we +% present the brackets, since the precedence of |nunion| is larger than the context +% precedence $n$. +% +% This algorithm --- which we call {\textbf{precedence-based bracket elision}} --- goes a +% long way towards approximating mathematical practice. Note that full bracket elision in +% mathematical practice is a reader-oriented process, it cannot be fully mechanical, +% e.g. in $(a\cap b\cap c\cap d\cap e\cap f\cap g)\cup h$ we better put the brackets +% around the septary intersection to help the reader even though they could have been +% elided by our algorithm. Therefore, the author has to retain full control\ednote{think +% about how to implement that. We need a way to override precedences locally} over +% bracketing in a bracket elision architecture. Otherwise it would become impossible to +% explain the concept of associativity in $(a\circ b)\circ c =a\circ(b\circ c)$, where we +% need the brackets for this one time on an otherwise associative operation $\circ$. +% +% \begin{figure}[htb] +% \begin{center} +% \begin{tabular}{|l|l|l|}\hline +% Precedence & Operators & Comment\\\hline\hline +% 800 & +,- & unary \\\hline +% 800 & $\hat{}$ & exponentiation \\\hline +% 600 & $*,\land,\cap$ & multiplicative \\\hline +% 500 & $+,-,\lor,\cup$ & additive\\\hline +% 400 & / & fraction \\\hline +% 300 & $=, \ne, \leq, <, >, \geq$ & relation\\\hline +% \end{tabular} +% \end{center}\vspace*{-1em} +% \caption{Common Operator Precedences}\label{fig:precedence} +% \end{figure} +% +% Furthermore, we supply an optional keyval arguments to the mixfix declarations and their +% abbreviations that allow to specify precedences: The key \DescribeMacro{p}|p| key is +% used to specify the {\bf{operator precedence}}, and the keys +% \DescribeMacro{pi}\DescribeMacro{pii}\DescribeMacro{piii}|p|\meta{i} can be used to +% specify the {\bf{argument precedence}s}. The latter will set the precedence level while +% processing the arguments, while the operator precedence invokes brackets, if it is +% smaller than the current precedence level --- which is set by the appropriate argument +% precedence by the dominating operators or the outer precedence. The values of the +% precedence keys can be integers or \DescribeMacro{\iprec}|\iprec| for the infinitely +% large precedence or \DescribeMacro{\niprec}|\niprec| for the infinitely small +% precedence. +% +% If none of the precedences is specified, then the defaults are assumed. The operator +% precedence is set to the default operator precedence, which defaults to 0. The argument +% precedences default to the operator precedence. +% +% Figure~\ref{fig:precedence} gives an overview over commonly used precedences. Note that +% most operators have precedences higher than the default precedence of 0, otherwise the +% brackets would not be elided. For our examples above, we would define +% \begin{verbatim} +% \newcommand{\nunion}[1]{\assoc[p=500]{\cup}{#1}} +% \newcommand{\ninters}[1]{\assoc[p=600]{\cap}{#1}} +% \end{verbatim} +% to get the desired behavior. +% +% Note that the presentation macros uses round brackets for grouping by default. We can +% specify other brackets via two more keywords: \DescribeMacro{lbrack}|lbrack| and +% \DescribeMacro{rbrack}|rbrack|. +% +% Note that formula parts that look like brackets usually are not. For instance, we should +% not define the finite set constructor via +% \begin{equation}\label{wrongset} +% |\newcommand{\fset}[1]{\assoc[lbrack=\{,rbrack=\}]{,}{#1}}| +% \end{equation} +% where the curly braces are used as brackets, but as presented in section~\ref{sec:assoc} +% even though both would format |\fset{a,b,c}| as $\{a,b,c\}$. In the encoding here, an +% operator with suitably high operator precedence (it is the best practice u)would be able +% to make the brackets disappear. Thus the correct version of (\ref{wrongset}) is +% \begin{equation}\label{goodset} +% |\newcommand{\fset}[1]{\mixfixa[p=\iprec,pi=0]{\{}{#1}{\}}{,}}| +% \end{equation} +% Note that |\prefix| and |\postfix| and their variants declared in +% section~\ref{sec:prepostfix} have brackets that do not participate (actively) in the +% precedence-based elision: function application brackets are not subject to elision. But +% the operator precedence |p| is still taken into account for outer brackets. The argument +% precedence |pi| has negative infinity as a default to avoid spurious brackets for +% arguments. +% +% \subsection{Flexible Elision}\label{sec:flexible-elision} +% +% There are several situations in which it is desirable to display only some parts of the +% presentation: +% \begin{itemize} +% \item We have already seen the case of redundant brackets above +% \item Arguments that are strictly necessary are omitted to simplify the notation, and the +% reader is trusted to fill them in from the context. +% \item Arguments are omitted because they have default values. For example $\log_{10}x$ +% is often written as $\log x$. +% \item Arguments whose values can be inferred from the other arguments are usually +% omitted. For example, matrix multiplication formally takes five arguments, namely the +% dimensions of the multiplied matrices and the matrices themselves, but only the latter +% two are displayed. +% \end{itemize} +% +% Typically, these elisions are confusing for readers who are getting acquainted with a +% topic, but become more and more helpful as the reader advances. For experienced readers +% more is elided to focus on relevant material, for beginners representations are more +% explicit. In the process of writing a mathematical document for traditional (print) +% media, an author has to decide on the intended audience and design the level of elision +% (which need not be constant over the document though). With electronic media we have new +% possibilities: we can make elisions flexible. The author still chooses the elision level +% for the initial presentation, but the reader can adapt it to her level of competence and +% comfort, making details more or less explicit. +% +% To provide this functionality, the |presentation| package provides the +% \DescribeMacro{\elide}|\elide| macro allows to associate a text with an integer +% {\textbf{visibility level}} and group them into {\textbf{elision groups}}. High levels +% mean high elidability. +% +% Elision can take various forms in print and digital media. In static media like +% traditional print on paper or the PostScript format, we have to fix the elision level, +% and can decide at presentation time which elidable tokens will be printed and which will +% not. In this case, the presentation algorithm will take visibility thresholds $T_g$ for +% every elidability group $g$ as a user parameter and then elide (i.e. not print) all +% tokens in visibility group $g$ with level $l>T_g$. We specify this threshold for via the +% \DescribeMacro{\setegroup}|\setegroup| macro. For instance in the example below, we have +% a two type annotations |par| for type parameters and |typ| for type annotations +% themselves. +% +% \begin{exfig}[ht] +% \begin{verbatim} +% $\mathbf{I}\elide{par}{500}{^\alpha}\elide{typ}{100}{_{\alpha\to\alpha}} +% :=\lambda{X\elide{typ}{500}{_\alpha}}.X$ +% \end{verbatim}\vspace*{-2em} +% \caption{Elision with Elision Groups}\label{ex:elision} +% \end{exfig} +% +% The visibility levels in the example encode how redundant the author thinks the elided +% parts of the formula are: low values show high redundancy. In our example the intuition +% is that the type parameter on the $\mathbf{I}$ combinator and the type annotation on the +% bound variable $X$ in the $\lambda$ expression are of the same obviousness to the +% reader. So in a document that contains |\setegroup{typ}{0}| and |\setegroup{par}{0}| +% Figure~\ref{ex:elision} will show $\mathbf{I}:=\lambda{X}.X$ eliding all redundant +% information. If we have both values at 600, then we will see +% $\mathbf{I}^\alpha:=\lambda{X_\alpha}.X$ and only if the threshold for |typ| rises above +% 900, then we see the full information: +% $\mathbf{I}^\alpha_{\alpha\to\alpha}:=\lambda{X_\alpha}.X$. +% +% In an output format that is capable of interactively changing its appearance, e.g. +% dynamic XHTML+MathML (i.e. XHTML with embedded Presentation {\mathml} formulas, which +% can be manipulated via JavaScript in browsers), an application can export the +% information about elision groups and levels to the target format, and can then +% dynamically change the visibility thresholds by user interaction. Here the visibility +% threshold would also be used, but here it only determines the default rendering; a user +% can then fine-tune the document dynamically to reveal elided material to support +% understanding or to elide more to increase conciseness. +% +% The price the author has to pay for this enhanced user experience is that she has to +% specify elided parts of a formula that would have been left out in conventional +% {\LaTeX}. Some of this can be alleviated by good coding practices. Let us consider the +% log base case. This is elided in mathematics, since the reader is expected to pick it up +% from context. Using semantic macros, we can mimic this behavior: defining two semantic +% macros: |\logC| which picks up the log base from the context via the |\logbase| macro +% and |\logB| which takes it as a (first) argument. +% +% \begin{verbatim} +% \provideEdefault{logbase}{10} +% \symdef{logB}[2]{\prefix{\mathrm{log}\elide{base}{100}{_{#1}}}{#2}} +% \abbrdef{logC}[1]{\logB{\fromEcontext{logbase}}{#1}} +% \end{verbatim} +% +% \DescribeMacro{\provideEdefault} Here we use the |\provideEdefault| macro to initialize +% a {\LaTeX} token register for the |logbase| default, which we can pick up from the +% elision context using \DescribeMacro{\fromEcontext}|\fromEcontext| in the definition of +% |\logC|. Thus |\logC{x}| would render as $\mathrm{log}_{10}(x)$ with a threshold of 50 +% for |base| and as $\mathrm{log}_2$, if the local {\TeX} group e.g. given by the +% |assertion| environment contains a +% \DescribeMacro{setEdefault}|\setEdefault{logbase}{2}|. +% +% \subsection{Variable Names}\label{sec:inter:vname} +% +% In mathematics we often use complex variable names like $x'$, $g_n$, $f^1$, +% $\widetilde\phi_i^j$ or even $foo$; for presentation-oriented {\LaTeX}, this is not a +% problem, but if we want to generate content markup, we must show that are complex +% identifiers (otherwise the variable name $foo$ might be mistaken for the product $f\cdot +% o\cdot o$). In careful mathematical typesetting, |$sin$| is distinguished from |$\sin$|, +% but we cannot rely on this effect for variable names. +% +% \DescribeMacro{\vname} |\vname| identifies a token sequence as a name, and allows the +% user to provide an ASCII ({\xml}-compatible) identifier for it. The optional argument is +% the identifier, and the second one the LaTeX representation. The identifier can also be +% used with \DescribeMacro{\vname} |\vnref| for referencing. So, if we have used +% |\vnname[xi]{x_i}|, then we can later use |\vnref{xi}| as a short name for +% |\vname{x_i}|. Note that in output formats that are capable of generating structure +% sharing, |\vnref{xi}| would be represented as a cross-reference. +% +% Since indexed variable names make a significant special case of complex identifiers, we +% provides the macros \DescribeMacro{\livar}|\livar| that allows to mark up variables with +% lower indices. If |\livar| is given an optional first argument, this is taken as a +% name. Thus |\livar[foo]{x}1| is ``short'' for |\vname[foo]{x_1}|. The macros +% \DescribeMacro{\livar}|\livar|, serve the analogous purpose for variables with upper +% indices, and \DescribeMacro{\ulivar}|\ulivar| for upper and lower indices. Finally, +% \DescribeMacro{\primvar}|\primvar| and \DescribeMacro{\pprimvar}|\pprimvar| do the same +% for variables with primes and double primes (triple primes are bad style). +% +% \StopEventually{\newpage\PrintIndex\newpage\PrintChanges\printbibliography} +% +% \section{The Implementation}\label{sec:implementation} +% +% The |presentation| package generates to files: the {\LaTeX} package (all the code +% between {\textsf{$\langle$*package$\rangle$}} and {\textsf{$\langle$/package$\rangle$}}) and the +% {\latexml} bindings (between {\textsf{$\langle$*ltxml$\rangle$}} and +% {\textsf{$\langle$/ltxml$\rangle$}}). We keep the corresponding code fragments together, +% since the documentation applies to both of them and to prevent them from getting out of +% sync. +% +% We first make sure that the KeyVal package is loaded (in the right +% version). For {\latexml}, we also initialize the package inclusions. +% \begin{macrocode} +%<package>\RequirePackage{keyval}[1997/11/10] +%<*ltxml> +# -*- CPERL -*- +package LaTeXML::Package::Pool; +use strict; +use LaTeXML::Package; +%</ltxml> +% \end{macrocode} +% We will first specify the default precedences and brackets, together with the macros +% that allow to set them. +% \begin{macrocode} +%<*package> +\def\pres@default@precedence{0} +\def\pres@infty{1000000} +\def\iprec{\pres@infty} +\def\niprec{-\pres@infty} +\def\pres@initial@precedence{0} +\def\pres@current@precedence{\pres@initial@precedence} +\def\pres@default@lbrack{(}\def\pres@lbrack{\pres@default@lbrack} +\def\pres@default@rbrack{)}\def\pres@rbrack{\pres@default@rbrack} +%</package> +%<*ltxml> +DefMacro('\iprec','1000000'); +DefMacro('\niprec','-1000000'); +%</ltxml> +% \end{macrocode} +% +% \subsection{The System Commands}\label{sec:impl:syscommands} +% +% \begin{macro}{\PrecSet} +% |\PrecSet| will set the default precedence.\ednote{need to implement this in {\latexml}?} +% \begin{macrocode} +%<*package> +\def\PrecSet#1{\def\pres@default@precedence{#1}} +%</package> +%<*ltxml> +%</ltxml> +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\PrecWrite} +% |\PrecWrite| will write a bracket, if the precedence mandates it, i.e. if |\pres@p| is +% greater than the current precedence specified by |\pres@current@precedence| +% \begin{macrocode} +%<*package> +\def\PrecWrite#1{\ifnum\pres@p>\pres@current@precedence\else{#1}\fi} +%</package> +% \end{macrocode} +% \end{macro} +% +% \subsection{Prefix \& Postfix Notations}\label{sec:impl:prepostfix} +% +% We first define the keys for the keyval arguments for |\prefix| and |\postfix|. +% +% \begin{macrocode} +%<*package> +\def\prepost@clearkeys{\def\pres@p@key{\pres@default@precedence}\def\pres@pi@key{\niprec} +\def\pres@lbrack{\pres@default@lbrack}\def\pres@rbrack{\pres@default@rbrack}} +\define@key{prepost}{lbrack}{\def\pres@lbrack{#1}} +\define@key{prepost}{rbrack}{\def\pres@lbrack{#1}} +\define@key{prepost}{p}{\def\pres@p@key{#1}} +\define@key{prepost}{pi}{\def\pres@pi@key{#1}} +%</package> +% \end{macrocode} +% +% \begin{macro}{\prefix} +% In prefix we always write the brackets. +% \begin{macrocode} +%<*package> +\newcommand{\prefix}[3][]%key, fn, arg +{\prepost@clearkeys\setkeys{prepost}{#1} +{#2}\pres@lbrack{\edef\pres@current@precedence{\pres@pi@key}#3}\pres@rbrack} +%</package> +%<*ltxml> +DefMacro('\prefix[]{}{}','\@prefix[#1]{$\crossrefOp[fun]{#2}$}{$#3 $}'); +DefConstructor('\@prefix OptionalKeyVals:mi {}{}', + "<omdoc:rendering " + . "?&defined(&KeyVal(#1,'p'))(precedence='&KeyVal(#1,'p')') " + . "argprec='&argument_precedence(#1)'>" + . "<m:mrow>" + . "#2" + . "<m:mrow>" + . "<m:mo fence='true'>(</m:mo>" + . "#3" + . "<m:mo fence='true'>)</m:mo>" + . "</m:mrow>" + . "</m:mrow>" + ."</omdoc:rendering>", + afterDigest=>sub { + #Default argument precedence is -\infty + my $keyval = $_[1]->getArg(1); + $keyval->setValue('pi',-1000000) unless ($keyval && defined($keyval->getValue('pi'))); + applyPrecedencePreferences(@_); + }, + properties=>sub { getSymmdefProperties($_[1]); }); +%</ltxml> +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\postfix} +% \begin{macrocode} +%<*package> +\newcommand{\postfix}[3][]%key, fn, arg +{\prepost@clearkeys\setkeys{prepost}{#1} +\pres@lbrack{\edef\pres@current@precedence{\pres@pi@key}#3}\pres@rbrack{#2}} +%</package> +%<*ltxml> +DefMacro('\postfix []{}{}','\@postfix[#1]{$\crossrefOp[fun]{#2}$}{$#3 $}'); +DefConstructor('\@postfix OptionalKeyVals:mi {}{}', + "<omdoc:rendering " + . "?&defined(&KeyVal(#1,'p'))(precedence='&KeyVal(#1,'p')') " + ."argprec='&argument_precedence(#1)'>" + . "<m:mrow>" + . "<m:mrow>" + . "<m:mo fence='true'>(</m:mo>" + . "#3" + . "<m:mo fence='true'>)</m:mo>" + . "</m:mrow>" + . "#2" + . "</m:mrow>" + ."</omdoc:rendering>", + afterDigest=>sub { + #Default argument precedence is -\infty + my $keyval = $_[1]->getArg(1); + $keyval->setValue('pi',-1000000) unless ($keyval && defined($keyval->getValue('pi'))); + applyPrecedencePreferences(@_); + }, + properties=>sub { getSymmdefProperties($_[1]); }); +%</ltxml> +% \end{macrocode} +% \end{macro} +% +% \subsection{Mixfix Operators}\label{sec:impl:mixfix} +% +% We need to enable notation definitions of the operators that have +% argument- and precedence-aware renderings. To this end, we +% circumvent {\latexml}'s limitations induced by its internal +% processing stages, by pulling most of the argument rendering +% functionality to the XSLT which produces the final {\omdoc} result. +% +% In the {\latexml} bindings, the internal structure of the mixfix +% operators is generically preserved, via the |symdef_presentation_pmml| subroutine +% in the Modules package. Nevertheless, in the current module we add the promised syntactic +% enhancements to each element of the mixfix family. Also, we use the +% |argument_precedence| subroutine to store the precedences given by +% the 'pi', 'pii', etc. keys as a temporary |argprec| +% attribute of the rendering, to be abolished during the final {\omdoc} generation. +% This setup is finally utilized by the XSLT stylesheet which combines +% the operator structure with the preserved precedences to produce the +% proper form of the argument render elements. +% +% \begin{macrocode} +%<*package> +\def\clearkeys{\let\pres@p@key=\relax +\let\pres@pi@key=\relax% +\let\pres@pi@key=\relax% +\let\pres@pii@key=\relax% +\let\pres@piii@key=\relax} +\define@key{mi}{nobrackets}[yes]{\def\pres@p@key{\pres@infty}% +\def\pres@pi@key{-\pres@infty}} +\define@key{mi}{lbrack}{\def\pres@lbrack@key{#1}} +\define@key{mi}{rbrack}{\def\pres@lbrack@key{#1}} +\define@key{mi}{p}{\def\pres@p@key{#1}} +\define@key{mi}{pi}{\def\pres@pi@key{#1}} +\def\prep@keys@mi% +{\edef\pres@lbrack{\@ifundefined{pres@lbrack@key}\pres@default@lbrack\pres@lbrack@key} +\edef\pres@rbrack{\@ifundefined{pres@rbrack@key}\pres@default@rbrack\pres@rbrack@key} +\edef\pres@p{\@ifundefined{pres@p@key}\pres@default@precedence\pres@p@key} +\edef\pres@pi{\@ifundefined{pres@pi@key}\pres@p\pres@pi@key}} +%</package> +%<*ltxml> +our $max_arguments = 10; #Currently max 10 arguments to \symdef. +DefKeyVal('mi','lbrack','Semiverbatim'); +DefKeyVal('mi','rbrack','Semiverbatim'); +DefKeyVal('mi','p','Semiverbatim'); +DefKeyVal('mi','pi','Semiverbatim'); +DefKeyVal('mi','pii','Semiverbatim'); #Why are we using this at mixfixai ? +DefKeyVal('mi','cd','Semiverbatim'); +DefKeyVal('mi','name','Semiverbatim'); +DefKeyVal('mi','nobrackets','Semiverbatim'); +sub argument_precedence { + my ($keyval) = @_; + my $attr = 'pi'; + my @precs = (); + foreach (1..$max_arguments) { + if (defined KeyVal($keyval,$attr)) { + push @precs, ToString(KeyVal($keyval,$attr)) + } else { + push @precs, ""; + } + $attr = $attr.'i'; + } + return join(" ",@precs)." "; +} +sub applyPrecedencePreferences { + my ($stomach,$whatsit) = @_; + my @args = $whatsit->getArgs; + my $keyvals = shift @args; + return unless (defined $keyvals); + my %kvhash = %{$keyvals->getKeyVals}; + #Default p (operator precedence) if not set: + my $default_precedence = LookupValue('default_precedence'); + $keyvals->setValue('p',$default_precedence) unless defined($keyvals->getValue('p')); + return unless (exists $kvhash{'nobrackets'}); + $keyvals->setValue('p',1000000); + $keyvals->setValue('pi',-1000000); + $keyvals->setValue('pii',-1000000); + $keyvals->setValue('piii',-1000000); + return; +}#$ +%</ltxml> +% \end{macrocode} +% +% \begin{macro}{\mixfixi} +% \begin{macrocode} +%<*package> +\newcommand{\mixfixi}[4][]%key, pre, arg, post +{\clearkeys\setkeys{mi}{#1}\prep@keys@mi% +\PrecWrite\pres@lbrack% +#2{\edef\pres@current@precedence{\pres@pi}#3}#4% +\PrecWrite\pres@rbrack} +%</package> +%<*ltxml> +DefMacro('\mixfixi[]{}{}{}', + '\@mixfixi[#1]{$\crossrefOp[fun]{#2}$}{$#3 $}' + . '{$\crossrefOp[fun]{#4}$}'); +DefConstructor('\@mixfixi OptionalKeyVals:mi {}{}{}', + "<omdoc:rendering" + . "?&defined(&KeyVal(#1,'p'))(precedence='&KeyVal(#1,'p')')" + . " argprec='&argument_precedence(#1)'>" + . "<m:mrow>" + . "<m:mo egroup='fence' fence='true'>(</m:mo>" + . "#2 #3 #4" + . "<m:mo egroup='fence' fence='true'>)</m:mo>" + . "</m:mrow>" + ."</omdoc:rendering>", + afterDigest=>sub { applyPrecedencePreferences(@_);}, + properties=>sub { getSymmdefProperties($_[1]); });#$ +%</ltxml> +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\@assoc} +% We are using functionality from the {\LaTeX} core packages here to iterate over the +% arguments. +% \begin{macrocode} +%<*package> +\def\@assoc#1#2#3{% precedence, function, argv +\let\@tmpop=\relax% do not print the function the first time round +\@for\@I:=#3\do{\@tmpop% print the function +% write the i-th argument with locally updated precedence +{\edef\pres@current@precedence{#1}\@I}% +\let\@tmpop=#2}}%update the function +%</package> +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\mixfixa} +% \begin{macrocode} +%<*package> +\newcommand{\mixfixa}[5][]%key, pre, arg, post, assocop +{\clearkeys\setkeys{mi}{#1}\prep@keys@mi% +\PrecWrite\pres@lbrack{#2}{\@assoc\pres@pi{#5}{#3}}{#4}\PrecWrite\pres@rbrack} +%</package> +%<*ltxml> +DefMacro('\mixfixa[]{}{}{}{}', + '\@mixfixa[#1]{$\crossrefOp[fun]{#2}$}{$#3 $}' + . '{$\crossrefOp[fun]{#4}$}' + . '{$\crossrefOp[fun]{#5}$}'); +DefConstructor('\@mixfixa OptionalKeyVals:mi {}{}{}{}', + "<omdoc:rendering " + . "?&defined(&KeyVal(#1,'p'))(precedence='&KeyVal(#1,'p')')>" + . "<m:mrow>" + . "<m:mo egroup='fence' fence='true'>(</m:mo>" + . "#2" + . "<omdoc:iterate name='args' " + . "?&defined(&KeyVal(#1,'pi'))(precedence='&KeyVal(#1,'pi')')>" + . "<omdoc:separator>#5</omdoc:separator>" + . "<omdoc:render name='arg' " + . "?&defined(&KeyVal(#1,'pi'))(precedence='&KeyVal(#1,'pi')')/>" + . "</omdoc:iterate>" + . "#4" + . "<m:mo egroup='fence' fence='true'>)</m:mo>" + . "</m:mrow>" + ."</omdoc:rendering>", + afterDigest=>sub { applyPrecedencePreferences(@_);}, + properties=>sub { getSymmdefProperties($_[1]); });#$ +%</ltxml> +% \end{macrocode} +% \end{macro} +% +% \begin{macrocode} +%<*package> +\define@key{mii}{nobrackets}[yes]{\def\pres@p@key{\pres@infty}% +\def\pres@pi@key{-\pres@infty}\def\pres@pii@key{-\pres@infty}} +\define@key{mii}{lbrack}{\def\pres@lbrack@key{#1}} +\define@key{mii}{rbrack}{\def\pres@lbrack@key{#1}} +\define@key{mii}{p}{\def\pres@p@key{#1}} +\define@key{mii}{pi}{\def\pres@pi@key{#1}} +\define@key{mii}{pii}{\def\pres@pii@key{#1}} +\def\prep@keys@mii{\prep@keys@mi% +\edef\pres@pii{\@ifundefined{pres@pii@key}\pres@p\pres@pii@key}} +%</package> +%<*ltxml> +DefKeyVal('mii','lbrack','Semiverbatim'); +DefKeyVal('mii','rbrack','Semiverbatim'); +DefKeyVal('mii','p','Semiverbatim'); +DefKeyVal('mii','pi','Semiverbatim'); +DefKeyVal('mii','pii','Semiverbatim'); +DefKeyVal('mii','cd','Semiverbatim'); +DefKeyVal('mii','name','Semiverbatim'); +DefKeyVal('mii','nobrackets','Semiverbatim'); +%</ltxml> +% \end{macrocode} +% +% \begin{macro}{\mixfixii} +% \begin{macrocode} +%<*package> +\newcommand{\mixfixii}[6][]%key, pre, arg1, mid, arg2, post +{\clearkeys\setkeys{mii}{#1}\prep@keys@mii% +\PrecWrite\pres@lbrack% write bracket if necessary +#2{\edef\pres@current@precedence{\pres@pi}#3}% +#4{\edef\pres@current@precedence{\pres@pii}#5}#6% +\PrecWrite\pres@rbrack} +%</package> +%<*ltxml> +DefMacro('\mixfixii[]{}{}{}{}{}', + '\@mixfixii[#1]{$\crossrefOp[fun]{#2}$}{$#3 $}' + . '{$\crossrefOp[fun]{#4}$}{$#5 $}' + . '{$\crossrefOp[fun]{#6}$}'); +DefConstructor('\@mixfixii OptionalKeyVals:mi {}{}{}{}{}', + "<omdoc:rendering " + . "?&defined(&KeyVal(#1,'p'))(precedence='&KeyVal(#1,'p')') " + . "argprec='&argument_precedence(#1)'>" + . "<m:mrow>" + . "<m:mo egroup='fence' fence='true'>(</m:mo>" + . "#2 #3 #4 #5 #6" + . "<m:mo egroup='fence' fence='true'>)</m:mo>" + . "</m:mrow>" + ."</omdoc:rendering>", + afterDigest=>sub { applyPrecedencePreferences(@_);}, + properties=>sub { getSymmdefProperties($_[1]); });#$ +%</ltxml> +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\mixfixia} +% \begin{macrocode} +%<*package> +\newcommand{\mixfixia}[7][]%key, pre, arg1, mid, arg2, post, assocop +{\clearkeys\setkeys{mii}{#1}\prep@keys@mii% +\PrecWrite\pres@lbrack% write bracket if necessary +#2{\edef\pres@current@precedence{\pres@pi}#3}% +#4{\@assoc\pres@pii{#7}{#5}}#6% +\PrecWrite\pres@rbrack} +%</package> +%<*ltxml> +DefMacro('\mixfixia[]{}{}{}{}{}{}', + '\@mixfixia[#1]{$\crossrefOp[fun]{#2}$}{$#3 $}' + . '{$\crossrefOp[fun]{#4}$}{$#5 $}' + . '{$\crossrefOp[fun]{#6}$}' + . '{$\crossrefOp[fun]{#7}$}'); +DefConstructor('\@mixfixia OptionalKeyVals:mi {}{}{}{}{}{}', + "<omdoc:rendering " + . "?&defined(&KeyVal(#1,'p'))(precedence='&KeyVal(#1,'p')') " + . " argprec='&argument_precedence(#1)'>" + . "<m:mrow>" + . "<m:mo egroup='fence' fence='true'>(</m:mo>" + . "#2 #3 #4" + . "<omdoc:iterate name='args' " + . "?&defined(&KeyVal(#1,'pi'))(precedence='&KeyVal(#1,'pi')')>" + . "<omdoc:separator>#7</omdoc:separator>" + . "<omdoc:render name='arg' " + . "?&defined(&KeyVal(#1,'pi'))(precedence='&KeyVal(#1,'pi')')/>" + . "</omdoc:iterate>" + . "#6" + . "<m:mo egroup='fence' fence='true'>)</m:mo>" + . "</m:mrow>" + ."</omdoc:rendering>", + afterDigest=>sub { applyPrecedencePreferences(@_);}, + properties=>sub { getSymmdefProperties($_[1]); });#$ +%</ltxml> +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\mixfixai} +% \begin{macrocode} +%<*package> +\newcommand{\mixfixai}[7][]%key, pre, arg1, mid, arg2, post, assocop +{\clearkeys\setkeys{mii}{#1}\prep@keys@mii% +\PrecWrite\pres@lbrack% write bracket if necessary +#2{\@assoc\pres@pi{#7}{#3}}% +#4{\edef\pres@current@precedence{\pres@pii}#5}#6% +\PrecWrite\pres@rbrack} +%</package> +%<*ltxml> +DefMacro('\mixfixai[]{}{}{}{}{}{}', + '\@mixfixai[#1]{$\crossrefOp[fun]{#2}$}{$#3 $}' + .'{$\crossrefOp[fun]{#4}$}{$#5 $}' + .'{$\crossrefOp[fun]{#6}$}' + .'{$\crossrefOp[fun]{#7}$}'); +DefConstructor('\@mixfixai OptionalKeyVals:mi {}{}{}{}{}{}', + "<omdoc:rendering " + . "?&defined(&KeyVal(#1,'p'))(precedence='&KeyVal(#1,'p')') " + . " argprec='&argument_precedence(#1)'>" + . "<m:mrow>" + . "<m:mo egroup='fence' fence='true'>(</m:mo>" + . "#2" + . "<omdoc:iterate name='args' " + . "?&defined(&KeyVal(#1,'pi'))(precedence='&KeyVal(#1,'pi')')>" + . "<omdoc:separator>#7</omdoc:separator>" + . "<omdoc:render name='arg' " + . "?&defined(&KeyVal(#1,'pi'))(precedence='&KeyVal(#1,'pi')')/>" + . "</omdoc:iterate>" + . "#4 #5 #6" + . "<m:mo egroup='fence' fence='true'>)</m:mo>" + . "</m:mrow>" + ."</omdoc:rendering>", + afterDigest=>sub { applyPrecedencePreferences(@_);}, + properties=>sub { getSymmdefProperties($_[1]); });#$ +%</ltxml> +% \end{macrocode} +% \end{macro} +% +% \begin{macrocode} +%<*package> +\define@key{miii}{nobrackets}[yes]{\def\pres@p@key{\pres@infty}% +\def\pres@pi@key{-\pres@infty}\def\pres@pii@key{-\pres@infty}\def\pres@pii@key{-\pres@infty}} +\define@key{miii}{lbrack}{\def\pres@lbrack@key{#1}} +\define@key{miii}{rbrack}{\def\pres@lbrack@key{#1}} +\define@key{miii}{p}{\def\pres@p@key{#1}} +\define@key{miii}{pi}{\def\pres@pi@key{#1}} +\define@key{miii}{pii}{\def\pres@pii@key{#1}} +\define@key{miii}{piii}{\def\pres@piii@key{#1}} +\def\prep@keys@miii{\prep@keys@mii\edef\pres@piii{\@ifundefined{pres@piii@key}{\pres@p}{\pres@piii@key}}} +%</package> +%<*ltxml> +DefKeyVal('miii','lbrack','Semiverbatim'); +DefKeyVal('miii','rbrack','Semiverbatim'); +DefKeyVal('miii','p','Semiverbatim'); +DefKeyVal('miii','pi','Semiverbatim'); +DefKeyVal('miii','pii','Semiverbatim'); +DefKeyVal('miii','piii','Semiverbatim'); +DefKeyVal('miii','cd','Semiverbatim'); +DefKeyVal('miii','name','Semiverbatim'); +DefKeyVal('miii','nobrackets','Semiverbatim'); +%</ltxml> +% \end{macrocode} +% +% \begin{macro}{\mixfixiii} +% \begin{macrocode} +%<*package> +\newcommand{\mixfixiii}[8][]%key, pre, arg1, mid1, arg2, mid2, arg3, post +{\clearkeys\setkeys{miii}{#1}\prep@keys@miii% +\PrecWrite\pres@lbrack% write bracket if necessary +#2{\edef\pres@current@precedence{\pres@pi}#3}% +#4{\edef\pres@current@precedence{\pres@pii}#5}% +#6{\edef\pres@current@precedence{\pres@pii}#7}#8% +\PrecWrite\pres@rbrack} +%</package> +%<*ltxml> +DefMacro('\mixfixiii[]{}{}{}{}{}{}{}', + '\@mixfixiii[#1]{$\crossrefOp[fun]{#2}$}{$#3 $}' + . '{$\crossrefOp[fun]{#4}$}{$#5 $}' + . '{$\crossrefOp[fun]{#6}$}{$#7 $}' + . '{$\crossrefOp[fun]{#8}$}'); +DefConstructor('\@mixfixiii OptionalKeyVals:mi {}{}{}{}{}{}{}', + "<omdoc:rendering " + . "?&defined(&KeyVal(#1,'p'))(precedence='&KeyVal(#1,'p')') " + . " argprec='&argument_precedence(#1)'>" + . "<m:mrow>" + . "<m:mo egroup='fence' fence='true'>(</m:mo>" + . "#2 #3 #4 #5 #6 #7 #8" + . "<m:mo egroup='fence' fence='true'>)</m:mo>" + . "</m:mrow>" + ."</omdoc:rendering>", + afterDigest=>sub { applyPrecedencePreferences(@_);}, + properties=>sub { getSymmdefProperties($_[1]); });#$ +%</ltxml> +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\mixfixaii} +% \begin{macrocode} +%<*package> +\newcommand{\mixfixaii}[9][]%key, pre, arg1, mid1, arg2, mid2, arg3, post, sep +{\clearkeys\setkeys{miii}{#1}\prep@keys@miii% +\PrecWrite\pres@lbrack% write bracket if necessary +#2{\@assoc\pres@pi{#9}{#3}}% +#4{\edef\pres@current@precedence{\pres@pii}#5}% +#6{\edef\pres@current@precedence{\pres@pii}#7}#8% +\PrecWrite\pres@rbrack} +%</package> +%<*ltxml> +DefMacro('\mixfixaii[]{}{}{}{}{}{}{}{}', + '\@mixfixaii[#1]{$\crossrefOp[fun]{#2}$}{$#3 $}' + . '{$\crossrefOp[fun]{#4}$}{$#5 $}' + . '{$\crossrefOp[fun]{#6}$}{$#7 $}' + . '{$\crossrefOp[fun]{#8}$}' + . '{$\crossrefOp[fun]{#9}$}'); +DefConstructor('\@mixfixaii OptionalKeyVals:mi {}{}{}{}{}{}{}{}', + "<omdoc:rendering " + . "?&defined(&KeyVal(#1,'p'))(precedence='&KeyVal(#1,'p')') " + . " argprec='&argument_precedence(#1)'>" + . "<m:mrow>" + . "<m:mo egroup='fence' fence='true'>(</m:mo>" + . "#2" + . "<omdoc:iterate name='args' " + . "?&defined(&KeyVal(#1,'pi'))(precedence='&KeyVal(#1,'pi')')>" + . "<omdoc:separator>#9</omdoc:separator>" + . "<omdoc:render name='arg' " + . "?&defined(&KeyVal(#1,'pi'))(precedence='&KeyVal(#1,'pi')')/>" + . "</omdoc:iterate>" + . "#4 #5 #6 #7 #8" + . "<m:mo egroup='fence' fence='true'>)</m:mo>" + . "</m:mrow>" + ."</omdoc:rendering>", + afterDigest=>sub { applyPrecedencePreferences(@_);}, + properties=>sub { getSymmdefProperties($_[1]); });#$ +%</ltxml> +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\mixfixiai} +% \begin{macrocode} +%<*package> +\newcommand{\mixfixiai}[9][]%key, pre, arg1, mid1, arg2, mid2, arg3, post, assocop +{\clearkeys\setkeys{miii}{#1}\prep@keys@miii% +\PrecWrite\pres@lbrack% write bracket if necessary +#2{\edef\pres@current@precedence{\pres@pi}#3}% +#4{\@assoc\pres@pi{#9}{#5}}% +#6{\edef\pres@current@precedence{\pres@pii}#7}#8% +\PrecWrite\pres@rbrack} +%</package> +%<*ltxml> +DefMacro('\mixfixiai[]{}{}{}{}{}{}{}{}', + '\@mixfixiai[#1]{$\crossrefOp[fun]{#2}$}{$#3 $}' + . '{$\crossrefOp[fun]{#4}$}{$#5 $}' + . '{$\crossrefOp[fun]{#6}$}{$#7 $}' + . '{$\crossrefOp[fun]{#8}$}' + . '{$\crossrefOp[fun]{#9}$}'); +DefConstructor('\@mixfixiai OptionalKeyVals:mi {}{}{}{}{}{}{}', + "<omdoc:rendering " + . "?&defined(&KeyVal(#1,'p'))(precedence='&KeyVal(#1,'p')') " + . " argprec='&argument_precedence(#1)'>" + . "<m:mrow>" + . "<m:mo egroup='fence' fence='true'>(</m:mo>" + . "#2 #3 #4" + . "<omdoc:iterate name='args' " + . "?&defined(&KeyVal(#1,'pi'))(precedence='&KeyVal(#1,'pi')')>" + . "<omdoc:separator>#9</omdoc:separator>" + . "<omdoc:render name='arg' " + . "?&defined(&KeyVal(#1,'pi'))(precedence='&KeyVal(#1,'pi')')/>" + . "</omdoc:iterate>" + . "#6 #7 #8" + . "<m:mo egroup='fence' fence='true'>)</m:mo>" + . "</m:mrow>" + ."</omdoc:rendering>", + afterDigest=>sub { applyPrecedencePreferences(@_);}, + properties=>sub { getSymmdefProperties($_[1]); });#$ +%</ltxml> +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\mixfixiia} +% \begin{macrocode} +%<*package> +\newcommand{\mixfixiia}[9][]%key, pre, arg1, mid1, arg2, mid2, arg3, post,assocop +{\clearkeys\setkeys{miii}{#1}\prep@keys@miii% +\PrecWrite\pres@lbrack% write bracket if necessary +#2{\edef\pres@current@precedence{\pres@pi}#3}% +#4{\edef\pres@current@precedence{\pres@pii}#5}% +#6{\@assoc\pres@pi{#9}{#7}}#8% +\PrecWrite\pres@rbrack} +%</package> +%<*ltxml> +DefMacro('\mixfixiia[]{}{}{}{}{}{}{}{}', + '\@mixfixiia[#1]{$\crossrefOp[fun]{#2}$}{$#3 $}' + . '{$\crossrefOp[fun]{#4}$}{$#5 $}' + . '{$\crossrefOp[fun]{#6}$}{$#7 $}' + . '{$\crossrefOp[fun]{#8}$}' + . '{$\crossrefOp[fun]{#9}$}'); +DefConstructor('\@mixfixiia OptionalKeyVals:mi {}{}{}{}{}{}{}', + "<omdoc:rendering " + . "?&defined(&KeyVal(#1,'p'))(precedence='&KeyVal(#1,'p')') " + . " argprec='&argument_precedence(#1)'>" + . "<m:mrow>" + . "<m:mo egroup='fence' fence='true'>(</m:mo>" + . "#2 #3 #4 #5 #6" + . "<omdoc:iterate name='args' " + . "?&defined(&KeyVal(#1,'pi'))(precedence='&KeyVal(#1,'pi')')>" + . "<omdoc:separator>#9</omdoc:separator>" + . "<omdoc:render name='arg' " + . "?&defined(&KeyVal(#1,'pi'))(precedence='&KeyVal(#1,'pi')')/>" + . "</omdoc:iterate>" + . "#8" + . "<m:mo egroup='fence' fence='true'>)</m:mo>" + . "</m:mrow>" + ."</omdoc:rendering>", + afterDigest=>sub { applyPrecedencePreferences(@_);}, + properties=>sub { getSymmdefProperties($_[1]); });#$ +%</ltxml> +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\prefixa} +% In prefix we always write the brackets. +% \begin{macrocode} +%<*package> +\newcommand{\prefixa}[4][]%keys, fn, arg, sep +{\prepost@clearkeys\setkeys{prepost}{#1} +{#2}\pres@lbrack{\@assoc\pres@pi@key{#3}{#4}}\pres@rbrack} +%</package> +%<*ltxml> +DefMacro('\prefixa[]{}{}{}','\@prefixa[#1]{$\crossrefOp[fun]{#2}$}{$#3 $}{$#4 $}'); +DefConstructor('\@prefixa OptionalKeyVals:mi {}{}{}', + "<omdoc:rendering " + . "?&defined(&KeyVal(#1,'p'))(precedence='&KeyVal(#1,'p')') " + . "argprec='&argument_precedence(#1)'>" + . "<m:mrow>" + . "#2" + . "<m:mrow>" + . "<m:mo fence='true'>(</m:mo>" + . "<omdoc:iterate name='args' " + . "?&defined(&KeyVal(#1,'pi'))(precedence='&KeyVal(#1,'pi')')>" + . "<omdoc:separator>#4</omdoc:separator>" + . "<omdoc:render name='arg' " + . "?&defined(&KeyVal(#1,'pi'))(precedence='&KeyVal(#1,'pi')')/>" + . "</omdoc:iterate>" + . "<m:mo fence='true'>)</m:mo>" + . "</m:mrow>" + . "</m:mrow>" + ."</omdoc:rendering>", + afterDigest=>sub { + #Default argument precedence is -\infty + my $keyval = $_[1]->getArg(1); + $keyval->setValue('pi',-1000000) unless ($keyval && defined($keyval->getValue('pi'))); + applyPrecedencePreferences(@_); + }, + properties=>sub { getSymmdefProperties($_[1]); }); +%</ltxml> +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\postfixa} +% \begin{macrocode} +%<*package> +\newcommand{\postfixa}[4][]%keys, fn, arg, sep +{\prepost@clearkeys\setkeys{prepost}{#1} +\pres@lbrack{\@assoc\pres@pi@key{#3}{#4}}\pres@rbrack{#2}} +%</package> +%<*ltxml> +DefMacro('\postfixa []{}{}{}','\@postfixa[#1]{$\crossrefOp[fun]{#2}$}{$#3 $}{$#4 $}'); +DefConstructor('\@postfixa OptionalKeyVals:mi {}{}{}', + "<omdoc:rendering " + . "?&defined(&KeyVal(#1,'p'))(precedence='&KeyVal(#1,'p')') " + ."argprec='&argument_precedence(#1)'>" + . "<m:mrow>" + . "<m:mrow>" + . "<m:mo fence='true'>(</m:mo>" + . "<omdoc:iterate name='args' " + . "?&defined(&KeyVal(#1,'pi'))(precedence='&KeyVal(#1,'pi')')>" + . "<omdoc:separator>#4</omdoc:separator>" + . "<omdoc:render name='arg' " + . "?&defined(&KeyVal(#1,'pi'))(precedence='&KeyVal(#1,'pi')')/>" + . "</omdoc:iterate>" + . "<m:mo fence='true'>)</m:mo>" + . "</m:mrow>" + . "#2" + . "</m:mrow>" + ."</omdoc:rendering>", + afterDigest=>sub { + #Default argument precedence is -\infty + my $keyval = $_[1]->getArg(1); + $keyval->setValue('pi',-1000000) unless ($keyval && defined($keyval->getValue('pi'))); + applyPrecedencePreferences(@_); + }, + properties=>sub { getSymmdefProperties($_[1]); }); +%</ltxml> +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\infix} +% |\infix|\ednote{need infixl as well, use counters for precedences here.} is a simple +% special case of |\mixfixii|. +% \begin{macrocode} +%<ltxml>RawTeX(' +%<*package|ltxml> +\newcommand{\infix}[4][]{\mixfixii[#1]{}{#3}{#2}{#4}{}} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\assoc} +% \begin{macrocode} +\newcommand{\assoc}[3][]{\mixfixa[#1]{}{#3}{}{#2}} +%</package|ltxml> +%<ltxml>'); +% \end{macrocode} +% \end{macro} +% +% \subsection{General Elision}\label{sec:impl:elision} +% +% \ednote{all of these still need to be tested and implemented in LaTeXML.} +% \begin{macro}{\setegroup} +% The elision macros are quite simple, a group |foo| is internally represented by a +% macro |foo@egroup|, which we set by a |\gdef|. +% \begin{macrocode} +%<*package> +\def\setegroup#1#2{\expandafter\def\csname #1@egroup\endcsname{#2}} +%</package> +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\elide} +% Then the elision command is picks up on this (flags an error) if the internal macro +% does not exist and prints the third argument, if the elision value threshold is above +% the elision group threshold in the paper.\ednote{do we need to turn this around as +% well?} We test the implementation with Figure~\ref{ex:elision-test}. +% \begin{macrocode} +%<*package> +\def\elide#1#2#3{\@ifundefined{#1@egroup}% +{\def\@elevel{0} +\PackageError{presentation}{undefined egroup #1, assuming value 0}% +{When calling \protect\elide{#1}... the elision group #1 has be have\MessageBreak +been set by \protect\setegroup before, e.g. by \protect\setegroup{an}{0}.}}% +{\edef\@elevel{\csname #1@egroup\endcsname}}% +\ifnum\@elevel>#2\else{#3}\fi} +%</package> +%<*ltxml> +%</ltxml> +% \end{macrocode} +% \end{macro} +% +% \begin{figure}[ht]\centering +% \begin{tabular}{|l|l|l|l|}\hline +% {\texttt{par}} & {\texttt{typ}} & result & expected \\\hline\hline +% 0 & 0 & \setegroup{par}{0}\setegroup{typ}{0} +% $\mathbf{I}\elide{par}{500}{^\alpha}\elide{typ}{100}{_{\alpha\to\alpha}} +% :=\lambda{X\elide{typ}{500}{_\alpha}}.X$ +% & $\mathbf{I}:=\lambda{X}.X$\\\hline +% 600 & 600 & \setegroup{par}{600}\setegroup{typ}{600} +% $\mathbf{I}\elide{par}{500}{^\alpha}\elide{typ}{100}{_{\alpha\to\alpha}} +% :=\lambda{X\elide{typ}{500}{_\alpha}}.X$ +% & $\mathbf{I}^\alpha:=\lambda{X_\alpha}.X$\\\hline +% 600 & 1000 & \setegroup{par}{600}\setegroup{typ}{1000} +% $\mathbf{I}\elide{par}{500}{^\alpha}\elide{typ}{100}{_{\alpha\to\alpha}} +% :=\lambda{X\elide{typ}{500}{_\alpha}}.X$ +% & $\mathbf{I}^\alpha_{\alpha\to\alpha}:=\lambda{X_\alpha}.X$\\\hline +% \end{tabular} +% \caption{Testing Elision with the example in Figure~\protect\ref{ex:elision}}\label{ex:elision-test} +% \end{figure} +% +% \begin{macro}{\provideEdefault} +% The |\provideEdefault| macro sets up the context for an elision default by locally +% defining the internal macro \meta{default}|@edefault| and (if necessary) exporting it +% from the module. +% \begin{macrocode} +%<*package> +\def\provideEdefault#1#2{\expandafter\def\csname#1@edefault\endcsname{#2} +\@ifundefined{this@module}{}% +{\expandafter\g@addto@macro\this@module{\expandafter\def\csname#1@edefault\endcsname{#2}}}} +%</package> +%<*ltxml> +%</ltxml> +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\setEdefault} +% The |\setEdefault| macro just redefines the internal \meta{default}|@edefault| in the +% local group +% \begin{macrocode} +%<*package> +\def\setEdefault#1#2{\expandafter\def\csname #1@edfault\endcsname{#2}} +%</package> +%<*ltxml> +%</ltxml> +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\fromEcontext} +% The |\fromEcontext| macro just calls internal \meta{default}|@edefault| macro. +% \begin{macrocode} +%<*package> +\def\fromEcontext#1{\csname #1@edefault\endcsname} +%</package> +%<*ltxml> +%</ltxml> +% \end{macrocode} +% \end{macro} +% +% \subsection{Variable Names}\label{sec:impl:vname} +% +% \begin{macro}{\vname} +% a name macro; the first optional argument is an identifier \meta{id}, this is standard +% for {\LaTeX}, but for {\latexml}, we want to generate attributes +% |xml:id="cvar.|\meta{id}|"| and |name="|\meta{id}|"|. However, if no id was given in +% we default them to |xml:id="cvar.|\meta{count}|"| and +% |name="name.cvar.|\meta{count}|"|. +% \begin{macrocode} +%<*package> +\newcommand{\vname}[2][]{#2\def\@opt{#1}\ifx\@opt\@empty\else\expandafter\gdef\csname MOD@name@#1\endcsname{#2}\fi} +%</package> +%<*ltxml> +sub cvar_id { + my ($id)=@_; + $id=ToString($id); + if (!$id) { + $id=LookupValue('cvar_id'); + $id=0 unless $id; + $id++; + AssignValue('cvar_id',$id,'global'); + } + $id="cvar.$id"; $id;} +DefConstructor('\vname[]{}', + "<ltx:XMWrap role='ID' xml:id='&cvar_id(#1)'>#2</ltx:XMWrap>", + requireMath=>1); +DefConstructor('\crossrefOp[]{}', + "?#2(<ltx:XMApp role='CROSSREFOP'>" + . "<ltx:XMTok role='CROSSREFOP' cr='?#1(#1)(fun)'/>" + . "<ltx:XMWrap>#2</ltx:XMWrap>" + ."</ltx:XMApp>)()", + requireMath=>1); +%</ltxml> +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\vnref} +% \begin{macrocode} +%<*package> +\def\vnref#1{\csname MOD@name@#1\endcsname} +%</package> +%<*ltxml> +DefMacro('\vnref{}','\@XMRef{#1}'); +%</ltxml> +% \end{macrocode} +% \end{macro} +% \ednote{the following macros are just ideas, they need to be implemented and documented} +% \begin{macro}{\uivar} +% constructors for variables\ednote{these are document them above} +% \begin{macrocode} +%<ltxml>RawTeX(' +%<*package|ltxml> +\newcommand{\primvar}[2][]{\vname[#1]{#2^\prime}} +\newcommand{\pprimvar}[2][]{\vname[#1]{#2^{\prime\prime}}} +\newcommand{\uivar}[3][]{\vname[#1]{{#2}^{#3}}} +\newcommand{\livar}[3][]{\vname[#1]{{#2}_{#3}}} +\newcommand{\ulivar}[4][]{\vname[#1]{{#2}^{#3}_{#4}}} +%</package|ltxml> +%<ltxml>'); +% \end{macrocode} +% \end{macro} +% +% \subsection{Finale} +% +% Finally, we need to terminate the file with a success mark for perl. +% \begin{macrocode} +%<ltxml>1; +% \end{macrocode} +% \Finale +\endinput +% +% LocalWords: dtx CPERL RequirePackage keyval lbrack rbrack DefKeyVal omdoc cd +% LocalWords: Semiverbatim DefConstructor OptionalKeyVals pmml ltx XMath mii +% LocalWords: pii miii piii KeyVal egroup namedef attr precs foreach ToString +% LocalWords: DefMacro locator stex srcref argprec mrow getSymmdefProperties +% LocalWords: args arg LaTeX cvar iffalse scsys sc sc mathml openmath latexml +% LocalWords: cmathml activemath twintoo atwin atwintoo texttt fileversion foo +% LocalWords: Deyan Ginev maketitle setcounter tocdepth tableofcontents symdef +% LocalWords: newpage ldots bigl bigr langle ary cdots subseteq mixfixi exfig +% LocalWords: mixfixii mixfixiii vspace hline sseteq ite tt tt tt tt uminus rb +% LocalWords: texorpdfstring assoc ednote nunion mixfixa mixfixa postfixa leq +% LocalWords: postfixa mixfixia mixfixia mixfixai mixfixai fntype rightarrow +% LocalWords: mixfixaii mixfixiai mixfixiia typej vdash cupcap ninters ninters +% LocalWords: capcup geq prec fset textbf textbf setegroup setegroup mathbf fn +% LocalWords: provideEdefault provideEdefault fromEcontext fromEcontext mathrm +% LocalWords: setEdefault setEdefault widetilde cdot vname vname vnref vnname +% LocalWords: ulivar ulivar primvar primvar pprimvar pprimvar textsf textsf +% LocalWords: printbibliography ltxml infty ifnum clearkeys nobrackets whatsit +% LocalWords: ifundefined keyvals kvhash newcommand setkeys crossrefOp argv +% LocalWords: tmpop i-th assocop textbackslash infixl gdef expandafter csname +% LocalWords: endcsname edefault edfault ifx prepostfix circ circ circ circ +% LocalWords: iprec iprec niprec niprec wrongset goodset prepost prepkeys diff --git a/Master/texmf-dist/source/latex/stex/problem/problem.dtx b/Master/texmf-dist/source/latex/stex/problem/problem.dtx index b1103449f1b..97346c6c729 100644 --- a/Master/texmf-dist/source/latex/stex/problem/problem.dtx +++ b/Master/texmf-dist/source/latex/stex/problem/problem.dtx @@ -27,7 +27,7 @@ %</driver> % \fi % -% \CheckSum{1} +% \CheckSum{365} % % \changes{v0.9}{2006/09/18}{First Version with Documentation} % \changes{v0.9a}{2007/01/02}{Renamed to \texttt{problem.sty}} diff --git a/Master/texmf-dist/source/latex/stex/reqdoc/reqdoc.dtx b/Master/texmf-dist/source/latex/stex/reqdoc/reqdoc.dtx new file mode 100644 index 00000000000..63acb86cee1 --- /dev/null +++ b/Master/texmf-dist/source/latex/stex/reqdoc/reqdoc.dtx @@ -0,0 +1,372 @@ +% \iffalse meta-comment +% Semantic Markup for Requirement Specification Documents +% Copyright (c) 2008 Michael Kohlhase, all rights reserved +% +% 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. +% +% The development version of this file can be found at +% $HeadURL: https://svn.kwarc.info/repos/stex/trunk/sty/reqdoc/reqdoc.dtx $ +% \fi +% +% \iffalse +%<package>\NeedsTeXFormat{LaTeX2e}[1999/12/01] +%<package>\ProvidesPackage{reqdoc}[2010/06/25 v0.3 Semantic Requirement Documents] +% +%<*driver> +\documentclass[twoside]{ltxdoc} +\EnableCrossrefs +%\CodelineIndex +%\OnlyDescription +\RecordChanges +\usepackage{reqdoc} +\usepackage{textcomp,url,a4wide} +\usepackage[show]{ed} +\usepackage[hyperref=auto,style=alphabetic]{biblatex} +\bibliography{kwarc} +\usepackage[eso-foot,today,draft]{svninfo} +\usepackage{stex-logo} +\usepackage{../ctansvn} +\usepackage{hyperref} +\makeindex +\begin{document} +\svnInfo $Id: reqdoc.dtx 1502 2010-07-20 08:17:00Z kohlhase $ +\svnKeyword $HeadURL: https://svn.kwarc.info/repos/stex/trunk/sty/reqdoc/reqdoc.dtx $ +\DocInput{reqdoc.dtx} +\end{document} +%</driver> +% \fi +% +%\CheckSum{195} +% +% \changes{v0.3}{2008/06/26}{Integrated LaTeXML bindings} +% \changes{v0.2}{2008/02/04}{First Version with Documentation} +% \changes{v0.1}{2008/01/18}{First Version} +% +% \GetFileInfo{reqdoc.sty} +% +% \MakeShortVerb{\|} +% \def\latexml{{\LaTeX}ML} +% +% \title{{\texttt{reqdoc.sty}}: Semantic Markup for Requirements Specification Documents\thanks{Version +% {\fileversion} (last revised {\filedate})}} +% \author{Michael Kohlhase\\ +% Computer Science, Jacobs University\\ +% \url{http://kwarc.info/kohlhase}} +% \maketitle +% +% \begin{abstract} +% This package provides an infrastructure for semantically enhanced requirements +% specifications used in software engineering. This allows to embed structural +% information into documents that can be used by semantic document management systems +% e.g. for management of change and requirements tracing. +% \end{abstract} +% +% \newpage\tableofcontents\newpage +% +% \section{Introduction}\label{sec:intro} +% +% In software engineering, the development process is accompanied with a trail of +% structured documents, user specifications, architecture specifications, test reports, +% etc. All of these documents\ednote{continue} +% +% For an example of a requirement document see the file |requirements.tex| provided in +% this package. \ednote{need to bring this in line with the \texttt{sref} package} +% +% \section{The User Interface}\label{sec:interface} +% +% \subsection{Package Options} +% +% The |reqdoc| package takes the package option \DescribeMacro{recorddeps}|recorddeps|. If +% this is given, then the package generates an external file with dependencies that can be +% used by external systems like the {\texttt{locutor}} system\ednote{add citation here}, +% see Section~\ref{sec:moc-deps}. +% +% \subsection{Requirements} +% The |reqdoc| package supplies two forms of writing down requirements that mainly differ +% in their presentation. We can have requirement lists and requirement tables. +% +% \DescribeEnv{requirements} The |requirements| environment marks up a list of +% requirements. It takes an optional key/value list as an argument: if |numbering| is set +% to |yes| (the default), then the requirements are numbered for referencing it visually; +% the label is created using the prefix specified in the key |prefix|. +% +% \DescribeEnv{requirement} The individual requirements are specified by the |requirement| +% environment, which takes an optional key/value list as an argument: the |id| key allows +% to specify a symbolic label for cross-referencing, the |prio| key allows to specify a +% priority of the requirement, the |reqs| key allows to specify a comma-separated list of +% labels of requibments this one depends on or refines. Finally, the visual label of the +% requirement can be fixed by the |num| key\ednote{this is not implemented yet}. +% +% \DescribeEnv{reqtable} The |reqtable| environment is a varian of the |\requirements| +% environment that shows the requirements in a tabular form that gives a better overview; +% its optional key/value argument works the same. \DescribeMacro{\reqline}The respective +% requirements are marked up with the |\reqline| macro, which takes three arguments. The +% first one is an optional key/value specification and corresponds to be one on the +% |requirement| environment. The second one contains the actual text of the requirements +% and the third one a comment. +% +% \DescribeMacro{\importreqs}Note that if we want to refer to requirements from a document +% \meta{doc}, then we will need to know about their representations and can import the +% necessary information via |\importreqs{|\meta{doc}|}|. +% +% \StopEventually{\newpage\PrintIndex\newpage\PrintChanges\printbibliography} +% \newpage +% +% \section{The Implementation}\label{sec.impl} +% +% The |reqdoc| package generates to files: the {\LaTeX} package (all the code between +% {\textsf{$\langle$*package$\rangle$}} and {\textsf{$\langle$/package$\rangle$}}) and the +% {\latexml} bindings (between {\textsf{$\langle$*ltxml$\rangle$}} and +% {\textsf{$\langle$/ltxml$\rangle$}}). We keep the corresponding code fragments together, +% since the documentation applies to both of them and to prevent them from getting out of +% sync. +% +% \subsection{Package Options}\label{sec.impl.options} +% +% We first introduce the single option |recorddeps| which comes with its own switch |\if@deps| +% +% \begin{macrocode} +%<*package> +\newif\if@deps\@depsfalse +\DeclareOption{recorddeps}{\@depstrue} +\ProcessOptions +% \end{macrocode} +% Then we load a couple of packages +% \begin{macrocode} +\RequirePackage{sref} +\RequirePackage{longtable} +%</package> +%<*ltxml> +package LaTeXML::Package::Pool; +use strict; +use LaTeXML::Package; +%</ltxml> +% \end{macrocode} +% +% Then we register the namespace of the requirements ontology +% \begin{macrocode} +%<*ltxml> +RegisterNamespace('r'=>"http://omdoc.org/ontology/requirements#"); +RegisterDocumentNamespace('r'=>"http://omdoc.org/ontology/requirements#"); +%</ltxml> +% \end{macrocode} +% +% \subsection{Requirements}\label{sec.impl.requirements} +% +% \begin{environment}{requirements} +% and now the |requirements| environment, it is empty at the moment\ednote{think about +% this again!} +% \begin{macrocode} +%<*package> +\newif\ifreqsnum\reqsnumfalse +\omdaddkey{reqs}{numbering} +\omdaddkey[R]{reqs}{prefix} +\def\reqs@no{no} +\newenvironment{requirements}[1][]% +{\omdsetkeys{reqs}{#1}\ifx\reqs@numbering\reqs@no\reqsnumfalse\else\reqsnumtrue\fi}{} +%</package> +%<*ltxml> +DefEnvironment('{requirements} OptionalKeyVals:reqs', + "<omdoc:omgroup type='itemize'>#body</omdoc:omgroup>"); +%</ltxml> +% \end{macrocode} +% \end{environment} +% +% We define a group of keywords using the |\omdaddkey| command from the |omd| +% package~\ctancite{Kohlhase:omd}. The group below, named as |req|, consists of three +% keywords |id|, |prio| and |refs|. +% \begin{macrocode} +%<*package> +\omdaddkey{req}{id} +\omdaddkey{req}{prio} +\omdaddkey{req}{refs} +\omdaddkey{req}{num} +\newcounter{reqnum}[section] +% \end{macrocode} +% This function cycles over a comma-separated list and does the references +% \begin{macrocode} +\def\req@do@refs#1#2{\let\@tmpop=\relax\@for\@I:=#1\do{\@tmpop\req@do@ref{\@I}\let\@tmpop=#2}} +% \end{macrocode} +% The |\req@do@ref| command creates a hyperlink from \ednote{What is req at ref? It has +% appeared for the first time.} +% \begin{macrocode} +\def\req@do@ref#1{\sref@hlink@ifh{#1}{\req@ref{#1}{number}}} +% \end{macrocode} +% this function defines a requirement aspect +% the first arg is the label, the second one the aspect to be defined and the third one the value +% expand |csname| before |xdef| +% +% The command |\req@def@aux| creates the name of a command, +% which is determined by the text given between |\csname| and |\endcsname|, +% and defines this command globally to function as |#3|. +% We use the command |\expandafter| in the definition of |\req@def@aux| +% to execute the command |\xdef| after |\csname| is executed. +% \begin{macrocode} +\def\req@def@aux#1#2#3{\expandafter\xdef\csname req@#1@#2\endcsname{#3}} +% \end{macrocode} +% this function takes the same arguments and writes the command to the aux file +% \begin{macrocode} +\def\req@write@aux#1#2#3{\protected@write\@auxout{}{\string\req@def@aux{#1}{#2}{\thesection.#3}}} +% \end{macrocode} +% and finally this function does both +% \begin{macrocode} +\def\req@def#1#2#3{\req@def@aux{#1}{#2}{#3}\req@write@aux{#1}{#2}{#3}} +% \end{macrocode} +% this function references an aspect of a requirement. +% \begin{macrocode} +\def\req@ref#1#2{\csname req@#1@#2\endcsname} +% \end{macrocode} +% these functions print the priority, label, and references (if specified) +% \begin{macrocode} +\def\print@req@prio{\ifx\req@prio\@empty\else(Priority: \req@prio)\fi} +\def\print@req@label{\sref@target@ifh\req@id{\reqs@prefix\arabic{reqnum}: }} +\def\print@req@refs{\ifx\req@refs\@empty\else\hfill [from~\req@do@refs{\req@refs}{,}]\fi} +% \end{macrocode} +% \ednote{What are |number| and |\thereqnum|?} +% First argument is a list of key-value pairs which are assigned to req. +% Increase the counter reqnum, i.e., increase the requirement number. +% Remember the number for reference. +% Print the requirement label (with the requirement number) +% Print the priority? +% Print the requirement (given as arg 2) +% Print the references +% We define a new command |\reqnote| to annotate the notes given for a requirement. +% The command |\reqnote| simply prints the note, which is given by the user as a text, +% in the form |Note: <text>|. +% \begin{environment}{requirement} +% \begin{macrocode} +\newenvironment{requirement}[1][]% +{\omdsetkeys{req}{#1}\stepcounter{reqnum} +\ifreqsnum\ifx\req@id\@empty\else\req@def\req@id{number}\thereqnum\fi +\noindent\textbf{\print@req@label}\fi +\newcommand{\reqnote}[1]{\par\noindent Note: ##1} +\print@req@prio} +{\medskip\print@req@refs} +%</package> +%<*ltxml> +DefCMPEnvironment('{requirement} OptionalKeyVals:req', + "<omdoc:omtext ?&KeyVal(#1,'id')(xml:id='&KeyVal(#1,'id')')() r:dummy='to ensure the namespace'>" + . "<omdoc:meta property='texttype' content='r:requirement'/>" + . "?&KeyVal(#1,'refs')(<omdoc:link rel='r:dependsOn' href='#&KeyVal(#1,'refs')'/>)()" + . "#body" + ."</omdoc:omtext>"); +DefConstructor('\reqnote{}', + "<omdoc:note type='requirement'>#1</omdoc:note>"); +%</ltxml> +% \end{macrocode} +% \end{environment} +% +% \begin{environment}{reqtable} +% \begin{macrocode} +%<*package> +\newenvironment{reqtable}[1][]{\omdsetkeys{reqs}{#1} +\begin{center}\begin{longtable}{|l|l|p{6cm}|p{5cm}|l|}\hline +\# & Prio & Requirement & Notes & Refs\\\hline\hline} +{\end{longtable}\end{center}} +%</package> +%<*ltxml> +DefEnvironment('{reqtable} OptionalKeyVals:reqs', + "<omdoc:omgroup type='itemize'>#body</omdoc:omgroup>"); +%</ltxml> +% \end{macrocode} +% \end{environment} +% +% \begin{macro}{\reqline} +% \begin{macrocode} +%<*package> +\newcommand{\reqline}[3][]% +{\omdsetkeys{req}{#1}\stepcounter{reqnum} +\req@def\req@id{number}\thereqnum% remember the number for reference +\textbf{\sref@target@ifh\req@id{\reqs@prefix\arabic{reqnum}}}& +\req@prio &\req@do@refs\req@refs{,}\tabularnewline\hline} +%</package> +%<*ltxml> +DefCMPConstructor('\reqline OptionalKeyVals:req{}{}', + "<omdoc:omtext type='requirement'><omdoc:CMP>#2</omdoc:CMP></omdoc:omtext>" + ."<omdoc:omtext type='note'><omdoc:CMP>#3</omdoc:CMP></omdoc:omtext>"); +%</ltxml> +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\importreqs} +% The |\importreqs| macro reports a dependency to the dependencies file. and then reads +% the |aux| file specified in the argument. +% \begin{macrocode} +%<*package> +\newcommand{\importreqs}[1]{\req@dep@write{"#1.tex"}{IMPORTREQS}\makeatletter\input{#1.aux}\makeatother} +%</package> +%<*ltxml> +DefConstructor('\importreqs {}',"<omdoc:imports from='#1'/>"); +%</ltxml> +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\rinput} +% The |\rinput| macro\ednote{this should go somewhere up; probably merge with sinput; +% which should also go into the stex package.} inputs the file and protocols this in +% the dependencies file. Note that this only takes place on the top level; i.e. the +% |\@ifdeps| switch is set to false. +% \begin{macrocode} +%<*package> +\newcommand{\rinput}[1]{\req@dep@write{"#1.tex"}{[dt="input"]}\bgroup\@depsfalse\input{#1}\egroup} +%</package> +%<*ltxml> +DefMacro('\rinput','\input'); +%</ltxml> +% \end{macrocode} +% \end{macro} +% +% \subsection{Recording the dependencies for Change Management}\label{sec:moc-deps} +% +% The macros in this section record dependencies in a special file to be used in change +% management by the {\texttt{locutor}} system. This is still not optimal, since we do not +% know the actual path. +% +% \begin{macrocode} +%<*package> +\if@deps\newwrite\req@depfile +\immediate\openout\req@depfile=\jobname.deps +\AtEndDocument{\closeout\req@depfile} +%</package> +% \end{macrocode} +% we redefine the |\importmodule| command, so that it does the reporting. +% \begin{macrocode} +%<*package> +\renewcommand{\importmodule}[2][]{\req@dep@write{"#1.tex"}{[dt="importmodule"]}\def\@test{#1}% +\ifx\@test\@empty\else\requiremodules{#1}\fi +\expandafter\gdef\csname#2@cd@file@base\endcsname{#1} +\activate@defs{#2}\export@defs{#2}} +\fi +%</package> +% \end{macrocode} +% +% \begin{macrocode} +%<*package> +\def\req@dep@write#1#2{\if@deps\protected@write\req@depfile{}{#1 #2}\fi} +%</package> +% \end{macrocode} +% \subsection{Finale} +% +% Finally, we need to terminate the file with a success mark for perl. +% \begin{macrocode} +%<ltxml>1; +% \end{macrocode} +% \Finale +\endinput + + + +% LocalWords: iffalse reqdoc reqdoc.dtx kohlhase latexml texttt fileversion +% LocalWords: maketitle newpage tableofcontents newpage ednote sref recorddeps +% LocalWords: recorddeps moc-deps DescribeEnv prio reqs reqtable reqtable deps +% LocalWords: reqline importreqs printbibliography sec.impl textsf langle ifx +% LocalWords: textsf langle ltxml newif depsfalse depstrue longtable ifreqsnum +% LocalWords: reqsnumfalse omdaddkey newenvironment omdsetkeys reqsnumtrue omd +% LocalWords: OptionalKeyVals omdoc omgroup ctancite req newcounter reqnum +% LocalWords: tmpop tmpop csname xdef endcsname expandafter auxout thesection +% LocalWords: hfill thereqnum reqnote stepcounter noindent textbf newcommand +% LocalWords: medskip omtext texttype hline tabularnewline makeatletter rinput +% LocalWords: makeatother sinput stex ifdeps bgroup egroup newwrite depfile +% LocalWords: openout jobname.deps renewcommand requiremodules gdef defs defs diff --git a/Master/texmf-dist/source/latex/stex/sproof/sproof.dtx b/Master/texmf-dist/source/latex/stex/sproof/sproof.dtx new file mode 100644 index 00000000000..dbfb53e897f --- /dev/null +++ b/Master/texmf-dist/source/latex/stex/sproof/sproof.dtx @@ -0,0 +1,726 @@ +% \iffalse meta-comment +% An Infrastructure for Structural Markup for Proofs +% Copyright (C) 2004-2006 Michael Kohlhase, all rights reserved +% this file is released under the +% LaTeX Project Public License (LPPL) +% +% The development version of this file can be found at +% $URL: https://svn.kwarc.info/repos/stex/trunk/sty/sproof/sproof.dtx $ +% $Rev: 1502 $; last modified by $Author: kohlhase $ +% $Date: 2010-07-20 10:17:00 +0200 (Tue, 20 Jul 2010) $ +% \fi +% +% \iffalse +%<package>\NeedsTeXFormat{LaTeX2e}[1999/12/01] +%<package>\ProvidesPackage{sproof}[2010/06/25 v0.9f Semantic Markup for Proofs] +% +%<*driver> +\documentclass{ltxdoc} +\usepackage{url,array,stex,float,moreverb} +\usepackage[show]{ed} +\usepackage[hyperref=auto,style=alphabetic]{biblatex} +\bibliography{kwarc} +\usepackage{../ctansvn} +\usepackage{hyperref} +\usepackage[eso-foot,today]{svninfo} +\svnInfo $Id: sproof.dtx 1502 2010-07-20 08:17:00Z kohlhase $ +\svnKeyword $HeadURL: https://svn.kwarc.info/repos/stex/trunk/sty/sproof/sproof.dtx $ +\makeindex +\floatstyle{boxed} +\newfloat{exfig}{thp}{lop} +\floatname{exfig}{Example} +\begin{document}\DocInput{sproof.dtx}\end{document} +%</driver> +% \fi +% +% \CheckSum{279} +% +% \changes{v0.9}{2005/06/14}{First Version with Documentation} +% \changes{v0.9a}{2005/07/01}{Completed Documentation} +% \changes{v0.9b}{2005/08/06}{Complete functionality and Updated Documentation} +% \changes{v0.9c}{2006/01/13}{more packaging} +% \changes{v0.9d}{2006/10/31}{made sproof.dtx independent of statements.dtx} +% \changes{v0.9d}{2006/10/31}{revamped the proof end mark management} +% \changes{v0.9e}{2008/10/11}{taking type seriously} +% \changes{v0.9f}{2009/12/14}{changing to omd metadata framework} +% \changes{v0.9f}{2008/12/14}{first steps to sref} +% +% \GetFileInfo{sproof.sty} +% +% \MakeShortVerb{\|} +%\def\scsys#1{{{\sc #1}}\index{#1@{\sc #1}}} +% \def\xml{\scsys{Xml}} +% \def\mathml{\scsys{MathML}} +% \def\omdoc{\scsys{OMDoc}} +% \def\openmath{\scsys{OpenMath}} +% \def\latexml{\scsys{LaTeXML}} +% \def\perl{\scsys{Perl}} +% \def\cmathml{Content-{\sc MathML}\index{Content {\sc MathML}}\index{MathML@{\sc MathML}!content}} +% \def\activemath{\scsys{ActiveMath}} +% \def\twin#1#2{\index{#1!#2}\index{#2!#1}} +% \def\twintoo#1#2{{#1 #2}\twin{#1}{#2}} +% \def\atwin#1#2#3{\index{#1!#2!#3}\index{#3!#2 (#1)}} +% \def\atwintoo#1#2#3{{#1 #2 #3}\atwin{#1}{#2}{#3}} +% \title{{\texttt{sproof.sty}}: Structural Markup for Proofs\thanks{Version {\fileversion} (last revised +% {\filedate})}} +% \author{Michael Kohlhase\\ +% Jacobs University, Bremen\\ +% \url{http://kwarc.info/kohlhase}} +% \maketitle +% +% \begin{abstract} +% 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. +% \end{abstract} +% +% \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,for=sum-over-odds] +% {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}[display=flow] then we compute $1=1^2$\end{spfstep} +% \end{spfcase} +% \begin{spfcase}{$n=2$} +% \begin{sproofcomment}[display=flow] +% This case is not really necessary, but we do it for the +% fun of it (and to get more intuition). +% \end{sproofcomment} +% \begin{spfstep}[display=flow] 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{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,for=sum-over-odds] +% {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}[display=flow] then we compute $1=1^2$\end{spfstep} +% \end{spfcase} +% \begin{spfcase}{$n=2$} +% \begin{sproofcomment}[display=flow] +% This case is not really necessary, but we do it for the fun +% of it (and to get more intuition). +% \end{sproofcomment} +% \begin{spfstep}[display=flow] +% 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{spfcases} The |pfcases| environment is used to mark up a proof by +% cases. 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). +% +% \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. +% +% \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{}|. +% +% \StopEventually{\newpage\PrintIndex\newpage\PrintChanges\printbibliography} +% \newpage +% +% \section{The Implementation} +% +% The |sproof| package generates to files: the {\LaTeX} package (all the code between +% {\textsf{$\langle$*package$\rangle$}} and {\textsf{$\langle$/package$\rangle$}}) and the +% {\latexml} bindings (between {\textsf{$\langle$*ltxml$\rangle$}} and +% {\textsf{$\langle$/ltxml$\rangle$}}). We keep the corresponding code fragments together, +% since the documentation applies to both of them and to prevent them from getting out of +% sync. +% +% We first set up the Perl Packages for {\latexml} +% +% \begin{macrocode} +%<*ltxml> +# -*- CPERL -*- +package LaTeXML::Package::Pool; +use strict; +use LaTeXML::Package; +RequirePackage('sref'); +%</ltxml> +% \end{macrocode} +% Then we make sure that the {\stex} |sref| package is loaded~\ctancite{Kohlhase:sref}. +% \begin{macrocode} +%<*package> +\RequirePackage{sref} +%</package> +% \end{macrocode} +% +% \subsection{Proofs}\label{sec:impl:proofs} +% +% We first define some keys for the |proof| environment. +% \begin{macrocode} +%<*package> +\srefaddidkey{spf} +\omdaddkey{spf}{display} +\omdaddkey{spf}{for} +\omdaddkey{spf}{from} +\omdaddkey[\sproof@box]{spf}{proofend} +\omdaddkey{spf}{type} +\omdaddkey{spf}{title} +\omdaddkey{spf}{continues} +%</package> +% \end{macrocode} +% +% \begin{macro}{\spf@flow} +% We define this macro, so that we can test whether the |display| key has the value |flow| +% \begin{macrocode} +%<package>\def\spf@flow{flow} +% \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} +%<*package> +\newenvironment{pst@with@label}[1]{\edef\pst@label{#1}\advance\count10 by 1\count\count10=1} +{\advance\count10 by -1} +% \end{macrocode} +% \end{environment} +% +% \begin{macro}{\the@pst@label} +% |\the@pst@label| evaluates to the current step label. +% \begin{macrocode} +\def\the@pst@label{\pst@label.\number\count\count10} +% \end{macrocode} +%\end{macro} +% +% \begin{macro}{\next@pst@label} +% |\next@pst@label| increments the step label at the current level. +% \begin{macrocode} +\def\next@pst@label{\global\advance\count\count10 by 1} +% \end{macrocode} +%\end{macro} +% +%\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\spf@proofend{\sproof@box} +\def\sproofend{\ifx\spf@proofend\@empty\else\hfil\null\nobreak\hfill\spf@proofend\par\smallskip\fi} +\def\sProofEndSymbol#1{\def\sproof@box{#1}} +%</package> +%<ltxml>DefConstructor('\sproofend',""); +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{spfsketch} +% \begin{macrocode} +%<*package> +\newcommand{\spfsketch}[2][]{\omdsetkeys{spf}{#1}\sref@target +\ifx\spf@display\spf@flow\else{\stDMemph{\ifx\spf@type\@empty{Proof}\else\spf@type\fi}:}\fi{ #2}% +\sref@label@id{this \ifx\spf@type\@empty{Proof}\else\spf@type\fi}} +%</package> +%<*ltxml> +DefConstructor('\spfsketch OptionalKeyVals:pf{}', + "<omdoc:proof " + . "?&defined(&KeyVal(#1,'id'))(xml:id='&KeyVal(#1,'id')')()>\n" + . "?#2(<omdoc:omtext>" + . "<omdoc:CMP><omdoc:p>#2</omdoc:p></omdoc:CMP>" + . "</omdoc:omtext>\n)()" + . "</omdoc:proof>\n"); +DefConstructor('\sProofEndSymbol {}',''); +%</ltxml> +% \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} +%<*package> +\newenvironment{@proof}[2][]{\omdsetkeys{spf}{#1}\sref@target +\count10=10 +\ifx\spf@display\spf@flow\else{\stDMemph{\ifx\spf@type\@empty{Proof}\else\spf@type\fi}:}\fi{ #2}% +\sref@label@id{this \ifx\spf@type\@empty{Proof}\else\spf@type\fi} +\def\pst@label{}\newcount\pst@count% initialize the labeling mechanism +\begin{description}\begin{pst@with@label}{P}} +{\end{pst@with@label}\end{description}} +\newenvironment{sproof}[2][]{\begin{@proof}[#1]{#2}}{\sproofend\end{@proof}} +\newenvironment{sProof}[2][]{\begin{@proof}[#1]{#2}}{\end{@proof}} +%</package> +%<*ltxml> +DefCMPEnvironment('{sproof} OptionalKeyVals:pf{}', + "<omdoc:proof " + . "?&KeyVal(#1,'for')(for='&hash_wrapper(&KeyVal(#1,'for'))')()" + . "?&defined(&KeyVal(#1,'id'))(xml:id='&KeyVal(#1,'id')')()>\n" + . "?#2(<omdoc:omtext>" + . "<omdoc:CMP><omdoc:p>#2</omdoc:p></omdoc:CMP>" + . "</omdoc:omtext>\n)()" + . "#body" + . "</omdoc:proof>\n"); +DefMacro('\sProof','\sproof'); +DefMacro('\endsProof','\endsproof'); +%</ltxml> +% \end{macrocode} +% \end{environment} +% +% \begin{environment}{spfidea} +% \begin{macrocode} +%<*package> +\newcommand{\spfidea}[2][]{\omdsetkeys{spf}{#1}% +\stDMemph{\ifx\spf@type\@empty{Proof Idea}\else\spf@type\fi:} #2\sproofend} +%</package> +%<*ltxml> +DefCMPConstructor('\spfidea OptionalKeyVals:pf {}', + "<omdoc:proof " + . "?&defined(&KeyVal(#1,'id'))(xml:id='&KeyVal(#1,'id')')()" + . "?&KeyVal(#1,'for')(for='&hash_wrapper(&KeyVal(#1,'for'))')()>\n" + . "<omdoc:omtext><omdoc:CMP><omdoc:p>#2</omdoc:p></omdoc:CMP></omdoc:omtext>\n" + . "</omdoc:proof>\n"); +%</ltxml> +% \end{macrocode} +% \end{environment} +% +% 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} +%<*package> +\newenvironment{spfstep}[1][]{\omdsetkeys{spf}{#1} +\ifx\spf@display\spf@flow\else\item[\the@pst@label]\fi +\ifx\spf@title\@empty\else{(\stDMemph{\spf@title})}\fi} +{\next@pst@label} +%</package> +%<*ltxml> +DefCMPEnvironment('{spfstep} OptionalKeyVals:pf', + "<omdoc:derive " + . "?&defined(&KeyVal(#1,'id'))(xml:id='&KeyVal(#1,'id')')()>" + . "<omdoc:CMP><omdoc:p>#body</omdoc:derive>\n", + beforeConstruct=>sub { + $_[0]->maybeCloseElement('omdoc:p'); + $_[0]->maybeCloseElement('omdoc:CMP'); + }); +%</ltxml> +% \end{macrocode} +% \end{environment} +% +% \begin{environment}{sproofcomment} +% \begin{macrocode} +%<*package> +\newenvironment{sproofcomment}[1][]{\omdsetkeys{spf}{#1} +\ifx\spf@display\spf@flow\else\item[\the@pst@label]\fi} +{\next@pst@label} +%</package> +%<*ltxml> +DefCMPEnvironment('{sproofcomment} OptionalKeyVals:pf', + "<omdoc:omtext " + . "?&defined(&KeyVal(#1,'id'))(xml:id='&KeyVal(#1,'id')')()>" + . "<omdoc:CMP><omdoc:p>#body</omdoc:p></omdoc:CMP>" + . "</omdoc:omtext>"); +%</ltxml> +% \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}{spfcases} +% In the |pfcases| environment, the start text is displayed as the first comment of the +% proof. +% \begin{macrocode} +%<*package> +\newenvironment{spfcases}[2][]{\omdsetkeys{spf}{#1} +\def\@test{#2}\ifx\@test\empty\else +\ifx\spf@display\spf@flow {#2}\else\item[\the@pst@label]{#2} \fi\fi +\begin{pst@with@label}{\pst@label.\number\count\count10}} +{\end{pst@with@label}\next@pst@label} +%</package> +%<*ltxml> +DefEnvironment('{spfcases} OptionalKeyVals:pf {}', + "<omdoc:derive " + . "?&defined(&KeyVal(#1,'id'))(xml:id='&KeyVal(#1,'id')')()>\n" + . "<omdoc:CMP><omdoc:p>#2</omdoc:p></omdoc:CMP>\n" + . "<omdoc:method xref='#proof-by-cases'>#body</omdoc:method>" + . "</omdoc:derive>\n"); +%</ltxml> +% \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} +%<*package> +\newenvironment{spfcase}[2][]{\omdsetkeys{spf}{#1} +\ifx\spf@display\spf@flow\else\item[\the@pst@label]\fi +\def\@test{#2}\ifx\@test\@empty\else{\stDMemph{#2}:}\fi +\begin{pst@with@label}{\pst@label.\number\count\count10}} +{\ifx\spf@display\spf@flow\else\sproofend\fi\end{pst@with@label}\next@pst@label} +%</package> +%<*ltxml> +DefEnvironment('{spfcase} OptionalKeyVals:pf{}', + "<omdoc:proof " + . "?&defined(&KeyVal(#1,'id'))(xml:id='&KeyVal(#1,'id')')()>\n" + . "?#2(<omdoc:omtext>" + . "<omdoc:CMP><omdoc:p>#2</omdoc:p></omdoc:CMP>" + . "</omdoc:omtext>\n)()" + . "#body" + . "</omdoc:proof>\n"); +%</ltxml> +% \end{macrocode} +% \end{environment} +% +% \begin{environment}{subproof} +% In the |subproof| environment, a new (lower-level) proof environment is +% started.\ednote{document this above} +% \begin{macrocode} +%<*package> +\newenvironment{subproof}{\begin{pst@with@label}{\pst@label.\number\count\count10}} +{\ifx\spf@display\spf@flow\else\sproofend\fi\end{pst@with@label}} +%</package> +%<*ltxml> +DefEnvironment('{subproof}', + "<omdoc:proof>\n #body\n</omdoc:proof>\n"); +%</ltxml> +% \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} +%<*package> +\srefaddidkey{just} +\omdaddkey{just}{method} +\omdaddkey{just}{premises} +\omdaddkey{just}{args} +%</package> +%<*ltxml> +DefKeyVal('just','id','Semiverbatim'); +DefKeyVal('just','method','Semiverbatim'); +DefKeyVal('just','premises','Semiverbatim'); +DefKeyVal('just','args','Semiverbatim'); +%</ltxml> +% \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} +%<*package> +\newenvironment{justification}[1][]{}{} +%</package> +%<*ltxml> +sub extractBodyText { + my ($box, $remove) = @_; + my $str = ''; + my @boxes = $box->unlist; + foreach my $b(@boxes) { + my $s = ''; + if ($b =~ /LaTeXML::Whatsit/) { + my $body = $b->getBody; + $s = $body ? extractBodyText($body, $remove) : ''; + } elsif ($b =~ /LaTeXML::Box/) { + $s = $b->toString || ''; + @{$b}[0] = '' if $remove; } + $str .= $s; } + $str =~ s/\s+/ /g; + $str; } + +DefEnvironment('{justification} OptionalKeyVals:just', sub { + my ($doc, $keys, %props) = @_; + my $text = extractBodyText($props{body}, 1); + my $node = LookupValue('_LastSeenCMP'); + #$node->appendText($text) if $node; + my $method = $keys ? $keys->getValue('method') : undef; + $doc->openElement("omdoc:method", $method ? (xref => $method) : ()); + $doc->absorb($props{body}) if $props{body}; + $doc->closeElement("omdoc:method"); + return; }); +%</ltxml> +% \end{macrocode} +% \end{environment} +% +% \begin{macro}{\premise} +% \begin{macrocode} +%<*package> +\newcommand{\premise}[2][]{#2} +%</package> +%<*ltxml> +DefMacro('\premise[]{}', sub { + my ($xref, $text) = ($_[1], $_[2]); + my @res = (T_CS('\premise@content')); + push(@res, T_OTHER('['), $xref->unlist, T_OTHER(']')) if $xref; + push(@res, T_SPACE, $text->unlist) if $text; + @res; }); +DefConstructor('\premise@content[]', + "<omdoc:premise xref='#1'/>"); +%</ltxml> +% \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} +%<*package> +\newcommand{\justarg}[2][]{#2} +%</package> +%<*ltxml> +DefMacro('\justarg[]{}', sub { (($_[1] ? $_[1]->unlist : ()), + T_SPACE, $_[2]->unlist, T_SPACE); }); +Tag('omdoc:derive', afterClose=>sub { + my ($doc, $node) = @_; + my @children = grep($_->nodeType == XML_ELEMENT_NODE, $node->childNodes); + my $firstCMP = undef; + foreach my $child(@children) { + next unless ($child->localname || '') eq 'CMP'; + if ($child->hasChildNodes()) { + next unless $#{$child->childNodes} == 0; + next unless $child->firstChild->nodeType == XML_TEXT_NODE; } + + if ($firstCMP) { + $firstCMP->appendText($child->textContent); + $node->removeChild($child); + } else { $firstCMP = $child; } + } + });#$ +%</ltxml> +% \end{macrocode} +% \end{macro} +% +% \subsection{Providing IDs for {\omdoc} Elements}\label{sec:impl:ids} +% +% To provide default identifiers, we tag all {\omdoc} +% elements that allow |xml:id| attributes by executing the |numberIt| procedure from |omdoc.sty.ltxml|. +% +% \begin{macrocode} +%<*ltxml> +Tag('omdoc:proof',afterOpen=>\&numberIt,afterClose=>\&locateIt); +Tag('omdoc:derive',afterOpen=>\&numberIt,afterClose=>\&locateIt); +Tag('omdoc:method',afterOpen=>\&numberIt,afterClose=>\&locateIt); +Tag('omdoc:premise',afterOpen=>\&numberIt,afterClose=>\&locateIt); +Tag('omdoc:derive',afterOpen=>\&numberIt,afterClose=>\&locateIt); +%</ltxml> +% \end{macrocode} +% +% \section{Finale} +% +% Finally, we need to terminate the file with a success mark for perl. +% \begin{macrocode} +%<ltxml>1; +% \end{macrocode} +% \Finale +\endinput +% 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 + +%%% Local Variables: +%%% mode: doctex +%%% TeX-master: t +%%% End: +% 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 omdaddkey pf.sty newenvironment hbox vrule vbox ifx +% LocalWords: hrule vskip hrule vrule hfil nobreak hfill smallskip newcommand +% LocalWords: omdsetkeys stDMemph newcount endsproof xref doctex diff --git a/Master/texmf-dist/source/latex/stex/sref/sref.dtx b/Master/texmf-dist/source/latex/stex/sref/sref.dtx new file mode 100644 index 00000000000..863967ed268 --- /dev/null +++ b/Master/texmf-dist/source/latex/stex/sref/sref.dtx @@ -0,0 +1,695 @@ +% \iffalse meta-comment +% A LaTeX Class and Package for Semantic Cross-Referencing +% Copyright (c) 2009 Michael Kohlhase, all rights reserved +% this file is released under the +% LaTeX Project Public License (LPPL) +% +% The development version of this file can be found at +% $HeadURL: https://svn.kwarc.info/repos/stex/trunk/sty/sref/sref.dtx $ +% \fi +% +% \iffalse +%<*package> +\NeedsTeXFormat{LaTeX2e}[1999/12/01] +\ProvidesPackage{sref}[2010/06/25 v0.9 Semantic Cross-References] +%</package> +%<*driver> +\documentclass{ltxdoc} +\usepackage{url,array,float} +\usepackage[show]{ed} +\usepackage[hyperref=auto,style=alphabetic]{biblatex} +\bibliography{kwarc} +\usepackage{stex-logo,sref} +\usepackage{../ctansvn} +\usepackage{hyperref} +\usepackage[eso-foot,today]{svninfo} +\svnInfo $Id: sref.dtx 1502 2010-07-20 08:17:00Z kohlhase $ +\svnKeyword $HeadURL: https://svn.kwarc.info/repos/stex/trunk/sty/sref/sref.dtx $ +\makeindex +\floatstyle{boxed} +\newfloat{exfig}{thp}{lop} +\floatname{exfig}{Example} +\begin{document}\DocInput{sref.dtx}\end{document} +%</driver> +% \fi +% +%\CheckSum{265} +% +% \changes{v0.5}{2008/03/28}{split off from omdoc.sty} +% \changes{v0.6}{2009/12/07}{introducing sequation} +% \changes{v0.9}{2009/14/07}{using omd for metadata} +% +% \GetFileInfo{sref.sty} +% +% \MakeShortVerb{\|} +% +% \def\omdoc{OMDoc} +% \def\latexml{{\LaTeX}ML} +% \title{{\texttt{sref.sty}}: Semantic Cross-Referencing in {\LaTeX}\thanks{Version {\fileversion} (last revised +% {\filedate})}} +% \author{Michael Kohlhase\\ +% Jacobs University, Bremen\\ +% \url{http://kwarc.info/kohlhase}} +% \maketitle +% +% \begin{abstract} +% The |sref| 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). +% +% The |sref| package supplies an for semantic cross-referencing over multiple documents. +% \end{abstract} +% +%\tableofcontents\newpage +% +%\section{Introduction}\label{sec:intro} +% +% The automatic computation of cross-references is one of the traditional strong points of +% {\LaTeX}. However, cross-referencing is limited to labels in the current document +% only. Cross-referencing between multiple documents in a jointly developed document +% collection is not easy to achieve in the {\LaTeX} processing model, which reads files +% sequentially and lacks a path concept. +% +% The |sref| package is mainly aimed at package developers. It supplies the internal +% macros that can be used to make document structuring elements cross-referencable. The +% general strategy here is to equip the document structuring macros with an +% \DescribeMacro{id}|id| key, so that the author can specify meaningful ones, but to let +% the transformation give default ones if the author did not. The value of the |id| key +% can also be used for cross-referencing like the |\label|/|\ref| mechanism in +% {\LaTeX}. We implement an independent referencing mechanism, since the referencing model +% is geared more towards referencing text fragments than text fragment labels like section +% numbers. Therefore we let the referenced fragments define the reference text much like +% the |\autoref| macro from |\hpyerref|. +% +% \section{The User Interface}\label{sec:user} +% +% This package is currently mainly meaningful in the context of the {\sTeX} collection, +% since all cross-referencable macros and environments must be extended to know about their +% referencing mechanism. We explain the user interface in \sref{sec:user:crossref}. To +% port the functionality to other {\LaTeX} classes and packages, they have to be upgraded +% via the API in \sref{sec:user:package-authors}. +% +% \subsection{Package and Class Options}\label{sec:user:options} +% +% The |sref| package has the \DescribeMacro{extrefs}|extrefs| package option, which can +% be set to activate multifile support (see subsection~\sref{sec:user:interdoc}). +% +% \subsection{Cross-Referencing}\label{sec:user:crossref} +% +% The \DescribeMacro{\sref}|\sref{|\meta{id}|}| macro is the main cross-referencing macro, +% see Figure~\ref{fig:mysection} for an example. Depending on the whether macro or +% environment marking up the respective document fragment carries the key/value pair +% |id=|\meta{id} the cross-reference will expand to ``Section 2.1'' or ``this remark'', +% both carrying hyper-references. The |\sref| macro takes an optional argument that allows +% to specify a link text that overrides the auto-generated one. +% +% \begin{exfig} +% \begin{verbatim} +% \mysection[id=foo]{#2} +% ... \sref{foo} ... +% \end{verbatim} +% \vspace*{-1.5em} +% \caption{Semantic Crossreferencing}\label{fig:mysection} +% \end{exfig} +% +% The +% \DescribeMacro{\srefs}|\srefl{|\meta{id\textsuperscript{1}}|}{|\meta{id\textsuperscript{2}}|}| +% is a variant it |\sref|, only that it allows to reference two semantic objects and +% expands to ``\meta{reference\textsuperscript{1}} and +% \meta{reference\textsuperscript{2}}''. \DescribeMacro{\srefl}|\srefl{|\meta{id\textsuperscript{1}}|}{|\meta{id\textsuperscript{n}}|}| +% is similar, but for ranges; it expands to ``\meta{reference\textsuperscript{1}} to +% \meta{reference\textsuperscript{n}}''. Its use should be restricted to cases, where the +% types of objects references are homogenous. +% +% Finally, there is a variant \DescribeMacro{\spageref}|\spageref| that only outputs the +% page number of the referenced object. It can be used in cases where no hyper-referencing +% is present. It uses the macro \DescribeMacro{\sref@page@label}|\sref@page@label| for +% styling the page reference. Redefining this will allows to customize this. The default +% setting is +% \begin{verbatim} +% \newcommand{\sref@page@label}[1]{p.~{#1}} +% \end{verbatim} +% +% \subsection{An API for Package Authors}\label{sec:user:package-authors} +% +% To make use of the |sref| package, the package must define the document structuring +% infrastructure using the |sref| internal macros. The {\sTeX} packages already does this, +% so we make an example here for a slightly upgraded sectioning command in +% Figure~\ref{fig:mysection:setup}. The first three lines define the keys for the keyval +% attribute of the |\mysection| command using the infrastructure supplied by the |omd| +% package~\ctancite{Kohlhase:omd} (remember the |\RequirePackage{omd}|). The first two just +% initialize the keys to save the key values in internal macros, and the |\omdsetkeys| +% activates the keys when reading the keyval argument. The +% \DescribeMacro{\srefaddidkey}|\srefaddidkey| macro is a variant of |\omdaddkey| macro +% supplied by the |sref| package that sets up the keys to set the +% \DescribeMacro{\sref@id}|\sref@id| register for later use by the |sref| +% infrastructure. Note that the |\srefaddidkey| macro uses the |prefix| key to +% systematically construct prefixed identifiers. This can be useful in particular for +% sectioning commands. +% +% \begin{exfig} +% \begin{verbatim} +% \omdaddkey{sec}{short} +% \omdaddkey[black]{sec}{color} +% \srefaddidkey[prefix=sec.]{sec} +% \newcommand{\mysection}[2][]{\omdsetkeys{#1}\sref@target\color{\sec@color} +% \section[\sec@short]{#2}\sref@label@id{Section \thesection}} +% \end{verbatim} +% \vspace*{-1.5em} +% \caption{A slightly upgraded sectioning command}\label{fig:mysection:setup} +% \end{exfig} +% +% In this situation, the |\mysection| macro processes the optional argument with +% |\omdsetkeys| and then sets the color of the section. The +% \DescribeMacro{\sref@target}|\sref@target| sets up the hypertarget for the |hyperref| +% package to use, then we use the regular |\section| command, and we use the +% \DescribeMacro{\sref@label@id}|\sref@label@id| macro to define the label that the +% |\sref| macro will use for cross-referencing. +% +% Note that the use of the straight use of the label ``Section'', which will be written +% into the auxiliary files is bad practice since it is not configurable. It would be much +% better to make it configurable via a presentation macro like |\my@section@label| in +% Figure~\ref{fig:mysection:configurable}. Then translators or even the user could redefine +% the |\my@section@label| to adapt them to their needs. +% +% \begin{exfig} +% \begin{verbatim} +% \newcommand{\my@section@label}[1]{Section~{#1}} +% \newcommand{\mysection}[2][]{\omdsetkeys{#1}\sref@target\color{\sec@color} +% \section[\sec@short]{#2}\sref@label@id{\my@section@label\thesection}} +% \end{verbatim} +% \vspace*{-1.5em} +% \caption{A Sectioning Command with Configurable Label}\label{fig:mysection:configurable} +% \end{exfig} +% +% \subsection{Inter-Document Cross-Referencing}\label{sec:user:interdoc} +% +% |sref.sty| provides inter-document cross-referencing. The use case is simple: we want to +% have a document collection (e.g. a book with conference proceedings), but also want to +% be able format the individual documents separately, and still have meaningful +% cross-references. To show off the possibilities, let us assume that we have a book with +% two separate papers, which we put into separate directories |idc| and |scr| to minimize +% interference between the authors Jane Doe and John Bull. To achieve this, we would set +% up paper driver files |main.tex| like the one in Figure~\ref{fig:paper-driver} in the +% two directories. These use the \DescribeMacro{\makeextrefs}|\makeextrefs| macro, which +% causes the |sref| package to generate a {\emph{external references file}} +% |main.refs|. Note that the |\makeextrefs| macros reads the previous |main.refs| file so +% that forward-referencing is possible (in the pass after a reference was labeled). +% +% \begin{exfig} +% \begin{verbatim} +% \documentclass{article} +% \usepackage[extrefs]{sref} +% \makeextrefs{idc} +% \inputrefs{scr}{../scr/main} +% \extrefstyle{scr}{\cite[\protect{\theextref}]{Doe09}} +% \title{Inter-Document Crossreferencing} +% \author{John Bull\\...} +% \begin{document}\maketitle\input{paper}\end{document} +% \end{verbatim} +% \vspace*{-2em} +% \caption{A document driver {\texttt{idc/main.tex}} for a paper}\label{fig:paper-driver} +% \end{exfig} +% +% The external references file can be read by other documents; in +% Figure~\ref{fig:paper-driver}, we read the references file of Jane Doe's paper via the +% \DescribeMacro{\inputrefs}|\inputrefs| macro. This allows John Bull to use\footnote{Note +% that the external references file is updated every time {\LaTeX} is run, so that +% references may be off by one version.} references like +% \DescribeMacro{\extref}|\extref{scr}{foo}| to reference document fragments in Jane Doe's +% paper she has labeled with the {\emph{reference prefix}} |\slabel{foo}| (assuming that +% she has added |\makeextrefs{scr}| in the preamble of her paper). Note that just as the +% |\sref| macro |\extref| takes an optional first argument that allows to specify the link +% text. Here, John Bull uses the \DescribeMacro{\extrefstyle}|\extrefstyle| macro to +% specify how the externa references are to be formatted, in this case he decided to use a +% {\LaTeX} citation. Generally, first argument of the |\extrefstyle| macro is the +% reference prefix which should be configured, and the second is the format, where the +% \DescribeMacro{\theextref}|\theextref| macro expands to the cross-reference. In this +% case, John chose to use a bib{\TeX} citation (he has an entry |Doe09| in his database) +% for the reference to the external paper. +% +% As the content of the respective paper is input from a file |paper.tex| in the +% individual papers, we can re-use these in the book. To do this we set up a book driver +% file like the one in Figure~\ref{fig:book-driver}. This one does not use the |extrefs| +% option, so the references are written to the |.aux| file. Furthermore |\extref| is +% redefined to act like |\sref| disregarding the first required argument. Thus all +% references work like they should. +% \begin{exfig} +% \begin{verbatim} +% \documentclass{book} +% \usepackage{sref} +% \title{Cross-Referencing in {\LaTeX}} +% \author{Elder Reseacher} +% \begin{document} +% \maketitle +% \chapter{Semantic Crossreferencing (Jane Doe, ...)} +% \input{scr/paper}\newpage +% ... +% \chapter{Inter-Document Crossreferencing (John Bull, ...)} +% \input{idc/paper}\newpage +% \end{document} +% \end{verbatim} +% \vspace*{-2em} +% \caption{A document driver for the book assembling the papers}\label{fig:book-driver} +% \end{exfig} +% +% This example has been carried through (without the separation of chapters in to +% subdirectories) in the files accompanying the source distribution of the |sref| +% package. They are used for testing the package. +% +% \subsection{Semantic Versions of Commonly used Referencing Commands}\label{sec:user:common} +% +% The |sref| package defines semantically referencable versions of commonly used {\LaTeX} +% environments and command sequences.\footnote{This section will be extended by need, so +% if you miss some semantic environment, please contact the package author, or (better) +% file an issue at~\cite{sTeX:online})} +% +% The \DescribeEnv{sequation}|sequation| environment takes an optional key/value argument +% that allows to specify an identifier and unifies the behavior of the |equation| (if an +% |id| key is given) and |displaymath| (else) environments. So the markup +% \begin{exfig} +% \begin{verbatim} +% A semantic equation with id +% \begin{sequation}[id=foo] +% e^{mc}=-1 +% \end{sequation} +% and another one without id +% \begin{sequation} +% e^{mc}=-1 +% \end{sequation} +% now, we reference the first equation: {\sref{foo}} +% \end{verbatim} +% \vspace*{-1.5em}\hrule +% yields the result:\hrule +% A semantic equation with id +% \begin{sequation}[id=foo] +% e^{mc}=-1 +% \end{sequation} +% and another one without id +% \begin{sequation} +% e^{mc}=-1 +% \end{sequation} +% now, we reference the first equation: {\sref{foo}} +% \caption{Semantic Equation}\label{fig:sequation} +% \end{exfig} +% +% \StopEventually{\newpage\PrintIndex\newpage\PrintChanges\printbibliography} +% \newpage +% +% \section{Implementation}\label{sec:impl} +% +% We first set up header information for the {\latexml} binding file. +% \begin{macrocode} +%<*ltxml> +package LaTeXML::Package::Pool; +use strict; +use LaTeXML::Package; +%</ltxml> +% \end{macrocode} +% +% \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> +\newif\ifextrefs\extrefsfalse +\DeclareOption{extrefs}{\extrefstrue} +\ProcessOptions +%</package> +%<*ltxml> +DeclareOption('extrefs',''); +%</ltxml> +% \end{macrocode} +% +% Then we need to set up the packages by requiring the |omd| package~\ctancite{Kohlhase:omd} +% to be loaded (in the right version). +% +% \begin{macrocode} +%<*package> +\RequirePackage{omd} +%</package> +%<ltxml>RequirePackage('omd'); +% \end{macrocode} +% +% \subsection{Crossreferencing}\label{sec:impl:crossref} +% +% The following user-level macros just use the |\sref@hlink| macros in various ways for +% internal referencing.\ednote{they need implementation in LaTeXML, the ones here only are +% stubs to make the error messages shut up.} +% +% \begin{macro}{\sref} +% \begin{macrocode} +%<*package> +\newcommand{\sref}[2][]{% +\@ifundefined{sref@part}{\sref@hlink[#1]{#2}}{\sref@hlink[#1]{\sref@part @#2}}} +%</package> +%<*ltxml> +DefConstructor('\sref[]{}', + "Section <omdoc:ref type='cite' xref='#2'/>"); +%</ltxml> +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\srefs} +% \begin{macrocode} +%<*package> +\newcommand{\srefs}[3][]{% +\def\@test{#1}\ifx\@test\@empty\sref{#2} and \sref{#3}\else #1\fi} +%</package> +%<*ltxml> +DefConstructor('\srefs[]{}', + "Section <omdoc:ref type='cite' xref='#2'/>"); +%</ltxml> +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\srefl} +% \begin{macrocode} +%<*package> +\newcommand{\srefl}[3][]{% +\def\@test{#1}\ifx\@test\@empty\sref{#2} to \sref{#3}\else #1\fi} +%</package> +%<*ltxml> +DefConstructor('\srefl[]{}', + "Section <omdoc:ref type='cite' xref='#2'/>"); +%</ltxml> +% \end{macrocode} +% \end{macro} +% \ednote{it is not clear what we want in the implementation of spageref} +% \begin{macro}{\spageref} +% \begin{macrocode} +%<*package> +\newcommand{\spageref}[2][]{% +\@ifundefined{sref@part}{\sref@hlink[#1]{#2}}{\sref@hlink[#1]{\sref@part @#2}}} +%</package> +%<*ltxml> +DefConstructor('\spageref[]{}', + "Section <omdoc:ref type='cite' xref='#2'/>"); +%</ltxml> +% \end{macrocode} +% \end{macro} +% +% \subsection{An API for Package Authors}\label{sec:impl:package-authors} +% +% We find out whether the |hyperref| package is loaded, since we may want to use it for +% cross-references, for which we set up some internal macros that gracefully degrade if +% |hyperref| is not loaded. +% +% \begin{macro}{\sref@*@ifh} +% \begin{macrocode} +%<*package> +\newif\ifhref\hreffalse +\AtBeginDocument{\@ifpackageloaded{hyperref}{\hreftrue}{\hreffalse}} +\def\sref@href@ifh#1#2{\ifhref\href{#1}{#2}\else#2\fi} +\def\sref@hlink@ifh#1#2{\ifhref\hyperlink{#1}{#2}\else#2\fi} +\def\sref@target@ifh#1#2{\ifhref\hypertarget{#1}{#2}\else#2\fi} +% \end{macrocode} +% \end{macro} +% +% Then we provide some macros for {\sTeX}-specific crossreferencing +% +% \begin{macro}{\sref@target} +% The next macro uses this and makes an target from the current |sref@id| declared by +% a |id| key. +% \begin{macrocode} +\def\sref@target% +{\ifx\sref@id\@empty\else% +\expandafter\sref@target@ifh% +{sref@\@ifundefined{sref@part}{}{\sref@part @}\sref@id @target}{}\fi} +% \end{macrocode} +% \end{macro} +% +% The next two macros are used for setting labels, it is mainly used for enabling forward +% references, to do this, it is written into \meta{jobname}|.aux| or \meta{jobname}|.refs|. +% +% \begin{macro}{\@sref@def} +% This macro stores the value of its last argument in a custom macro for reference. +% \begin{macrocode} +\def\@sref@def#1#2#3{\expandafter\gdef\csname sref@#1@#2\endcsname{#3}} +% \end{macrocode} +% \end{macro} +% +% The next step is to set up a file to which the references are written, this is normally +% the |.aux| file, but if the |extref| option is set, we have to use an |.ref| file. +% \begin{macrocode} +\ifextrefs\newwrite\refs@file\else\def\refs@file{\@auxout}\fi +% \end{macrocode} +% +% \begin{macro}{\sref@def} +% This macro writes an |\@sref@def| command to the current aux file and also executes it. +% \begin{macrocode} +\def\sref@def#1#2#3{%\@sref@def{#1}{#2}{#3}% +\protected@write\refs@file{}{\string\@sref@def{#1}{#2}{#3}}} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\srefaddidkey} +% |\srefaddidkey[|\meta{keyval}|]{|\meta{group}|}| extends the metadata keys of the +% group \meta{group} with an |id| key. In the optional key/value pairs in \meta{keyval} +% the |prefix| key can be used to specify a prefix. +% \begin{macrocode} +\omdaddkey{srefaddidkey}{prefix} +\newcommand\srefaddidkey[2][]{\omdsetkeys{srefaddidkey}{#1}% +\@omd@ext@clear@keys{#2}{sref@id}{}% id cannot have a default +\define@key{#2}{id}{\edef\sref@id{\srefaddidkey@prefix ##1}}} +%</package> +% \end{macrocode} +% \end{macro} +% +% \subsection{Inter-Document Crossreferencing}\label{sec:impl:interdoc} +% +% \begin{macro}{\makeextrefs} +% \begin{macrocode} +%<*package> +\def\makeextrefs#1{\gdef\sref@part{#1}% +\makeatletter +\IfFileExists{\jobname.refs}{\input{\jobname.refs}}{}% +\immediate\openout\refs@file=\jobname.refs +\makeatother} +%</package> +%<ltxml>DefConstructor('\makeextrefs{}',''); +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\sref@label} +% The |\sref@label| macro writes a label definition to the auxfile. +% \begin{macrocode} +%<*package> +\def\sref@label#1#2{% +\sref@def{\@ifundefined{sref@part}{}{\sref@part @}#2}{page}{\thepage} +\sref@def{\@ifundefined{sref@part}{}{\sref@part @}#2}{label}{#1}} +%</package> +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\sref@label@id} +% The |\sref@label@id| writes a label definition for the current |\sref@id| if it is +% defined. +% \begin{macrocode} +%<*package> +\def\sref@label@id#1{\ifx\sref@id\@empty\else\sref@label{#1}{\sref@id}\fi} +%</package> +% \end{macrocode} +% \end{macro} +% +% Finally we come to the user visible macro |\sref| which is used for +% referencing.\ednote{The {\latexml} does not take into account the optional argument +% yet.} +% +% \begin{macro}{\sref@hlink} +% The next macro creates an error message if the target is not defined, and otherwise +% generates a hyperlinked reference. +% \begin{macrocode} +%<*package> +\newcommand{\sref@hlink}[2][]{\def\@test{#1}% +\@ifundefined{sref@#2@label}% +{\protect\G@refundefinedtrue\@latex@warning{reference #2 undefined}??}% +{\sref@hlink@ifh{sref@#2@target}{\ifx\@test\@empty\@nameuse{sref@#2@label}\else #1\fi}}} +%</package> +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\sref@page@label} +% This macro styles a page reference. +% \begin{macrocode} +%<*package> +\newcommand{\sref@page@label}[1]{p.~{#1}} +%</package> +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\sref@pageref} +% The next macro creates an error message if the target is not defined, and otherwise +% generates a page reference. +% \begin{macrocode} +%<*package> +\newcommand{\sref@pageref}[1]{\@ifundefined{sref@#1@page}% +{\protect\G@refundefinedtrue\@latex@warning{reference #1 undefined}\sref@page@label{??}}% +{\sref@hlink@ifh{sref@#1@target}{\sref@page@label{\@nameuse{sref@#1@page}}}}} +%</package> +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\sref@href} +% The next macro creates an error message if the target is not defined, and otherwise +% generates a hyperlinked reference. +% \begin{macrocode} +%<*package> +\newcommand{\sref@href}[3][]{\def\@test{#1}% +\@ifundefined{sref@#2@label}% +{\protect\G@refundefinedtrue\@latex@warning{reference #2 undefined}??}% +{\@ifundefined{sref@#3@URI}% +{\protect\G@refundefinedtrue\@latex@warning{external refs of type #3 undefined}??}% +{\edef\@uri{\@nameuse{sref@#3@URI}.pdf\#sref@#2@target} +\edef\@label{\ifx\@test\@empty\@nameuse{sref@#2@label}\else #1\fi} +\sref@href@ifh\@uri\@label}}} +%</package> +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\extref} +% The next macros use |\sref@hlink| with the respective prefix for external referencing +% if external references are used as indicated by the |extrefs| option; otherwise it +% disregards the first required macro and uses internal referencing.\ednote{This needs +% to be implemented on the LaTeXML side.} +% \begin{macrocode} +%<*package> +\ifextrefs +\newcommand{\extref}[3][]{\def\theextref{\sref@href[#1]{#2@#3}{#2}}% +\csname doextref@#2\endcsname} +\else +\newcommand{\extref}[3][]{\sref[#1]{#3}} +\fi +%</package> +%<*ltxml> +DefConstructor('\extref[]{}', + "Section <omdoc:ref type='cite' xref='#2'/>"); +DefConstructor('\theextref',''); +%</ltxml> +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\extrefstyle} +% This user macro defines an internal macro that is used for internal styling; for +% instance |\extrefstyle{foo}{\theextref in bar}| defines the macro |\doextref@foo| +% which evaluates to \meta{the reference} |in bar|. This is used in the |\extref| macro. +% \begin{macrocode} +%<*package> +\def\extrefstyle#1#2{\expandafter\gdef\csname doextref@#1\endcsname{#2}} +%</package> +%<*ltxml> +DefConstructor('\extrefstyle{}{}',""); +%</ltxml> +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\inputrefs} +% If the external references file exists, it is read (under the protection of +% |\makeatother|) otherwise an error message is displayed. +% \begin{macrocode} +%<*package> +\newcommand{\inputrefs}[2]{% +\@namedef{sref@#1@URI}{#2} +\makeatletter% +\IfFileExists{#2.refs}{\input{#2.refs}} + {\PackageError{sref}{Reference file #1.refs does not exist} + {Maybe you have to run LaTeX on #2.tex first}} +\makeatother} +%</package> +%<*ltxml> +DefConstructor('\inputrefs{}{}',''); +%</ltxml> +% \end{macrocode} +% \end{macro} +% +% \subsection{Semantic Versions of Commonly used Referencing Commands}\label{sec:impl:common} +% +% \begin{environment}{sequation} +% \begin{macrocode} +%<*package> +\srefaddidkey{sequation} +\def\sref@sequation@heading{equation} +\newenvironment{sequation}[1][]{\omdsetkeys{sequation}{#1}% +\ifx\sref@id\@empty\begin{displaymath}\else% no id, using equation* +\begin{equation}\sref@target\sref@label@id{\sref@sequation@heading~(\theequation)}\fi} +{\ifx\sref@id\@empty\end{displaymath}\else\end{equation}\fi} +%</package> +%<*ltxml> +DefEnvironment('{sequation} OptionalKeyVals', + "<ltx:equation " + . "?&KeyVal(#1,'id')(xml:id='&KeyVal(#1,'id')' " + . "refnum='#refnum')(xml:id='#id')>" + . "<ltx:Math mode='display'>" + . "<ltx:XMath>#body</ltx:XMath>" + . "</ltx:Math>" + . "</ltx:equation>", + mode=>'display_math', + properties=> sub { RefStepCounter('equation') }, + locked=>1); +%</ltxml> +% \end{macrocode} +% \end{environment} +% +% \begin{environment}{seqnarray} +% \begin{macrocode} +%<*package> +\newenvironment{seqnarray}[1][]% +{\omdsetkeys{sequation}{#1}\begin{eqnarray*}\sref@target% +\sref@label@id{\sref@sequation@heading~(\theequation)}} +{\end{eqnarray*}} +%</package> +%<*ltxml> +DefMacro('\seqnarray OptionalKeyVals','\begin{eqnarray*}'); +DefMacro('\endseqnarray','\end{eqnarray*}'); +%</ltxml> +% \end{macrocode} +% \end{environment} +% +% +% \subsection{Finale}\label{sec:common} +% +% Finally, we need to terminate the file with a success mark for perl. +% \begin{macrocode} +%<ltxml>1; +% \end{macrocode} +% \Finale +\endinput + +% \iffalse +%%% Local Variables: +%%% mode: doctex +%%% TeX-master: t +%%% End: +% \fi + +% LocalWords: GPL structuresharing STR omdoc dtx stex CPERL LoadClass url dc +% LocalWords: RequirePackage RegisterNamespace namespace xsl DocType ltxml dtd +% LocalWords: ltx DefEnvironment beforeDigest AssignValue inPreamble getGullet +% LocalWords: afterDigest keyval omgroup DefKeyVal Semiverbatim KeyVal iffalse +% LocalWords: OptionalKeyVals DefParameterType IfBeginFollows skipSpaces CMP +% LocalWords: ifNext DefMacro needwrapper unlist DefConstructor omtext bgroup +% LocalWords: useCMPItemizations RefStepItemCounter egroup beginItemize li di +% LocalWords: beforeDigestEnd useTheoryItemizations dt autoclose ul ol dl env +% LocalWords: afterOpen LastSeenCMP autoClose proto ToString textsuperscript +% LocalWords: addAttribute nlex nlcex omdocColorMacro args tok MergeFont qw +% LocalWords: TokenizeInternal toString isMath foreach maybeCloseElement id'd +% LocalWords: autoOpen minipage footnotesize scriptsize numberIt whatsit href +% LocalWords: getAttribute setAttribute OMDoc RelaxNGSchema noindex xml lec +% LocalWords: Subsubsection useDefaultItemizations refundefinedtrue blockquote +% LocalWords: DefCMPConstructor inlinequote idx idt ide idp emph sref extrefs +% LocalWords: flushleft flushright DeclareOption hyperref LaTeX tex pdf hlink +% LocalWords: sequation omd def texorpdfstring raisebox latexml texttt newpage +% LocalWords: fileversion maketitle tableofcontents autoref hpyerref mysection +% LocalWords: exfig vspace omdsetkeys srefaddidkey srefaddidkey omdaddkey scr +% LocalWords: makeextrefs makeextrefs inputrefs inputrefs extref extref foo +% LocalWords: extrefstyle theextref theextref displaymath hrule impl ednote +% LocalWords: printbibliography newif ifextrefs extrefsfalse extrefstrue srefs +% LocalWords: Crossreferencing newcommand ifundefined ifx srefl xref ifh gdef +% LocalWords: ifhref hreffalse ifpackageloaded hreftrue expandafter jobname +% LocalWords: jobname csname endcsname newwrite auxout makeatletter openout +% LocalWords: makeatother auxfile nameuse doextref namedef newenvironment +% LocalWords: theequation refnum refnum seqnarray eqnarray endseqnarray doctex +% LocalWords: textsuperscript spageref spageref thepage pageref ctancite diff --git a/Master/texmf-dist/source/latex/stex/statements/statements.dtx b/Master/texmf-dist/source/latex/stex/statements/statements.dtx new file mode 100644 index 00000000000..6619bc73714 --- /dev/null +++ b/Master/texmf-dist/source/latex/stex/statements/statements.dtx @@ -0,0 +1,1312 @@ +% \iffalse meta-comment +% An Infrastructure for Mathematical Statements in sTeX +% Copyright (C) 2004-2008 Michael Kohlhase, all rights reserved +% this file is released under the +% LaTeX Project Public License (LPPL) +% +% The development version of this file can be found at +% $HeadURL: https://svn.kwarc.info/repos/stex/trunk/sty/statements/statements.dtx $ +% \fi +% +% \iffalse +%<package>\NeedsTeXFormat{LaTeX2e}[1999/12/01] +%<package>\ProvidesPackage{statements}[2010/06/25 v1.0 Semantic Markup for Statements] +% +%<*driver> +\documentclass{ltxdoc} +\usepackage{url,array,float,amsfonts} +\usepackage{statements,modules,presentation} +\usepackage{paralist} +\usepackage[show]{ed} +\usepackage[hyperref=auto,style=alphabetic]{biblatex} +\bibliography{kwarc} +\usepackage[eso-foot,today]{svninfo} +\usepackage{stex-logo} +\usepackage{../ctansvn} +\usepackage{hyperref} +\svnInfo $Id: statements.dtx 1502 2010-07-20 08:17:00Z kohlhase $ +\svnKeyword $HeadURL: https://svn.kwarc.info/repos/stex/trunk/sty/statements/statements.dtx $ +\makeindex +\floatstyle{boxed} +\newfloat{exfig}{thp}{lop} +\floatname{exfig}{Example} +\begin{document}\DocInput{statements.dtx}\end{document} +%</driver> +% \fi +% +% \CheckSum{433} +% +% \changes{v0.9}{2005/06/14}{First Version with Documentation} +% \changes{v0.9a}{2005/07/01}{Completed Documentation} +% \changes{v0.9b}{2005/08/06}{Complete functionality and Updated Documentation} +% \changes{v0.9c}{2006/01/13}{more packaging} +% \changes{v0.9d}{2007/09/09}{moved omtext and friends to the omdoc package} +% \changes{v0.9d}{2007/09/09}{made dependence on the omdoc package explicit} +% \changes{v0.9d}{2007/09/09}{adding ids to many elements} +% \changes{v0.9e}{2008/05/27}{adding cross-references} +% \changes{v0.9e}{2008/09/29}{augmenting the index macros with optional values} +% \changes{v0.9f}{2008/12/04}{changed 'consymb' to 'symboldec' and documented it.} +% \changes{v0.9g}{2010/01/14}{the package is now based on {\texttt{ntheorem for presentation}}} +% \changes{v0.9g}{2010/01/19}{Added support for localization} +% \changes{v0.9g}{2010/02/23}{added {\texttt{\textbackslash symref}}} +% \changes{v1.0}{2010/06/18}{now based on {\texttt{omtext}} package instead of {\texttt{omdoc}}} +% +% \GetFileInfo{statements.sty} +% +% \MakeShortVerb{\|} +% \def\scsys#1{{{\sc #1}}\index{#1@{\sc #1}}} +% \def\xml{\scsys{Xml}} +% \def\mathml{\scsys{MathML}} +% \def\omdoc{\scsys{OMDoc}} +% \def\openmath{\scsys{OpenMath}} +% \def\latexml{\scsys{LaTeXML}} +% \def\perl{\scsys{Perl}} +% \def\activemath{\scsys{ActiveMath}} +% \title{Semantic Markup for Mathematical Statements\thanks{Version {\fileversion} (last revised +% {\filedate})}} +% \author{Michael Kohlhase\\ +% Jacobs University, Bremen\\ +% \url{http://kwarc.info/kohlhase}} +% \maketitle +% +% \begin{abstract} +% The |statements| 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 provides semantic markup facilities for mathematical statements like +% Theorems, Lemmata, Axioms, Definitions, etc. in {\stex} files. This structure can be +% used by MKM systems for added-value services, either directly from the {\sTeX} +% sources, or after translation. +% \end{abstract} +% +% \setcounter{tocdepth}{2}\tableofcontents\newpage +% +% \section{Introduction}\label{sec:statements} +% +% The motivation for the |statements| package is very similar to that for semantic macros +% in the |modules| package: We want to annotate the structural semantic properties of +% statements in the source, but present them as usual in the formatted documents. In +% contrast to the case for mathematical objects, the repertoire of mathematical statements +% and their structure is more or less fixed. +% +% 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 |sproofs|. +% +% {\stex}~\cite{Kohlhase:ulsmf08,sTeX:online} 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). Currently the {\omdoc} format~\cite{Kohlhase:omdoc1.2} is directly +% supported. +% +% \section{The User Interface}\label{sec:user-interface} +% +% The |statements| package supplies a semantically oriented infrastructure for marking up +% mathematical statements: fragments of natural language that state properties of +% mathematical objects, e.g. axioms, definitions, or theorems. The |statement| package +% provides an infrastructure for marking up the semantic relations between statements for +% the {\omdoc} transformation and uses the |ntheorem| package~\cite{MaySch:eltte09} for +% formatting (i.e. transformation to PDF). +% +% \subsection{Statements}\label{sec:statements} +% +% All the statements are marked up as environments, that take a |KeyVal| argument that +% allows to annotate semantic information. Generally, we distinguish two forms of +% statements: +% \begin{description} +% \item[{\twintoo{block}{statement}s}] have explicit discourse markers that delimit their +% content in the surrounding text, e.g. the boldface word ``{\bf{Theorem}:}'' as a start +% marker and a little line-end box as an end marker of a proof. +% \item[{\twintoo{flow}{statement}s}] do not have explicit markers, they are interspersed +% with the surrounding text. +% \end{description} +% Since they have the same semantic status, they must both be marked up, but styled +% differently. We distinguis between these two presentational forms with the +% \DescribeMacro{display=}|display| key, which is allowed on all statement +% environments. If it has the value |block| (the default), then the statement will be +% presented in a paragraph of its own, have explicit discourse markers for its begin and +% end, possibly numbering, etc. If it has the value |flow|, then no extra presentation +% will be added the semantic information is invisible to the reader. Another key that is +% present on all statement environments in the \DescribeMacro{id=}|id| key it allows to +% identify the statement with a name and to reference it with the semantic referencing +% infrastructure provided by the |sref| package~\ctancite{Kohlhase:sref}. +% +% \subsubsection{Axioms and Assertions}\label{sec:user:axiomassertion} +% +% The \DescribeEnv{assertion}|assertion| environment is used for marking up statements +% that can be justified from previously existing knowledge (usually marked with the +% monikers ``Theorem'', ``Lemma'', ``Proposition'', etc. in mathematical vernacular). The +% environment |assertion| is used for all of them, and the particular subtype of +% assertion is given in the \DescribeMacro{type=}|type| key. So instead of +% |\begin{Lemma}|\iffalse\end{Lemma}\fi we have to write +% |\begin{assertion}[type=Lemma]|\iffalse\end{assertion}\fi (see +% Example~\ref{fig:assertion} for an example). +% \begin{exfig} +% \begin{verbatim} +% \begin{assertion}[id=sum-over-odds,type=lemma] +% $\sum_{i=1}^n{2i-1}=n^2$ +% \end{assertion} +% \end{verbatim} +% \vspace{-1em}will lead to the result\vspace{-2em}\par\noindent +% \begin{assertion}[id=sum-over-odds,type=lemma] +% $\sum_{i=1}^n{2i-1}=n^2$ +% \end{assertion} +% \caption{Semantic Markup for a Lemma in a {\texttt{module}} context}\label{fig:assertion} +% \end{exfig} +% +% Whether we will see the keyword ``Lemma'' will depend on the value of the optional +% |display| key. In all of the |assertion| environments, the presentation expectation is +% that the text will be presented in italic font. The presentation (keywords, spacing, and +% numbering) of the |assertion| environment is delegated to a theorem styles from the +% |ntheorem| environment. For an assertion of type \meta{type} the |assertion| environment +% calls the |ST|\meta{type}|AssEnv| environment provided by the |statements| package; see +% Figure~\ref{fig:assertion-types} for a list of provided assertion types. Their +% formatting can be customized by redefining the |ST|\meta{type}|AssEnv| environment via +% the |\renewtheorem| command from the |ntheorem| package; see~\cite{MaySch:eltte09} for +% details. +% +% \begin{exfig} +% \begin{tabular}{|l|l|}\hline +% Value & Explanation \\\hline\hline +% \textbf{theorem}, \textbf{proposition} +% & an important assertion with a proof\\\hline +% \multicolumn{2}{|p{12cm}|}{\footnotesize Note that the meaning of \textbf{theorem} +% (in this case the existence of a proof) is not +% enforced by {\omdoc} applications. It can be appropriate to give an assertion +% the \textbf{theorem}, if the +% author knows of a proof (e.g. in the literature), but has not formalized it in +% {\omdoc} yet.}\\\hline\hline +% \textbf{lemma} & a less important assertion with a proof\\\hline +% \multicolumn{2}{|p{12cm}|}{\footnotesize The difference of importance specified +% here is even softer than the other ones, since e.g. reusing +% a mathematical paper as a chapter in a larger monograph, may make it necessary to +% downgrade a theorem (e.g. the main theorem of the paper) and give it the status of +% a lemma in the overall work.}\\\hline\hline +% \textbf{corollary} & a simple consequence\\\hline +% \multicolumn{2}{|p{12cm}|}{\footnotesize An assertion is +% sometimes marked as a corollary to some other statement, if the proof is +% considered simple. This is often the case for important theorems that are simple +% to get from technical lemmata.}\\\hline\hline +% \textbf{postulate}, \textbf{conjecture} +% & an assertion without proof or counter-exam\-ple\\\hline +% \multicolumn{2}{|p{12cm}|}{\footnotesize Conjectures are assertions, whose +% semantic value is not yet decided, but which the author considers likely to be +% true. In particular, there is no proof or counter-example.}\\\hline\hline +% \textbf{false-conjecture} +% & an assertion with a counter-example\\\hline +% \multicolumn{2}{|p{12cm}|}{\footnotesize A conjecture that has proven to be false, +% i.e. it has a counter-example. Such assertions are often kept for illustration and +% historical purposes.}\\\hline\hline +% \textbf{obligation}, \textbf{assumption} +% & an assertion on which a proof of another depends\\\hline +% \multicolumn{2}{|p{12cm}|}{\footnotesize These kinds of assertions +% are convenient during the exploration of a mathematical theory. They can be used +% and proven later (or assumed as an axiom).}\\\hline\hline +% \textbf{observation} & if everything else fails\\\hline +% \multicolumn{2}{|p{12cm}|}{\footnotesize This type is the catch-all if none of the others +% applies.}\\\hline +% \end{tabular} +% \caption{Types of Mathematical Assertions}\label{fig:assertion-types} +% \end{exfig} +% +% \DescribeEnv{axiom} The |axiom| environment is similar to |assertion|, but the content +% has a different ontological status: axioms are assumed without (formal) justification, +% whereas assertions are expected to be justified from other assertions, axioms or +% definitions. This environment relegates the formatting to the |STaxiomEnv| environment, +% which can be redefined for configuration. +% +% \subsubsection{Symbols}\label{sec:user:symbol} +% +% \DescribeEnv{symboldec} The |symboldec| environment can be used for declaring concepts +% and symbols. Note the the |symdef| forms from the |modules| package will not do this +% automatically (but the |definition| environment and the |\inlinedef| macro will for all +% the definienda; see below). The |symboldec| environment takes an optional keywords +% argument with the keys |id|, |role|, |title| and |name|. The first is for general +% identification, the |role| specifies the {\openmath}/{\omdoc} role, which is one of +% |object|, |type|, |sort|, |binder|, |attribution|, |application|, |constant|, +% |semantic-attribution|, and |error| (see the {\omdoc} specification for details). The +% |name| key specifies the {\openmath} name of the symbol, it should coincide with the +% control sequence introduced by the corresponding |\symdef| (if one is present). The +% |title| key is for presenting the title of this symbol as in other statements. Usually, +% |axiom| and |symboldec| environments are used together as in Figure~\ref{fig:axioms}. +% +%\begin{exfig} +% \begin{verbatim} +% \symdef{zero}{0} +% \begin{symboldec}[name=zero,title=The number zero,type=constant] +% The number zero, it is used as the base case of the inductive definition +% of natural numbers via the Peano Axioms. +% \end{symboldec} +% +% \symdef{succ}[1]{\prefix{s}{#1}} +% \begin{symboldec}[name=succ,title=The Successor Function,type=application] +% The successor function, it is used for the step case of the inductive +% definition of natural numbers via the Peano Axioms. +% \end{symboldec} +% +% \symdef{NaturalNumbers}{\mathbb{N}} +% \begin{symboldec}[name=succ,title=The Natural Numbers,type=Constants] +% The natural numbers inductively defined via the Peano Axioms. +% \end{symboldec} +% +% \begin{axiom}[id=peano.P1,title=P1] +% $\zero$ is a natural number. +% \end{axiom} +% ... +% \begin{axiom}[id=peano.P5,title=P5] +% Any property $P$ such $P(\zero)$ and $P(\succ{k})$ whenever $P(k)$ +% holds for all $n$ in $\NaturalNumbers$ +% \end{axiom} +% \end{verbatim} +% \vspace{-1em}will lead to the result\medskip\par\noindent +% \begin{module}[id=peano] +% \symdef{zero}{0} +% \begin{symboldec}[name=zero,title=The number zero,role=constant] +% The number zero, it is used as the base case of the inductive definition +% of natural numbers via the Peano Axioms. +% \end{symboldec} +% +% \symdef{succ}[1]{\prefix{s}{#1}} +% \begin{symboldec}[name=succ,title=The Successor Function,role=application] +% The successor function, it is used for the step case of the inductive +% definition of natural numbers via the Peano Axioms. +% \end{symboldec} +% +% \symdef{NaturalNumbers}{\mathbb{N}} +% \begin{symboldec}[name=succ,title=The Natural Numbers,role=constant] +% The natural numbers inductively defined via the Peano Axioms. +% \end{symboldec} +% +% \begin{axiom}[id=peano.P1,title=P1] +% $\zero$ is a natural number. +% \end{axiom} +% \ldots \stepcounter{STtheoremAssEnv}\stepcounter{STtheoremAssEnv}\stepcounter{STtheoremAssEnv} +% \begin{axiom}[id=peano.P5,title=P5] +% Any property $P$ such $P(\zero)$ and $P(\succ{k})$ whenever $P(k)$ +% holds for all $n$ in $\NaturalNumbers$ +% \end{axiom} +% \end{module} +% \caption{Semantic Markup for the Peano Axioms}\label{fig:axioms} +% \end{exfig} +% +% \subsubsection{Definitions}\label{sec:definition} +% +% \DescribeEnv{definition} The |definition| environment is used for marking up +% mathematical definitions. Its peculiarity is that it defines (i.e. gives a meaning to) +% new mathematical concepts or objects. These\DescribeMacro{\definiendum} are identified +% by the |definiendum| macro, which takes two arguments. The first one is the system name +% of the symbol defined (for reference via |\term|), the second one is the text that is to +% be emphasized in the presentation. Note that the |\definiendum| macro can only be used +% inside the |definition| environment. If you find yourself in a situation where you want +% to use it outside, you will most likely want to wrap the appropriate text fragment in a +% |\begin{definition}[display=flow]| ... and |\end{definition}|. For instance, we could +% continue the example in Figure~\ref{fig:axioms} with the |definition| environment in +% Figure~\ref{fig:definition}. +% +%\begin{exfig} +% \begin{verbatim} +% \symdef{one}{1} +% \begin{definition}[id=one.def,for=one] +% $\notatiendum[one]{\one}$ is the successor of $\zero$ +% (formally: $\one\colon=\succ\zero$) +% \end{definition} +% \end{verbatim} +% \vspace{-1em}will lead to the result\medskip\par\noindent +% \begin{module} +% \importmodule{peano} +% \symdef{one}{1} +% \begin{definition}[id=one.def,for=one] +% $\notatiendum[one]{\one}$ is the successor of $\zero$ +% (formally: $\one\colon=\succ\zero$) +% \end{definition} +% \end{module} +% \caption{A Definition based on Figure {\ref{fig:axioms}}}\label{fig:definition} +% \end{exfig} +% The \DescribeMacro{defin}|\defin{|\meta{word}|}| macro combines the functionality of the +% |\definiendum| macro with index markup from the |omdoc| +% package~\ctancite{Kohlhase:smomdl}: use |\defin[|\meta{name}|]{|\meta{word}|}| to +% markup a definiendum \meta{word} with system name \meta{name} that appear in the index +% --- in other words in almost all definitions of single-word concepts. We also have the +% variants \DescribeMacro{\twindef}|\twindef| and \DescribeMacro{\atwindef}|\atwindef| for +% (adjectivized) two-word compounds. Finally, the varaiants +% \DescribeMacro{\twindefalt}|\twindefalt| and \DescribeMacro{\atwindefalt}|\atwindefalt| +% have an additional first argument that allows to specify an alternative text; see +% Figure~\ref{fig:defin} +% +% \begin{exfig} +% \begin{tabular}{l|l|l} +% \multicolumn{3}{l}{source}\\ +% system name & result & index \\\hline +% \multicolumn{3}{l}{\texttt{\textbackslash defin\{concept\}}}\\ +% |concept| & concept& concept\\\hline +% \multicolumn{3}{l}{\texttt{\textbackslash defin[csymbol]\{concept\}}}\\ +% |csymbol| & concept & concept\\\hline +% \multicolumn{3}{l}{\texttt{\textbackslash definalt[csymbol]\{concepts\}\{concept\}}}\\ +% |csymbol| & concepts & concept\\\hline +% \multicolumn{3}{l}{\texttt{\textbackslash twindef\{concept\}\{group\}}}\\ +% |concept-group| & concept group & concept group, \\ +% && group - , concept\\\hline +% \multicolumn{3}{l}{\texttt{\textbackslash atwindef\{small\}\{concept\}\{group\}}}\\ +% |small-concept-group| & small concept group & small concept group, \\ +% && concept group - , small\\ +% \end{tabular} +% \caption{Some definienda with Index}\label{fig:defin} +% \end{exfig} +% +% \DescribeMacro{\inlinedef} Sometimes we define mathematical concepts in passing, e.g. in +% a phrase like ``\ldots $s(o)$ which we call {\textbf{one}}.''. For this we cannot use +% the |definition| environment, which presupposes that its content gives all that is +% needed to understand the definition. But we do want to make use of the infrastructure +% introduced for the |definition| environment. In this situation, we just wrap the phrase +% in an |\inlinedef| macro that makes them available. The |\inlinedef| macro accepts the +% same |id| and |for| keys in its optional argument, and additionally the |verbalizes| key +% which can be used to point to a full definition of the concept somewhere else. +% +% \subsubsection{Examples}\label{sec:user:example} +% +% \DescribeEnv{example} The |example| environment is a generic statement environment, +% except that the |for| key should be given to specify the identifier what this is an +% example for. The |example| environment also expects a |type| key to be specified, so +% that we know whether this is an example or a counterexample. +% +% \subsection{Cross-Referencing Symbols and Concepts}\label{sec:user:crossref} +% +% If we have defined a concept with the |\definiendum| macro, then we can mark up other +% occurrences of the term as referring to this concept. Note that this process cannot be +% fully automatized yet, since that would need advanced language technology to get around +% problems of disambiguation, inflection, and non-contiguous phrases\footnote{We do have a +% program that helps annotate larger text collections spotting the easy cases; see +% {\url{http://kwarc.info/projects/stex}} and look for the program +% |termin|.}. Therefore, the \DescribeMacro{\termref}|\termref| can be used to make this +% information explicit. It takes the keys +% \begin{compactdesc} +% \item[\texttt{cdbase}] to specify a URI (a path actually, since {\LaTeX} cannot load +% from URIs) where the module can be found. +% \item[\texttt{cd}] to specify the module in which the term is defined. If the |cd| key +% is not given, then the current module is assumed. If no |cdbase| is specified (this is +% the usual case), then the CD has to be imported via a |\importmodule| from the +% |modules| package~\ctancite{KohAmb:smmssl}. +% \item[\texttt{name}] to specify the name of the definiendum (which is given in the body +% of the |\definiendum| or the optional argument). If the |name| key is not specified, +% then argument of the |\termref| macro is used. +% \item[\texttt{role}] is currently unused. +% \end{compactdesc} +% |\termref[cd=|\meta{cd}|,name=|\meta{name}|]{|\meta{text}|}| will just typeset +% \meta{text} with (if the |hyperref| package is loaded) a hyperlink to the definition in +% module \meta{cd} that defines the concept \meta{name}, i.e. that contains +% |\definiendum[|\meta{name}|]{|\meta{something}|}|. +% +% Just as the |\definiendum| macro has the variants |\twindef| and |\atwindef| for +% composita, the |\termref| has variants |\twinref| and |\atwinref| that take two and +% three arguments for the parts of the compositum. Generally, concepts that are marked up +% by |\definiendum{|\meta{name}|}| or |\defin|{|\meta{name}|} in the definition are +% referenced by |\termref|{|\meta{name}|}, concepts defined via +% |\twindef{|\meta{first}|}{|\meta{second}|}| with +% |\twinref{|\meta{first}|}{|\meta{second}|}| and analogously for |\atwindef| and +% |\atwinref|. +% +% Note that the |\termref| treatment above is natural for ``concepts'' declared by the +% |\termdef| macro from the |modules| package~\ctancite{KohAmb:smmssl}. Concepts are +% natural language names for mathematical objects. For ``symbols'', i.e. symbolic +% identifiers for mathematical objects used in mathematical formulae, we use the |\symdef| +% macro from the |modules| package. Sometimes, symbols also have an associated natural +% language concept, and we want to use the symbol name to reference it (instead of +% specifying |cd| and |name| which is more inconvenient). For this the |statements| +% package supplies the \DescribeMacro{\symref}|\symref| macro. Like |\termref|, and +% invocation of |\symref{|\meta{cseq}|}{|\meta{text}|}| will just typeset \meta{text} with +% a hyperlink to the relevant definition (i.e. the one that has the declaration +% |for=|\meta{cseq} in the metadata argument.) +% +% \section{Configuration}\label{sec:user:rest} +% +% \DescribeMacro{\defemph} The |\defemph| macro is a configuration hook that allows to +% specify the style of presentation of the {\index*{definiendum}}. By default, it is set to +% |\bf| as a fallback, since we can be sure that this is always available. It can be +% customized by redefinition: For instance |\renewcommand{\defemph}[1]{\emph{#1}}|, +% changes the default behavior to italics. +% +% \DescribeMacro{\termemph} The |\termenph| macro does the same for the style for +% |\termin|, it is empty by default. Note the term might carry an implicit hyper-reference +% to the defining occurrence and that the presentation engine might mark this up, changing +% this behavior. +% +% \DescribeMacro{\stDMemph} The |\stDMemph| macro does the same for the style for the +% markup of the discourse markers like ``Theorem''. If it is not defined, it is set to +% |\bf|; that allows to preset this in the class file. \ednote{function declarations} +% +% Some authors like to lowercase the semantic references, i.e. use ``axiom 2.6'' instead +% of the default ``\sref{peano.P5}'' to refer to the last axiom in +% Figure~\ref{fig:axioms}. This can be achieved by redefining the +% \DescribeMacro{\STpresent}|\STpresent| macro, which is applied to the keyword of the +% |ST*Env| theorem environments.\ednote{this does not quite work as yet, since +% \textbf{STpresent} is applied when the label is written. But we would really like to +% have it applied when the reference is constructed. But for that we need to split the +% label into keyword and number in package |sref|.} +% +% Finally, we provide configuration hooks in Figure~\ref{fig:hooks} for the statement +% types provided by the |statement| package. 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{statements-babel} in the future.}. +%\begin{exfig} +% \begin{tabular}{lll} +% Environment & configuration macro & value\\\hline\hline +% \texttt{STtheoremAssEnv} & \texttt{\textbackslash st@theorem@kw} & \makeatletter\st@theorem@kw\\\hline +% \texttt{STlemmaAssEnv} & \texttt{\textbackslash st@lemma@kw} & \makeatletter\st@lemma@kw \\\hline +% \texttt{STpropositionAssEnv} & \texttt{\textbackslash st@proposition@kw} & \makeatletter\st@proposition@kw \\\hline +% \texttt{STcorollaryAssEnv} & \texttt{\textbackslash st@corollary@kw} & \makeatletter\st@corollary@kw\\\hline +% \texttt{STconjectureAssEnv} & \texttt{\textbackslash st@conjecture@kw} & \makeatletter\st@conjecture@kw\\\hline +% \texttt{STfalseconjectureAssEnv} & \texttt{\textbackslash st@falseconjecture@kw} & \makeatletter\st@falseconjecture@kw\\\hline +% \texttt{STpostulateAssEnv} & \texttt{\textbackslash st@postulate@kw} & \makeatletter\st@postulate@kw\\\hline +% \texttt{STobligationAssEnv} & \texttt{\textbackslash st@obligation@kw} & \makeatletter\st@obligation@kw\\\hline +% \texttt{STassumptionAssEnv} & \texttt{\textbackslash st@assumption@kw} & \makeatletter\st@assumption@kw\\\hline +% \texttt{STobservationAssEnv} & \texttt{\textbackslash st@observation@kw} & \makeatletter\st@observation@kw\\\hline +% \texttt{STexampleEnv} & \texttt{\textbackslash st@example@kw} & \makeatletter\st@example@kw\\\hline +% \texttt{STaxiomEnv} & \texttt{\textbackslash st@axiom@kw} & \makeatletter\st@axiom@kw\\\hline +% \texttt{STdefinitionEnv} & \texttt{\textbackslash st@definition@kw} & \makeatletter\st@definition@kw\\\hline +% \texttt{STnotationEnv} & \texttt{\textbackslash st@notation@kw} & \makeatletter\st@notation@kw +% \end{tabular} +% \caption{Configuration Hooks for statement types}\label{fig:hooks} +% \end{exfig} +% +% \StopEventually{\newpage\PrintIndex\newpage\PrintChanges\printbibliography} +% +% \section{The Implementation}\label{sec:impl} +% +% The |statements| package generates two files: the {\LaTeX} package (all the code between +% {\textsf{$\langle$*package$\rangle$}} and {\textsf{$\langle$/package$\rangle$}}) and the +% {\latexml} bindings (between {\textsf{$\langle$*ltxml$\rangle$ and +% $\langle$/ltxml$\rangle$}}). We keep the corresponding code fragments together, +% since the documentation applies to both of them and to prevent them from getting out of +% sync. +% +% 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). First we have the general options +% \begin{macrocode} +%<*package> +\DeclareOption*{\PassOptionsToPackage{\CurrentOption}{omdoc}} +% \end{macrocode} +% Finally, we need to declare the end of the option declaration section to {\LaTeX}. +% \begin{macrocode} +\ProcessOptions +%</package> +% \end{macrocode} +% +% The next measure is to ensure that some {\sTeX} packages are loaded: |omdoc| for the +% statement keys, |modules| since we need module identifiers for referencing. Furthermore, +% we need the |ntheorem| package for presenting statements. For {\latexml}, we also +% initialize the package inclusions, there we do not need |ntheorem|, since the XML does +% not do the presentation. +% \begin{macrocode} +%<*package> +\RequirePackage{omtext} +\RequirePackage{modules} +\RequirePackage[hyperref]{ntheorem} +\theoremstyle{plain} +%</package> +%<*ltxml> +# -*- CPERL -*- +package LaTeXML::Package::Pool; +use strict; +use LaTeXML::Package; +RequirePackage('omtext'); +RequirePackage('modules'); +%</ltxml> +% \end{macrocode} +% Now, we define an auxiliary function that lowercases strings +% \begin{macrocode} +%<*ltxml> +sub lowcase {my ($string) = @_; $string ? return lc(ToString($string)) : return('')}#$ +sub dashed { join('-',map($_->toString,@_));}#$ +%</ltxml> +% \end{macrocode} +% Sometimes it is necessary to fallback to symbol names in order to generate xml:id attributes. For this purpose, +% we define an auxiliary function which ensures the name receives a unique NCName equivalent.\ednote{Hard to be unique here, +% e.g. the names "foo\_bar" and "foo bar" would receive the same xml:id attributes... of course we can devise a more complex scheme +% for the symbol replacement.} +% \begin{macrocode} +%<*ltxml> +sub makeNCName { + my ($name) = @_; + my $ncname=$name; + $ncname=~s/\s/_/g; #Spaces to underscores + $ncname="_$ncname" if $ncname!~/^(\w|_)/; #Ensure start with letter or underscore + ##More to come... + $ncname; +} +%</ltxml> +% \end{macrocode} +% The following functions are strictly utility functions that makes our life easier later on +% \begin{macrocode} +%<*ltxml> +sub simple_wrapper { + my @input = @_; + return '' if (!@input); + @input = map(split(/\s*,\s*/,$_->toString),@input); + my $output=join(" ",@input); + $output=~s/(^ )|[{}]//g; #remove leading space and list separator brackets + $output||''; +} +sub hash_wrapper{ + my @input = @_; + return '' if (!@input); + @input = map(split(/\s*,\s*/,$_->toString),@input); + my $output=join(".sym #",@input); + $output=~s/(^\.sym )|[{}]//g; #remove leading space and list separator brackets + "#$output"||''; +} +%</ltxml> +% \end{macrocode} +% +% \subsection{Statements}\label{sec:impl:statements} +% +% \begin{macro}{\STpresent} +% \begin{macrocode} +%<*package> +\def\STpresent#1{#1} +%</package> +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\define@statement@env} +% We define a meta-macro that allows us to define several variants of statements. Upon +% beginning this environment, we first set the |KeyVal| attributes, then we decide +% whether to print the discourse marker based on the value of the |display| key, then +% (given the right Options were set), we show the semantic annotations, and finally +% initialize the environment using the appropriate macro. Upon ending the environment, +% we just run the respective termination macro. +% \begin{macrocode} +%<*package> +\def\define@statement@env#1{% +\newenvironment{#1}[1][]{\omdsetkeys{omtext}{##1}\sref@target% +\ifx\omtext@display\st@flow\else% +\ifx\omtext@title\@empty\begin{ST#1Env}\else\begin{ST#1Env}[\omtext@title]\fi% +\ifx\sref@id\@empty\else\label{#1.\sref@id}\fi +\csname st@#1@initialize\endcsname\fi +\ifx\sref@id\@empty\sref@label@id{here}\else% +\sref@label@id{\STpresent{\csname ST#1EnvKeyword\endcsname}~\@currentlabel}\fi} +{\csname st@#1@terminate\endcsname\ifx\omtext@display\st@flow\else\end{ST#1Env}\fi}} +%</package> +% \end{macrocode} +% \end{macro} +% +% \begin{environment}{assertion} +% \begin{macrocode} +%<*package> +\newenvironment{assertion}[1][]{\omdsetkeys{omtext}{#1}\sref@target% +\ifx\omtext@display\st@flow\else% +\ifx\omtext@title\@empty\begin{ST\omtext@type AssEnv}% +\else\begin{ST\omtext@type AssEnv}[\omtext@title]\fi\fi% +\ifx\omtext@type\@empty\sref@label@id{here}\else% +\sref@label@id{\STpresent{\csname ST\omtext@type AssEnvKeyword\endcsname}~\@currentlabel}\fi} +{\ifx\omtext@display\st@flow\else\end{ST\omtext@type AssEnv}\fi} +%</package> +%<*ltxml> +DefCMPEnvironment('{assertion} OptionalKeyVals:omtext', + "<omdoc:assertion " + . "?&KeyVal(#1,'id')(xml:id='&KeyVal(#1,'id')')() " + . "?&KeyVal(#1,'theory')(theory='&KeyVal(#1,'theory')')() " + . "type='&lowcase(&KeyVal(#1,'type'))'>" + . "?&KeyVal(#1,'title')(<dc:title>&KeyVal(#1,'title')</dc:title>)()" + . "<omdoc:CMP><omdoc:p>#body" + ."</omdoc:assertion>\n"); +%</ltxml> +% \end{macrocode} +% \end{environment} +% +% \begin{macro}{\st@*@kw} +% We configure the default keywords for the various theorem environments. +% \begin{macrocode} +%<*package> +\def\st@theorem@kw{Theorem} +\def\st@lemma@kw{Lemma} +\def\st@proposition@kw{Proposition} +\def\st@corollary@kw{Corollary} +\def\st@conjecture@kw{Conjecture} +\def\st@falseconjecture@kw{Conjecture (false)} +\def\st@postulate@kw{Postulate} +\def\st@obligation@kw{Obligation} +\def\st@assumption@kw{Assumption} +\def\st@observation@kw{Observation} +% \end{macrocode} +% \end{macro} +% Then we configure the presentation of the theorem environments +% \begin{macrocode} +\theorembodyfont{\itshape} +\theoremheaderfont{\normalfont\bfseries} +% \end{macrocode} +% and then we finally define the theorem environments in terms of the statement keywords +% defined above. They are all numbered together with the section counter. +% \begin{environment}{ST*AssEnv} +% \begin{macrocode} +\newtheorem{STtheoremAssEnv}{\st@theorem@kw} +\newtheorem{STlemmaAssEnv}[STtheoremAssEnv]{\st@lemma@kw} +\newtheorem{STpropositionAssEnv}[STtheoremAssEnv]{\st@proposition@kw} +\newtheorem{STcorollaryAssEnv}[STtheoremAssEnv]{\st@corollary@kw} +\newtheorem{STconjectureAssEnv}[STtheoremAssEnv]{\st@conjecture@kw} +\newtheorem{STfalseconjectureAssEnv}[STtheoremAssEnv]{\st@falseconjecture@kw} +\newtheorem{STpostulateAssEnv}[STtheoremAssEnv]{\st@postulate@kw} +\newtheorem{STobligationAssEnv}[STtheoremAssEnv]{\st@obligation@kw} +\newtheorem{STassumptionAssEnv}[STtheoremAssEnv]{\st@assumption@kw} +\newtheorem{STobservationAssEnv}[STtheoremAssEnv]{\st@observation@kw} +%</package> +% \end{macrocode} +% \end{environment} +% +% \begin{environment}{example} +% \begin{macrocode} +%<*package> +\def\st@example@initialize{}\def\st@example@terminate{} +\define@statement@env{example} +\def\st@example@kw{Example} +\theorembodyfont{\upshape} +\newtheorem{STexampleEnv}[STtheoremAssEnv]{\st@example@kw} +%</package> +%<*ltxml> +DefCMPEnvironment('{example} OptionalKeyVals:omtext', + "<omdoc:example " + . "?&KeyVal(#1,'id')(xml:id='&KeyVal(#1,'id')')() " + . "?&KeyVal(#1,'for')(for='&hash_wrapper(&KeyVal(#1,'for'))')()>" + . "<omdoc:CMP><omdoc:p>#body" + . "</omdoc:example>\n"); +%</ltxml> +% \end{macrocode} +% \end{environment} +% +% \begin{environment}{axiom} +% \begin{macrocode} +%<*package> +\def\st@axiom@initialize{}\def\st@axiom@terminate{} +\define@statement@env{axiom} +\def\st@axiom@kw{Axiom} +\theorembodyfont{\upshape} +\newtheorem{STaxiomEnv}[STtheoremAssEnv]{\st@axiom@kw} +%</package> +%<*ltxml> +DefCMPEnvironment('{axiom} OptionalKeyVals:omtext', + "<omdoc:axiom " + . "?&KeyVal(#1,'id')(xml:id='&KeyVal(#1,'id')')()>" + . "?&KeyVal(#1,'title')(<dc:title>&KeyVal(#1,'title')</dc:title>)()" + . "<omdoc:CMP><omdoc:p>#body" + . "</omdoc:axiom>\n"); +%</ltxml> +% \end{macrocode} +% \end{environment} +% +% \begin{environment}{symboldec} +% \begin{macrocode} +%<*package> +\srefaddidkey{symboldec} +\omdaddkey{symboldec}{functions} +\omdaddkey{symboldec}{role} +\omdaddkey{symboldec}{title} +\omdaddkey{symboldec}{name} +\omdaddkey{symboldec}{display} +\def\symboldec@type{Symbol} +\newenvironment{symboldec}[1][]{\omdsetkeys{symboldec}{#1}\sref@target +\ifx\symboldec@display\st@flow\else{\stDMemph{\symboldec@type} \symboldec@name:}\fi% +\ifx\symboldec@title\@empty~\else~(\stDMemph{\symboldec@title})\par\fi}{} +%</package> +%<*ltxml> +DefEnvironment('{symboldec} OptionalKeyVals:symboldec', + "<omdoc:symbol " + . " ?&KeyVal(#1,'id')(xml:id='&KeyVal(#1,'id')')" + . "(xml:id='&makeNCName(&KeyVal(#1,'name')).def.sym')" + . "name='&KeyVal(#1,'name')'>" + . "<dc:description>#body</dc:description>" + ."</omdoc:symbol>\n"); +%</ltxml> +% \end{macrocode} +% \end{environment} +% +% \begin{macro}{\symtype} +% \begin{macrocode} +%<*package> +\newcommand{\symtype}[2]{Type (#1): #2} +%</package> +%<*ltxml> +DefConstructor('\symtype{}{}', + "<omdoc:type system='#1'>#2</omdoc:type>"); +%</ltxml> +% \end{macrocode} +% \end{macro} +% +% \begin{environment}{definition} +% The |definition| environment itself is quite similar to the other's but we need to set +% the |\st@indef| switch to suppress warnings from |\st@def@target|. +% \begin{macrocode} +%<*package> +\newif\ifst@indef\st@indeffalse +\newenvironment{definition}[1][]{\omdsetkeys{omtext}{#1}\sref@target\st@indeftrue% +\ifx\omtext@display\st@flow\else% +\ifx\omtext@title\@empty\begin{STdefinitionEnv}\else\begin{STdefinitionEnv}[\omtext@title]\fi\fi% +\ifx\sref@id\@empty\sref@label@id{here}\else% +\sref@label@id{\STpresent{\csname STdefinitionEnvKeyword\endcsname}~\@currentlabel}\fi} +{\ifx\omtext@display\st@flow\else\end{STdefinitionEnv}\fi} +\def\st@definition@kw{Definition} +\theorembodyfont{\upshape} +\newtheorem{STdefinitionEnv}[STtheoremAssEnv]{\st@definition@kw} +%</package> +%<*ltxml> +sub definitionBody { + my ($doc, $keyvals, %props) = @_; + my $for = $keyvals->getValue('for') if $keyvals; + my $type = $keyvals->getValue('type') if $keyvals; + my %for_attr=(); + if (ToString($for)) { + $for = ToString($for); + $for =~ s/^{(.+)}$/$1/eg; + foreach (split(/,\s*/,$for)) { + $for_attr{$_}=1; + }} + my @symbols = @{$props{defs} || []}; + foreach my $symb(@symbols) { + next if $for_attr{$symb}; + $for_attr{$symb}=1; + $doc->insertElement('omdoc:symbol', undef, (name=>$symb, "xml:id"=>makeNCName("$symb.def.sym"))); + } + my %attrs = (); + $for = join(" ",(keys %for_attr)); + $attrs{'for'} = $for if $for; + my $id = $keyvals->getValue('id') if $keyvals; + $attrs{'xml:id'} = $id if $id; + $attrs{'type'} = $type if $type; + $doc->openElement('omdoc:definition', %attrs); + my $title = $keyvals->getValue('title') if $keyvals; + if ($title) { + $doc->openElement('omdoc:metadata'); + $doc->openElement('dc:title'); + $doc->absorb($title); + $doc->closeElement('dc:title');} + $doc->openElement('omdoc:CMP'); + $doc->openElement('omdoc:p'); + $doc->absorb($props{body}) if $props{body}; + $doc->maybeCloseElement('omdoc:p'); + $doc->maybeCloseElement('omdoc:CMP'); + $doc->closeElement('omdoc:definition'); + return; } +DefCMPEnvironment('{definition} OptionalKeyVals:omtext', sub{definitionBody(@_)}, + afterDigestBegin=>sub { + my ($stomach, $whatsit) = @_; + my @symbols = (); + $whatsit->setProperty(defs=>\@symbols); + AssignValue('defs', \@symbols); return; }, + afterDigest => sub { AssignValue('defs', undef); return; }); +%</ltxml> +% \end{macrocode} +% \end{environment} +% +% \begin{environment}{notation} +% We initialize the |\def\st@notation@initialize{}| here, and extend it with +% functionality below. +% \begin{macrocode} +%<*package> +\def\notemph#1{{\bf{#1}}} +\def\st@notation@terminate{} +\def\st@notation@initialize{} +\define@statement@env{notation} +\def\st@notation@kw{Notation} +\theorembodyfont{\upshape} +\newtheorem{STnotationEnv}[STtheoremAssEnv]{\st@notation@kw} +%</package> +%<*ltxml> +DefCMPEnvironment('{notation} OptionalKeyVals:omtext', + "<omdoc:definition " + . "?&KeyVal(#1,'id')(xml:id='&KeyVal(#1,'id').not')()" + . "?&KeyVal(#1,'for')(for='&simple_wrapper(&KeyVal(#1,'for'))')()>" + . "?&KeyVal(#1,'title')(<dc:title>&KeyVal(#1,'title')</dc:title>)()" + . "<omdoc:CMP><omdoc:p>#body" + . "</omdoc:definition>\n"); +DefConstructor('\notatiendum OptionalKeyVals:notation {}', + "<omdoc:phrase type='notation'>#2</omdoc:phrase>"); +%</ltxml> +% \end{macrocode} +% \end{environment} +% +% \begin{macro}{\st@def@target} +% The next macro is a variant of the |\sref@target| macro provided by the |sref| package +% specialized for the use in the |\definiendum|, |\defin|, |\twindef|, and |\atwindef| +% macros. |\st@def@target{|\meta{opt}|}{|\meta{name}|}| makes a target with label +% |sref@|\meta{opt}|@|\meta{modulename}|@target|, if \meta{opt} is non-empty, else with +% the label |sref@|\meta{name}|@|\meta{modulename}|@target|. Also it generates the +% necessary warnings for a definiendum-like macro. +% \begin{macrocode} +%<*package> +\def\st@def@target#1#2{\def\@test{#1}% +\@ifundefined{mod@id}% +{\PackageError{statements}{definiendum in unidentified module}% +{\protect\definiendum, \protect\defin, +\protect\twindef, \protect\atwindef\MessageBreak +may only be called in a module with id key}}% +{\ifst@indef\else\PackageWarning{statements} + {definiendum outside definition context\MessageBreak +\protect\definiendum, \protect\defin, +\protect\twindef, \protect\atwindef\MessageBreak +do not make sense semantically outside a definition.\MessageBreak +Consider wrapping the defining phrase in a \protect\inlinedef}\fi +\ifx\@test\@empty% +\expandafter\sref@target@ifh{sref@#2@\mod@id @target}{}\else% +\expandafter\sref@target@ifh{sref@#1@\mod@id @target}{}\fi}} +%</package> +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\definiendum} +% The |\definiendum| and |\notatiendum| macros are very simple, but instead of defining +% them directly, we guard in the |\st@definition@initialize| macro so that they are +% local to the |definition| environment. +% \begin{macrocode} +%<*package> +\newcommand{\definiendum}[2][]{\st@def@target{#1}{#2}\defemph{#2}} +%</package> +%<*ltxml> +DefConstructor('\definiendum [] {}', + "<omdoc:term role='definiendum' name='#name' cd='#theory'>#2</omdoc:term>", + afterDigest => sub { + my ($stomach, $whatsit) = @_; + my $addr = LookupValue('defs'); + my $name = $whatsit->getArg(1); + $name = $whatsit->getArg(2) unless $name; + $whatsit->setProperty(name=>$name->toString); + push(@$addr, $name->toString) if ($addr and $name); + $whatsit->setProperty(theory=>LookupValue('current_module')); + return; });#$ +%</ltxml> +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\notatiendum} +% the |notatiendum| macro also needs to be visible in the |notation| and |definition| +% environments +% \begin{macrocode} +%<*package> +\newcommand{\notatiendum}[2][]{\notemph{#2}} +%</package> +% \end{macrocode} +% \end{macro} +% +% We expand the {\latexml} bindings for |\defin|, |\twindef| and |\atwindef| into two +% instances one will be used for the definition and the other for indexing. +% +% \begin{macro}{\defin} +% \begin{macrocode} +%<*package> +\newcommand{\defin}[2][]{\definiendum[#1]{#2}\omdoc@index[#1]{#2}} +%</package> +%<*ltxml> +DefConstructor('\defin[]{}', + "<omdoc:idx>" + . "<omdoc:idt>" + . "<omdoc:term role='definiendum' name='?#1(#1)(#2)' cd='#theory'>#2</omdoc:term>" + . "</omdoc:idt>" + . "<omdoc:ide index='default'><omdoc:idp>#2</omdoc:idp></omdoc:ide>" + ."</omdoc:idx>", + afterDigest => sub { + my ($stomach, $whatsit) = @_; + my $addr = LookupValue('defs'); + my $name = $whatsit->getArg(1); + $name = $whatsit->getArg(2) unless $name; + push(@$addr, $name->toString) if ($addr and $name); + $whatsit->setProperty(theory=>LookupValue('current_module'));#$ + return; }, + alias=>'\defin'); +%</ltxml> +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\definalt} +% \begin{macrocode} +%<*package> +\newcommand{\definalt}[3][]{\definiendum[#1]{#2}\omdoc@index[#1]{#3}} +%</package> +%<*ltxml> +DefConstructor('\definalt[]{}{}', + "<omdoc:idx>" + . "<omdoc:idt>" + . "<omdoc:term role='definiendum' name='?#1(#1)(#3)' cd='#theory'>#2</omdoc:term>" + . "</omdoc:idt>" + . "<omdoc:ide index='default'><omdoc:idp>#3</omdoc:idp></omdoc:ide>" + ."</omdoc:idx>", + afterDigest => sub { + my ($stomach, $whatsit) = @_; + my $addr = LookupValue('defs'); + my $name = $whatsit->getArg(1); + $name = $whatsit->getArg(3) unless $name; + push(@$addr, $name->toString) if ($addr and $name); + $whatsit->setProperty(theory=>LookupValue('current_module'));#$ + return; }, + alias=>'\definalt'); +%</ltxml> +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\twindef} +% \begin{macrocode} +%<*package> +\newcommand{\twindef}[3][]{\st@def@target{#1}{#2-#3}\defemph{#2 #3}\@twin[#1]{#2}{#3}} +%</package> +%<*ltxml> +DefConstructor('\twindef[]{}{}', + "<omdoc:idx>" + . "<omdoc:idt>" + . "<omdoc:term role='definiendum' name='?#1(#1)(&dashed(#2,#3))' cd='#theory'>" + . "#2 #3" + . "</omdoc:term>" + . "</omdoc:idt>" + . "<omdoc:ide index='default'>" + . "<omdoc:idp>#2</omdoc:idp>" + . "<omdoc:idp>#3</omdoc:idp>" + . "</omdoc:ide>" + ."</omdoc:idx>", + afterDigest => sub { + my ($stomach, $whatsit) = @_; +my $addr = LookupValue('defs'); + my $name = $whatsit->getArg(1); + $name = $name->toString if $name; + $name = $whatsit->getArg(2)->toString.'-'.$whatsit->getArg(3)->toString unless $name; + push(@$addr, $name) if ($addr and $name); + $whatsit->setProperty(theory=>LookupValue('current_module')); + return; }, + alias=>'\twindef');#$ +%</ltxml> +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\twindefalt} +% \begin{macrocode} +%<*package> +\newcommand{\twindefalt}[4][]{\definiendum[#1]{#2}\@twin[#1]{#3}{#4}} +%</package> +%<*ltxml> +DefConstructor('\twindefalt[]{}{}{}', + "<omdoc:idx>" + . "<omdoc:idt>" + . "<omdoc:term role='definiendum' name='?#1(#1)(&dashed(#3,#4))' cd='#theory'>" + . "#2" + . "</omdoc:term>" + . "</omdoc:idt>" + . "<omdoc:ide index='default'>" + . "<omdoc:idp>#3</omdoc:idp>" + . "<omdoc:idp>#4</omdoc:idp>" + . "</omdoc:ide>" + ."</omdoc:idx>", + afterDigest => sub { + my ($stomach, $whatsit) = @_; + my $addr = LookupValue('defs'); + my $name = $whatsit->getArg(1); + $name = $name->toString if $name; + $name = $whatsit->getArg(3)->toString.'-'.$whatsit->getArg(4)->toString unless $name; + push(@$addr, $name) if ($addr and $name); + $whatsit->setProperty(theory=>LookupValue('current_module')); + return; }, + alias=>'\twindef');#$ +%</ltxml> +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\atwindef} +% \begin{macrocode} +%<*package> +\newcommand{\atwindef}[4][]{\st@def@target{#1}{#2-#3-#4}\defemph{#2 #3 #4}\@atwin[#1]{#2}{#3}{#4}} +%</package> +%<*ltxml> +DefConstructor('\atwindef[]{}{}{}', + "<omdoc:idx>" + . "<omdoc:idt>" + . "<omdoc:term role='definiendum' cd='#theory' name='?#1(#1)(&dashed(#2,#3,#4))'>#2 #3 #4</omdoc:term>" + . "</omdoc:idt>" + . "<omdoc:ide index='default'>" + . "<omdoc:idp>#2</omdoc:idp>" + . "<omdoc:idp>#3</omdoc:idp>" + . "<omdoc:idp>#4</omdoc:idp>" + . "</omdoc:ide>" + . "</omdoc:idx>", + afterDigest => sub { + my ($stomach, $whatsit) = @_; + my $addr = LookupValue('defs'); + my $name = $whatsit->getArg(1); + $name = $name->toString if $name; + $name = $whatsit->getArg(2)->toString.'-'.$whatsit->getArg(3)->toString.'-'.$whatsit->getArg(4)->toString unless $name; + push(@$addr, $name) if ($addr and $name); + $whatsit->setProperty(theory=>LookupValue('current_module')); + return; }, + alias=>'\atwindef'); +%</ltxml> +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\atwindefalt} +% \begin{macrocode} +%<*package> +\newcommand{\atwindefalt}[5][]{\definiendum[#1]{#2}\@atwin[#1]{#3}{#4}{#5}} +%</package> +%<*ltxml> +DefConstructor('\atwindefalt[]{}{}{}{}', + "<omdoc:idx>" + . "<omdoc:idt>" + . "<omdoc:term role='definiendum' cd='#theory' name='?#1(#1)(&dashed(#3,#4,#5))'>#2</omdoc:term>" + . "</omdoc:idt>" + . "<omdoc:ide index='default'>" + . "<omdoc:idp>#3</omdoc:idp>" + . "<omdoc:idp>#4</omdoc:idp>" + . "<omdoc:idp>#5</omdoc:idp>" + . "</omdoc:ide>" + . "</omdoc:idx>", + afterDigest => sub { + my ($stomach, $whatsit) = @_; + my $addr = LookupValue('defs'); + my $name = $whatsit->getArg(1); + $name = $name->toString if $name; + $name = $whatsit->getArg(3)->toString.'-'.$whatsit->getArg(4)->toString.'-'.$whatsit->getArg(5)->toString unless $name; + push(@$addr, $name) if ($addr and $name); + $whatsit->setProperty(theory=>LookupValue('current_module')); + return; }, + alias=>'\atwindef'); +%</ltxml> +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\inlinedef} +% \begin{macrocode} +%<*package> +\newcommand{\inlinedef}[2][]{\omdsetkeys{omtext}{#1}\sref@target\sref@label@id{here}\st@indeftrue #2} +%</package> +%<*ltxml> +DefConstructor('\inlinedef OptionalKeyVals:omtext {}', sub { + my ($document, $keyvals, $body, %props) = @_; + my $for = $keyvals->getValue('for') if $keyvals; + my %for_attr=(); + if (ToString($for)) { + $for = ToString($for); + $for =~ s/^{(.+)}$/$1/eg; + foreach (split(/,\s*/,$for)) { + $for_attr{$_}=1; + }} + my @symbols = @{$props{defs} || []}; + #Prepare for symbol insertion -insert before the parent of the closest ancestor CMP element + my $original_node = $document->getNode; + my $xc = XML::LibXML::XPathContext->new( $original_node ); + $xc->registerNs('omdoc', 'http://omdoc.org/ns'); + my ($statement_ancestor) = $xc->findnodes('./ancestor::omdoc:CMP/..'); + foreach my $symb(@symbols) { + next if $for_attr{$symb}; + $for_attr{$symb}=1; + my $symbolnode = XML::LibXML::Element->new('symbol'); + $symbolnode->setAttribute(name=>$symb); + $symbolnode->setAttribute("xml:id"=>makeNCName("$symb.def.sym")); + $statement_ancestor->parentNode->insertBefore($symbolnode,$statement_ancestor); + } + #Restore the insertion point + $document->setNode($original_node); + my %attrs = (); + $for = join(" ",(keys %for_attr)); + $attrs{'for'} = $for if $for; + my $id = $keyvals->getValue('id') if $keyvals; + $attrs{'xml:id'} = $id if $id; + $attrs{'type'} = 'inlinedef'; + $document->openElement('omdoc:phrase',%attrs); + $document->absorb($body); + $document->closeElement('omdoc:phrase'); }, + #Prepare 'defs' hooks for \defin and \definiendum symbol names + beforeDigest=>sub { + my @symbols = (); + AssignValue('defs', \@symbols); return; }, + #Adopt collected names as 'defs' property, remove hooks + afterDigest=>sub { + my ($stomach, $whatsit) = @_; + my $defsref = LookupValue('defs'); + my @defs = @$defsref; + $whatsit->setProperty('defs',\@defs); + AssignValue('defs',undef); + return; }); +%</ltxml> +% \end{macrocode} +% \end{macro} +% +% \subsection{Cross-Referencing Symbols and Concepts}\label{sec:impl:crossref} +% +% \begin{macro}{\termref@set} +% The |term| macro uses the |cd| and |name| keys for hyperlinking to create hyper-refs, +% if the |hyperref| package is loaded: We first see if the |cd| key was given, if not we +% define it as the local module identifier. +% \begin{macrocode} +%<*package> +\omdaddkey[\mod@id]{termref}{cd} +\omdaddkey{termref}{cdbase} +\omdaddkey{termref}{name} +\omdaddkey{termref}{role} +\def\termref@set#1#2{\def\termref@name{#2}\omdsetkeys{termref}{#1}} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\termref} +% \begin{macrocode} +\newcommand{\termref}[2][]{\omdsetkeys{termref}{#1}\st@termref{#2}} +%</package> +%<*ltxml> +DefConstructor('\termref OptionalKeyVals:termref {}', + "<omdoc:term cd='&KeyVal(#1,'cd')' name='&KeyVal(#1,'name')'>" + . "#2" + ."</omdoc:term>"); +%</ltxml> +% \end{macrocode} +% \end{macro} +% The next macro is where the actual work is done. +% \begin{macro}{\st@termref} +% We determine whether the macro \meta{module}|@cd@file@base| is defined. If it is, we +% make the prefix of a URI reference in the local macro |\@uri|, which we compose to the +% hyper-reference. +% \begin{macrocode} +%<*package> +\def\st@termref#1{\ifx\termref@name\@empty\def\termref@name{#1}\fi% +\mod@termref\termref@cd\termref@name{#1}} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\twinref} +% \begin{macrocode} +\newcommand{\twinref}[3][]{\termref@set{#1}{#2-#3}\st@termref{#2 #3}} +%</package> +%<*ltxml> +DefConstructor('\twinref OptionalKeyVals:termref {}{}', + "<omdoc:term cd='&KeyVal(#1,'cd')' name='&KeyVal(#1,'name')'>" + . "#2" + ."</omdoc:term>"); +%</ltxml> +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\atwinref} +% \begin{macrocode} +%<*package> +\newcommand{\atwinref}[4][]{\termref@set{#1}{#2-#3-#4}\st@termref{#2 #3 #4}} +%</package> +%<*ltxml> +DefConstructor('\atwinref OptionalKeyVals:termref {}{}{}', + "<omdoc:term cd='&KeyVal(#1,'cd')' name='&KeyVal(#1,'name')'>" + . "#2" + ."</omdoc:term>"); +%</ltxml> +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\termin} +% The |termin| macro is very simple, it just adds an index. +% \begin{macrocode} +%<*package> +\newcommand{\termin}[2][]{\termref[#1]{#2}\index{#2}} +%</package> +%<*ltxml> +DefConstructor('\termin OptionalKeyVals:term {}', + "<omdoc:idx>" + . "<omdoc:idt>" + . "<omdoc:term cd='&KeyVal(#1,'cd')' name='&KeyVal(#1,'name')'>#2</omdoc:term>" + . "</omdoc:idt>" + . "<omdoc:ide index='default'><omdoc:idp>#2</omdoc:idp></omdoc:ide>" + . "</omdoc:idx>"); +%</ltxml> +% \end{macrocode} +% \end{macro} +% +% Now we care about the configuration switches, they are set to sensible values, if they +% are not defined already. These are just configuration parameters, which should not +% appear in documents, therefore we do not provide {\latexml} bindings for them. +% \begin{macro}{\*emph} +% \begin{macrocode} +%<*package> +\providecommand{\termemph}[1]{#1} +\providecommand{\defemph}[1]{{\textbf{#1}}} +\providecommand{\stDMemph}[1]{{\textbf{#1}}} +%</package> +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\symref} +% The |\symref| macros is quite simple, since we have done all the heavy lifting in the +% |modules| package: we simply apply |\mod@symref@|\meta{arg1} to +% \meta{arg2}. +% \begin{macrocode} +%<*package> +\newcommand{\symref}[2]{\@nameuse{mod@symref@#1}{#2}} +%</package> +%<*ltxml> +DefConstructor('\symref{}{}', + "<omdoc:term cd='&LookupValue('symdef.#1.cd')' name='&LookupValue('symdef.#1.name')'>" + . "#2" + ."</omdoc:term>"); +%</ltxml> +% \end{macrocode} +% \end{macro} +% +% \subsection{Providing IDs for {\omdoc} Elements}\label{sec:impl:ids} +% +% To provide default identifiers, we tag all {\omdoc} +% elements that allow |xml:id| attributes by executing the |numberIt| procedure from |omdoc.sty.ltxml|. +% +% \begin{macrocode} +%<*ltxml> +Tag('omdoc:assertion',afterOpen=>\&numberIt,afterClose=>\&locateIt); +Tag('omdoc:definition',afterOpen=>\&numberIt,afterClose=>\&locateIt); +Tag('omdoc:example',afterOpen=>\&numberIt,afterClose=>\&locateIt); +Tag('omdoc:requation',afterOpen=>\&numberIt,afterClose=>\&locateIt); +Tag('omdoc:axiom',afterOpen=>\&numberIt,afterClose=>\&locateIt); +Tag('omdoc:symbol',afterOpen=>\&numberIt,afterClose=>\&locateIt); +Tag('omdoc:type',afterOpen=>\&numberIt,afterClose=>\&locateIt); +Tag('omdoc:term',afterOpen=>\&numberIt,afterClose=>\&locateIt); +%</ltxml> +% \end{macrocode} +% +% \subsection{Finale} +% +% Finally, we need to terminate the file with a success mark for perl. +% \begin{macrocode} +%<ltxml>1; +% \end{macrocode} +% +% \Finale +% +\endinput +% \iffalse +% LocalWords: GPL structuresharing STR dtx keyval env envfalse idfalse idtrue +% LocalWords: displayfalse envtrue displaytrue forfalse typefalse titlefalse +% LocalWords: continuesfalse fortrue fromtrue typetrue titletrue CPERL omdoc +% LocalWords: continuestrue symboldec omtext RequirePackage lowcase lc ToString +% LocalWords: foreach hyperref href hlink DefCMPEnvironment OptionalKeyVals ne +% LocalWords: KeyVal xml CMP simpleDef PatternDef DefEnvironment PatternRule +% LocalWords: requation PatternCMP RecDef DefConstructor keyvals defs psymbols +% LocalWords: openElement symb closeElement ffor getValue attrs metadata undef +% LocalWords: afterDigestBegin setProperty AssignValue afterDigest definiendum +% LocalWords: cd addr LookupValue getArg toString idx idt definiendum ide idp +% LocalWords: DefMacro args unlist inlinedef uri pdf afterOpen numberIt texttt +% LocalWords: iffalse consymb ntheorem textbackslash symref def scsys sc sc kw +% LocalWords: mathml openmath latexml activemath fileversion maketitle stex +% LocalWords: setcounter tocdepth tableofcontents newpage sproofs ulsmf08 sref +% LocalWords: MaySch eltte09 twintoo sref subsubsection exfig vspace vspace +% LocalWords: noindent renewtheorem hline textbf textbf footnotesize ple peano +% LocalWords: STaxiomEnv symdef medskip succ mathbb ldots stepcounter ednote +% LocalWords: STtheoremAssEnv stepcounter STtheoremAssEnv stepcounter defin +% LocalWords: STtheoremAssEnv notatiendum defin smomdl biblatex twindef cdbase +% LocalWords: twindef atwindef atwindef adjectivized varaiants twindefalt cseq +% LocalWords: twindefalt atwindefalt atwindefalt csymbol definalt termref emph +% LocalWords: termref compactdesc KohAmb smmssl twinref atwinref newpart impl +% LocalWords: termdef defemph defemph renewcommand termemph termenph stDMemph +% LocalWords: stDMemph STpresent STpresent makeatletter STlemmaAssEnv textsf +% LocalWords: STpropositionAssEnv STcorollaryAssEnv STconjectureAssEnv langle +% LocalWords: STfalseconjectureAssEnv STpostulateAssEnv STobligationAssEnv foo +% LocalWords: STassumptionAssEnv STobservationAssEnv STexampleEnv textsf ltxml +% LocalWords: STdefinitionEnv STnotationEnv printbibliography langle ncname +% LocalWords: theoremstyle sym newenvironment omdsetkeys ifx csname endcsname +% LocalWords: currentlabel theorembodyfont itshape theoremheaderfont bfseries +% LocalWords: normalfont newtheorem upshape srefaddidkey omdaddkey symtype +% LocalWords: newcommand indef newif ifst indeffalse indeftrue attr whatsit +% LocalWords: STdefinitionEnvKeyword notemph modulename ifundefined atwin +% LocalWords: expandafter providecommand nameuse doctex ctancite funval + +%%% Local Variables: +%%% mode: doctex +%%% TeX-master: t +%%% End: +% \fi +% LocalWords: funsymbs findnodes symbolnode defsref |