问题
是否可以获取多段文本的宽度?例如,如果我想获取单段文本的宽度,我可以执行以下操作:
\documentclass[a4paper]{article}
\begin{document}
\newlength{\mytextwidth}
\settowidth{\mytextwidth}{some text}
\end{document}
但是,如果该文本有多个段落,则不起作用。例如,如果我执行以下操作,则会收到错误Paragraph ended before \@settodim was complete. <to be read again>
:
\documentclass[a4paper]{article}
\begin{document}
\newlength{\testlen}
\settowidth{\testlen}{
some text
some longer text
}
\end{document}
我想知道是否有办法获取文本内容(即使它是多段文本)的最宽宽度。因此,对于第一个例子,它仍然会给出的长度,some text
而对于第二个例子,它会给出的长度some longer text
。
语境
以上是我认为我正在尝试做的事情所需要的,但是为了以防万一它有用,我还会添加我对此感兴趣的背景信息。
我正在尝试编写一个命令,用于接收左侧和右侧的文本内容。内容将分为两列,左侧内容与左侧对齐,右侧内容与右侧对齐。列将自行调整以在一行中容纳尽可能多的文本,然后再换行到下一行。
因此,如果左侧内容比右侧内容长得多,则右侧列的宽度将比左侧列短得多,反之亦然。如果两侧的内容都不需要一半的行宽,则每列的宽度将只是行宽的一半。同样,如果两侧的内容都需要至少一半的行宽,则每列的宽度将只是行宽的一半。
以下是我所拥有的,适用于单段文本:
\documentclass[a4paper]{article}
\begin{document}
% length variables for the command below
\newlength{\leftwidth}
\newlength{\rightwidth}
\newlength{\halfline}
\newlength{\leftexcess}
\newlength{\rightexcess}
% arg1: flush left minipage content
% arg2: flush right minipage content
\newcommand{\mycmd}[2]{
\settowidth{\leftwidth}{#1}
\settowidth{\rightwidth}{#2}
\setlength{\halfline}{0.5\linewidth}
% if the left side content doesn't need at least half of the
% line width, store the excess leftover space
\ifdim\leftwidth<\halfline\relax
\setlength{\leftexcess}{\dimexpr(\halfline-\leftwidth)}
\else
\setlength{\leftexcess}{0pt}
\fi
% if the right side content doesn't need at least half of the
% line width, store the excess leftover space
\ifdim\rightwidth<\halfline\relax
\setlength{\rightexcess}{\dimexpr(\halfline-\rightwidth)}
\else
\setlength{\rightexcess}{0pt}
\fi
% neither side has any leftover space, so each column just gets half the line
\ifdim\rightexcess=0pt\relax
\ifdim\leftexcess=0pt\relax
\setlength{\leftwidth}{\halfline}
\setlength{\rightwidth}{\halfline}
\fi
\fi
% neither side needs any extra space to fit, so each column just gets half the line
\ifdim\leftexcess>0pt\relax
\ifdim\rightexcess>0pt\relax
\setlength{\leftwidth}{\halfline}
\setlength{\rightwidth}{\halfline}
\fi
\fi
% if the right side has space to spare and the left side needs more space than
% just half the line, give the left side the excess space from the right side.
\ifdim\rightexcess>0pt\relax
\ifdim\leftwidth>\halfline\relax
\setlength{\leftwidth}{\dimexpr(\halfline+\rightexcess)}
\fi
\fi
% if the left side has space to spare and the right side needs more space than
% just half the line, give the right side the excess space from the left side.
\ifdim\leftexcess>0pt\relax
\ifdim\rightwidth>\halfline\relax
\setlength{\rightwidth}{\dimexpr(\halfline+\leftexcess)}
\fi
\fi
% command output
\par\noindent%
\begin{minipage}[t]{\leftwidth}%
\begin{flushleft}%
#1
\end{flushleft}%
\end{minipage}%
\begin{minipage}[t]{\rightwidth}%
\begin{flushright}%
#2
\end{flushright}%
\end{minipage}%
}
% works fine
\mycmd
{
left left left left left left left left left left left left left left left
}
{
right right
}
% errors with: Paragraph ended before \@settodim was complete.
% \mycmd
% {
% left left left left left left left left left left left left left left left
% left left left
% }
% {
% right right
% }
\end{document}
答案1
这varwidth
包裹提供了一个类似名称的varwidth
环境,其作用类似于minipage
。它接受一个宽度参数,如minipage
,但不是将输出固定为此宽度,而是如果内容可以适合这个较小的宽度,它会将结果框的宽度缩小到更小的宽度。因此,您可以指定可能的最大宽度(\maxdimen
),并将varwidth
其缩小到您需要的宽度 - 环境主体内任何段落的最大宽度。
\documentclass{article}
\usepackage{varwidth}
\newsavebox{\mybox}
\newlength{\mylen}
\begin{document}
\settowidth{\mylen}{left left left left left left left left left left left left left left left}%
1: \the\mylen
\begin{lrbox}{\mybox}
\begin{varwidth}{\maxdimen}
left left left left left left left left left left left left left left left
right right
\end{varwidth}
\end{lrbox}%
2: \the\wd\mybox
\end{document}
答案2
tabulary
可以用来获得类似的效果。
\documentclass{article}
\usepackage{tabulary}
\newcommand\mycmd[2]{%
\begin{center}
\begin{tabulary}{\textwidth}{@{}LR@{}}
#1
\end{tabulary}
\end{center}}
\begin{document}
\mycmd
{
left left left left left left left left left left left left left left left
left left left
}
{
right right
}
\mycmd
{
left left left left left
left left left
}
{
right right
}
\mycmd
{
left left left left left left left left left left left left left left left
left left left left left left left left left left left left left left left
left left left
}
{
right right
}
\mycmd
{
left left left left left left left left left left left left left left left
left left left
}
{
right right right right right right right right right right right right right right
right right right right right right right right right right right right right right
right right right right right right right right right right right right right right
right right right right right right right right right right right right right right
right right right right right right right right right right right right right right
}
\end{document}
答案3
在这里,我计算了所有 cat-11 和 12 标记的宽度,以及\parindent
与段落相关的宽度(我绕过了任何宏扩展并忽略了它们的宽度)。在 中\balance
,我进行数学运算以计算每个宽度与总宽度的比率。
我创建了小页面,使用指定的可用线宽分数来根据这些比率设置小页面中的部分。由于不知道段落末尾有多少空白空间,我添加了 .25\usablewidth
作为非常近似的平均值。因此,如果双方的段落数量不同,这可能会有点麻烦。
另外,在这一点上,我还没有考虑到非常短的条目,宽度小于一条线...如果一个条目非常短而另一个条目非常长,我不确定通用算法应该如何处理这种情况。
\documentclass{article}
\usepackage{tokcycle}
\newlength\Xwd
\newlength\Ywd
\edef\svparindent{\the\parindent}
\newcommand\addtowd[2]{\sbox0{#2}\addtolength #1{\wd0}}
\newcommand\countwidth[3]{%
\def#1{#3}%
\setlength#2{0pt}%
\tokcycle
{\tctestifcatnx A##1{\addtowd{#2}{##1}}
{\tctestifcatnx.##1{\addtowd{#2}{##1}}{}}\addcytoks{##1}}
{\processtoks{##1}}
{\tctestifx\par##1{\addtolength{#2}{%
\dimexpr\parindent+.25\usablewidth}}{}\addcytoks{##1}}
{\addtowd{#2}{##1}\addcytoks{##1}}
{#3}%
}
\newlength\Awd
\newlength\Bwd
\newlength\ABwd
\newlength\usablewidth
\usablewidth=.9\textwidth
\def\truncdec#1.#2\relax{#1}
\makeatletter
\newcommand\balance[4]{%
\Awd=#2\relax
\Bwd=#4\relax
\ABwd=\dimexpr\Awd+\Bwd\relax
\edef\ABcnt{\strip@pt\ABwd}
\divide\Awd by \expandafter\truncdec\ABcnt\relax
\divide\Bwd by \expandafter\truncdec\ABcnt\relax
\edef\Apct{\strip@pt\Awd}%
\edef\Bpct{\strip@pt\Bwd}%
\par\noindent
\begin{minipage}[t]{\Apct\usablewidth}
\parindent=\svparindent#1\end{minipage}%
\hfill
\begin{minipage}[t]{\Bpct\usablewidth}
\parindent=\svparindent#3\end{minipage}%
\bigskip
}
\makeatother
\begin{document}
\countwidth{\X}{\Xwd}{This is a test of blah bla blah.
This is a test of blah bla blah.
This is a test of blah bla blah.
This is a test of blah bla blah.
This is a test of blah bla blah.
This is a test of blah bla blah.}
\countwidth{\Y}{\Ywd}{This is a test of blah bla blah.
This is a test of blah bla blah.
This is a test of blah bla blah.}
\balance{\X}{\Xwd}{\Y}{\Ywd}
\countwidth{\Y}{\Ywd}{This is a test of blah bla blah.
This is a test of blah bla blah.
This is a test of blah bla blah.
This is a test of blah bla blah.
This is a test of blah bla blah.
This is a test of blah bla blah.
This is a test of blah bla blah.
This is a test of blah bla blah.
This is a test of blah bla blah.
This is a test of blah bla blah.
This is a test of blah bla blah.
This is a test of blah bla blah.
This is a test of blah bla blah.
This is a test of blah bla blah.
This is a test of blah bla blah.
This is a test of blah bla blah.
This is a test of blah bla blah.
This is a test of blah bla blah.}
\balance{\X}{\Xwd}{\Y}{\Ywd}
\countwidth{\Y}{\Ywd}{This is a test of blah bla blah.
This is a test of blah bla blah.
This is a test of blah bla blah.
This is a test of blah bla blah.
This is a test of blah bla blah.
This is a test of blah bla blah.
This is a test of blah bla blah.
This is a test of blah bla blah.
This is a test of blah bla blah.
This is a test of blah bla blah.
This is a test of blah bla blah.
This is a test of blah bla blah.}
\balance{\X}{\Xwd}{\Y}{\Ywd}
\end{document}