[Tex/LaTex] How to properly use \DeclareOption within a macro

conditionalsmacrospackage-optionspackages

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}

Best Answer

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}
Related Question