% \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[]{}', "#2"); DefConstructor('\footnotemark[]',""); DefConstructor('\footnotetext[]{}', "#2"); 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