存储值、宏选项以及与其他包的交互的问题

存储值、宏选项以及与其他包的交互的问题

抱歉,标题太笼统了,我想解决一个非常具体的问题:
我正在尝试增强 Alan Munn 提供的框架这里 表示自然发生的话语(还有一些额外的内容,这里省略),代码来自frougon 的回答。这一切的意义在于为 Alan 的代码(使用该expex包)提供一种机制,使其不打印重复的说话者标签。我以为我能够整合这两种解决方案,但是,随着复杂性的增加,不知何故我设法把它搞砸了,我无论如何也想不出哪里出了问题。

这是最小的 WE:

% !TEX TS-program = xelatexmk
\RequirePackage{filecontents}

\begin{filecontents}{discourse.sty}
\NeedsTeXFormat{LaTeX2e}
\ProvidesPackage{discourse}

\RequirePackage[user,savepos]{zref}
\RequirePackage{expex}
\newcounter{linenum}
\newlength{\largestspkr}
\newlength{\largestnum}
\newcommand{\deflargestlabel}[2][99]{
\settowidth{\largestnum}{#1}
\settowidth{\largestspkr}{~#2}}
\deflargestlabel[999]{speaker~99}

\RequirePackage{perpage}

\newcounter{spkrcounter}
    \MakePerPage{spkrcounter}

\newenvironment{discourseenv}{%
  \setcounter{linenum}{0}%
  \setcounter{spkrcounter}{0}%
  \ignorespaces
}{%
  \par\ignorespacesafterend
}

\DeclareOption{skiprepetitions}{%
  \AtBeginDocument{\let\discourse@print\discourse@print@skip}%
}
\DeclareOption{keeprepetitions}{%
  \AtBeginDocument{\let\discourse@print\discourse@print@keep}%
}
\ExecuteOptions{skiprepetitions}
\ProcessOptions\relax

\RequirePackage{xifthen}

\def\discourse@storedval{} % create a macro to later store a value in

\newcommand{\spkr}[1]{%
  % create line numbers:
  \refstepcounter{linenum}\makebox[\largestnum][r]{\thelinenum}\hspace{1em}
  \ifthenelse{\isempty{#1}}%
    {\makebox[\largestspkr][l]{}}% if empty > empty box
    {% If this is the first \stepcounter{spkrcounter} executed since the current
     % page was started, this sets 'spkrcounter' to 1.
     \stepcounter{spkrcounter}% 
     \discourse@print{#1}%
     \def\discourse@storedval{#1}%
    }%
}

\def\discourse@print@skip#1{%
  \ifthenelse{\cnttest{\value{spkrcounter}}>{1}\AND
        \equal{#1}{\discourse@storedval}}%
   {\makebox[\largestspkr][l]{}}% if repeated > empty box
   {\makebox[\largestspkr][l]{#1:}}%
}
\def\discourse@print@keep#1{\makebox[\largestspkr][l]{#1:}}

\end{filecontents}

\documentclass{article}
\usepackage{discourse}

\begin{document}

Here it works:

\spkr{A} OK

\spkr{A} OK

\spkr{B} OK

\spkr{A} OK

\vbox{}
Here too in the environment:

\begin{discourseenv}

\spkr{A} OK

\spkr{A} OK

\spkr{B} OK

\end{discourseenv}

\vbox{}
But in combination with expex it screws up:

\begin{discourseenv}

\ex[exno=\spkr{A}, exnoformat=X] OK (prints A) \xe

\ex[exno=\spkr{A}, exnoformat=X] OK (empty) \xe

\ex[exno=\spkr{B}, exnoformat=X] OK (prints B) \xe

\ex[exno=\spkr{A}, exnoformat=X] OK (empty) \xe

\ex[exno=\spkr{B}, exnoformat=X] OK (prints B) \xe

\end{discourseenv}

\begin{discourseenv}

\ex[exno=\spkr{B}, exnoformat=X] OK (prints B) \xe

\newpage

\ex[exno=\spkr{B}, exnoformat=X] OK (prints B) \xe

\ex[exno=\spkr{B}, exnoformat=X] This one should be empty \xe

\ex[exno=\spkr{B}, exnoformat=X] This one should be empty \xe

\ex[exno=\spkr{A}, exnoformat=X] This one should print A  \xe

\ex[exno=\spkr{A}, exnoformat=X] OK (empty) \xe

\end{discourseenv}

\end{document} 

宏的前几个实例运行正常\spkr,但在下一页时,它的行为就很奇怪了。有人能发现哪里出了问题吗?

答案1

您只需要使定义全局化,因为\ex ... \xe它是在组内执行的。

\newcommand{\spkr}[1]{%
  % create line numbers:
  \refstepcounter{linenum}\makebox[\largestnum][r]{\thelinenum}\hspace{1em}
  \ifthenelse{\isempty{#1}}%
    {\makebox[\largestspkr][l]{}}% if empty > empty box
    {% If this is the first \stepcounter{spkrcounter} executed since the current
     % page was started, this sets 'spkrcounter' to 1.
     \stepcounter{spkrcounter}%
     \discourse@print{#1}%
     \gdef\discourse@storedval{#1}% <--- global!!!
    }%
}

在此处输入图片描述

相关内容