我想创建一个像这样的命令
\CalcNumber{<the text>}{<width>}{<cs>}
并且存储如果在宽度为的框中排版所需的行数(即\baselineskip
四舍五入的高度)。<the text>
<cs>
<width>
例如\CalcNumber{A}{\columwith}{\AHeight}\AHeight
应该屈服1
,而类似的东西\CalcNumber{M M M}{1em}{\MMMHeight}\MMMHeight
应该给予某物3
。
我怎样才能做到这一点?
PS 也欢迎使用 LuaLaTeX 解决方案。
答案1
您可以使用adjustbox
将内容装箱在minipage
给定宽度内并存储其总高度,然后使用 eTeX 计算基线跳过的因子(最后是discard
内容)。
这与使用装箱的其他答案类似,但是是一种更加开箱即用的解决方案(无双关语)。
\documentclass{article}
\usepackage{adjustbox}
\newlength\mycalclength
\newcommand\CalcNumber[3]{%
\adjustbox{minipage={#2}, gstore totalheight=\mycalclength, discard}{#1}%
\edef#3{\the\numexpr\dimexpr \mycalclength/\baselineskip\relax\relax}%
}
\begin{document}
\CalcNumber{A}{\columnwidth}{\AHeight}\AHeight
\CalcNumber{M M M M M M M}{1em}{\MMMHeight}\MMMHeight
\end{document}
如果您重新排列参数的顺序并将内容放在最后,则可以使用 的功能\adjustbox
将最后一个参数读取为框,而不是参数,从而允许逐字和其他特殊内容。请注意,分配是全局的,因为它发生在组中。
\documentclass{article}
\usepackage{adjustbox}
\newlength\mycalclength
\newcommand\CalcNumber[2]{%
\adjustbox{minipage={#1}, gstore totalheight=\mycalclength, execute={\gdef#2{\the\numexpr\dimexpr \mycalclength/\baselineskip\relax\relax}}, discard}
}
\begin{document}
\CalcNumber{\columnwidth}{\AHeight}{A}\AHeight
\CalcNumber{1em}{\MMMHeight}{M M M M M M M}\MMMHeight
\end{document}
答案2
有两种方法可以做到这一点:一种是使用\prevgraf
,另一种是手动计算线条。
如果您使用 执行此操作\prevgraf
,则会为您提供上一段中的行数。这仅在您的输入只有一个段落时才有效。我们所做的是使用 将\setbox0
文本放入我们不打印的 vbox 中。在 vbox 中,我们将 设置hsize
为您的宽度,即第二个参数,然后将第一个参数打印为段落。我们手动用 结束段落\par
,并使用 将\xdef
的当前值保存\prevgraf
到您作为第三个参数传递的 cs 中。
\def\CalcNumber#1#2#3{%
\setbox0\vbox{\hsize=#2 \noindent#1\par\xdef#3{\the\prevgraf}}}
如果您的输入超过一个段落,那么您可以使用相同的设置,如下所示:
\makeatletter
\long\def\CalcNumber#1#2#3{%
\setbox0\vbox{\hsize=#2 \noindent#1}}
\@tempcnta=\dimexpr(\ht0+\dp0)/\baselineskip
\xdef#3{\the\@tempcnta}}
\makeatother
与我们的其他方法类似,我们将文本排版在一个框中。我们需要将我们的定义\CalcNumber
为\long
,以便它可以接受多段文本。然后,我们将框的高度和深度相加,并除以\baselineskip
,将其保存在 LaTeX 临时计数寄存器中(这将为我们舍入数字)。然后,我们将其存储在给定的控制序列中,如上所述。
需要注意的是,当您调用宏时,这将使用 baselineskip。您需要考虑字体大小的变化,具体取决于您计划将其用于什么用途。
答案3
值得一提的是,ConTeXt 提供了一个宏\determinenofline{...}
,用于确定内容的行数(在 中排版时\vbox
)。结果存储在计数器中:\noflines
。
这将计算排版行数(而不是倍数的高度(或LaTeX 中\lineheight
所说的)。这里有一个例子来表明:\baselineskip
supp-box.mkiv
\starttext
\determinenoflines{test\\test}
\the\noflines
\determinenoflines{\bfd test\\test}
\the\noflines
\determinenoflines{\definedfont[Sans at 40pt]test\\test}
\the\noflines
\stoptext
所有这三个测试都给出了结果2
。
要计算特定宽度的内容的行数,只需\hsize
为内容设置即可。例如:
\starttext
\vbox{\hsize=3cm \input ward\relax}
\determinenoflines{\hsize=3cm \input ward\relax}
\the\noflines
\stoptext
得出(第一个\vbox
只是为了验证结果)。
答案4
这用来\vsplit
计算行数。唯一令人惊讶的是它在开头intemise
添加了一个空行(和一些负数)。\vspace
\theNLcount
可以通过在宏末尾添加来返回行数。在本例中,我想使用来显示数字\marginpar
,并且它使用\marginparwidth
默认宽度。
由于您一次只想分割一行,因此最好请求尽可能少,因此为 0pt。
\documentclass{article}
\usepackage{amsmath}
\usepackage{blindtext}
\newcounter{NLcount}
\newcommand{\numberoflines}[2][\linewidth]% #1=width (optional), #2=text
{\bgroup
\hsize=#1\relax
\clubpenalty=0
\widowpenalty=0
\displaywidowpenalty=0
\predisplaypenalty=0
\postdisplaypenalty=0
\interlinepenalty=0
\setbox0=\vbox{#2}%
\setcounter{NLcount}{0}%
\loop\ifdim\ht0>0pt
\stepcounter{NLcount}%
\setbox1=\vsplit0 to 0pt
\repeat
\egroup}% \theNLcount
\begin{document}
\numberoflines{above \[x=a\] more text \begin{equation} y=b \end{equation} below}
\hrule\leavevmode\marginpar{\theNLcount{} lines}
above \[x=a\] more text \begin{equation} y=b \end{equation} below
\hrule
\numberoflines{above\newline \rule{1in}{1in}\newline below}
\hrule\leavevmode\marginpar{\theNLcount{} lines}
above\newline \rule{1in}{1in}\newline below
\hrule
\numberoflines{\begin{itemize}
\item One
\item Two
\end{itemize}}
\hrule\leavevmode\marginpar{\theNLcount{} lines}
\begin{itemize}
\item One
\item Two
\end{itemize}
\hrule
\numberoflines{\blindtext}
\hrule\leavevmode\marginpar{\theNLcount{} lines}
\blindtext
\hrule
\numberoflines{\tiny\blindtext}
\hrule\leavevmode\marginpar{\theNLcount{} lines}
{\tiny\blindtext}
\hrule
\newpage
\numberoflines[2in]{\blindtext}
\hrule\noindent\marginpar{\theNLcount{} lines}
\parbox{2in}{\strut\blindtext}
\hrule
\end{document}