在组中创建一个 \savebox,并使其在组外可用

在组中创建一个 \savebox,并使其在组外可用

下面的 MWE\savebox在一个组内创建,从而产生了几行空白行:

在此处输入图片描述

如果我注释掉\begingroup\endgroup得到期望的结果:

在此处输入图片描述

我的想法是添加应该\global可以解决这个问题。

那么,如何\savebox在组内创建和定义,同时又能够使用组外的内容?

笔记:

  • 虽然这里的 MWE 不需要分组,但我的实际用例需要,所以我真的不希望消除分组。

代码:

\documentclass{article}
\usepackage{etoolbox}

\newcommand*{\MyLink}[2]{%
\begingroup
    \ifcsdef{MyBox #1-#2}{%
    }{%
        \typeout{*** Defined savebox for #1-#2}%
        \global\expandafter\newsavebox\csname MyBox #1-#2\endcsname%
        \global\expandafter\savebox\csname MyBox #1-#2\endcsname{#2: #1}%
    }%
    \expandafter\usebox\csname MyBox #1-#2\endcsname%
\endgroup
}%


\begin{document}
    \MyLink{http://www.wikipedia.org}{W} 
    
    \MyLink{http://www.wikipedia.org}{W} 
    
    \MyLink{http://www.apple.org}{A} 
    
    \MyLink{http://www.google.com}{G} 

    \MyLink{http://www.wikipedia.org}{W} 

    \MyLink{http://www.wikipedia.org}{W} 
\end{document}

答案1

我怀疑在这里使用本地分配的框是错误的做法,但要做到这一点,只需使用原始命令来设置内容:

\documentclass{article}
\usepackage{etoolbox}

\newcommand*{\MyLink}[2]{%
\begingroup
    \ifcsdef{MyBox #1-#2}{%
    }{%
        \typeout{*** Defined savebox for #1-#2}%
        \global\expandafter\newsavebox\csname MyBox #1-#2\endcsname%
        \global\expandafter\setbox\csname MyBox #1-#2\endcsname\hbox{{#2: #1}}%
    }%
    \expandafter\usebox\csname MyBox #1-#2\endcsname%
\endgroup
}%


\begin{document}
    \MyLink{http://www.wikipedia.org}{W} 

    \MyLink{http://www.wikipedia.org}{W} 

    \MyLink{http://www.apple.org}{A} 

    \MyLink{http://www.google.com}{G} 

    \MyLink{http://www.wikipedia.org}{W} 

    \MyLink{http://www.wikipedia.org}{W} 
\end{document}

答案2

让我们看看\global\savebox\foo做了什么:

  1. \global扩展\savebox,因此输入流是

    \global\@ifnextchar ({\@savepicbox \foo}{\@ifnextchar [{\@savebox #1}{\sbox \foo}}
    
  2. \global扩展\@ifnextchar,因此输入流是

    \global\let\reserved@d=( [...]
    

    (其中[...]表示不相关的标记)。

  3. \global适用于\let

\global请注意,直到找到可以应用的标记(\def,,\let寄存器地址等;一般为赋值)后,它才会消失。

这解释了为什么您没有收到错误,也解释了为什么您没有获得盒子的全局设置。

这样做\global\sbox\foo{tokens}是可行的,因为由触发的第一步扩展\global

\global\setbox\foo\hbox{\color@setgroup tokens\color@endgroup}

但是,您可能正在使用精简的示例,并且也许您需要 的全部力量\savebox,而不是\sbox,因此您可以使用临时盒子寄存器进行构造,然后全局设置新寄存器与构建的盒子相同。

\documentclass{article}
\usepackage{etoolbox}

\newsavebox{\mylinkbox}
\newcommand*{\MyLink}[2]{%
\begingroup
    \ifcsdef{MyBox #1-#2}{%
    }{%
        \typeout{*** Defined savebox for #1-#2}%
        \global\expandafter\newsavebox\csname MyBox #1-#2\endcsname
        \savebox\mylinkbox{#2: #1}%
        \global\expandafter\setbox\csname MyBox #1-#2\endcsname\box\mylinkbox
    }%
    \expandafter\usebox\csname MyBox #1-#2\endcsname
\endgroup
}


\begin{document}
    \MyLink{http://www.wikipedia.org}{W}

    \MyLink{http://www.wikipedia.org}{W}

    \MyLink{http://www.apple.org}{A}

    \MyLink{http://www.google.com}{G}

    \MyLink{http://www.wikipedia.org}{W}

    \MyLink{http://www.wikipedia.org}{W}
\end{document}

在此处输入图片描述

相关内容