我拼凑了一个\basis
宏,它设置并获取隐藏/内部长度\b@sis
。它的工作原理如下:
- 调用
\basis
返回值\b@sis
- 调用
\basis{}
设置\b@sis
为默认值(当前字体大小\f@size
)并 - 调用
\basis{1ex}
将设置\b@sis
为指定的长度。
\basis
2 和 3 有效,但 1 并不总是按预期返回值。例如,我无法在 TikZ 中用作长度,也无法使用\the\basis
或显示其值\showthe\basis
。我还尝试\expandafter
在前两个“the”命令前添加前缀,但没有效果。以下是我目前的代码
\documentclass{standalone}
\usepackage{luatex85}
\usepackage{xparse}
\usepackage{ifthen}
\usepackage{xifthen}
\usepackage{tikz}
\usepackage{booktabs}
\makeatletter
\newlength{\b@sis}
\newlength{\length}
\setlength{\length}{2pt}
\setlength{\b@sis}{2pt}
\ProvideDocumentCommand{\basis}{g}{%
\IfNoValueTF{#1}{%
\b@sis}{%
\ifthenelse{\isempty{#1}}%
{\setlength{\b@sis}{\f@size pt}%
\setlength{\length}{\f@size pt}}%
{\setlength{\b@sis}{#1}%
\setlength{\length}{#1}}}}%
\newcommand{\showbasis}{\the\b@sis}
\makeatother
\begin{document}
\begin{tabular}{|l|r|c|c|} % The following calls fail
\toprule
No response & \basis \showbasis & \tikz \draw circle(0.5*\length); \\%& \tikz \draw circle(0.5*\basis); \\
\midrule
Sets default & \basis{} \showbasis & \basis{}\tikz \draw circle(0.5*\length); \\%& \tikz \draw circle(0.5*\basis); \\
\midrule
Sets Value & \basis{1ex} \showbasis & \basis{1ex}\tikz \draw circle(0.5*\length); \\%& \tikz \draw circle(0.5*\basis); \\
\bottomrule
\end{tabular}
\end{document}
其输出如下所示
我认为,\IfNoValueTF
当没有参数时,就不会扩展,也不会返回预期的长度。是否有某种方法可以扩展它以返回内部长度,或者是否有更好的方法来实现这一点。
我看到\ProvideDocumentCommand
允许一个l
论点,也许我应该在我的定义中使用它?例如,是否有变化\basis
正在提前读取第一个非空白字符,xparse
手册暗示可能是这种情况。
更新
Egreg 显然有更好的解决方案,但我是在 David Carlisle 回应之后才看到它,而且我又对其进行了一些调整。我必须使用界面\basis
来\basis[VALUE]
设置值并\basis*
检索它。但这确实是一种糟糕的做法,当然不是什么星星代表什么。
\ProvideDocumentCommand{\basis}{s o}{%
\IfBooleanTF{#1}
{\the\b@sis}
{\IfNoValueTF{#2}{%
\setlength{\b@sis}{\f@size pt}%
\setlength{\length}{\f@size pt}}
{\setlength{\b@sis}{#2}%
\setlength{\length}{#2}}}
}%
答案1
使用可选参数定义的命令g
是不可扩展的,因此不能\basis
在扩展上下文中使用不带参数的命令,例如
\draw circle(0.5*\basis)
按照建议,最好将调用分为设置变量和使用变量。您可以充分利用 的功能expl3
来获得更高效的代码。
\documentclass[border=4pt]{standalone}
\usepackage{luatex85}
\usepackage{xparse}
\usepackage{tikz}
\usepackage{booktabs}
\ExplSyntaxOn
\dim_new:N \l_carel_basis_dim
\dim_set:Nn \l_carel_basis_dim { 2pt }
\NewDocumentCommand{\setbasis}{O{\use:c {f@size} pt}}
{
\dim_set:Nn \l_carel_basis_dim { #1 }
}
\NewExpandableDocumentCommand{\basis}{}{\dim_use:N \l_carel_basis_dim}
\ExplSyntaxOff
\begin{document}
\begin{tabular}{lrcc}
\toprule
Initial value & \basis & \tikz \draw circle(0.5*\basis); \\
\midrule
Sets default & \setbasis\basis & \setbasis\tikz \draw circle(0.5*\basis); \\
\midrule
Sets Value & \setbasis[1ex]\basis & \setbasis[1ex]\tikz \draw circle(0.5*\basis); \\
\bottomrule
\end{tabular}
\end{document}
答案2
发布的代码运行时没有错误并且产生了我所期望的结果,但是您没有说出您期望它做什么。
使用相同命令来设置和检索的用户界面非常令人困惑,也许这就是混乱的根源。
在第二行和第三行的第二列中,你设置了长度,但在第一行中,你有一个相当奇怪的构造
\basis \showbasis
\basis
扩展到内部长度的使用并\showbasis
扩展到\the
应用于该长度。
如果你把它改成
\basis \showbasis\showbasis
因此如果\b@sis
最初设置为 2pt,那么
\basis \showbasis
是
\b@sis \the\b@sis
扩展为
\b@sis 2pt
因此设置\b@sis
为其已有的值 2pt。
像我一样添加第二个,\showbasis
将 2pt 打印到表格中,
然后您会看到该值为 2pt,因此圆圈很小。
如果您只\basis
在单元格上单独放置一个单元格,那么您会得到一个缺失数字错误,因为它是一个长度的分配,而没有提供值。