使用 \input 作为命令参数

使用 \input 作为命令参数

我正在制作一个角色扮演游戏系统。我想将咒语的内容与咒语的格式分开,例如,能够针对角色表和专用咒语文档对咒语进行不同的格式化,等等。

我正在尝试使用一个单独的文件,该文件包含以预定义方式排列的格式化宏(\spell)的参数,然后将其输入到文档中。

这是我尝试过的。

\documentclass{article}

\newcommand{\spell}[4]{
\noindent   \textbf{#1}
\\  \underline{#2}
\\  \textit{#3}
\\  #4
}

\newcommand{\info}{
{SPELL NAME}
{MANA COST}
{CASTING TIME}
{DESCRIPTION}
}

\begin{document}
    \input{spells/spell template.tex}

    \spell{spell name}{mana cost}{casting time}{description}

    \expandafter\spell\info

%   \expandafter\spell\input{spells/spell template.tex}
\end{document}

咒语/咒语模板.tex 包含

{Spell Name}
{Mana Cost}
{Casting Time}
{Description}

我在这个文件中的前三个测试运行得很好,但当我试图取消注释第四个测试时,LaTeX 崩溃了。我读过它\input不可扩展,但我还没有看到任何可以解决这个问题的解决方案。这篇文章看起来很有希望,但似乎已经过时了(https://tex.stackexchange.com/a/282602/301785)任何帮助我都会很感激,谢谢。

答案1

假设您需要从文件中选择参数的行为不仅仅是\spell,下面定义了一个辅助宏\FromFile,它将文件内容应插入其后的代码作为第一个参数,将文件路径作为第二个参数。

\documentclass{article}

\begin{filecontents}{spell_template.tex}
{SPELL NAME}
{MANA COST}
{CASTING TIME}
{DESCRIPTION}
\end{filecontents}

\newcommand{\spell}[4]{%
  \noindent   \textbf{#1}
  \\  \underline{#2}
  \\  \textit{#3}
  \\  #4%
}

\ExplSyntaxOn
\msg_new:nnn { amit } { file-not-found }
  { File~ #1~ not~ found.~ RPG-element~ not~ defined! }
\NewDocumentCommand \FromFile { m m }
  {
    \file_get:nnNTF {#2} {} \l_tmpa_tl
      { \exp_last_unbraced:Nno \use:n {#1} \l_tmpa_tl }
      { \msg_error:nnn { amit } { file-not-found } {#2} }
  }
\ExplSyntaxOff

\newcommand\info
  {%
    {SPELL NAME}%
    {MANA COST}%
    {CASTING TIME}%
    {DESCRIPTION}%
  }

\begin{document}
    \input{spell_template.tex}

    \spell{spell name}{mana cost}{casting time}{description}

    \expandafter\spell\info

   \FromFile\spell{spell_template.tex}
\end{document}

如果处理前导和尾随空格很重要,则可以使用以下变体:

\documentclass{article}

\begin{filecontents}{spell_template.tex}
{SPELL NAME}
{MANA COST}
{CASTING TIME}
{DESCRIPTION}
\end{filecontents}

\newcommand{\spell}[4]{%
  \noindent   \textbf{#1}
  \\  \underline{#2}
  \\  \textit{#3}
  \\  #4%
}

\ExplSyntaxOn
\msg_new:nnn { amit } { file-not-found }
  { File~ #1~ not~ found.~ RPG-element~ not~ defined! }
\NewDocumentCommand \FromFile { m m }
  {
    \file_get:nnNTF {#2} {} \l_tmpa_tl
      { \use:e { \exp_not:n {#1} \tl_trim_spaces:o \l_tmpa_tl } }
      { \msg_error:nnn { amit } { file-not-found } {#2} }
  }
\ExplSyntaxOff

\newcommand\info
  {%
    {SPELL NAME}%
    {MANA COST}%
    {CASTING TIME}%
    {DESCRIPTION}%
  }

\begin{document}
    \input{spell_template.tex}

    \spell{spell name}{mana cost}{casting time}{description}

    \expandafter\spell\info

   \FromFile\spell{spell_template.tex}
\end{document}

答案2

LaTeX 将 TeX 基元隐藏\input到控制序列中\@@input。您可以通过以下方式设置等效命令\primitiveinput

{\catcode`\@=11 \global\let\primitiveinput=\@@input}

然后你可以说

\expandafter\spell\primitiveinput{spells/spell-template.tex}

编辑:接受的答案实现了一个\FromFile宏,用于测试给定文件是否存在。我可以使用 OpTeX 展示这样的实现,仅用于比较

\fontfam[lm]

\def\spell#1#2#3#4{1:#1, 2:#2, 3:#3, 4:#4}

\def\FromFile#1#2{%
    \isfile{#2}\iftrue \ea#1\input{#2}%
    \else \opwarning{File "#2" not found, \string#1 not executed}\fi
}

\FromFile\spell{template.tex}

\bye

答案3

这个答案和 wipet 给出的答案类似。这个想法是使用 的原始含义\input。使用 XeTeX 或 LuaTeX,您可以使用\primitive原始含义(在 pdfTeX 中称为\pdfprimitive)。

\documentclass{article}

\begin{filecontents}{spell_template.tex}
    {SPELL NAME}
    {MANA COST}
    {CASTING TIME}
    {DESCRIPTION}
\end{filecontents}

\newcommand{\spell}[4]{
    \noindent   \textbf{#1}
    \\  \underline{#2}
    \\  \textit{#3}
    \\  #4
}

\newcommand{\info}{
    {SPELL NAME}
    {MANA COST}
    {CASTING TIME}
    {DESCRIPTION}
}

\begin{document}
    \input{spell_template.tex}
    
    \spell{spell name}{mana cost}{casting time}{description}
    
    \expandafter\spell\info
    
    \expandafter\spell\primitive\input spell_template.tex
\end{document}

答案4

这是一个变体,它尝试处理文件中四个参数后面的空格和其他内容。

\documentclass{article}

\begin{filecontents*}{template.tex}
{SPELL NAME}
{MANA COST}
{CASTING TIME}
{DESCRIPTION} Something that gets ignored.
Something that gets ignored, too.
\end{filecontents*}

\newcommand{\spell}[4]{%
  \par
  \noindent\textbf{#1}\\%
  \underline{#2}\\%
  \textit{#3}\\%
  #4%
}%

\newcommand\spellGetArguments[4]{\spellRemoveToEndOfLine{\spell{#1}{#2}{#3}{#4}}}%
\newcommand\SpellSwitchEndlinecharcategory{\catcode\endlinechar=12 }%
\makeatletter
\begingroup
\catcode`\^^M=12 %
\@firstofone{%
  \endgroup%
  \@ifdefinable\spellRemoveToEndOfLine{%
    \long\def\spellRemoveToEndOfLine#1#2^^M{\endgroup#1}%
  }%
}%
\newcommand\spellinput[1]{%
  \begingroup
  \expandafter\expandafter\expandafter\SpellSwitchEndlinecharcategory
  \expandafter\expandafter\expandafter\endinput
  \expandafter\spellGetArguments\@@input"#1" %
}%
\makeatother

\begin{document}

\spellinput{template.tex} Space.

\bigskip

\spellinput{template.tex}NoSpace.

\end{document}

在此处输入图片描述

相关内容