% \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 %\NeedsTeXFormat{LaTeX2e}[1999/12/01] %\ProvidesPackage{omtext}[2012/01/28 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 1999 2012-01-28 07:32:11Z 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} \def\tracissue#1{\cite{sTeX:online}, \hyperlink{http://trac.kwarc.info/sTeX/ticket/#1}{issue #1}} \begin{document}\DocInput{omtext.dtx}\end{document} % % \fi % %\CheckSum{375} % % \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} % % \begin{omgroup}[id=sec:user:options]{Package Options} % % The |omtext| package takes a single option: \DescribeMacro{showmeta}|showmeta|. If % this is set, then the metadata keys are shown (see~\cite{Kohlhase:metakeys:ctan} for % details and customization options). % \end{omgroup} % % \begin{omgroup}[id=sec:user:omtext]{Mathematical Text} % % The \DescribeEnv{omtext}|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 \DescribeMacro{title=}|title| key. Often it is also helpful to % annotate the \DescribeMacro{type=}|type| key. The standard relations from rhetorical % structure theory |abstract|, |introduction|, |conclusion|, |thesis|, |comment|, % |antithesis|, |elaboration|, |motivation|, |evidence|, |transition|, | note|, |annote| % are recommended as values. Note that some of them are unary relations like % |introduction|, which calls for a target. In this case, a target using the % \DescribeMacro{for=}|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 \DescribeMacro{from=}|from| key. % % Note that the values of the |title| and |type| keys are often displayed in the % text. This can be turned off by setting the \DescribeMacro{display=}|display| key to % the value |flow|. Sometimes we want to specify that a text is a continuation of % another, this can be done by giving the identifier of this in the % \DescribeMacro{continues=}|continues| key. % % Finally, there is a set of keys that pertain to the mathematical formulae in the % text. The \DescribeMacro{functions=}|functions| key allows to specify a list of % identifiers that are to be interpreted as functions in the generate content % markup. The \DescribeMacro{theory=}|theory| specifies a module % (see~\cite{KohAmb:smmssl:svn}) that is to be pre-loaded in this one\ednote{this is not % implemented yet.} Finally, \DescribeMacro{verbalizes=}|verbalizes| specifies a (more) % formal statement (see~\cite{Kohlhase:smms:svn}) that this text verbalizes. % \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 % \DescribeMacro{verbalizes=}|verbalizes| and \DescribeMacro{type=}|type| as above and % \DescribeMacro{style}|style,| \DescribeMacro{class}|class|, % \DescribeMacro{index}|index| that are disregarded in the {\LaTeX}, but copied into the % generated content markup. % % \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: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} % \end{omgroup} % % % \section{Limitations}\label{sec:limitations} % % In this section we document known limitations. If you want to help alleviate them, % please feel free to contact the package author. Some of them are currently discussed in % the \sTeX TRAC~\cite{sTeX:online}. % \begin{compactenum} % \item none reported yet % \end{compactenum} % % \StopEventually{\newpage\PrintIndex\newpage\PrintChanges\printbibliography}\newpage % % \begin{omgroup}[id=sec:impl]{Implementation} % % The |omtext| 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. % % \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); % % \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> \DeclareOption{showmeta}{\PassOptionsToPackage{\CurrentOption}{metakeys}} \newif\ifindex\indextrue \DeclareOption{noindex}{\indexfalse} \ProcessOptions \ifindex\makeindex\fi % %<*ltxml> DeclareOption('noindex',''); % % \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} % %<*ltxml> RequirePackage('sref'); % % \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); % % \end{macrocode} % % 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> 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;});#$ % % \end{macrocode} % % 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 % ||, 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. % \begin{macrocode} %<*ltxml> 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); % % \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} \addmetakey[]{omtext}{functions} \addmetakey*{omtext}{display} \addmetakey{omtext}{for} \addmetakey{omtext}{from} \addmetakey{omtext}{type} \addmetakey*{omtext}{title} \addmetakey*{omtext}{start} \addmetakey{omtext}{theory} \addmetakey{omtext}{continues} \addmetakey{omtext}{verbalizes} \addmetakey{omtext}{subject} % %<*ltxml> DefKeyVal('omtext','functions','Undigested'); 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','start','Plain'); #Math mode in start phrases DefKeyVal('omtext','theory','Semiverbatim'); DefKeyVal('omtext','continues','Semiverbatim'); DefKeyVal('omtext','verbalizes','Semiverbatim'); % % \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} % % \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\metasetkeys{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} % %<*ltxml> DefEnvironment('{omtext} OptionalKeyVals:omtext', "" . "?&KeyVal(#1,'title')(&KeyVal(#1,'title'))()" . "" . "?&KeyVal(#1,'start')(&KeyVal(#1,'start'))()" . "#body" .""); % % \end{macrocode} % \end{environment} % % We also make our life easier If defining an environment that is % turned into something that contains ||\meta{body}||, 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); }#$ % % \end{macrocode} % \end{omgroup} % % \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} \addmetakey{phrase}{style} \addmetakey{phrase}{class} \addmetakey{phrase}{index} \addmetakey{phrase}{verbalizes} \addmetakey{phrase}{type} \newenvironment{phrase}[1][]{\metasetkeys{phrase}{#1}}{} % %<*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 {}', "#2"); % % \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> DefConstructor('\nlex{}', "#1"); DefConstructor('\nlcex{}', "#1"); % % \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} % %<*ltxml> DefConstructor('\sinlinequote [] {}', "" . "?#1(#1\n)()" . "#2" . ""); % % \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} % %<*ltxml> DefEnvironment('{sblockquote} []', "?#1(" . "#1" . "#body" . " )" . "(#body)"); % % \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} % %<*ltxml> DefConstructor('\lec{}', "\n#1"); % % \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} %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}}} % %'); % \end{macrocode} % \end{macro} % \end{omgroup} % % \begin{omgroup}[id=sec:impl:index]{Index Markup} % % \begin{macrocode} % this is the main internal indexing comman. It makes sure that the modules necessary for % interpreting the math in the index entries are loaded. %<*package> \newcommand{\omdoc@index}[2][]{\ifindex\def\@test{#1}%% \ifx\@test\@empty\def\@@idx{#2}\else\def\@@idx{#1}\fi% \@ifundefined{mod@id}{\index{\@@idx @#2}}% {\index{\@@idx @{\importmodule{\mod@id} #2}}\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 % % \end{macrocode} % % this puts two-compound words into the index in various permutations % % \begin{macrocode} %<*package> \newcommand{\@twin}[3][]{\ifindex\def\@test{#1}%% \ifx\@test\@empty\def\@@idx{#2}\else\def\@@idx{#1}\fi% \@ifundefined{mod@id} {\index{\@@idx @#2!#3}% \ifx\@test\@empty\def\@@idx{#3}\else\def\@@idx{#1}\fi% \index{\@@idx @#2!#3}}% {\index{\@@idx @{\importmodule{\mod@id} #2}!{\importmodule{\mod@id} #3}}% \ifx\@test\@empty\def\@@idx{#3}\else\def\@@idx{#1}\fi% \index{\@@idx @{\importmodule{\mod@id} #3}!{\importmodule{\mod@id} #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 % % \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][]{\ifindex\def\@test{#1}%% \ifx\@test\@empty\def\@@idx{#2}\else\def\@@idx{#1}\fi% \@ifundefined{mod@id}% {\index{\@@idx @#2!#3!#4}% \ifx\@test\@empty\def\@@idx{#3}\else\def\@@idx{#1}\fi \index{\@@idx @#3!#2 (#4)}}% {\index{\@@idx @{\importmodule{\mod@id} #2}!{\importmodule{\mod@id} #3}!{\importmodule{\mod@id} #4}} \ifx\@test\@empty\def\@@idx{#3}\else\def\@@idx{#1}\fi% \index{\@@idx @{\importmodule{\mod@id} #3}!{\importmodule{\mod@id} #2} ({\importmodule{\mod@id} #4})}\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 % %<*ltxml> DefConstructor('\indextoo[]{}', "" . "#2" . "" . "#2" . "" .""); DefConstructor('\indexalt[]{}{}', "" . "#2" . "" . "#3" . "" .""); % % \end{macrocode} % % \begin{macrocode} %<*ltxml> DefConstructor('\twintoo[]{}{}', "" . "#2 #3" . "" . "#2" . "#3" . "" .""); DefConstructor('\twinalt[]{}{}{}', "" . "#2" . "" . "#2" . "#3" . "" .""); % % \end{macrocode} % % \begin{macrocode} %<*ltxml> DefConstructor('\atwintoo[]{}{}{}', "" . "#2 #3" . "" . "#2" . "#3" . "#4" . "" .""); DefConstructor('\atwinalt[]{}{}{}{}', "" . "#2" . "" . "#2" . "#3" . "#4" . "" .""); % % \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 |ltx:p| element for paragraphs inside |CMP|s. For that we have modified % the DTD only to allowed |ltx:p| elements in |omdoc:CMP| (in particular no text). Then % we instruct the |\par| macro to close a |ltx:p| element if possible. The next % |ltx:p| element is then opened automatically, since we make |ltx:p| and |omdoc:CMP| % autoclose and autoopen. % % \begin{macrocode} %<*ltxml> # needed? DefConstructor('\par',sub { $_[0]->maybeCloseElement('ltx:p'); },alias=>"\\par\n"); Tag('omdoc:CMP', autoClose=>1, autoOpen=>1); Tag('omdoc:omtext', 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}.\ednote{MK: we should probably let % LaTeXML deal with these and allow more text in the omdoc+ltml.xsl} % \begin{macrocode} %\def\omspace#1{\hspace*{#1}} %<*ltxml> DefConstructor('\footnote[]{}', "#2"); DefConstructor('\footnotemark[]',""); DefConstructor('\footnotetext[]{}', "#2"); % % \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. Furthermore, we use the % |locateIt| procedure to give source links. % % \begin{macrocode} %<*ltxml> Tag('omdoc:omtext',afterOpen=>\&numberIt,afterClose=>\&locateIt); Tag('omdoc:omgroup',afterOpen=>\&numberIt,afterClose=>\&locateIt); Tag('omdoc:CMP',afterOpen=>\&numberIt,afterClose=>\&locateIt); Tag('omdoc:idx',afterOpen=>\&numberIt,afterClose=>\&locateIt); Tag('omdoc:ide',afterOpen=>\&numberIt,afterClose=>\&locateIt); Tag('omdoc:idt',afterOpen=>\&numberIt,afterClose=>\&locateIt); Tag('omdoc:note',afterOpen=>\&numberIt,afterClose=>\&locateIt); Tag('omdoc:metadata',afterOpen=>\&numberIt,afterClose=>\&locateIt); Tag('omdoc:meta',afterOpen=>\&numberIt,afterClose=>\&locateIt); Tag('omdoc:resource',afterOpen=>\&numberIt,afterClose=>\&locateIt); Tag('ltx:p',afterOpen=>\&numberIt,afterClose=>\&locateIt); % % \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); % % \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')); my $localname = $node->localname; $node->setAttribute('xml:id'=>$prefix."$localname$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; if ($locator) { # There is a BUG with namespace declarations (or am I using the API wrongly??) which # does not recognize the stex namespace. Hence, I need to redeclare it... my $parent=$document->getNode; if(! defined $parent->lookupNamespacePrefix("http://kwarc.info/ns/sTeX")) { # namespace not already declared? $document->getDocument->documentElement->setNamespace("http://kwarc.info/ns/sTeX","stex",0); } $node->setAttribute('stex:srcref'=>$locator); }return;} 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 } my $parent = $document->getNode; if(! defined $parent->lookupNamespacePrefix("http://kwarc.info/ns/sTeX")) { # namespace not already declared? $document->getDocument->documentElement->setNamespace("http://kwarc.info/ns/sTeX","stex",0); } $node->setAttribute('stex:srcref' => $locator); return; } %#$ % \end{macrocode} % \end{omgroup} % % \begin{omgroup}{Finale} % % We need to terminate the file with a success mark for perl. % \begin{macrocode} %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 % 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 smallskip showmeta % LocalWords: providecommand stDMemph textbf newenvironment hfil showmeta % 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 textsf langle textsf langle funval % LocalWords: metakeys funsymbs addmetakey metasetkeys startemph textsl textit % LocalWords: compactenum