我经常从 Word 转换文档,但经常忘记转义%
,导致部分文本丢失。因此,我希望在主文档正文中发生以下情况:
- 没有
\%
按预期工作; - 单独
%
导致错误; - 双重
%%
行为就像一条评论。
您认为这可行吗?我认为可以通过制作%
catcodeactive
并更改代码(如果下一个代码%
也如此)来实现,然后根据此代码将其更改comment
为其余代码。
起点/MWE:
\documentclass{article}
\usepackage{lipsum}
%\usepackage{lipsum} % should cause no error
\begin{document}
Hello!
I use to forget to escape up to 70 % of my percent-signs, which causes missing ends of sentences. So I would like this to cause error.
%% On the other hand, sometimes I really need to make a comment, so I want to use a double-percent-sign for that.
And of course, the 30 \% of escaped percent-signs should work correctly.
\lipsum
\end{document}
答案1
我不知道这是否可以通过 LuaTeX 实现(也许可以)。但在 (pdf)TeX 下,这无法完全实现。
首先让我们回顾一下注释是如何工作的。TeX 读取一行输入,在开始将字符转换为标记之前,它会做一些工作。
它会丢弃操作系统提供的记录结束字节(如果有的话;有些旧操作系统没有它)以及其后行中剩余的所有内容。
它会丢弃记录末尾可能保留的所有空格(以及基于 Web2C 的实现下最常用的制表符)。这与类别代码无关,因为它们尚未附加到字符上。
它在记录末尾添加当前值
\endlinechar
(如果参数为负数或者超出引擎相关的最大值,则为 none,对于 TeX 为 255,pdftex
对于0x1FFFFF
XeTeX 和 LuaTeX 为)。它按照当前规定执行状态对于类别代码 5 和 10 个字符;在正常情况下,它会丢弃初始空格并且可能插入一个
\par
标记(有关详细信息,请参阅 TeXbook 或 TeX by Topic)。现在它开始标记,并且在这里注释被丢弃:类别代码 14 的字符会导致 TeX 忽略它以及直到行尾的所有内容(包括添加的内容)
\endlinechar
。
有人可能会想将其定义%
为活动字符,它会寻找后续字符%
,在本例中,在输入中插入类别代码 14 的字符。也许只在环境中这样做document
,这样注释在序言中就可以正常工作。这在两个方面都失败了。
如果 TeX 没有扩展宏,那么这
%%
对宏的识别就会太晚。例如\parbox{abc %% def}
不会按预期工作,因为
%
当参数被吸收时,活动不会扩展\parbox
。即使确保没有
%%
宏的参数中不存在任何对,它也是不可能的将字符代码为 14 的字符放入宏的替换文本中:不类别代码 0、5、9、14 和 15 个字符可以到达 TeX 的“胃”,在那里,宏替换文本被检查并存储在内存中(TeXbook,练习 7.3)。
有人可能会想通过定义%
来寻找以下内容来克服这一限制%
,在本例中,发出一个宏,\gobbletoend
定义如下:
\def\gobbletoend%1^^M{}
但遗憾的是,由于两个原因,这无法实现:^^M
类别代码 5)不能到达 TeX 的胃部,而且 TeX 甚至看不到这对括号,因为当吸收那条线时,它会看到^^M
哪个是ASCII 行尾,它会将其与行的其余部分一起丢弃。因此,宏不能将其参数用类别代码 5 分隔^^M
,如下所示\obeylines
does,但你不希望每个没有以 开头的行尾%%
都有一个最后的\par
,所以定义应该更加复杂。
一种可能的方法是像以下示例中那样操作:
\documentclass{article}
\usepackage{amsmath}
\makeatletter
\begingroup\lccode`~=`\%
\lowercase{\endgroup\def~{\new@ifnextchar~\tohecz@comment\%}}
\def\tohecz@comment{\catcode`\^^M=3 \tohecz@commentignore}
\begingroup\lccode`$=`\^^M
\lowercase{\endgroup\def\tohecz@commentignore#1$}{\catcode`\^^M=5 }
\makeatother
\begin{document}
\catcode`\%=\active
abc %% def
abc % def
abc %
def
\end{document}
Kant 段落只是为了表明段落正确终止;\new@ifnextchar
fromamsmath
用于避免吞噬空格。不过回想一下,%%
不能出现在命令的参数中。
答案2
ConTeXt 提供了一个宏\asciimode
(和一个环境\startasciimode
... ),它使除和之外\stopasciimode
的所有字符都表现为普通字符。在这个环境中,表现为普通字符,表现为注释字符。\
{
}
%
%%
笔记:%
并%%
在宏的参数中正常工作。
\setuppapersize[A7]
\starttext
\rightaligned{\asciimode Hello! %World
%% This is a comment
}
% Normal comment
\asciimode
\rightaligned{Hello! again %World
%% This is a comment
}
I use to forget to escape up to 70 % of my percent-signs, which causes missing
ends of sentences. asciimode simply typesets them corrects. And also typesets
all special characters # & $ correctly.
%% On the other hand, sometimes I really need to make a comment, so I want to
%% use a double-percent-sign for that.
And of course, the 30 \% of escaped percent-signs should work correctly.
\stoptext
答案3
我对更改这样的设置持谨慎态度。我不确定这样做会引发什么其他问题。
%
我建议使用正则表达式来查找所有未转义的单个实例。
如果您使用的是 Unix,那么grep % doc.tex | grep -v %% | grep -v '\\%'
应该这样做。或者,如果您的文本编辑器可以根据正则表达式进行查找和替换,那么您应该能够轻松地更改它们。
答案4
这是使用 LuaTeX 的 LaTeX 解决方案。调用\CheckPercent
以启用该功能并\StopCheckPercent
禁用它。
\documentclass{article}
\usepackage{fontspec}
\usepackage{luacode}
\begin{luacode*}
-- Prepare LPeg pattern
local percent = lpeg.P('%') -- a percent character
local normal_char = lpeg.P(1) - lpeg.S('\\%') -- any character that isn't \ or %
local command = lpeg.P('\\') * lpeg.P(1) -- \ followed by any character
local prefix = (normal_char+command)^0 -- normal_char or command, 0 or more times
local bad_percent = prefix * percent -- prefix followed by %
-- Callback to check for a bad percent character
function check_lone_percent(line)
-- First check if the line contains %%.
-- If yes, keep only what comes before %%.
before_comment = line:match('(.-)%%%%') -- %% is the pattern for %
if before_comment ~= nil then
line = before_comment
end
-- Now check for a % that isn't \%
if bad_percent:match(line) then
tex.error("Found lone percent character",
{"Make it a comment: %%, or a percent sign: \\%"})
end
return nil
end
\end{luacode*}
\newcommand{\CheckPercent}{%
\directlua{luatexbase.add_to_callback('process_input_buffer',
check_lone_percent, 'check for lone percent')}%
}
\newcommand{\StopCheckPercent}{%
\directlua{luatexbase.remove_from_callback('process_input_buffer',
'check for lone percent')}%
}
\begin{document}
\CheckPercent
Some text %% Comments with double-percent work
Text can include \% characters.
Newlines before \% also work: \\\%, \\\\\%
But a percent alone will make an error, hopefully
in 100% of cases.
Also after newlines: \\%
\end{document}
它在行输入级别工作,在 TeX 进行任何处理之前。如果不是因为一个棘手的情况,它会非常简单:如何确定一个序列是否\\\...\%
有效?如果反斜杠的数量是偶数,那么在 a 之前会有一堆换行符,%
因此它应该会引发错误。但如果反斜杠的数量是奇数,则意味着后面跟着一堆换行符\%
,这是有效的。
上述代码的检查实现方式略有不同:首先,它通过搜索 来丢弃所有注释%%
。然后,它从行首开始,忽略普通字符(即,不是\
或%
)。它还会忽略反斜杠后跟的任何字符(例如\\
、\%
或\e
中的\emph
)。如果这个被忽略的部分后跟%
,则会引发错误。