环境中修改回车符的行为

发布于 2022-08-13 19:35:34

问题背景:
想通过在环境中修改回车的行为,化简代码。
例如,exam-zh 中的选择题代码如下

\begin{choices}
\item 选
\item 项
\end{choices}

思考能否优化 choices 环境,使 每行 自动变成一个条目,不用再写 \item
上述选择题的代码精简为:

\begin{choices}
选
项
\end{choices}

我的构思如下,(为了方便查看理解,用\n 表示回车符)

先定义一个以回车符为结尾的命令: \everyEnter#1\n ,一行的内容就是其参数

\def\everyEnter#1\n{\doSomethingWith{#1}%分离出一行的内容进行处理
\@ifnextchar\end{\relax}{\everyEnter}}%如果回车后是 \end 就休息,否则重复 \everyEnter

\newenvironment{makeEnterMacro}{\catcode`\^^M\active \everyEnter}
{\catcode`\^^M=10}

然而,尝试在 newenvironment 改变 回车行为问题失败,
请大佬指点迷津

MWE 如下

\documentclass[UTF8]{ctexart}\pagestyle{empty}
\begin{document}
\section{改变回车行为示例}

\catcode`\^^M\active
\let^^M\TeX\relax
让回车符变成宏,可自定义

\def^^M{我是回车\par}

\catcode`\^^M=10 % 恢复正常回车

\section{在环境中 手工 改变回车行为}

\begin{center}
\catcode`\^^M\active \let^^M\LaTeX\relax

\end{center}

环境外,利用环境限制 回车 的修改范围

\section{问题来了:定义一个改变回车的环境,怎么就报错了呢}

\newenvironment{makeEnterMacro}{\catcode`\^^M\active \let^^M\LaTeX\relax}{\catcode`\^^M=10}

% newenvironment 有问题,以下瞎改
%\def\cc{\protect\catcode`\^^M=13\relax\def\zz##1^^M{【##1】}\zz}
%\def\endcc{\catcode`\^^M=10}

%\begin{makeEnterMacro}
此环境
怎么就出错了呢
%\end{makeEnterMacro}

\end{document}

这个问题本质上是:
寻求一种将 字符串 分割成 列表
(或者说,在 LaTeX 中实现一种简约的列表数据结构)
供 maping 的方法

查看更多

关注者
0
被浏览
1.1k
雾月
雾月 2022-08-13
这家伙很懒,什么也没写!

这个问题涉及到 TeX 的内部处理,最好读过 TeX by topic 的第 1、2 章

首先说说 TeX 是怎样处理一个输入行的。
TeX 从文件中读入一行,去掉行终止符(catcode=5),去掉行尾空格,插入 \endlinechar,一般为 return 字符(ASCII 13)。
然后逐个读取字符,当遇到控制词(转义符+一串catcode=11的字符)或控制空格(转义符+空格字符ASCII 32)时进入状态 S,此状态后续的空格符(catcode=10)被忽略,如果在这个状态遇到行终止符,则连同这个行终止符及本行未读入的字符都被忽略了。

问题出现在 \newenvironment 这一行。
当读到控制序列 \let 后,进入状态 S,随即遇到行终止符 ^^M(ASCII 13),它连同这行未处理的字符都被忽略了。所以正常情况下,一直到文件的结束 TeX 都没有遇到与 { 匹配的那个 }

但为什么你的没有报错呢?是因为你之前把 ^^M 的 catcode 设置为 10 了,这是空格的 catcode,而不是行结束符(catcode=5)的。如果你把之前的 ^^M 的 catcode 设为 5,就会得到 low-level 的错误。

为了正确定义这个环境,需首先修改 ^^M 的 catcode,然后定义完再恢复:

\catcode`\^^M=13 % 这里最好使用注释符
\newenvironment{makeEnterMacro}{\catcode`\^^M\active \let^^M\LaTeX\relax}{\catcode`\^^M=5 }% 同上
\catcode`\^^M=5 % 同上

MWE:

\documentclass[UTF8]{ctexart}\pagestyle{empty}
\begin{document}

\catcode`\^^M=13 %
\newenvironment{makeEnterMacro}{\catcode`\^^M\active \let^^M\LaTeX\relax}{\catcode`\^^M=5 }%
\catcode`\^^M=5 %

\begin{makeEnterMacro}
此环境
怎么就出错了呢
\end{makeEnterMacro}

\end{document}

得到了想要的结果:
image.png

另外,如果你更新到了最新的 LaTeX 发行版(2022-06-01),则可以直接修改 \obeyedline,然后使用 \obeylines

\makeatletter
\newenvironment{mychoices}
  {\def\obeyedline{\@ifnextchar\end{\par}{\item}}\obeylines
    \begin{itemize}}
  {\end{itemize}}
\makeatother

\begin{mychoices}
选
项
\end{mychoices}
1 个回答

撰写答案

请登录后再发布答案,点击登录

发布
问题

分享
好友

手机
浏览

扫码手机浏览