\leftmargin
我将自定义长度设置为等于列表内的值enumitem
。但是一旦我退出列表,该值就会消失,我的自定义长度将恢复为零。
我在 MWE 中展示了以下行为:
\documentclass{article}
\usepackage{enumitem}
\newlength\Mylen
\setlength{\Mylen}{0em}
\begin{document}
Hello world. Value of Mylen is \the\Mylen.
\begin{enumerate}[leftmargin=40pt,labelsep=1em, label={P\arabic*}]
\item Test line 1.
\item Test line 2.
\item Test line 3. The value of leftmargin is \the\leftmargin. Value of Mylen is \the\Mylen. \addtolength{\Mylen}{\leftmargin} Value of Mylen is now the sum of leftmargin and original value = \the\Mylen.
\end{enumerate}
Value of Mylen is \the\Mylen ~again!
\end{document}
我不明白为什么会发生这种情况。有什么帮助吗?
答案1
长度调整尊重它们所处的范围,如下面的最小示例所示。因此,在组内设置或更改它会将其恢复为组之前的原始定义/设置。你可以用来\global<len>=<len>
使改变全球化,从而避免了范围限制:
\documentclass{article}
\begin{document}
\newlength{\mylen}
\setlength{\mylen}{40pt}\the\mylen% 40.0pt
\begingroup
\setlength{\mylen}{50pt}\the\mylen% 50.0pt
% https://tex.stackexchange.com/a/119738/5764
%\global\mylen=\mylen% Make above assignment global
\endgroup
\the\mylen% 40.0pt, or 50.0pt when using \global
\end{document}
另一种选择是使用全局定义而不是长度来保持长度:
\documentclass{article}
\begin{document}
\newlength{\mylen}
\setlength{\mylen}{40pt}\the\mylen% 40.0pt
\begingroup
\setlength{\mylen}{50pt}\the\mylen% 50.0pt
\xdef\mylenval{\the\mylen}% 50.0pt
\endgroup
\the\mylen% 40.0pt
\mylenval% 50.0pt
\setlength{\mylen}{\mylenval}\the\mylen% 50.0pt
\end{document}
虽然\mylenval
是一个(全局)宏,但它包含定义时的长度,您可以在其他长度的设置中使用它,如\setlength{\mylen}{\mylenval}
。
答案2
\setlength
诸如、\addtolength
、\settowidth
和\settoheight
之类的作业\settodepth
是当地的,它们只在发出它们的组中有效;环境构成一个组,如对齐单元和框(\mbox
、\makebox
等等\fbox
)。
calc
如果您需要这些命令的全局版本,那么制作可以使用且不需要\global
在野外使用的版本并不困难。
\documentclass{article}
\usepackage{enumitem}
\usepackage{calc} % just for testing
\makeatletter
\newlength{\g@temp@len}
\newcommand{\gsetlength}[2]{%
\setlength{\g@temp@len}{#2}%
\global#1\g@temp@len
}
\newcommand{\gaddtolength}[2]{%
\addtolength{\g@temp@len}{#2}%
\global#1\g@temp@len
}
\newcommand{\gsettowidth}[2]{%
\g@settodim\wd{#1}{#2}%
}
\newcommand{\gsettoheight}[2]{%
\g@settodim\ht{#1}{#2}%
}
\newcommand{\gsettodepth}[2]{%
\g@settodim\dp{#1}{#2}%
}
\newcommand{\g@settodim}[3]{%
\@settodim#1\g@temp@len{#3}%
\global#2\g@temp@len
}
\makeatother
\newlength\Mylen
\begin{document}
Hello world. Value of Mylen is \the\Mylen.
\begin{enumerate}[leftmargin=40pt,labelsep=1em, label={P\arabic*}]
\item Test line 1.
\item Test line 2.
\item Test line 3. The value of leftmargin is \the\leftmargin.
Value of Mylen is \the\Mylen. \gaddtolength{\Mylen}{\leftmargin}
Value of Mylen is now the sum of leftmargin and original value = \the\Mylen.
\end{enumerate}
Value of Mylen is \the\Mylen{} as expected!
\mbox{\gsetlength{\Mylen}{3pt}X}\the\Mylen
\mbox{\gsettowidth{\Mylen}{\widthof{XX}}}\the\Mylen
\mbox{\gaddtolength{\Mylen}{2pt}}\the\Mylen
\end{document}
最好避免对同一个变量进行局部和全局分配。
答案3
LaTeX
与计数器不同,length
寄存器是组安全的,即,在组内更改其值(如\begin{enumerate}...\end{enumerate}
)不会在退出该组后继续存在,即,除非\global\addtolength
在这里使用,否则更改不是持久的。
由于 的定义\addtolength
是(见latex.ltx
)
\def\addtolength#1#2{\advance#1 #2\relax}
\global\addtolength...
\global\advance....
和这里一样
然而,由于calc
的定义发生了变化\addtolength
,我提供了另一个版本:
\documentclass{article}
\usepackage{enumitem}
\usepackage{calc}%
\newcommand{\increaselength}[2]{%
\global\advance#1 by #2\relax
}%
\newlength\Mylen
\setlength{\Mylen}{0em}
\begin{document}
Hello world. Value of Mylen is \the\Mylen.
\begin{enumerate}[leftmargin=40pt,labelsep=1em, label={P\arabic*}]
\item Test line 1.
\item Test line 2.
\item Test line 3. The value of leftmargin is \the\leftmargin. Value of Mylen is \the\Mylen. \global\advance\Mylen by \leftmargin. Value of Mylen is now the sum of leftmargin and original value = \the\Mylen.
\item Test line 3. The value of leftmargin is \the\leftmargin. Value of Mylen is \the\Mylen. \increaselength{\Mylen}{10pt} Value of Mylen is now the sum of leftmargin and original value = \the\Mylen.
\end{enumerate}
Value of Mylen is \the\Mylen ~again!
\end{document}