summaryrefslogtreecommitdiff
path: root/Master/texmf-dist/source/latex/stex/omdoc.dtx
diff options
context:
space:
mode:
Diffstat (limited to 'Master/texmf-dist/source/latex/stex/omdoc.dtx')
-rw-r--r--Master/texmf-dist/source/latex/stex/omdoc.dtx775
1 files changed, 775 insertions, 0 deletions
diff --git a/Master/texmf-dist/source/latex/stex/omdoc.dtx b/Master/texmf-dist/source/latex/stex/omdoc.dtx
new file mode 100644
index 00000000000..6a38bcd0ade
--- /dev/null
+++ b/Master/texmf-dist/source/latex/stex/omdoc.dtx
@@ -0,0 +1,775 @@
+% \iffalse meta-comment
+% A LaTeX Class and Package for OMDoc Document Structures
+% Copyright (c) 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
+% https://svn.kwarc.info/repos/kwarc/projects/stex/sty/omdoc.dtx
+% \fi
+%
+% \iffalse
+%<package>\NeedsTeXFormat{LaTeX2e}[1999/12/01]
+%<package>\ProvidesPackage{omdoc}[2007/09/09 v0.3 OMDoc document Structure]
+%<cls>\NeedsTeXFormat{LaTeX2e}[1999/12/01]
+%<cls>\ProvidesClass{omdoc}[2007/09/09 v0.3 OMDoc Documents]
+%
+%<*driver>
+\documentclass{ltxdoc}
+\usepackage{url,array,omdoc,float}
+\usepackage[show]{ed}
+\usepackage{hyperref}
+\makeindex
+\floatstyle{boxed}
+\newfloat{exfig}{thp}{lop}
+\floatname{exfig}{Example}
+\begin{document}\DocInput{omdoc.dtx}\end{document}
+%</driver>
+% \fi
+%
+%\CheckSum{341}
+%
+% \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}
+%
+% \GetFileInfo{omdoc.sty}
+%
+% \MakeShortVerb{\|}
+%
+% \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\sTeX{{\raisebox{-.5ex}S\kern-.5ex\TeX}}
+% \def\omdoc{OMDoc}
+% \def\latexml{{\LaTeX}ML}
+% \title{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| packge 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 a the 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
+%
+%\section{Introduction}\label{sec:STR}
+%
+% The |omdoc| package supplies macros and environment that allow to label document
+% fragements and to reference them later in the same document or in other documents. In
+% essence, this enhances the docuent-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 conly 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).
+%
+% 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.}
+%
+% \section{The User Interface}\label{sec:user}
+%
+% \subsection{Document Structure}\label{sec:user:struct}
+%
+% \DescribeEnv{omgroup} The structure of the document is given by the |omgroup|
+% environment just like in {\omdoc}.
+%
+% \subsection{Providing IDs for {\omdoc} Elements}\label{sec:user:ids}
+%
+% Some of the {\omdoc} elements need IDs to function corrrectly. The general strategy here
+% is to equip the {\sTeX} macros with keys, so that the author can specify meaningful
+% ones, but to let the transformation give default ones if the author did not.
+%
+% \subsection{Mathematical Text}\label{sec:user:omtext}
+%
+% \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 rhethorical 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.\ednote{describe the keys more fully}
+%
+% \subsection{Structure Sharing}\label{sec:user: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}
+%
+% \subsection{Phrase-Level Markup}\label{sec:user:phrase}
+%
+% \DescribeEnv{phrase} The |phrase| enviornment allows to mark up phrases with semantic
+% information. It takes an optional |KeyVal| argument with the keys
+% \StopEventually{\ednotemessage}
+%
+% \section{Implementation: The OMDoc Class}\label{sec:impl:cls}
+%
+% We load |article.cls|, and the desired packages. For the {\latexml} bindings, we make
+% sure the right packages are loaded.
+% \begin{macrocode}
+%<*cls>
+\LoadClass{article}
+\RequirePackage{omdoc}
+%</cls>
+%<*ltxml.cls>
+# -*- CPERL -*-
+package LaTeXML::Package::Pool;
+use strict;
+use LaTeXML::Package;
+LoadClass('article');
+%</ltxml.cls>
+% \end{macrocode}
+% Now, we also need to register the namespace prefixes for {\latexml} to use.
+% \begin{macrocode}
+%<*ltxml.cls>
+RegisterNamespace('omdoc'=>"http://www.mathweb.org/omdoc"); # OMDoc namespace
+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");
+%</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('/Users/kohlhase/stex/rnc/omdoc+ltxml',
+ '#default'=>"http://www.mathweb.org/omdoc",
+ '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");
+%</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 need to provide with an identifier.\ednote{probably move to the
+% omdoc package}
+% \begin{macrocode}
+%<*ltxml.cls>
+DefEnvironment('{document}','<omdoc:omdoc>#body</omdoc:omdoc>',
+ beforeDigest=> sub { AssignValue(inPreamble=>0); },
+ afterDigest=> sub { $_[0]->getGullet->flush; return; });
+%</ltxml.cls>\iffalse$\fi
+% \end{macrocode}
+%
+% \section{Implementation: OMDoc Package}\label{sec:impl:sty}
+% We first need to set up the packages by requiring the |KeyVal| package to be loaded (in
+% the ritht version).
+%
+% \begin{macrocode}
+%<package>\RequirePackage{keyval}[1997/11/10]
+%<*ltxml.sty>
+package LaTeXML::Package::Pool;
+use strict;
+use LaTeXML::Package;
+RequirePackage('keyval');
+%</ltxml.sty>
+% \end{macrocode}
+%
+% \subsection{Document Structure}\label{sec:impl:struct}
+%
+% 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{macrocode}
+%<*package>
+\define@key{omgroup}{id}{\label{#1}}
+\define@key{omgroup}{type}{\def\omgroup@type{#1}}
+\define@key{omgroup}{display}{\def\omgroup@display{#1}}
+\def\omgroup@flow{flow}
+\newcount\section@level\section@level=1
+\newenvironment{omgroup}[2][]% title
+{\setkeys{omgroup}{#1}
+\ifx\omgroup@display\omgroup@flow{#2}\else
+\ifnum\section@level=1\section{#2}\fi
+\ifnum\section@level=2\subsection{#2}\fi
+\ifnum\section@level=3\subsubsection{#2}\fi
+\ifnum\section@level=4\paragraph{#2}\fi
+\advance\section@level by 1\fi}{}
+\def\tgroup{\omgroup}\def\endtgroup{\endomgroup}
+%</package>
+%<*ltxml.sty>
+DefKeyVal('omgroup','id','Semiverbatim');
+DefKeyVal('omgroup','type','Semiverbatim');
+DefKeyVal('omgroup','display','Semiverbatim');
+DefEnvironment('{omgroup} OptionalKeyVals:omgroup {}',
+ "<omdoc:omgroup ?&KeyVal(#1,'id')(xml:id='#1')() ?&KeyVal(#1,'type')(type='#1')()>\n"
+ . "?#1(<omdoc:metadata><dc:title>#1</dc:title></omdoc:metadata>\n)()"
+ . "#body\n"
+ . "</omdoc:omgroup>");
+
+DefEnvironment('{tgroup} OptionalKeyVals:omgroup {}',
+ "<omdoc:tgroup ?&KeyVal(#1,'id')(xml:id='#1')() ?&KeyVal(#1,'type')(type='#1')()>\n"
+ . "?#1(<omdoc:metadata><dc:title>#1</dc:title></omdoc:metadata>\n)()"
+ . "#body\n"
+ . "</omdoc:tgroup>");
+%</ltxml.sty>
+% \end{macrocode}
+%
+%
+% the |itemize|, |description|, and |enumerate| environments do double duty in OMDoc,
+% \begin{enumerate}
+% \item outside a |CMP| they are transformed into a
+% |<omgroup type='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.
+% \item inside a |CMP|, they are transformed into |<ul>|, |<dl>|, and |<ol>| elements
+% like in html.
+% \item Outside a |CMP|, |\item| is turned into |\ignoe@item|
+% \end{enumerate}
+% \begin{macrocode}
+%<*ltxml.sty>
+DefParameterType('IfBeginFollows', sub {
+ my ($gullet) = @_;
+ $gullet->skipSpaces;
+ return 1 unless $gullet->ifNext(T_CS('\begin'));
+ return; },
+ reversion=>'', optional=>1);
+
+Let('\group@item@maybe@unwrap','\relax');
+
+DefMacro('\group@item[] IfBeginFollows', sub {
+ my($gullet,$tag,$needwrapper)=@_;
+ ( T_CS('\group@item@maybe@unwrap'),
+ ($needwrapper ? (Invocation(T_CS('\group@item@wrap'),$tag)->unlist) : ()) ); });
+
+DefConstructor('\group@item@wrap {}',
+ "<omdoc:omtext>"
+ . "?#1(<omdoc:metadata><dc:title>#1</dc:title></omdoc:metadata>)()"
+ . "<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',
+ "</omdoc:p></omdoc:CMP></omdoc:omtext>",
+ beforeDigest=>sub {
+ $_[0]->egroup;
+ Let('\group@item@maybe@unwrap','\relax'); });
+
+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' type='itemize'>#body</omdoc:omgroup>",
+ properties=>sub { beginItemize('itemize'); },
+ beforeDigestEnd=>sub { Digest(T_CS('\group@item@maybe@unwrap')); });
+DefEnvironment('{enumerate}',
+ "<omdoc:omgroup xml:id='#id' type='enumerate'>#body</omdoc:omgroup>",
+ properties=>sub { beginItemize('enumerate'); },
+ beforeDigestEnd=>sub { Digest(T_CS('\group@item@maybe@unwrap')); });
+DefEnvironment('{description}',
+ "<omdoc:omgroup xml:id='#id' type='description'>#body</omdoc:omgroup>",
+ properties=>sub { beginItemize('description'); },
+ beforeDigestEnd=>sub { Digest(T_CS('\group@item@maybe@unwrap')); });
+%</ltxml.sty>
+% \end{macrocode}
+%
+% Inside a |theory| element , use |tgroup| instead of |omgroup|, otherwise, same as default case
+%
+% \begin{macrocode}
+%<*ltxml.sty>
+Let('\tgroup@itemize@item'=>'\group@item');
+Let('\tgroup@enumerate@item'=>'\group@item');
+Let('\tgroup@description@item'=>'\group@item');
+
+DefEnvironment('{tgroup@itemize}',
+ "<omdoc:tgroup xml:id='#id' type='itemize'>#body</omdoc:tgroup>",
+ properties=>sub { beginItemize('tgroup@itemize'); },
+ beforeDigest=>sub { Let(T_CS('\end{itemize}') =>T_CS('\end{tgroup@itemize}')); },
+ beforeDigestEnd=>sub { Digest(T_CS('\group@item@maybe@unwrap')); });
+DefEnvironment('{tgroup@enumerate}',
+ "<omdoc:tgroup xml:id='#id' type='enumerate'>#body</omdoc:tgroup>",
+ properties=>sub { beginItemize('tgroup@enumerate'); },
+ beforeDigest=>sub{ Let(T_CS('\end{enumerate}') =>T_CS('\end{tgroup@enumerate}'));},
+ beforeDigestEnd=>sub { Digest(T_CS('\group@item@maybe@unwrap')); });
+DefEnvironment('{tgroup@description}',
+ "<omdoc:tgroup xml:id='#id' type='description'>#body</omdoc:tgroup>",
+ properties=>sub { beginItemize('tgroup@description'); },
+ beforeDigest=>sub{ Let(T_CS('\end{description}') =>T_CS('\end{tgroup@description}'));},
+ beforeDigestEnd=>sub { Digest(T_CS('\group@item@maybe@unwrap')); });
+
+sub useTheoryItemizations {
+ Let(T_CS('\begin{itemize}') =>T_CS('\begin{tgroup@itemize}'));
+ Let(T_CS('\begin{enumerate}') =>T_CS('\begin{tgroup@enumerate}'));
+ Let(T_CS('\begin{description}')=>T_CS('\begin{tgroup@description}'));
+ return; }
+%</ltxml.sty>
+% \end{macrocode}
+%
+% Inside a |CMP|, we generate |omdoc:li|, |omdoc:di| with |autoclose|
+%
+% \begin{macrocode}
+%<*ltxml.sty>
+DefConstructor('\CMP@itemize@item[]',
+ '<omdoc:li>'
+ . '?#1(<omdoc:metadata><dc:title>#1</dc:title></omdoc:metadata>)()',
+ properties=>sub{ RefStepItemCounter(); });
+
+DefConstructor('\CMP@enumerate@item[]',
+ '<omdoc:li>'
+ . '?#1(<omdoc:metadata><dc:title>#1</dc:title></omdoc:metadata>)()',
+ 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 xml:id='#id'>#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; }
+
+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.sty>
+% \end{macrocode}
+%
+% \subsection{Mathematical Text}\label{sec:impl:mtxt}
+%
+% 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.
+%
+% \begin{macrocode}
+%<*package>
+\define@key{stat}{id}{\def\st@id{#1}}
+\define@key{stat}{display}{\def\st@display{#1}}
+\define@key{stat}{for}{\def\stat@for{#1}}
+\define@key{stat}{from}{\def\stat@from{#1}}
+\define@key{stat}{type}{\def\stat@type{#1}}
+\define@key{stat}{title}{\def\stat@title{#1}}
+\define@key{stat}{continues}{\def\stat@continues{#1}}
+%</package>
+%<*ltxml.sty>
+DefKeyVal('stat','id','Semiverbatim');
+DefKeyVal('stat','for','Semiverbatim');
+DefKeyVal('stat','title','Semiverbatim');
+DefKeyVal('stat','from','Semiverbatim');
+DefKeyVal('stat','type','Semiverbatim');
+DefKeyVal('stat','display','Semiverbatim'); # not used at the moment
+%</ltxml.sty>
+% \end{macrocode}
+%
+% \begin{macro}{\show@st@keys@aux}
+% We now define a macro that shows the |st| keys, if in draft mode, they annotate the
+% document with key/value pairs.
+% \begin{macrocode}
+%<*package>
+\def\show@st@keys@aux{%
+\@ifundefined{st@id}{}{\ifst@id{id=\st@id},\fi}%
+\@ifundefined{st@display}{}{\ifst@display{display=\st@display}\fi}}
+\def\clear@st@keys{\let\st@id=\relax\let\st@display=\relax}
+%</package>
+% \end{macrocode}
+% \end{macro}
+% \begin{macro}{\show@stat@keys@aux}
+% we do the same for the |stat| keys.
+% \begin{macrocode}
+%<*package>
+\def\show@stat@keys@aux{%
+\@ifundefined{st@for}{}{\ifstat@for{for=\stat@for},\fi}%
+\@ifundefined{st@from}{}{\ifstat@from{from=\stat@from},\fi}%
+\@ifundefined{st@type}{}{\ifstat@type{type=\stat@type},\fi}%
+\@ifundefined{st@title}{}{\ifstat@title{title=\stat@title},\fi}%
+\@ifundefined{st@continues}{}{\ifstat@continues{continues=\stat@continues}\fi}}
+%</package>
+% \end{macrocode}
+% \end{macro}
+% \begin{macro}{\show@stat@keys}
+% and combine them, so that the code is more readable.
+% \begin{macrocode}
+%<*package>
+\def\show@stat@keys#1{\footnote{#1[\show@st@keys@aux\show@stat@keys@aux]}%
+\clear@st@keys\clear@stat@keys}
+\def\clear@stat@keys{\let\stat@for=\relax\let\stat@from=\relax%
+\let\stat@type=\relax\let\stat@title=\relax\let\stat@continues=\relax}
+%</package>
+% \end{macrocode}
+% \end{macro}
+%
+% \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}
+% \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.
+% \begin{macrocode}
+%<*package>
+\def\omtext@pre@skip{\smallskip}
+\def\omtext@post@skip{}
+\newenvironment{omtext}[1][]{\setkeys{stat}{#1}{% keyval args
+\def\lec#1{\@lec{#1}}% so the trailing \par does not get into the way
+\omtext@pre@skip\par\noindent
+\@ifundefined{stat@title}{}{\ifx\st@display\st@flow\else\stDMemph{\stat@title}:\fi}}
+\ifst@env\show@stat@keys{omtext:\stat@title}\fi
+\omtext@post@skip}{}
+%</package>
+%<*ltxml.sty>
+DefCMPEnvironment('{omtext} OptionalKeyVals:stat',
+ "<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')(<omdoc:metadata><dc:title>&KeyVal(#1,'title')</dc:title></omdoc:metadata>)()"
+ . "<omdoc:CMP><omdoc:p>#body</omdoc:p></omdoc:CMP>"
+ . "</omdoc:omtext>\n");
+%</ltxml.sty>
+% \end{macrocode}
+% \end{environment}
+%
+% We also make our life easier If defininig an environment that is
+% turned into something that contains |<CMP>|\meta{body}|</CMP>|, use this method instead
+% \begin{macrocode}
+%<*ltxml.sty>
+sub DefCMPEnvironment {
+ my ($proto, $replacement, %options) = @_;
+ my @before = $options{beforeDigest} ? ($options{beforeDigest}) : ();
+ push(@before, \&useCMPItemizations);
+ $options{beforeDigest} = \@before;
+ DefEnvironment($proto, $replacement, %options);
+}
+%</ltxml.sty>
+% \end{macrocode}
+%
+%
+% \subsection{Structure Sharing}\label{sec:impl:share}
+%
+% \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}{\@semantics}
+% if we have a presentation form and a semantic form, then we can use
+% \begin{macrocode}
+%<*package>
+\long\def\@semantics[#1]#2#3{#2\STRlabeldef{#1}{#2}}
+%</package>
+% \end{macrocode}
+% \end{macro}
+%
+% \begin{macro}{\STRlabeldef}
+% This is the macro that does the actual labelling. 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}
+%
+% \begin{macro}{\STRsemantics}
+% \ednote{some explanation here}
+% \begin{macrocode}
+%<*package>
+\def\STRsemantics{\@ifnextchar[\@semantics{\@semantics[]}}
+%</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}
+%
+% \subsection{Phrase-level Markup}
+%
+% \begin{environment}{phrase}
+% For the moment, we do disregard the most of the keys
+% \begin{macrocode}
+%<*package>
+\define@key{phrase}{id}{}
+\define@key{phrase}{style}{}
+\define@key{phrase}{class}{}
+\define@key{phrase}{index}{}
+\define@key{phrase}{verbalizes}{}
+\define@key{phrase}{type}{}
+\newenvironment{phrase}[1][]{\setkeys{phrase}{#1}}{}
+%</package>
+%<*ltxml.sty>
+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)>#body</omdoc:phrase>");
+%</ltxml.sty>
+% \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.sty>
+DefConstructor('\nlex{}',"<omdoc:phrase type='nlex'>#1</omdoc:phrase>");
+DefConstructor('\nlcex{}',"<omdoc:phrase type='nlcex'>#1</omdoc:phrase>");
+%</ltxml.sty>
+% \end{macrocode}
+% \end{environment}
+%
+% \begin{environment}{inlinequote}
+% \ednote{describe above}
+% \begin{macrocode}
+%<package>\def\inlinequote#1{``{\sl{#1}}''}
+%<ltxml.sty>DefConstructor('\inlinequote{}',"<omdoc:phrase type='inlinequote'>#1</omdoc:phrase>");
+% \end{macrocode}
+% \end{environment}
+%
+% \subsection{Colors}
+%
+% \begin{environment}{blue, red, green, magenta}
+% We will use the following abbreviations for colors from |color.sty|
+% \begin{macrocode}
+%<*package>
+\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}}
+%</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}
+%
+%
+% \subsection{{\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 |p| element for paragraphs inside |CMP|s. For that we have modified the
+% DTD only to allowed |p| elements in |CMP| (in particular no text). Then we instruct the
+% |\par| macro to close a |p| element if possible. The next |p| element is then opened
+% automatically, since we make |p| autoclose.
+% \begin{macrocode}
+%<*ltxml.sty>
+DefConstructor('\par',sub { $_[0]->maybeCloseElement('omdoc:p'); },alias=>"\\par\n");
+Tag('omdoc:p', autoClose=>1, autoOpen=>1);
+%</ltxml.sty>
+% \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.sty>
+DefConstructor('\omspace{}','');
+DefConstructor('\emph{}',"<omdoc:phrase class='emphasis'>#1</omdoc:phrase>");
+DefConstructor('\em',"<omdoc:phrase class='emphasis'>");
+Tag('omdoc:phrase', autoClose=>1);
+DefEnvironment('{center}','#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('{small}','#body');
+DefEnvironment('{footnotesize}','#body');
+DefEnvironment('{tiny}','#body');
+DefEnvironment('{scriptsize}','#body');
+DefConstructor('\LARGE','');
+DefConstructor('\Large','');
+DefConstructor('\large','');
+DefConstructor('\small','');
+
+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.sty>
+% \end{macrocode}
+%
+% \subsection{Providing IDs for {\omdoc} Elements}\label{sec:impl:ids}
+%
+% To provide default identifiers (see section~\ref{sec:user:ids}), we tag all {\omdoc}
+% elements that allow |xml:id| attributes by excuting the |numberIt| procedure below.
+%
+% \begin{macrocode}
+%<*ltxml.sty>
+Tag('omdoc:p',afterOpen=>\&numberIt);
+Tag('omdoc:omtext',afterOpen=>\&numberIt);
+Tag('omdoc:omgroup',afterOpen=>\&numberIt);
+Tag('omdoc:tgroup',afterOpen=>\&numberIt);
+Tag('omdoc:CMP',afterOpen=>\&numberIt);
+%</ltxml.sty>
+% \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.
+% \begin{macrocode}
+%<*ltxml.sty>
+sub numberIt {
+ my($document,$node,$whatsit)=@_;
+ my(@parents)=$document->findnodes('ancestor::*[@xml:id]',$node); # find 1st id'd parent.
+ 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; }
+%</ltxml.sty>
+% \end{macrocode}
+%
+% \subsection{Leftovers}
+%
+% \begin{macrocode}
+%<*ltxml.sty>
+DefConstructor('\url Semiverbatim',"<omdoc:link href='#1'>#1</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}
+% \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 tgroup
+% 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 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