用化学符号显示材料序列

用化学符号显示材料序列

我经常需要描述层堆栈中的材料序列,例如以下内容:

钽/铜/钽/铜/钴-铁-硼/氧化镁/钴-铁-硼/钽/钌/金

破折号表示成分不明的合金。我的问题是如何在 LaTeX 中正确排版。

我的 MWE 是

\documentclass{article}

\usepackage{lipsum}
\usepackage{mhchem}

\begin{document}
\lipsum[1]

The layer stack consist of \ce{Ta}/\ce{Cu}/\ce{Ta}/\ce{Cu}/\ce{Co-Fe-B}/\ce{MgO}/\ce{Co-Fe-B}/\ce{Ta}/\ce{Ru}/\ce{Au} and all layers are sputtered in a bla bla bla

Co-Fe
\end{document}

层堆栈

然而,这种做法存在几个问题。

  1. 斜线后未插入换行符
  2. 破折号变成了连字符(我认为是长破折号)
  3. 频繁使用\ce看起来很尴尬并且代码几乎无法阅读。

有没有更好的方法可以做到这一点(使用 mhchem)?请注意,大多数出版商(在我们的研究领域)建议使用破折号和斜线,不应被其他符号取代。

答案1

在向下滚动到我的代码之前,请注意,仅仅因为该代码有效并不意味着它是一种好方法。

一般来说,有一种数据结构叫做“逗号列表”。逗号列表在 LaTeX 编程中起着重要作用。例如,在使用时,geometry我们可能会说\usepackage[top=2cm,left=3cm]{geometry}。在这种情况下,top=2cm,left=3cm是一个包含两个项目的逗号列表:top=2cmleft=3cm。(它们用逗号分隔,因此得名。)(然后top=2cm被解释为键值对:top键和2cm值。)

同样,您的符号确实是“嵌套逗号列表”。外层称为“堆栈”,是/其分隔符。内层称为“层”,是-其分隔符。因此,您需要做的就是模仿或者迭代嵌套的斜线破折号列表。

由于您的请求相对简单(仅涉及字母和数字),因此简短的 TeX 代码足以说明如何处理您的逗号列表嵌套斜杠破折号列表:

  • 首先\CE接受一个参数,即完整列表,并将其传递给CEii
  • \CEii 接受两个参数,以 分隔/。因此第一个参数是第一个 之前的子字符串/。之后的子字符串成为第二个参数。例如Co-Fe-B/MgO/Co-Fe-B分为Co-Fe-BMgO/Co-Fe-B
  • 现在第一个参数Co-Fe-B应该是第一层,将其传递给\Ce
  • 如果第二个参数不为空,则会出现更多层。插入一个\newslash
  • 将第二个参数(其他层MgO/Co-Fe-B)视为一个新列表并从头开始。(MgO/Co-Fe-B变成MgOCo-Fe-B。它们都\Ce按顺序传递给。另一个\newslash插入它们之间。)
  • \CeCeii的作用与CE和相同CEii。不同之处在于它根据 划分字符串-并插入\newdash。(Co-Fe-B变为CoFe和。)并按顺序B将这些元素传递给。\ce
  • (MgO 不是一种元素......我的错)
  • 你的工作是重新定义\newskash\newdash

\documentclass{article}
\usepackage{mhchem}
\begin{document}

