% \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
%\NeedsTeXFormat{LaTeX2e}[1999/12/01]
%\ProvidesPackage{omdoc}[2007/09/09 v0.3 OMDoc document Structure]
%\NeedsTeXFormat{LaTeX2e}[1999/12/01]
%\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}
%
% \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}
%
%<*ltxml.cls>
# -*- CPERL -*-
package LaTeXML::Package::Pool;
use strict;
use LaTeXML::Package;
LoadClass('article');
%
% \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");
%
% \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");
%
% \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');
%
% \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}','#body',
beforeDigest=> sub { AssignValue(inPreamble=>0); },
afterDigest=> sub { $_[0]->getGullet->flush; return; });
%\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}
%\RequirePackage{keyval}[1997/11/10]
%<*ltxml.sty>
package LaTeXML::Package::Pool;
use strict;
use LaTeXML::Package;
RequirePackage('keyval');
%
% \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}
%
%<*ltxml.sty>
DefKeyVal('omgroup','id','Semiverbatim');
DefKeyVal('omgroup','type','Semiverbatim');
DefKeyVal('omgroup','display','Semiverbatim');
DefEnvironment('{omgroup} OptionalKeyVals:omgroup {}',
"\n"
. "?#1(#1\n)()"
. "#body\n"
. "");
DefEnvironment('{tgroup} OptionalKeyVals:omgroup {}',
"\n"
. "?#1(#1\n)()"
. "#body\n"
. "");
%
% \end{macrocode}
%
%
% the |itemize|, |description|, and |enumerate| environments do double duty in OMDoc,
% \begin{enumerate}
% \item outside a |CMP| they are transformed into a
% ||, where the text after the macros
% |\item| come to be the children. If that is only text, then it is enclosed in an
% ||, otherwise it is left as it is. The optional argument of the |\item|
% is transformed into the || of the generated |\item| element.
% \item inside a |CMP|, they are transformed into ||, ||, and || 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 {}',
""
. "?#1(#1)()"
. "",
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'); });
Let('group@item@maybe@unwrap','\relax');
Let('\itemize@item'=>'\group@item');
Let('\enumerate@item'=>'\group@item');
Let('\description@item'=>'\group@item');
DefEnvironment('{itemize}',
"#body",
properties=>sub { beginItemize('itemize'); },
beforeDigestEnd=>sub { Digest(T_CS('\group@item@maybe@unwrap')); });
DefEnvironment('{enumerate}',
"#body",
properties=>sub { beginItemize('enumerate'); },
beforeDigestEnd=>sub { Digest(T_CS('\group@item@maybe@unwrap')); });
DefEnvironment('{description}',
"#body",
properties=>sub { beginItemize('description'); },
beforeDigestEnd=>sub { Digest(T_CS('\group@item@maybe@unwrap')); });
%
% \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}',
"#body",
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}',
"#body",
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}',
"#body",
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; }
%
% \end{macrocode}
%
% Inside a |CMP|, we generate |omdoc:li|, |omdoc:di| with |autoclose|
%
% \begin{macrocode}
%<*ltxml.sty>
DefConstructor('\CMP@itemize@item[]',
''
. '?#1(#1)()',
properties=>sub{ RefStepItemCounter(); });
DefConstructor('\CMP@enumerate@item[]',
''
. '?#1(#1)()',
properties=>sub{ RefStepItemCounter(); });
DefConstructor('\CMP@description@item[]',
''
. '?#1(#1)()', # trust di and dt to autoclose
properties=>sub{ RefStepItemCounter(); });
DefEnvironment('{CMP@itemize}',
"#body",
properties=>sub { beginItemize('CMP@itemize'); },
beforeDigest=>sub { Let(T_CS('\end{itemize}') =>T_CS('\end{CMP@itemize}')); });
DefEnvironment('{CMP@enumerate}',
"#body",
properties=>sub { beginItemize('CMP@enumerate'); },
beforeDigest=>sub { Let(T_CS('\end{enumerate}') =>T_CS('\end{CMP@enumerate}')); });
DefEnvironment('{CMP@description}',
"#body",
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);
%
% \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}}
%
%<*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
%
% \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}
%
% \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}}
%
% \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}
%
% \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}
%\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}{}
%
%<*ltxml.sty>
DefCMPEnvironment('{omtext} OptionalKeyVals:stat',
""
. "?&KeyVal(#1,'title')(&KeyVal(#1,'title'))()"
. "#body"
. "\n");
%
% \end{macrocode}
% \end{environment}
%
% We also make our life easier If defininig an environment that is
% turned into something that contains ||\meta{body}||, 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);
}
%
% \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}}
%
%<*ltxml.sty>
DefConstructor('\STRlabel{}{}', sub {
my($document,$label,$object)=@_;
$document->absorb($object);
$document->addAttribute('xml:id'=>ToString($label)) if $label; });
%
% \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}
%
%<*ltxml.sty>
DefConstructor('\STRcopy{}',"");
%
% \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}}
%
% \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}
%
%<*ltxml.sty>
DefMacro('\STRlabeldef{}{}', "");
%
% \end{macrocode}
% \end{macro}
%
% \begin{macro}{\STRsemantics}
% \ednote{some explanation here}
% \begin{macrocode}
%<*package>
\def\STRsemantics{\@ifnextchar[\@semantics{\@semantics[]}}
%
%<*ltxml.sty>
DefConstructor('\STRsemantics[]{}{}', sub {
my($document,$label,$ignore,$object)=@_;
$document->absorb($object);
$document->addAttribute('xml:id'=>ToString($label)) if $label; });
%
% \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}}{}
%
%<*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 {}',
"#body");
%
% \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}}}
%
%<*ltxml.sty>
DefConstructor('\nlex{}',"#1");
DefConstructor('\nlcex{}',"#1");
%
% \end{macrocode}
% \end{environment}
%
% \begin{environment}{inlinequote}
% \ednote{describe above}
% \begin{macrocode}
%\def\inlinequote#1{``{\sl{#1}}''}
%DefConstructor('\inlinequote{}',"#1");
% \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}}
%
% \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; });
%
% \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)(#2)");
foreach my $color(qw(blue red green magenta cyan brown yellow)) {
DefMacro("\\".$color.'{}', sub { omdocColorMacro($color, @_); }); }
%
% \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);
%
% \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}
%\def\omspace#1{\hspace*{#1}}
%<*ltxml.sty>
DefConstructor('\omspace{}','');
DefConstructor('\emph{}',"#1");
DefConstructor('\em',"");
Tag('omdoc:phrase', autoClose=>1);
DefEnvironment('{center}','#body');
DefEnvironment('{minipage}{}','#body');
DefEnvironment('{quote}',"#body");
DefEnvironment('{quotation}',"#body");
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[]{}',
"");
DefConstructor('\footnotemark[]',"");
DefConstructor('\footnotetext[]{}',
"");
DefConstructor('\sf', '');
DefConstructor('\sc', '');
%
% \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);
%
% \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; }
%
% \end{macrocode}
%
% \subsection{Leftovers}
%
% \begin{macrocode}
%<*ltxml.sty>
DefConstructor('\url Semiverbatim',"#1");
%
% \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}
%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