如何使用方括号作为简写命令?

如何使用方括号作为简写命令?

我定义了一个命令,用于舞台剧的文本脚本。

目前,你可以写:

\says[quietly]{Minka}{Hello, are you there?}

编译后的结果类似如下:

*Minka*:     (quietly) Hello, are you there?

其中Minka为粗体、quietly倾斜且有颜色。

然而,他们问我是否可以提供“多个方括号”,因为他们想写:

\says{Minka}{[quietly]Hello, are you there? [shouting] Is anyone there?}

编译结果应为:

*Minka*:     (quieltly) Hello, are you there? (shouting) Is anyone there?

我的问题是,我能否以某种方式解析给出的文本\says{name}{text}并用某些命令替换方括号之间的所有部分?


编辑:当前命令:

\newlength\widest
\settowidth\widest{\textbf{Longest Name in document}}
\newcommand{\says}[2]{
\begin{description}[leftmargin=\dimexpr\widest+\labelsep\relax,labelindent=0pt,labelwidth=\widest]
    \item[#1] #2
\end{description}
}

其中 应该#2是右侧的部分。我还在脚本开头重新定义了命令:

\newcommand\minka[1]{\says{Minka}{#1}} \newcommand\arthur[1]{\says{Arthur}{#1}}

并且可能使用多行或多段文字:

\minka{Hello, you//
[louder] yes, you there!

[normal voice] Is it you that helped me with that latex stuff?
}


答案1

您的要求可以通过 LaTeX3 的regex模块来完成:

\documentclass{article}
\usepackage{xcolor}
\usepackage{xparse}

\definecolor{saysHow}{RGB}{37,29,118}

\ExplSyntaxOn

\regex_const:Nn \l__tobiscript_howsays_regex { \[ ([^\]]+) \] }

\cs_new_protected:Npn \tobiscript_says:nn #1#2
  {
    \tl_set:Nn \l_tmpa_tl {#2}
    \regex_replace_all:NnN \l__tobiscript_howsays_regex
      { \c{how} \cB\{ \1 \cE\} }
      \l_tmpa_tl

    \textbf{#1:} \nobreakspace \tl_use:N \l_tmpa_tl
    \par
  }

\NewDocumentCommand \says { m m }
  {
    \tobiscript_says:nn {#1} {#2}
  }

\ExplSyntaxOff

% Define how to format the things inside brackets
\newcommand*{\how}[1]{%
  \textcolor{saysHow}{\textsl{(#1)}}%
  ~\ignorespaces             % replace following spaces with one nobreak space
}

\setlength{\parindent}{0pt}

\begin{document}

\says{Minka}{[quietly]Hello, are you there? [shouting] Is anyone there?}
\says{Arthur}{[hesitating] Uh, maybe me?.. [now assured] Patsy!
  Patsy's here!}

\end{document}

截屏

关于您编辑的问题,您可以使用这个。如果您不再对旧\says命令感兴趣,只需删除其定义,然后重命名\newsays\says使用您想要的新命令的任何名称。

\documentclass{article}
\usepackage{xcolor}
\usepackage{enumitem}
\usepackage{xparse}

\definecolor{saysHow}{RGB}{37,29,118}

\ExplSyntaxOn

\regex_const:Nn \l__tobiscript_howsays_regex { \[ ([^\]]+) \] }

\cs_new_protected:Npn \tobiscript_format_howsays_in_text:n #1
  {
    \tl_set:Nn \l_tmpa_tl {#1}
    \regex_replace_all:NnN \l__tobiscript_howsays_regex
      { \c{how} \cB\{ \1 \cE\} }
      \l_tmpa_tl

    \tl_use:N \l_tmpa_tl
  }

\cs_new_protected:Npn \tobiscript_says:nn #1#2
  {
    \textbf{#1:} \nobreakspace \tobiscript_format_howsays_in_text:n {#2}
    \par
  }

% \says command as requested in the original question
\NewDocumentCommand \says { m +m }
  {
    \tobiscript_says:nn {#1} {#2}
  }

\NewDocumentCommand \formathowsaysintext { +m }
  {
    \tobiscript_format_howsays_in_text:n {#1}
  }

\ExplSyntaxOff

\newlength{\widest}
\settowidth\widest{\textbf{Longest Name in document}}

% \newsays: command added to the question after the answer was provided
\newcommand{\newsays}[2]{%
  \begin{description}[leftmargin=\dimexpr\widest+\labelsep\relax,
                      labelindent=0pt,labelwidth=\widest]
    \item[#1] \formathowsaysintext{\ignorespaces #2\unskip}
  \end{description}%
}

% Define how to format the things inside brackets
\newcommand*{\how}[1]{%
  \textcolor{saysHow}{\textsl{(#1)}}%
  ~\ignorespaces             % replace following spaces with one nobreak space
}

\setlength{\parindent}{0pt}

\begin{document}

\says{Minka}{[quietly]Hello, are you there? [shouting] Is anyone there?}
\says{Arthur}{[hesitating] Uh, maybe me?.. [now assured] Patsy!
  Patsy's here!}

\newsays{Roger}{
  [irritated]Oh, what sad times are these when passing ruffians can say ``ni''
  at will to old ladies.

  [sorry for interrupting the show] Stupid paragraph added only to show this
  can be done. [again, really sorry!] Back to the text in one second.

  There is a pestilence upon this land. Nothing is sacred. Even
  those who arrange and design shrubberies are under considerable economic
  stress at this period in history.
}

\newsays{Arthur}{
  [showing sudden interest] Did you say ``shrubberies''?
 }
\end{document}

截屏

答案2

您可以使用不同的宏来表示某人“如何”说某事,例如:

\documentclass{article}
\usepackage{xcolor}
\newcommand{\how}[1]{
    \textit{\textcolor{red}{(#1)}}
}
\begin{document}
\how{quietly} Hello, are you there? \how{shouting} Is anyone there? 
\end{document} 

答案3

如果你确实想要这个界面,你可以用 TeX 解析文本:

\documentclass{article}

\usepackage{enumitem}

\newlength\widest
\settowidth\widest{\textbf{Longest Name in document}}

\makeatletter
    \def\@stop{\@stop}%
    \long\def\says@parse#1[#2]{%
        #1%
        \ifx\@stop#2\else
            \how{#2}%
            \expandafter\says@parse
        \fi
    }
    \long\def\says#1#2{%
        \begin{description}[leftmargin=\dimexpr\widest+\labelsep\relax,labelindent=0pt,labelwidth=\widest]%
            \item[#1]%
            \says@parse #2[\@stop]%
        \end{description}%
    }
    \def\how#1{%
        \ifhmode\unskip\ \fi
        \textsl{(#1)}%
        ~\ignorespaces
    }
    \let\normalbackslash\@backslashchar
\makeatother

\begin{document}

\says{Minka}{[quietly]Hello, are you there? [shouting] Is anyone there?}
\says{Tobi}{
    [annoyed]  Oh, don't be so fearful.
    You know I'm here!
    Just don't concentrate on what you're doing and you'll be fine.

    [rambling]
    It's not like a lot could go wrong anyway.
    I mean, it's just a program, your computer won't literally explode.
    If you somehow mess it up completely, we'll just reinstall it and you can try again.
    [resigned] But okay, I'll explain it to you again.

    [lecturing] You just write \texttt{\normalbackslash says}, then a pair of braces containing the name of the person speaking\dots
    [pausing] Good, like that.
    Now you open another pair of braces and put their dialogue in there.
    Close the brace, and [happily] you're done.
}

\end{document}

MWE 输出

但这有一些缺点。

  • 我认为语法不太适合使用。每当你输入许多段落作为宏的参数时,停下来问问自己这是否真的应该是一个环境
  • 更重要的是,由于这个原因,您不能使用任何改变\catcode文本内部 s 的宏(例如\verb)。在我的示例中,我不得不使用\textttand \@backslashchar

我认为,更好的方法是使用环境和主动角色。我们确实不是想要使[(或]) 处于活动状态,因为这会破坏所有可选参数。不过,如果您愿意将语法从 更改为[instruction]|instruction|我们可以很好地做到这一点。

\documentclass{article}

\usepackage{enumitem}

\newlength\widest
\settowidth\widest{\textbf{Longest Name in document}}

\makeatletter
    \def\@speech#1{%
        \item[#1]%
        \catcode`\|=13
    }
    \newenvironment{dialogue}{%
        \let\speech\@speech
        \begin{description}[leftmargin=\dimexpr\widest+\labelsep\relax,labelindent=0pt,labelwidth=\widest]%
    }{%
        \end{description}%
    }
    \def\how#1{%
        \ifhmode\unskip\ \fi
        \textsl{(#1)}%
        ~\ignorespaces
    }
    {
        \catcode`\|=12
        \gdef\verticalbar{|}
        \catcode`\|=13
        \AtBeginDocument{%
            \gdef|{\ifmmode\verticalbar\else\expandafter\@how\fi}%
        }
        \gdef\@how#1|{%
            \how{#1}%
        }
    }
\makeatother

\begin{document}

\begin{dialogue}
    \speech{Minka}
        |quietly|Hello, are you there? |shouting| Is anyone there?

    \speech{Tobi}
        |annoyed|  Oh, don't be so fearful.
        You know I'm here!
        Just don't concentrate on what you're doing and you'll be fine.

        |rambling|
        It's not like a lot could go wrong anyway.
        I mean, it's just a program, your computer won't literally explode.
        If you somehow mess it up completely, we'll just reinstall it and you can try again.
        |resigned| But okay, I'll explain it to you again.

        |lecturing| In the \verb|dialogue| environment, you just write \verb|\speech|, then a pair of braces containing the name of the person speaking\dots
        |pausing| Good, like that.
        Now you just type on what they should say.
        Close the brace, and |happily| you're done.
\end{dialogue}

\end{document}

相关内容