\def\newslash{///}
\def\newdash{---}
\newif\ifmoreelements
\newif\ifmorelayers

\def\Ce#1{%
    \def\templayer{#1}%
    \loop%
        \expandafter\Ceii\templayer-=%
        \expandafter\ce\expandafter{\tempfirstelement}%
    \ifmoreelements%
        \newdash%
        \expandafter\Cei\tempotherelements=%
    \repeat}
\def\Cei#1-={%
    \def\templayer{#1}}
\def\Ceii#1-#2={%
    \def\tempfirstelement{#1}\def\tempotherelements{#2}%
    \ifx\tempotherelements\empty\moreelementsfalse\else\moreelementstrue\fi}
\def\CE#1{%
    \def\tempstack{#1}%
    \loop%
        \expandafter\CEii\tempstack/+%
        {\expandafter\Ce\expandafter{\tempfirstlayer}}%
    \ifmorelayers%
        \newslash%
        \expandafter\CEi\tempotherlayers+%
    \repeat}
\def\CEi#1/+{%
    \def\tempstack{#1}}
\def\CEii#1/#2+{%
    \def\tempfirstlayer{#1}\def\tempotherlayers{#2}%
    \ifx\tempotherlayers\empty\morelayersfalse\else\morelayerstrue\fi}

\CE{Ta/Cu/Ta/Cu/Co-Fe-B/MgO/Co-Fe-B/Ta/Ru/Au}

\end{document}

关于好的方式

有时我听到人们说我们永远不应该使用\def。原因很明显:使用TeX语法在某种意义上危险的。例如,如果有人说\CE{-==-+//+-==-},它不会按预期工作。此外,还有一些外貌问题。例如,\CE{ Ta // Cu }将调用带有空格的\ce{ Ta }和,而应忽略逗号周围的所有空格。\ce{ Cu }\CE

不过,这完全取决于你。如果你知道你的代码永远不会像这样\CE{-==-+//+-==-},并且你确实喜欢这种简单的方式,那么就使用它。但是如果你正在寻找一种强大而安全的方式,那么\DeclareCommaListParser\CE[/][-]{blahblahblah}就给xparse它一个机会吧。

对我来说,xparse到目前为止还很复杂。但是,如果有一天 LaTeX3 发布,并且这些命令有详细的文档,我可能就不用再回答问题了def

答案2

对于那些使用chemformula代替mhchem有一个快速解决方案。 I 足以替换/be\slash以允许在斜线后换行。 由于chemformula已经有一种在复合词中用输出符号替换输入符号的机制,我们只需要访问它:

\ExplSyntaxOn
\cs_new_protected:Npn \chemformula_new_compound_property:nn #1#2
  { \prop_put_if_new:Nnn \l__chemformula_cmpd_prop {#1} {#2} }

\NewDocumentCommand \NewChemCompoundProperty { mm }
  { \chemformula_new_compound_property:nn {#1} {#2} }
\ExplSyntaxOff

现在只剩下说了\NewChemCompoundProperty{/}{\slash}。这利用了一个内部变量,所以它不是完全安全的,但我倾向于在包中添加一些类似的东西。

至于-被转换为单键——同样适用于,chemformula但使用chemformula语法"..."可以在这里有所帮助。或者——使用新命令可以说\NewChemCompoundProperty{:}{-}(或类似的话):

\documentclass{article}

\usepackage{chemformula,mhchem}

\ExplSyntaxOn
% I might add this to chemformula:
\cs_new_protected:Npn \chemformula_new_compound_property:nn #1#2
  { \prop_put_if_new:Nnn \l__chemformula_cmpd_prop {#1} {#2} }

\NewDocumentCommand \NewChemCompoundProperty { mm }
  { \chemformula_new_compound_property:nn {#1} {#2} }
\ExplSyntaxOff

\NewChemCompoundProperty{/}{\slash}

\usepackage{showframe}

\begin{document}

Bla.  The layer stack consists of \ch{Ta/Cu/Ta/Cu/Co "-" Fe "-" B/MgO/Co "-"
  Fe "-" B/Ta/Ru/Au} and all layers are sputtered in a bla bla bla

% or even:
\NewChemCompoundProperty{:}{-}

Bla.  The layer stack consists of
\ch{Ta/Cu/Ta/Cu/Co:Fe:B/MgO/Co:Fe:B/Ta/Ru/Au} and all layers are sputtered in
a bla bla bla

\end{document}

在此处输入图片描述


更新版本 4.10 (2015/03/16) 直接支持此功能:

\documentclass{article}
\usepackage{chemformula}[2015/03/16]

\NewChemCompoundProperty{/}{\slash}

\usepackage{showframe}

\begin{document}

Bla.  The layer stack consists of \ch{Ta/Cu/Ta/Cu/Co "-" Fe "-" B/MgO/Co "-"
  Fe "-" B/Ta/Ru/Au} and all layers are sputtered in a bla bla bla

% or even:
\NewChemCompoundProperty{:}{-}

Bla.  The layer stack consists of
\ch{Ta/Cu/Ta/Cu/Co:Fe:B/MgO/Co:Fe:B/Ta/Ru/Au} and all layers are sputtered in
a bla bla bla

\end{document}

答案3

这可以与新的 RegExp 引擎配合使用。出于好奇,我尝试了一下并找到了解决方案。这是新旧语法的奇怪组合。

\documentclass{article}
\usepackage[version=3]{mhchem}
\usepackage{l3regex}
\begin{document}
\newcommand*\stackslash{\text{/}\allowbreak}
\newcommand*\stackdash{\text{-}\allowbreak}
\ExplSyntaxOn
\newcommand\stack[1] {
  \tl_new:N \l_my_tl
  \tl_set:Nx \l_my_tl { \exp_not:N \ce { #1 } }
  \regex_replace_all:nnN { \/ } { \cE] \c{stackslash} \c{ce}\cB[ } \l_my_tl
  \regex_replace_all:nnN { \- } { \cE] \c{stackdash} \c{ce}\cB[ } \l_my_tl
  \tl_use:N \l_my_tl
}
\ExplSyntaxOff

The layer stack consist of \stack{Ta/Cu/Ta/Cu/Co-Fe-B/MgO/Co-Fe-B/Ta/Ru/Au} and all layers are sputtered in a bla bla bla
\end{document}

基本上,它接受A/B/C-D/E并将其转换为\ce{A}\stackslash\ce{B}\stackslash\ce{C}\stackdash\ce{D}\stackslash\ce{E}

答案4

这是一个小的 Lua 代码片段,演示了不同的方法,该方法将纯文本(以空格结尾)传递给 Lua,使用正则表达式并将输出传回 TeX 引擎。它将除斜杠和减号之外的一系列文本字符扩展为命令\ce,将 divis 更改为 endash 并\allowbreak在每个斜杠后添加命令。

设输入为:Cu/Ta/H2O/Cu/Ta/Cu/Co-Fe-B/MgO/Co-Fe-B/Ta/Ru/Au

修改后的文本如下所示:\ce{Cu}/\allowbreak{}\ce{Ta}/\allowbreak{}\ce{H2O}/\allowbreak{}\ce{Cu}/\allowbreak{}\ce{Ta}/\allowbreak{}\ce{Cu}/\allowbreak{}\ce{Co}--\allowbreak{}\ce{Fe}--\allowbreak{}\ce{B}/\allowbreak{}\ce{MgO}/\allowbreak{}\ce{Co}--\allowbreak{}\ce{Fe}--\allowbreak{}\ce{B}/\allowbreak{}\ce{Ta}/\allowbreak{}\ce{Ru}/\allowbreak{}\ce{Au}

我们执行lualatex mal-chem.tex

\documentclass{article}
\pagestyle{empty}
\usepackage{lipsum}
\usepackage{luacode}
\usepackage[version=3]{mhchem}
\begin{document}
\begin{luacode*}
function malstr(text)
text=string.gsub(text, "[^/-]+", "\\ce{%1}")
text=string.gsub(text, "%-", "--\\allowbreak{}") 
-- -- or --\\allowbreak{}
text=string.gsub(text, "/", "/\\allowbreak{}")
tex.print(text); print(text)
end -- of function malstr
\end{luacode*}
\def\nobonds#1 {\directlua{malstr([[#1]])} }
\lipsum[1]\par
The layer stack consist of \nobonds Cu/Ta/H2O/Cu/Ta/Cu/Co-Fe-B/MgO/Co-Fe-B/Ta/Ru/Au and all layers are sputtered in...
% result is: \ce{Cu}/\allowbreak{}\ce{Ta}/\allowbreak{}\ce{H2O}/\allowbreak{}\ce{Cu}/\allowbreak{}\ce{Ta}/\allowbreak{}\ce{Cu}/\allowbreak{}\ce{Co}--\allowbreak{}\ce{Fe}--\allowbreak{}\ce{B}/\allowbreak{}\ce{MgO}/\allowbreak{}\ce{Co}--\allowbreak{}\ce{Fe}--\allowbreak{}\ce{B}/\allowbreak{}\ce{Ta}/\allowbreak{}\ce{Ru}/\allowbreak{}\ce{Au}
\end{document}

得到的结果图

相关内容