1

Using \ifthenelse statements I've defined a macro that prints it's value as long as it is different from the value of the previous time it was used.

\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

The purpose for this is that I get data generated by another program but do not want to print the data if it is repeated. In the document, this:

\mycommand{A}
\mycommand{A}
\mycommand{A}
\mycommand{}
\mycommand{B}
\mycommand{C}
\mycommand{C}
\mycommand{A}

... gives me A, three empty lines, B, C, an empty line, and A. That's what I want.

Now I would like to store this in a package and define an option that would let me choose whether or not I want to print repeated lines. I couldn't figure out how to use \DeclareOption properly. I could of course repeat the whole code, and place it inside of two \DeclareOption statements. But I assume there's a more economical way.

So I gave it a shot trying the following MWE, but this is clearly the wrong way (outcommented the lines that are not working). (Disclaimer: this is the first time I'm trying to declare an option for a package ...)

\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
    You usually don't do much stuff with declare option. You just set a bool/switch and work with the bools later. – Johannes_B Sep 5 '18 at 5:01
  • 1
    As mentioned a already, declareoption is clearly wrong here, it its for package/class stars not macro states. Are you sure that equal statement for the stored value expands the stored value before comparing? Most of these don't, thus I haven't used xifthen.... – daleif Sep 5 '18 at 5:19
  • @daleif I'm not sure if the equal statement expands the stored value, but it's only text that needs to get stored ... it's been working so far. But any other improvements to make the code better are also welcome. – jan Sep 5 '18 at 5:21
  • 3
    you can use \DeclareOption within a macro (but that is very unusual) but you need to declare any option before \ProcessOptions is used otherwise it does nothing. In your case the option declaration (even if you ignore the ifthenelse tests) is not executed until (if) \mycommand is executed and that is in the document body long after the package and its options have been processed. – David Carlisle Sep 5 '18 at 7:08
2

Here's a fully working package which does what you want. It uses expl3 and related packages and you have three ways of using your commands: you can specify a package option globally, use a setup command locally or pass an optional argument to one of the macros.

Note that the second A in the example is produced by passing an optional macro parameter.

example

\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}
  • Thank you very much, this is a very comprehensive solution, especially including the options as local switches. I must admit, as a beginner, I don't quite understand most of the code, so if you have some spare time to add some comments what the commands do, I'd be very grateful ... or other resources to read – jan Sep 6 '18 at 20:01
  • 1
    @jan I added some explanations. There is a document called interface3.pdf that describes the interfaces I used. – TeXnician Sep 6 '18 at 20:11
2

Referring to your question's title I don't think that \DeclareOption can be used inside a macro (properly). For macros you want to use a key-value-system as provided by pgfkeys (https://www.ctan.org/pkg/pgfkeys) or similar packages.

However from your actual question I deduce that you are creating a package that defines the respective macro and you want to add an option to the package that can be given when loading it. In that case \DeclareOption is the right way to go.
But not the way you did it. You want the \DeclareOption command to be executed before \ProcessOptions is being called. Therefore you want them to be executed right at the loading of the package and thus they can't be used inside a macro definition (besides maybe an \edef but let's not get into that).

The way to go is to create a new boolean flag whose value will be changed if using that option. In my example I am making use of the etoolbox package:

\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
    }%
}
  • The OP has provided an MWE. Could you please turn your code in an MWE as well? – TeXnician Sep 5 '18 at 6:23
1

Define two macros and let the options decide which one to use.

\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}

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.