%D \module %D [ file=x-cml, %D version=2007.09.03, % reimplementation %D title=\CONTEXT\ XML Modules, %D subtitle=MkIV ChemML renderer, %D author=Hans Hagen, %D date=\currentdate, %D copyright={PRAGMA ADE}] %C %C This module is part of the \CONTEXT\ macro||package and is %C therefore copyrighted by \PRAGMA. See mreadme.pdf for %C details. \writestatus{loading}{ConTeXt XML Macros / Chemistry} \usemodule[pictex,chemic] % someday we will do structural fomulas in mp %D The following code assumes a load||flush approach to \XML. \unprotect \startxmlsetups xml:cml:process \xmlstrip {\xmldocument} {cml:chem|cml:ichem|cml:dchem|cml:reaction|cml:molecule|cml:ion|cml:structure} \xmlgrab {\xmldocument} {cml:*} {*} \xmlgrab {\xmldocument} {cml:gives|cml:equilibrium|cml:mesomeric} {cml:arrow} \xmlgrab {\xmldocument} {cml:plus|cml:minus|cml:equal} {cml:operator} \xmlgrab {\xmldocument} {cml:bond|cml:singlebond|cml:doublebound|cml:triplebond} {cml:bond} \xmlgrab {\xmldocument} {pi::chemml} {cml:pi} \stopxmlsetups \xmlregistersetup{xml:cml:process} \xmlregisterns{cml}{chemml} \unexpanded\def\setupCMLappearance[#1]{\dodoubleargument\getparameters[@@CML#1]} \setupCMLappearance [ion] [\c!alternative=\v!a] \startluacode function lxml.cml_do_pi(id) local str = xml.content(lxml.id(id)) local _, class, key, value = str:match("^(%S+)%s+(%S+)%s+(%S+)%s+(%S+)%s*$") if key and value then tex.sprint(tex.ctxcatcodes,string.format("\\setupCMLappearance[%s][%s=%s]",class, key, value)) end end \stopluacode \def\doifelseCMLvariable#1#2#3% id key value {\doifelse{\xmlatt{#1}{#2}}{#3} \firstoftwoarguments {\doifelse{\getvalue{@@CML\xmltag{#1}#2}}{#3} \firstoftwoarguments \secondoftwoarguments}} \startxmlsetups cml:pi \ctxlua{lxml.cml_do_pi(#1)} \stopxmlsetups \startxmlsetups cml:chem \automathematics{\xmlflush{#1}} \stopxmlsetups \startxmlsetups cml:ichem \inlinemathematics{\xmlflush{#1}} \stopxmlsetups \startxmlsetups cml:dchem \displaymathematics{\xmlflush{#1}} \stopxmlsetups \startxmlsetups cml:reaction \xmlflush{#1} \stopxmlsetups \def\doCMLtext#1#2#3% main top bot {\setbox0\hbox{\doifsomething{#2}{\txx\setstrut\strut\ignorespaces#2\unskip}}% \setbox2\hbox{\ignorespaces\strut#1\unskip}% \setbox4\hbox{\doifsomething{#3}{\txx\setstrut\strut\ignorespaces#3\unskip}}% \scratchdimen=\wd2\advance\scratchdimen-.5em \ifdim\wd0>\scratchdimen \setbox0\hbox spread .5em{\hss\box0\hss}% \fi \ifdim\wd4>\scratchdimen \setbox4\hbox spread .5em{\hss\box4\hss}% \fi \setbox6=\vbox {\offinterlineskip\halign{\hss##\hss\cr\copy0\cr\copy2\cr\copy4\cr}}% \hbox{\lower\ht4\hbox{\lower\dp2\box6}}} \def\doCMLamount#1% {\scratchcounter0\xmlatt{#1}{n}\relax \ifnum\scratchcounter>0 \number\scratchcounter \fi} \startxmlsetups cml:molecule \doCMLtext {\doCMLamount{#1} \xmlall{#1}{cml:atom|cml:bond|cml:singlebond|cml:doublebond|cml:triplebond}} {\xmlindex{#1}{cml:caption}{2}} {\xmlindex{#1}{cml:caption}{1}} \stopxmlsetups \startxmlsetups cml:atom \doCMLtext { \lohi { $\tfxx\xmlatt{#1}{protons}$ } { $\tfxx\xmlatt{#1}{weight}$ } \xmlflush{#1} \lohi { $\tfxx\xmlatt{#1}{n}$ } { $\tfxx\xmlatt{#1}{charge}$% } } {\xmlindex{#1}{cml:caption}{2}} {\xmlindex{#1}{cml:caption}{1}} \stopxmlsetups \startxmlsetups cml:ion \doifelseCMLvariable{#1}{alternative}{b} { \left[ \doCMLtext {\doCMLamount{#1} \xmlall{#1}{cml:atom}} {\xmlindex{#1}{cml:caption}{2}} {\xmlindex{#1}{cml:caption}{1}} \right] } { \doCMLtext {\doCMLamount{#1} \xmlall{#1}{cml:atom}} {\xmlindex{#1}{cml:caption}{2}} {\xmlindex{#1}{cml:caption}{1}} } \high {\xmlatt{#1}{charge}} \stopxmlsetups \def\doCMLgives {\xrightarrow} \def\doCMLequilibrium{\xleftrightarrow} \def\doCMLmesomeric {\xrightoverleftarrow} \def\doCMLplus {+} \def\doCMLminus {-} \def\doCMLequal {=} \startxmlsetups cml:arrow \quad \executeifdefined{doCML\xmlname{#1}}\doCMLgives{\tf\xmlindex{#1}{cml:caption}{2}}{\tf\xmlindex{#1}{cml:caption}{1}} \quad \stopxmlsetups \startxmlsetups cml:operator \quad \mathop{\executeifdefined{doCML\xmlname{#1}}\doCMLplus} \quad \stopxmlsetups \startxmlsetups cml:bond \executeifdefined{doCML\xmlname{#1}} { \ifcase0\xmlatt{#1}{n}\relax \doCMLsinglebond \or \doCMLdoublebond \or \doCMLtriplebond \fi } \stopxmlsetups \def\doCMLbond {\hrule\!!width\hsize\!!height.1ex\relax} \def\dodoCMLbond#1#2#3% {\begingroup \setbox\scratchbox\hbox{$M$}% \vbox to \ht\scratchbox {\hsize\wd\scratchbox \vskip.1\wd\scratchbox #1\vfill#2\vfill#3% \vskip.1\wd\scratchbox}% \endgroup} \def\doCMLsinglebond{\dodoCMLbond\relax \doCMLbond\relax } \def\doCMLdoublebond{\dodoCMLbond\doCMLbond\relax \doCMLbond} \def\doCMLtriplebond{\dodoCMLbond\doCMLbond\doCMLbond\doCMLbond} \startxmlsetups cml:structure \startchemical \xmlall{#1}{cml:component} \stopchemical \stopxmlsetups % It makes not much sense to adapt ppchtex to accept different input. Maybe some day. \startluacode function lxml.cml_do_graphic(id) local t = { } for r, d, k in xml.elements(lxml.id(id),"cml:graphic") do t[#t+1] = xml.tostring(d[k].dt) end tex.sprint(tex.ctxcatcodes,table.concat(t,",")) end function lxml.cml_no_graphic(id) local t = { } for r, d, k in xml.elements(lxml.id(id),"cml:text|cml:oxidation|cml:annotation") do local dk = d[k] if dk.tg == "oxidation" then t[#t+1] = string.format("\\chemicaloxidation{%s}{%s}{%s}",r.at.sign or "",r.at.n or 1,xml.tostring(dk.dt)) elseif dk.tg == "annotation" then local location = r.at.location or "r" local caption = xml.content(xml.first(dk,"cml:caption")) local text = xml.content(xml.first(dk,"cml:text")) t[#t+1] = string.format("\\doCMLannotation{%s}{%s}{%s}",location,caption,text) else t[#t+1] = xml.tostring(dk.dt) or "" end end tex.sprint(tex.ctxcatcodes,table.concat(t,",")) end \stopluacode \startxmlsetups cml:component \expanded { \chemical [\ctxlua{lxml.cml_do_graphic("#1")}] [\ctxlua{lxml.cml_no_graphic("#1")}] } \stopxmlsetups \unexpanded\def\doCMLannotation#1% #2#3% loc caption text {\XMLval{cml:a:l}{#1}{\chemicalright}}% {#2}{#3}} \mapXMLvalue {cml:a:l} {t} {\chemicaltop} \mapXMLvalue {cml:a:l} {b} {\chemicalbottom} \mapXMLvalue {cml:a:l} {l} {\chemicalleft} \mapXMLvalue {cml:a:l} {r} {\chemicalright} \mapXMLvalue {cml:a:l} {lc} {\chemicalleftcentered} % \mapXMLvalue {cml:a:l} {cl} {\chemicalleftcentered} \mapXMLvalue {cml:a:l} {rc} {\chemicalrightcentered} % \mapXMLvalue {cml:a:l} {cr} {\chemicalrightcentered} \mapXMLvalue {cml:a:l} {tl} {\chemicaltopleft} % \mapXMLvalue {cml:a:l} {lt} {\chemicaltopleft} \mapXMLvalue {cml:a:l} {bl} {\chemicalbottomleft} % \mapXMLvalue {cml:a:l} {lb} {\chemicalbottomleft} \mapXMLvalue {cml:a:l} {tr} {\chemicaltopright} % \mapXMLvalue {cml:a:l} {rt} {\chemicaltopright} \mapXMLvalue {cml:a:l} {br} {\chemicalbottomright} % \mapXMLvalue {cml:a:l} {rb} {\chemicalbottomright} \mapXMLvalue {cml:a:l} {lt} {\chemicallefttop} % \mapXMLvalue {cml:a:l} {tl} {\chemicallefttop} \mapXMLvalue {cml:a:l} {lb} {\chemicalleftbottom} % \mapXMLvalue {cml:a:l} {bl} {\chemicalleftbottom} \mapXMLvalue {cml:a:l} {rt} {\chemicalrighttop} % \mapXMLvalue {cml:a:l} {tr} {\chemicalrighttop} \mapXMLvalue {cml:a:l} {rb} {\chemicalrightbottom} % \mapXMLvalue {cml:a:l} {br} {\chemicalrightbottom} \mapXMLvalue {cml:a:l} {x} {\chemicaltighttext} \mapXMLvalue {cml:a:l} {sl} {\chemicalsmashedleft} % \mapXMLvalue {cml:a:l} {ls} {\chemicalsmashedleft} \mapXMLvalue {cml:a:l} {sm} {\chemicalsmashedmiddle} % \mapXMLvalue {cml:a:l} {ms} {\chemicalsmashedmiddle} \mapXMLvalue {cml:a:l} {sr} {\chemicalsmashedright} % \mapXMLvalue {cml:a:l} {rs} {\chemicalsmashedright} \startxmlsetups cml:forever \left[\xmlflush{#1}\right] \stopxmlsetups % \starttext % \xmlprocess{main}{cmltest.xml}{xml:process} % \stoptext \protect \endinput