换句话说,
如何允许任何可见字符后出现断行?...[当水平框的长度总和等于时,行就会断开
\linewidth
]我如何禁用或影响 TeX 间距/换行算法以允许在行满时进行换行?
这是之前提出的一个问题的后续问题我怎样才能让 LaTeX 识别我的宏中的空格(catcode 10)?。
我遇到了两个问题:
- 处理主动角色
- 处理记忆
活动字符会导致问题(正如预期的那样)。David Carlisle 提到我可以使用\noexpand
来正确处理活动字符。我试过了,但无济于事。此外,由于整个文本都被输入到宏中,因此整个内容在实际发送之前都存储在内存中。
这个东西是如何工作的:
\treateachletterasword
将其全部输入发送到扫描仪(这是内存占用大的问题)- 扫描仪通过抓取令牌
\xscan
将单个令牌发送到\xxscan
\afterassignment
\xxscan
测试 catcode 并相应地工作- 最后,
\xxscan
调用\xscan
下一个标记(当遇到等效项时,此循环会中断\relax
- 可能是也可能不是最佳解决方案)
代码
(David Carlisle 提到\hskip 0pt plus 1sp minus 1sp
,我应该使用而不是\hskip 0pt
,或者更好的方法\penalty0
来提高效率。这样,TeX 就不需要为每一行进行太多计算了。)
\documentclass{article}
\usepackage{fontspec}
\newfontfamily\monofont{Inconsolatazi4-Regular.otf}% let's pretend this is not a mono font for practice
%\makeatletter % or \catcode"0040=11
\long\def\treateachletterasword#1{\xscan #1\relax}% calls initial \xscan on first char
\def\xscan{\afterassignment\xxscan\let\token= }% assign next single token to \token and send it to \xxscan
\def\xxscan{%
\monofont% apply mono font
\ifx\token\relax\normalfont\else%test for end-of-line or end of group and switch back to normal font
\ifcat\token\space%
\token% token is catcode 10
\spaceskip=.5em% remove glue from space for fixed-width space and precise control
\xspaceskip=.5em% remove glue from space for fixed-width space and precise control
\else%
\ifcat\token\active% deal with active character backslash
%\noexpand\token
\textbackslash% for lack of a solution, this macro should be expanded
\else
\token\hskip 0pt plus 1sp minus 1sp% add glue to any non-catcode 10 (space)
\fi
\fi
\expandafter\xscan%calls subsequent xscan until next char representd by \token = \relax
\fi}
%\makeatother % or \catcode"0040=12
\parindent=0pt % remove firstpar autoindent
\obeylines% insert \par after each end-of-line (^^M)
\begin{document}
\section{SomeTeXFile.tex}\subsection{Typesetting Failure}
\treateachletterasword{
This is XeTeX, Version 3.14159265-2.6-0.99996 (TeX Live 2016) (preloaded format=xelatex 2016.6.27) 11 AUG 2017 13:15
entering extended mode
restricted \char"005C{}write18 enabled.
file:line:error style messages enabled.
\%\&-line parsing enabled.
**ThirdPartyLicenses.tex
(./ThirdPartyLicenses.tex
LaTeX2e <2016/03/31> patch level 2
Babel <3.9r> and hyphenation patterns for 83 language(s) loaded.
(../../DocumentClass.tex (/usr/local/texlive/2016/texmf-dist/tex/latex/base/article.cls
Document Class: article 2014/09/29 v1.4h Standard LaTeX document class
(/usr/local/texlive/2016/texmf-dist/tex/latex/base/size10.clo
File: size10.clo 2014/09/29 v1.4h Standard LaTeX file (size option)
)
\char"005C{}c@part=\char"005C{}count79
\char"005C{}c@section=\char"005C{}count80
\char"005C{}c@subsection=\char"005C{}count81
\char"005C{}c@subsubsection=\char"005C{}count82
\char"005C{}c@paragraph=\char"005C{}count83
\char"005C{}c@subparagraph=\char"005C{}count84
\char"005C{}c@figure=\char"005C{}count85
\char"005C{}c@table=\char"005C{}count86
\char"005C{}abovecaptionskip=\char"005C{}skip41
\char"005C{}belowcaptionskip=\char"005C{}skip42
\char"005C{}bibindent=\char"005C{}dimen102
}
\end{document}
输出
注意
- 通过向每个非 catcode 10(活动字符除外)添加粘连,并从每个 catcode 10(空格)中删除粘连,TeX 会用尽可能多的方框填充行,而不会拉伸空格。这实际上禁用了 TeX 美化机制。
- 宏应该被扩展,但实际上并没有。
\"005C
例如,请参阅。 - 我还忘了说另一点:尽管有,新行还是会被忽略
\obeylines
。这是因为}
和\par
(来自^^M
)都会产生\relax
。这是不受欢迎的。
答案1
我能够使用 XeTeX 独有的概念来解决这个问题:David Carlisle 建议的字符和字符间类别。Will Robertson 和 Khaled Hosny 很好地记录了此功能,http://mirror.unl.edu/ctan/info/xetexref/xetex-reference.pdf。
似乎有两种方法可以使用设置在标记之间注入字符的分隔符\XeTeXinterchartoks
:
- 角色槽与角色间类别之间。例如,使用
\XeTeXcharclass
分配`\A
给 a\macro
并最终将注入定义为\XeTeXinterchartoks \macro 0 = {\penalty0\relax}
。当“A”字符后跟 0 类字符时,每次出现该字符时都会增加 0 的惩罚。 - 字符间类别之间。例如,字符间类别是一个从 0 到 255 的数字,代表一组相关字符。例如
\XeTeXinterchartoks 0 0 = {\penalty0\relax}
。不幸的是,文档的这一部分对我来说不清楚,因此我进行了快速搜索,找到了另一篇对字符间类别有更多说明的文档:https://github.com/zohooo/interchar/blob/master/interchar.tex。
代码
我在这个版本中删除了标记扫描器。它不再是必需的,可能是因为该\XeTeXinterchartoks
功能发生在类别代码分配之前或期间。我不确定它究竟是如何工作的。唯一的缺点是我失去了对空格的控制。可能有一种方法可以使用字符类再次实现此控制。
\documentclass{article}
\usepackage{fontspec}
\usepackage{lipsum}
\newfontfamily\monofont{Inconsolatazi4-Regular.otf}% let's pretend this is not a mono font for practice
\long\def\treateachletterasword{%
\bgroup
\XeTeXinterchartokenstate=1% Enable Character Classes (unique to xelatex) 0=off 1=on
\XeTeXinterchartoks 0 0 = {\penalty0\relax}% Set token to be inserted between interchar class 0 and interchar class 0
\monofont% Set monospaced font
\setlength{\parindent}{0pt}% rm new par indents
\obeylines% \catcode`\^^M\active \let ^^M\par
}%
\def\endtreateachletterasword{\egroup}
\begin{document}
\section{SomeTeXFile.tex}\subsection{Typesetting Failure}
\begin{treateachletterasword}
This is XeTeX, Version 3.14159265-2.6-0.99996 (TeX Live 2016) (preloaded format=xelatex 2016.6.27) 11 AUG 2017 13:15
entering extended mode
restricted \char"005C{}write18 enabled.
file:line:error style messages enabled.
\%\&-line parsing enabled.
**ThirdPartyLicenses.tex
(./ThirdPartyLicenses.tex
LaTeX2e <2016/03/31> patch level 2
Babel <3.9r> and hyphenation patterns for 83 language(s) loaded.
(../../DocumentClass.tex (/usr/local/texlive/2016/texmf-dist/tex/latex/base/article.cls
Document Class: article 2014/09/29 v1.4h Standard LaTeX document class
(/usr/local/texlive/2016/texmf-dist/tex/latex/base/size10.clo
File: size10.clo 2014/09/29 v1.4h Standard LaTeX file (size option)
)
\char"005C{}c@part=\char"005C{}count79
\char"005C{}c@section=\char"005C{}count80
\char"005C{}c@subsection=\char"005C{}count81
\char"005C{}c@subsubsection=\char"005C{}count82
\char"005C{}c@paragraph=\char"005C{}count83
\char"005C{}c@subparagraph=\char"005C{}count84
\char"005C{}c@figure=\char"005C{}count85
\char"005C{}c@table=\char"005C{}count86
\char"005C{}abovecaptionskip=\char"005C{}skip41
\char"005C{}belowcaptionskip=\char"005C{}skip42
\char"005C{}bibindent=\char"005C{}dimen102
\end{treateachletterasword}
\end{document}
输出
当心!后面\relax
的\penalty0
是必需的,否则连续的数字将被 TeX 吞噬,如输出图像所示。我已经在代码中更正了这个错误。此外,我已经添加了\setlength{\parindent}{0pt}
删除由 引起的每行新代码后的新段落缩进\obeylines
。