截断多行文本

截断多行文本

我们可以使用截短包截断一段文本以便它适合例如 5 厘米宽的盒子。

但是,该包只能处理一行文本。

如果我有一个(可能很长的)文本,我想将其排版在 5 厘米宽的小页面中,右边参差不齐,以便它最多使用 6 行?

基本上,我只想让 LaTeX 排版一段文本,以便我们像往常一样最多添加 5 次换行符,然后根据需要截断最后一行(使用某种截断标记,如“...”)。

我知道这对于正确对齐的文本来说很难实现,但对于右边不整齐的文本来说这可能是可行的?


编辑:为了澄清起见,如果文本被截断,我想生成如下输出:

Lorem ipsum dolor sit amet,
consectetur adipiscing
elit, sed do eiusmod tempor
incididunt ut labore et
dolore magna aliqua. Ut
enim ad minim veniam, ...

(截断标记是最后一行的一部分,而不是单独的一行。)

答案1

根据我在这里的回答:是否有一个包可以截断超出固定宽度和高度的文本?

我介绍\trunclines{<lines>}{<width>}{<content>}如何制作给定宽度和给定文本行的截断完全对齐的框省略号。

\documentclass{article}
\usepackage{trimclip,lipsum,stackengine}
\newcommand\trunclines[3]{%
  \setbox0=\hbox{\parbox[t]{#2}{\strut#3}}%
  \stackengine{0pt}{\clipbox{0pt \dimexpr\dp0-#1\baselineskip%
    -\dp\strutbox+\baselineskip\relax%
    {} 0in 0pt}{\copy0}}{...\strut}{U}{l}{F}{F}{S}%
}
\begin{document}
\textsf{original text in 5cm wide parbox}\smallskip

\parbox{5cm}{\lipsum[4]}\bigskip

\textsf{5cm wide parbox, truncated to 8 lines + ellipsis}\smallskip

\trunclines{8}{5cm}{\lipsum[4]}\bigskip

\textsf{or 3 lines, ragged right}\smallskip

\trunclines{3}{5cm}{\raggedright\lipsum[4]}
\end{document}

在此处输入图片描述

答案2

这是所有基于 e-TeX 的编译器的简单版本,它定义了一个命令\shortvbox{number of lines}{width}{text}。这个想法基于第 5.9.6 节中描述的垂直框剖析算法TeX 按主题分类

第一步是照常在\vbox给定宽度的 a 中设置框文本(实际上\vtop使用 a 来将框对齐到其第一行而不是最后一行,但这并不重要)。请注意,这也允许设置完全对齐的文本。接下来是两次运行解剖命令\shortvbox@。该命令运行一个循环,在每次迭代时检查添加到 vbox 的最后一个节点。为此,我们使用 e-TeX 命令,\lastnodetype它会给我们一个数字,指示哪种节点是当前列表中的最后一个节点(hbox、glue、penalty 等)。根据节点类型,我们使用适当的命令来移除并稍后重新组装最终的框。

如上所述,这里需要两次运行。这是因为我们从下往上遍历框,但需要第一次n最终输出的框的行数。因此,在第一次运行(由参数指示C)时,我们仅计算列表中出现的行数/水平框数并跳过重新组装。在第二次运行中,我们实际上重新组装了垂直框,现在倒着计算行数。跳过最终输出中所需行数之后出现的所有行,其他行将添加到结果框中。最后一步是输出重新组装的框,并\ldots在末尾添加一些行。

完整示例代码:

\documentclass{article}

\usepackage{lipsum}

\makeatletter
\endlinechar=-1

\newcount\shortvbox@lines

% #1: Number of lines in the final box
% #2: Width of the box
% #3: Text
\long\def\shortvbox#1#2#3{
    \begingroup
    \setbox0=\vtop{\hsize=#2 #3\par}
    \setbox2=\vtop{\unvcopy0\shortvbox@{#1}C}
    \setbox2=\vtop{\unvcopy0\shortvbox@{#1}B}
    \vtop{\hsize=#2\unvbox1\par\noindent\strut\ldots\par}
    \endgroup
}

% #1: number of lines to reassemble
% #2: C = count lines only, otherwise also build box
\def\shortvbox@#1#2{
    \begingroup
    \global\setbox1=\vtop{}
    \if#2C
        \global\shortvbox@lines=0\relax
    \fi
    \loop
        \count1=\lastnodetype
        \ifnum\count1=1\relax  % hbox
            \setbox10=\lastbox
            \global\advance\shortvbox@lines by \if#2C 1\else -1\fi
        \fi
        \ifnum\count1=11\relax  % glue
            \skip10=\lastskip
            \unskip
        \fi
        \ifnum\count1=13\relax  % penalty
            \count10=\lastpenalty
            \unpenalty
        \fi
%    \message{lastnodetype=\the\count1}
    \edef\@stop{
        \ifnum\count1<0 0\else
        \ifnum\count1=1 1\else
        \ifnum\count1=11 1\else
        \ifnum\count1=13 1\else
        0% stop early if we don't know how to handle the last node
        \fi\fi\fi\fi
    }
    \if\@stop0
    \else
        \if#2C\else
        \global\setbox1=\vtop{
            \ifnum\shortvbox@lines<#1\relax
                \ifnum\count1=1\relax  % hbox
                    \box10
                \fi
                \ifnum\count1=11\relax  % glue
                    \vskip\skip10
                \fi
                \ifnum\count1=13\relax  % penalty
                    \penalty\count10
                \fi
                \unvbox1
            \fi
        }
        \fi
    \repeat
    \endgroup
}

\endlinechar=`\^^M
\makeatother

\begin{document}

\fbox{\shortvbox{7}{5cm}{What if I have got a (possibly long) text that I would like to typeset in a 5cm wide minipage, \textbf{ragged right}, so that it uses at most 6 lines?
\vskip2ex
Basically, I would just like to ask \LaTeX to typeset a piece of text so that we add line breaks as usual at most 5 times, and then the last line is truncated (with some kind of a truncation marker such as \texttt{"..."}) if needed.}}
\hskip1em
\fbox{\shortvbox{4}{5cm}{\raggedright What if I have got a (possibly long) text that I would like to typeset in a 5cm wide minipage, \textbf{ragged right}, so that it uses at most 6 lines?
\vskip2ex
Basically, I would just like to ask \LaTeX to typeset a piece of text so that we add line breaks as usual at most 5 times, and then the last line is truncated (with some kind of a truncation marker such as \texttt{"..."}) if needed.}}

\shortvbox{4}{\linewidth}{\lipsum}

\end{document}

在此处输入图片描述

这个版本应该更像是一个概念验证实现。例如,在当前版本中,它仅适用于简单的文本段落。当然,可以添加更多节点类型。另一件事是连字符可能出现在最后一行之前。我想摆脱它需要更多的努力。

相关内容