文件内快捷方式的类似输入的命令

文件内快捷方式的类似输入的命令

我正在寻找一个快捷方式生成器,它不像\newcommand-something 那样挑剔\input,而是来自文件内部。例如,我希望有一个普通的 .tex 文件,我可以在某个时候在其中写入类似的东西,\this[20c]{\that}并且接下来的 20 个字符在我每次在文档中写入时都会使用\that,就像这 20 个字符是在文档的那个位置写入的一样。

答案1

当 TeX 处理 .tex 输入文件时,它会读取该文件并将其作为一组指令,用于生成所谓的标记并将它们逐个插入到标记流中。标记可以是控制序列标记或字符标记。

我最近在回答这个问题时详细阐述了处理 .tex-input 的不同阶段使命令输出成为另一个命令的(多个)参数

您可以让 LaTeX 在 verbatim-catcode-régime 下读取并标记 .tex-input 的接下来几行或几个字符,然后再将结果字符标记集传递给\scantokens。在 verbatim-catcode-régime 下,.tex-input-file 的每个字符都被标记化为字符标记。\scantokens本质上就像将其参数的标记未扩展地写入文本文件一样,然后通过 启动读取和标记该文本文件的内容\input。如果 的参数\scantokens仅由字符标记组成,则将它们未扩展地写入(真正完成或由\scantokens' 写入部分模拟)将产生与在 .tex-input-file 的相应位置可以找到的相同的字符集。因此\input的 -part\scantokens将找到与在 .tex-input-file 的相应位置可以找到的相同的字符。但是,在\scantokens执行其部分时读取和标记该组字符的结果取决于执行其部分\input时有效的 catcode 制度。\scantokens\input

我想对于逐行处理,你希望有一个宏可以

  • 从 verbatim-catcode-régime 下的 .tex-input-file 中读取接下来的几行,
  • 在除最后一行之外的每一行标记后面插入换行符
  • 并从结果中定义一个宏,将所有内容传递给\scantokens

我想对于逐字符处理,你希望有一个宏可以

  • 在 verbatim-catcode-régime 下从 .tex-input-file 中读取接下来的几个字符,
  • 附加注释字符以确保插入的最后一个结束符\scantokens无效,
  • 并从结果中定义一个宏,将所有内容传递给\scantokens

下面是一个如何实现此类宏的小例子:

\documentclass{article}
\begingroup
% Make @ a letter which can occur in names of control sequences:
\makeatletter
% Make return, which usually is TeX's endline-character, an ordinary character:
\catcode`\^^M=12 %
% Let's use as comment-character ^^A instead of %:
\catcode`\^^A=14 %
% Make % an ordinary character:
\catcode`\%=12 ^^A
\@firstofone{^^A
  \endgroup^^A
  \newcommand{\makenextlines}[2]{^^A
   \begingroup^^A
   \let\do\@makeother\dospecials^^A
   \catcode`\^^I=12 ^^A
   \catcode`\^^M=12 ^^A
   \romannumeral0^^A
   \expandafter\innermakenextlines\expandafter{\romannumeral\number\number#1 000}{#2}{}^^A
  }^^A
  \long\def\innermakenextlines#1#2#3#4^^M{^^A
    ^^A \innermakenextlines just checks whether there are more lines to collect.
    ^^A If not, defimes command to define to deliver the lines collected so far nested in
    ^^A a call to \scantokens.
    ^^A If so calls \innerinnermakenextlines for collecting the next line of .tex-input
    ^^A and then calling \innermakenextlines again.
    ^^A #1 = Characters m in an amount that equals the amount of lines still to collect.
    ^^A #2 = Command to define.
    ^^A #3 = Lines collected so far.
    ^^A #4 = In the first iteration:   Remaining characters of the line which contains the call to \makenextlines.
    ^^A                                These will silently be discarded. (One could implement triggering an error-message
    ^^A                                depending on the non-emptiness of #4.)
    ^^A      In subsequent iterations: Empty as TeX's endline-character ^^M  is provided explicitly as argument-delimiter
    ^^A                                right  behind the third argument.
    \ifx X#1X\expandafter\@firstoftwo\else\expandafter\@secondoftwo\fi^^A
    { \endgroup^^A
      \newcommand#2{\scantokens{#3}}^^A
    }{^^A
      \innerinnermakenextlines{#1}{#2}{#3}^^A
    }^^A
  }^^A
  \long\def\innerinnermakenextlines#1#2#3#4^^M{^^A
    ^^A #1 = Characters m in an amount that equals the amount of lines to collect.
    ^^A #2 = Command to define.
    ^^A #3 = Lines collected so far.
    ^^A #4 = Collected next line.
    \expandafter\ifx\expandafter X\@firstoftwo{}#1X\expandafter\@firstoftwo\else\expandafter\@secondoftwo\fi^^A
    {^^A There is only one m left, thus the last line is to be collected. With the last line no
     ^^A newline-character will be attached.
      \expandafter\innermakenextlines\expandafter{\@firstoftwo{}#1}{#2}{#3#4}{}^^M^^A
    }{^^A Not yet the last line, so attach a newline-character ^^J. When \scantokens, which emulates
      ^^A unexpanded writing to file and inputtong that file, does its unexpanded-writing-part, the
      ^^A newline-character will not br written verbatim but will cause TeX to begin writing another line.
      \expandafter\innermakenextlines\expandafter{\@firstoftwo{}#1}{#2}{#3#4^^J}{}^^M^^A
    }^^A
  }^^A
  ^^A-----------------------------------------------------------------------------------------------------------
  ^^A-----------------------------------------------------------------------------------------------------------
  ^^A-----------------------------------------------------------------------------------------------------------
  \newcommand{\makenextcharacters}[2]{^^A
   \begingroup^^A
   \let\do\@makeother\dospecials^^A
   \catcode`\^^I=12 ^^A
   \catcode`\^^M=12 ^^A
   \romannumeral0^^A
   \expandafter\innermakenextcharacters\expandafter{\romannumeral\number\number#1 000}{#2}{}^^A
  }^^A
  \long\def\innermakenextcharacters#1#2#3{^^A
    ^^A #1 = Characters m in an amount that equals the amount of lines to collect.
    ^^A #2 = Command to define.
    ^^A #3 = Characters collected so far.
    \ifx X#1X\expandafter\@firstoftwo\else\expandafter\@secondoftwo\fi^^A
    { \endgroup^^A
      ^^A Let's append a percent to make sure the endline-character apppended to what
      ^^A can be taken for the last line when \scantokens does its \input-part 
      ^^A will have no effect as under normal catcode-régime that percent will be taken
      ^^A for a comment whereafter characters and thus also the appended endline-character
      ^^A are dropped instead of being tokenized.
      \newcommand#2{\scantokens{#3%}}^^A
    }{^^A
      \innerinnermakenextcharacters{#1}{#2}{#3}^^A
    }^^A
  }^^A
  \long\def\innerinnermakenextcharacters#1#2#3#4{^^A
    ^^A #1 = Characters m in an amount that equals the amount of lines to collect.
    ^^A #2 = Command to define.
    ^^A #3 = Characters collected so far.
    ^^A #4 = Collected next character.
    ^^A Be aware that endline-characters need to be replaced by newline-characters
    ^^A so that they yield line-break when \scantokens does its writing-part-
    \ifx#4^^M\expandafter\@firstoftwo\else\expandafter\@secondoftwo\fi^^A
    {^^A
      \expandafter\innermakenextcharacters\expandafter{\@firstoftwo{}#1}{#2}{#3^^J}^^A
    }{^^A
      \expandafter\innermakenextcharacters\expandafter{\@firstoftwo{}#1}{#2}{#3#4}^^A
    }^^A
  }^^A
}%

\begin{document}

\makenextlines{10}{\thiscommand}
\super-complicated-that{ @\ \makeatletter magic @ fireworks}
\another-fragile-thing{ @\ \makeatletter smoke @ mirrors}
\super-complicated-that{ @\ \makeatletter magic @ fireworks}
\another-fragile-thing{ @\ \makeatletter smoke @ mirrors}
\super-complicated-that{ @\ \makeatletter magic @ fireworks}
\another-fragile-thing{ @\ \makeatletter smoke @ mirrors}
\super-complicated-that{ @\ \makeatletter magic @ fireworks}
\another-fragile-thing{ @\ \makeatletter smoke @ mirrors}
\super-complicated-that{ @\ \makeatletter magic @ fireworks}
\another-fragile-thing{ @\ \makeatletter smoke @ mirrors}
\show\thiscommand

\makenextcharacters{17}{\thatcommand}12345678901234567\show\thatcommand

% A linebreak is counted like one character:

\makenextcharacters{17}{\onemorecommand}1234
567890123456\show\onemorecommand

\end{document}

控制台输出是:

> \thiscommand=\long macro:
->\scantokens {\super-complicated-that{ @\ \makeatletter magic @ fireworks}
\another-fragile-thing{ @\ \makeatletter smoke @ mirrors}
\super-complicated-that{ @\ \makeatletter magic @ fireworks}
\another-fragile-thing{ @\ \makeatletter smoke @ mirrors}
\super-complicated-that{ @\ \makeatletter magic @ fireworks}
\another-fragile-thing{ @\ \makeatletter smoke @ mirrors}
\super-complicated-that{ @\ \makeatletter magic @ fireworks}
\another-fragile-thing{ @\ \makeatletter smoke @ mirrors}
\super-complicated-that{ @\ \makeatletter magic @ fireworks}
\another-fragile-thing{ @\ \makeatletter smoke @ mirrors}}.
l.113 \show\thiscommand

? 
> \thatcommand=\long macro:
->\scantokens {12345678901234567%}.
l.115 ...ommand}12345678901234567\show\thatcommand

? 
> \onemorecommand=\long macro:
->\scantokens {1234
567890123456%}.
l.120 567890123456\show\onemorecommand

? 
[...]
No pages of output.

相关内容