![格式化逐字段落](https://linux22.com/image/268332/%E6%A0%BC%E5%BC%8F%E5%8C%96%E9%80%90%E5%AD%97%E6%AE%B5%E8%90%BD.png)
如何格式化逐字段落?即断开、填充和连接输入行以产生全局平衡的输出,每行的长度\textwidth
尽可能接近目标。
使用listings
包我可以断线,但不能连接短线。也就是说,以下
\documentclass{article}
\usepackage{listings}
\lstnewenvironment{exampleA}{\lstset{%
language=,
basicstyle=\ttfamily,
breaklines=true,
prebreak=+,
postbreak=->,
columns=fullflexible,
breakindent=5pt} }{}
\begin{document}
\begin{exampleA}
Long line Long line Long line Long line Long line Long line Long line Long line Long line Long line Long line Long line Long line Long line Long line Long line Long line
Short Line
Short Line
Short Line
\end{exampleA}
\end{document}
生产
我想要实现的功能类似于 LaTeX 默认对段落执行的操作。例如
\documentclass{article}
\newenvironment{exampleB}{\tt}{}
\begin{document}
\begin{exampleB}
Long line Long line Long line Long line Long line Long line Long line Long line Long line Long line Long line Long line Long line Long line Long line Long line Long line
Short Line
Short Line
Short Line
\end{exampleB}
\end{document}
将产生:
使用后一种方法的问题是,我无法在逐字文本中使用特殊符号(如#
或 ) 。因此,我需要使用逐字环境(如或的环境)。(如上所述:在环境中,可以自动换行,但对于环境中,此功能似乎也缺失) %
lstlisting
fancyvrb
Verbatim
lstlisting
Verbatim
编辑:(这是对下面弗兰克的回答的评论)
现在似乎有一个问题,即行变得太短。以下输入
\noindent\hrulefill
\begin{myverbatim}
xxxxxxx xxxx xxxxx: 1234567890123456789012345,
123, 1234567890,
\end{myverbatim}
\noindent\hrulefill\
现在生产
(我现在想在第一行末尾加上单词“123”,因为那里肯定有足够的空间:))
更新
上述问题现已解决,请参阅下面 Frank 的回答中的评论。
答案1
大卫确实比我早了几分钟,但这个版本确实按要求缩进,并且没有产生过满的行(在合理范围内):
\documentclass{article}
\makeatletter
% this defines myverbatim environment. to change name replace "myverbatim" in all places below (strctly speaing it is only necessary in some but ... :-)
\newdimen\outerparindent
\def\myverbatim{%
% fix for \@noligs as the definition in LaTeX is swallowing any following space
\def\do@noligs##1{%
\catcode`##1\active
\begingroup
\lccode`\~`##1\relax
\lowercase{\endgroup\def~{\leavevmode\kern\z@\char`##1 }}}%
% save the \parindent used outside
\outerparindent\parindent
% I'm lazy reusing existing setup of verbatim as much as possible, so obeylines is my way too hook in
\def\obeylines{\rightskip=0pt plus 1fil
\parindent=\outerparindent % if you like a defined \parindent value instead set it here
\let\par\@@par
\leavevmode\indent}%
% different definitions to handle spaces, select one:
\def\@xobeysp{\penalty\z@\char 32 \penalty\z@}% % this produces a visible space
% \let\@xobeysp\space % this version will drop spaces at linebreaks
% \def\@xobeysp{\penalty\z@\mbox{}\space\penalty\z@}% % this will keep spaces after line breaks
%
\@verbatim
\@myverbatimescape\@myverbatimnewline
\frenchspacing\@vobeyspaces\@xmyverbatim}
\let\endmyverbatim\endverbatim
% setting up the behavior of end-off-line: on its one behave like a (special) space,
% two in a row end a paragraph
\begingroup
\catcode`\^^M=\active%
\gdef\@myverbatimnewline{\catcode`\^^M=\active \let^^M\@xmyverbatimnewline}%
\gdef\@xmyverbatimnewline{\@ifnextchar ^^M{\@myverbatimpar}{\@xobeysp}}%
\gdef\@ymyverbatimnewline{\@ifnextchar ^^M{\@myverbatimpar}{}}%
\gdef\@myverbatimpar ^^M{\par%
\vskip\baselineskip% % this line will generate an extra baselineskip per empty line
% comment out if not wanted
\@ymyverbatimnewline}%
% and this part is to get rid of the first ^^M after \begin{verbatim} but not any other
\gdef\@zmyverbatimnewline{\@ifnextchar ^^M{\@zmyverbatimpar}{}}%
\gdef\@zmyverbatimpar^^M{\@ifnextchar ^^M{\@myverbatimpar}{}}%
\endgroup
\begingroup \catcode `|=0 \catcode `[= 1
\catcode`]=2 \catcode `\{=12 \catcode `\}=12
% to support \\ as a line break we need to make \ active and make a lot of extra horrible definitions:
\catcode`\\=13
|gdef|@myverbatimescape[|catcode`|\|active|let\|@myverbatimbslash]
% using \@ifnextchar is ok because "space" is active too so isn't gobbled in case of "\ \"
|gdef|@myverbatimbslash[|@ifnextchar\[|@xmyverbatimbslash][|string\]]
|gdef|@xmyverbatimbslash\[|\]
% a newline char before the end of the environment also needs some special handling therefore the gymnastics
|catcode`|^^M=|active
|long|gdef|@xmyverbatim#1\end{myverbatim}[|@zmyverbatimnewline#1^^M|vskip-|lastskip|vskip|z@skip|end[myverbatim]]%
|endgroup
\makeatother
\begin{document}
Normal line Normal line Normal line Normal line Normal line Normal line Normal line Normal line Normal line
Normal line Normal line Normal line Normal line Normal line Normal line Normal line Normal line Normal line
\begin{myverbatim}
Long line Long line with \ or \ \ is okay but \\now breaks the line Long line Long line Long line Long line Long line Long line Long line Long line Long line Long line
Long line Long line Long line Long line Long line
Short Line
Short Line # ^& %
Short Line
\end{myverbatim}
\end{document}
根据评论中的要求,上面的代码现在支持\\
换行符,而单独使用\
将生成反斜杠。在这种情况下,代码会变得有点混乱,但这就是改变 catcodes 的代价 :-)
输出将是
更新
最初我之所以设置\rightskip
为,0pt plus 4em
主要是因为我忘记了在这种环境下不会使用连字符。因此,如果“单词”较长,则会导致行数过满。因此,我现在将其改为,0pt plus 1fil
只要所有内容都短于整行,就不会出现行数过满的情况。
当然,换行只会发生在空格处,因此在 OP 给出的例子中,它会在第一组数字后换行,因为第二组数字已经使行溢出。
更新 2
事实证明,上述解决方案会吞掉,
输入中 a 后面的一个空格(实际上是在一组特定字符之后)。这种奇怪的行为是由于我会声称TeXbook 中的文档错误(第 44 页),即
\chardef\%=`\%
只是一种更有效的方式实现相同的效果
\def\%{\char`\%}
事实上并非如此。后一个定义会吞掉后面可选的空格,而前一个不会!这就产生了问题,因为 verbatim 中的逗号是活动的,以防止连字,它的定义由以下代码生成
\def\do@noligs#1{%
\catcode`#1\active
\begingroup
\lccode`\~`#1\relax
\lowercase{\endgroup\def~{\leavevmode\kern\z@\char`#1}}}
这意味着它会扩展为
\leavevmode\kern\z@\char`\,
因此后面的空格会被吞掉。因此,要么必须在定义中添加额外的空格,\do@noligs
要么必须进行修改\xobeysp
以扩展为类似
\def\@xobeysp{\kern\z@\space}%
\char
因此,在和 之间总会有一些东西\space
。后一种方法不适用于源代码中换行符产生的空格,因为默认情况下,它会被转换为直空格(会被吞掉)。因此,要么改变^^M
(行尾)的行为,要么必须使用 的修复\do@noligs
。
更新 3
\@xobeysp
哦,好吧 :-) 在普通段落中(这也是最初要求的),换行符处的空格会消失,这就是当前解决方案所做的。如果不希望这样,那么一种可能性是更改上述代码中的定义。
假设我们有以下输入:
\begin{myverbatim}
xxxxxxxxxxx xxxx xxxxx: 1234567890123456789012345, 123, 1234567890,
xxxxxxxxxxx xxxx xxxxx: 1234567890123456789012345, \\ 123, 1234567890,
xxxxxxxxxxx xxxx xxxxx: 1234567890123456789012345, \\
123, 1234567890,
\end{myverbatim}
上述当前解决方案导致
即自然换行符和强制换行符处的空格消失。现在如果我们改用以下定义:
\def\@xobeysp{\penalty\z@\char 32 \penalty\z@}%
这将排版字体中位置 32 的字符(空格),并在其前后留有空格,然后我们得到以下输出:
两侧都有惩罚,因此可以在空格字符之前或之后进行中断。默认情况下,最佳中断是最后一个,这意味着空格往往会出现在右侧,但在紧急情况下,可以在连续的第一个空格字符之前进行中断。
或者我们也可以使用:
\def\@xobeysp{\mbox{}\space\penalty\z@}%
在这种情况下,空格不会消失在左边距,我们得到相同的结果,只是空格现在“再次变成空白”。
(顺便说一下缩进是 15 点,打字机中的一个空格似乎是 5.24995pt,这意味着缩进接近但不完全是 3 个空格,所以这可能是一个需要改进的地方)
更新 4
随着 OP 进一步明确他在寻找什么,一个新的要求出现了:
- 空行应该导致输出中出现空行,即,它不应该只是结束段落(就像在 TeX 中通常发生的那样),而是明确地生成一个空行,并因此生成 2 个空行等等。
因此,我再次更新了上述代码,以包含对行尾处理的明确处理。因为这^^M
被激活(即调用命令)而不是执行其标准魔法。然后该命令会查看它后面是否跟着另一个^^M
。如果没有,它将执行\@xobeysp
(生成在正常空格的情况下设置的任何内容)。另一方面,如果后面跟着另一个换行符(即,如果我们有一个空行),它将生成一个\par
后跟,以\vskip\baselineskip
生成一个相当于空行的垂直空间。然后它继续寻找进一步的换行符,以便在必要时生成更多的垂直空间。
有两种边界情况需要特殊处理,这会使代码变得更糟:\begin{myverbatim}
通常,换行符之后不应触发此行为,而\end{myverbatim}
换行符之前不应生成空格。上面的代码很好地处理了第一种情况。如果第二种情况没有\end{myverbatim}
单独一行,则无法正常工作,但就是这样……这个答案已经比预期的要长得多了 :-)
如果我们再次使用上面的例子但添加两个空行我们现在得到以下内容:
答案2
verbatim
您只想要不包含该部分的定义\obeylines
:
!
\documentclass{article}
\usepackage[T1]{fontenc}
\makeatletter
\newenvironment{exB}{%
\trivlist
\item\relax
\let\do\@makeother \dospecials
\verbatim@font \@noligs
\hyphenchar\font\m@ne
\catcode`\ \active
\catcode`\^^M\active
\catcode`\\\active
\lccode`\~`\\%
\lowercase{\let~\getendxB}%
\lccode`\~`\^^M%
\lowercase{\let~\space}%
}
{\endtrivlist}
\def\getendxB#1#2#3#4#5#6#7#8{%
\def\a{#1#2#3#4#5#6#7#8}%
\ifx\a\endxB
\end{exB}%
\else
\textbackslash
\expandafter\a
\fi
}
\edef\endxB{end\string{exB\string}}
\makeatother
\begin{document}
\begin{exB}
Long line Long line \ # ^ & Long line Long line Long line Long line Long line Long line Long line Long line Long line Long line Long line Long line Long line Long line Long line % ^ & $ \ ---
Short Line
Short Line
Short Line
\end{exB}
\end{document}