使用\ifthenelse
语句我定义了一个宏,只要它与上次使用时的值不同,它就会打印它的值。
\RequirePackage{xifthen}
\def\storedval{} % create a macro to later store a value in
\newcommand{\mycommand}[1]{%
\ifthenelse{\isempty{#1}{}}{\\}{% If empty, don't print anything but keep an empty line.
\ifthenelse{\equal{#1}{\storedval}}{\\}% If value is the same as the previous one, don't print it but keep an empty line.
{#1\\}\def\storedval{#1}}} % Else: print value and store it in \storedval
这样做的目的是,我获取另一个程序生成的数据,但如果重复,我不想打印该数据。在文档中,这:
\mycommand{A}
\mycommand{A}
\mycommand{A}
\mycommand{}
\mycommand{B}
\mycommand{C}
\mycommand{C}
\mycommand{A}
... 给我 A、三行空行、B、C、一行空行和 A。这就是我想要的。
现在我想将其存储在一个包中,并定义一个选项,让我选择是否要打印重复的行。我不知道如何\DeclareOption
正确使用。我当然可以重复整个代码,并将其放在两个\DeclareOption
语句中。但我认为有一种更经济的方法。
因此,我尝试了以下 MWE,但这显然是错误的方法(注释掉不起作用的行)。(免责声明:这是我第一次尝试为包声明选项...)
\documentclass{article}
\usepackage{filecontents}
\begin{filecontents}{mypackage.sty}
\NeedsTeXFormat{LaTeX2e}
\ProvidesPackage{mypackage}
\RequirePackage{xifthen}
\def\storedval{} % create a macro to later store a value in
\newcommand{\mycommand}[1]{%
\ifthenelse{\isempty{#1}{}}{\\}{% If empty, don't print anything but keep an empty line.
%\DeclareOption{skiprepetitions}{\ifthenelse{\equal{#1}{\storedval}}{\\}}% If value is the same as the previous one, don't print it but keep an empty line.
%\DeclareOption{keeprepetitions}{} % don't do anything if this is selected
{#1\\}\def\storedval{#1}}} % Else: print value and store it in \storedval
\DeclareOption*{\PackageWarning{mypackage}{Unknown ‘\CurrentOption’}}
\ProcessOptions\relax
\end{filecontents}
\usepackage{mypackage}
%\usepackage[skiprepetitions]{mypackage}
\begin{document}
Testing:\\
\mycommand{A}
\mycommand{A}
\mycommand{A}
\mycommand{}
\mycommand{B}
\mycommand{C}
\mycommand{C}
\mycommand{A}
\mycommand{A}
\end{document}
答案1
这是一个功能齐全的包,可以满足您的需求。它使用expl3
相关包,并且有三种使用命令的方式:您可以全局指定包选项、在本地使用设置命令或将可选参数传递给其中一个宏。
请注意,示例中的第二个 A 是通过传递可选的宏参数产生的。
\documentclass{article}
\usepackage{filecontents}
\begin{filecontents}{mypackage.sty}
\RequirePackage{xparse} % enable LaTeX3 interfaces
\ProvidesExplPackage{mypackage}{2018-09-05}{0.1.0}{Data processing}
\RequirePackage{l3keys2e}
\keys_define:nn { jan } % define keys for module `jan`
{
skiprepetitions .bool_set:N = \l__jan_skiprep_bool, % define a boolean switch which is saved into a local variable
skiprepetitions .initial:n = true, % set the value that is used when nothing is defined
skiprepetitions .default:n = true, % set the value to use if you only pass `skiprepetitions` and no `=…`
keeprepetitions .bool_set_inverse:N = \l__jan_skiprep_bool,
keeprepetitions .default:n = true
}
\ProcessKeysOptions { jan } % make sure package options are processed
\NewDocumentCommand { \datasetup } { m } % define a command that locally sets the keys (as underscores are not allowed in normal LaTeX commands)
{
\keys_set:nn { jan } { #1 }
}
\tl_new:N \g_jan_storedval_tl % create a new auxiliary variable to hold the last value
\prg_generate_conditional_variant:Nnn \tl_if_eq:nn { nV } { T, F, TF } % make \tl_if_eq semantically (and expansion-wise) better for our use-case
\NewDocumentCommand { \mycommand } { O{} m } % this is the main command with the first optional argument being empty if omitted and the second argument being mandatory
{
\group_begin: % start a group to make key changes local
\keys_set:nn { jan } { #1 } % locally set keys
\tl_if_empty:nTF { #2 } { \\ } % test if mandatory argument empty
{
\tl_if_eq:nVTF { #2 } \g_jan_storedval_tl % test if the mandatory argument equals the last value
{
\bool_if:NF \l__jan_skiprep_bool { #2 } % only output the mandatory argument if we are not in skip-mode
} { #2 }
\\
\tl_gset:Nn \g_jan_storedval_tl { #2 }
}
\group_end:
}
\end{filecontents}
\usepackage{mypackage}
\begin{document}
Testing:\\
\mycommand{A}
\mycommand[keeprepetitions]{A}
\mycommand{A}
\mycommand{}
\mycommand{B}
\mycommand{C}
\mycommand{C}
\mycommand{A}
\mycommand{A}
\end{document}
答案2
参照你的问题标题,我认为不能\DeclareOption
在宏中使用(正确)。对于宏,你需要使用由pgfkeys
(https://www.ctan.org/pkg/pgfkeys) 或类似的包。
但是从您的实际问题中,我推断您正在创建一个定义相应宏的包,并且您想要向包添加一个选项,该选项可以在加载时提供。在这种情况下\DeclareOption
是正确的做法。
但不是您这样做的方式。您希望在调用\DeclareOption
命令之前执行命令\ProcessOptions
。因此,您希望它们在加载包时立即执行,因此它们不能在宏定义中使用(除了可能\edef
但我们不要讨论这个)。
解决方法是创建一个新的布尔标志,如果使用该选项,其值将会改变。在我的示例中,我使用了以下etoolbox
包:
\RequirePackage{etoolbox}
\newbool{@skiprepetitions}
\DeclareOption{skiprepetitions}{%
% switch the bool-flag if this option is set
\setbool{@skiprepetitions}{true}%
}
\ProcessOptions\relax
\newcommand{\myCommand}{%
\ifthenelse{\isEmpty{#1}{}}{
% if empty
\ifbool{@skiprepetitions}{%
% skip repetitions
}{%
% don't care about repetitions
}%
}{%
% if not empty
}%
}
答案3
定义二宏并让选项决定使用哪一个。
\RequirePackage{filecontents}
\begin{filecontents}{mypackage.sty}
\NeedsTeXFormat{LaTeX2e}
\ProvidesPackage{mypackage}
\DeclareOption{skiprepetitions}{%
\AtBeginDocument{\let\mypackage@print\mypackage@print@skip}%
}
\DeclareOption{keeprepetitions}{%
\AtBeginDocument{\let\mypackage@print\mypackage@print@keep}%
}
\ExecuteOptions{keeprepetitions}
\ProcessOptions\relax
\RequirePackage{xifthen}
\def\mypackage@storedval{} % create a macro to later store a value in
\newcommand{\mycommand}[1]{%
\ifthenelse{\isempty{#1}}
{% if empty just print an empty line
\mbox{}\\%
}
{% if not empty
\mypackage@print{#1}%
\def\mypackage@storedval{#1}%
}%
}
\def\mypackage@print@skip#1{%
\ifthenelse{\equal{#1}{\mypackage@storedval}}
{\mbox{}}
{#1}%
\\%
}
\def\mypackage@print@keep#1{#1\\}
\end{filecontents}
\documentclass{article}
%\usepackage{mypackage}
\usepackage[skiprepetitions]{mypackage}
\begin{document}
Testing:\\
\mycommand{A}
\mycommand{A}
\mycommand{A}
\mycommand{}
\mycommand{B}
\mycommand{C}
\mycommand{C}
\mycommand{A}
\mycommand{A}
\mbox{}
\end{document}