我的一个用户menukeys
包发现了一个奇怪的错误,如果不知道原因是什么以及如何修复它……
以下示例如果后面有\menu
包括right则使项目符号在文本内向右移动。\lstinline
\item
\documentclass{article}
\usepackage{listings}
\usepackage{menukeys}
\begin{document}
\begin{itemize}
\item Test
\item \menu{Test \lstinline|test|}
\item \lstinline|test|
\item \menu{Test}
\item \mbox{}\menu{Test \lstinline|test|}
\end{itemize}
\end{document}
用户发现这个\mbox
可以提供帮助,但这不应该是解决这个问题的唯一方法——我希望……
答案1
LaTeX 的\item
of 环境itemize
使用 来延迟其标签的设置\everypar
。标签存储在一个框中,打印在左侧段落的开头(\parindent
是0pt
),之后该框无效。
\menu
用途。首先将内容存储在盒子中menukeys
,\tikz
然后设置盒子。非常简单:
\setbox0=\hbox{...}%
\leavevmode\box0
\menu
/的内容\tikz
包含\lstinline
。它\leavevmode
在开头就调用 。这解释了为什么\lstinline
紧接着\item
它起作用。在 中,\hbox
\leavevmode
并不开始一个段落。\lstinline
调用\lst@Init
,其定义摘录如下:
\def\lst@Init#1{%
...
\ifhmode\ifinner \lst@boxtrue \fi\fi
\lst@ifbox
\lsthk@BoxUnsafe
\hbox to\z@\bgroup
$\if t\lst@boxpos \vtop
\else \if b\lst@boxpos \vbox
\else \vcenter \fi\fi
\bgroup \par\noindent
\else
...
}
的默认值为\lst@boxpos
,b
因此\noindent
在 内开始一个段落\vbox
。在段落的开头\everytoks
执行 并设置标签。之后标签框无效(由\box
,直到 的组级别\item
)。这解释了菜单项内的标签。
然后将存储在框中的菜单项设置为环境中的条目itemize
,正确使用\leavevmode
。但现在为时已晚,标签已经设置并且没有重复,标签框无效。
修复建议:
正如 egreg 所说,
\menu
(和其他类似的宏)应该\leavevmode
在开头调用。无论如何\menu
都会打印出一个段落的开头材料。可以手动重新定义:
\makeatletter \newcommand*{\org@menu}{} \let\org@menu\menu \protected\def\menu{\leavevmode\org@menu}% or % \renewcommand*{\menu}{\leavevmode\org@menu} \makeatother
\lst@Init
\lsthk@BoxUnsafe
如果使用垂直框则 使用钩子。\everypar
可以在那里清除:\makeatletter \lst@AddToHook{BoxUnsafe}{\everypar{}}% \makeatother
两种方法都可以解决问题: