百分号——同时具有“评论”和“活跃”两个含义?

百分号——同时具有“评论”和“活跃”两个含义?

我经常从 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 读取一行输入,在开始将字符转换为标记之前,它会做一些工作。

  1. 它会丢弃操作系统提供的记录结束字节(如果有的话;有些旧操作系统没有它)以及其后行中剩余的所有内容。

  2. 它会丢弃记录末尾可能保留的所有空格(以及基于 Web2C 的实现下最常用的制表符)。这与类别代码无关,因为它们尚未附加到字符上。

  3. 它在记录末尾添加当前值\endlinechar(如果参数为负数或者超出引擎相关的最大值,则为 none,对于 TeX 为 255,pdftex对于0x1FFFFFXeTeX 和 LuaTeX 为)。

  4. 它按照当前规定执行状态对于类别代码 5 和 10 个字符;在正常情况下,它会丢弃初始空格并且可能插入一个\par标记(有关详细信息,请参阅 TeXbook 或 TeX by Topic)。

  5. 现在它开始标记,并且在这里注释被丢弃:类别代码 14 的字符会导致 TeX 忽略它以及直到行尾的所有内容(包括添加的内容)\endlinechar

有人可能会想将其定义%为活动字符,它会寻找后续字符%,在本例中,在输入中插入类别代码 14 的字符。也许只在环境中这样做document,这样注释在序言中就可以正常工作。这在两个方面都失败了。

  1. 如果 TeX 没有扩展宏,那么这%%对宏的识别就会太晚。例如

    \parbox{abc %%
      def}
    

    不会按预期工作,因为%当参数被吸收时,活动不会扩展\parbox

  2. 即使确保没有%%宏的参数中不存在任何对,它也是不可能的将字符代码为 14 的字符放入宏的替换文本中:类别代码 0、5、9、14 和 15 个字符可以到达 TeX 的“胃”,在那里,宏替换文本被检查并存储在内存中(TeXbook,练习 7.3)。

有人可能会想通过定义%来寻找以下内容来克服这一限制%,在本例中,发出一个宏,\gobbletoend定义如下:

\def\gobbletoend%1^^M{}

但遗憾的是,由于两个原因,这无法实现:^^M类别代码 5)不能到达 TeX 的胃部,而且 TeX 甚至看不到这对括号,因为当吸收那条线时,它会看到^^M哪个ASCII 行尾,它会将其与行的其余部分一起丢弃。因此,宏不能将其参数用类别代码 5 分隔^^M,如下所示\obeylinesdoes,但你希望每个没有以 开头的行尾%%都有一个最后的\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@ifnextcharfromamsmath用于避免吞噬空格。不过回想一下,%%不能出现在命令的参数中。

在此处输入图片描述

答案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)。如果这个被忽略的部分后跟%,则会引发错误。

相关内容