3

Consider a package file eqbox.sty:

% Preamble
\NeedsTeXFormat{LaTeX2e}[1994/06/01]
\ProvidesPackage{eqbox}[2018/01/01 Boxed Equations]

% Packages
\RequirePackage{xcolor}
\RequirePackage{pgfopts}
\RequirePackage{amsmath}
\RequirePackage{fancybox}
\RequirePackage[most]{tcolorbox}

% Options
\pgfkeys{
    /eqbox/.cd,
    colframe/.store in = \colframe,
    colframe/.default = {black},
    colback/.store in = \colback,
    colback/.default = {white},
    shadow/.store in = \shadow,
    shadow/.default = {black},
}
\ProcessPgfPackageOptions*

% Body
\tcbset{
    highlight math style={
        enhanced,
        sharp corners,
        breakable,
        colframe=\colframe{},
        colback=\colback{},
        boxrule=0.4pt,
        shadow={2pt}{-2pt}{0mm}{\shadow{}},
        boxsep = 3pt,
        left = 0pt,
        right = 0pt,
        top = 0pt,
        bottom = 0pt
    }
}

and a .tex file that uses this package:

% Preamble
\documentclass[letterpaper, 11pt, onecolumn]{article}

% Packages
\usepackage{lipsum}
\usepackage{eqbox}

% Body
\begin{document}
\lipsum
\begin{equation}
\tcbhighmath{x^2 + 3}
\end{equation}
\lipsum
\end{document}

I am a beginer with pgf and what I tried does not seem to work. What I would like to do is have three options in the package: colback, colframe and shadow. For example with the syntax:

\usepackage{eqbox}

or

\usepackage[shadow=blue]{eqbox}

or

\usepackage[%
    colback=red,
    shadow=\color[RGB]{100,150,200},
]{eqbox}

For the sake of the example, I would like:

  • colframe to be blue by default
  • colback to be undefined by default
  • shadow to be undefined by default (and if shadow is undefined, don't want this line shadow={2pt}{-2pt}{0mm}{\shadow{}} to appear in the tcbset)

I also don't want to "pollute" the global namespace, so from the package user's standpoint I don't want the command \shadow to be known in the main tex file (I want it to be an internal detail of the package eqbox).

How to do that in the cleanest possible way?

Vincent
  • 5,257
  • 1
    For internal commands use the @ within the command name. Concerning "is it the right thing to do": Why not simply doing a \tcbset with default parameters and providing an optional argument for the macro? – TeXnician Jan 20 '19 at 08:43

1 Answers1

2

What happens when you call \pgfkeys{key1, key2=value2, ...} is determined by the rules documented in section 86 of the pgf manual.

Note that the \pgfkeys command is part of the pgfkeys package, while \ProcessPgfPackageOptions comes from pgfopts. This command effectively calls \pgfkeys{/package/key=value} for every key=value pair passed to the package options. In your case,

\usepackage[shadow=blue]{eqbox}

will be processed inside eqbox.sty as if by calling \pgfkeys{/eqbox/shadow=blue}.

Note that

\pgfkeys{/path/key=...}

is the same as

\pgfkeys{
  /path/.cd,
  key=...
}

Although the equals sign makes it seem so, \pgfkeys{key=value} is not actually an assignment. To make it behave like an assignment, you would need to first call

\pgfkeys{key/.store in=\someMacroName}

after which, calling \pgfkeys{key=value} will define the macro \someMacroName to value.

You might also be confused with the meaning of

\pgfkeys{key/.default=value}

which does not assign a default value to key; rather, it causes all subsequent calls to \pgfkeys{key} to behave as \pgfkeys{key=value}.

Putting it all together, your example becomes:

% eqbox.sty

\NeedsTeXFormat{LaTeX2e}[1994/06/01]
\ProvidesPackage{eqbox}[2018/01/01 Boxed Equations]

\RequirePackage{pgfopts}
\RequirePackage[most]{tcolorbox}

\pgfkeys{
  /eqbox/.cd,  % Change the prefix path to /eqbox/
  %
  colframe/.store in=\colframe, % Make subsequent calls to 
                                % \pgfkeys{/eqbox/colframe=<value>}
                                % cause \def\colframe{<value>}
  %
  colframe=black,   % Hence, this causes \def\colframe{black},
                    % which is effectively a default value.
  %
  % Same for the rest of the keys.
  colback/.store in=\colback,
  colback=white,
  shadow/.store in=\shadow,
  shadow=black
}

\ProcessPgfPackageOptions{/eqbox} % If the .tex file contains
                                  % \usepackage[shadow=purple]{eqbox},
                                  % that would result in the call
                                  % \pgfkeys{/eqbox/shadow=purple}.
                                  % This will in turn cause \def\shadow{purple},
                                  % because of the .store handler.

\tcbset{
  highlight math style={
    enhanced,
    sharp corners,
    breakable,
    colframe=\colframe,
    colback=\colback,
    boxrule=0.4pt,
    shadow={2pt}{-2pt}{0mm}{\shadow},
    boxsep=3pt,
    left=0pt,
    right=0pt,
    top=0pt,
    bottom=0pt
  }
}
% .tex file that uses the package

\documentclass[letterpaper, 11pt, onecolumn]{article}

\usepackage[shadow=purple]{eqbox}

\begin{document}
\begin{equation}
\tcbhighmath{x^2 + 3}
\end{equation}
\end{document}

The result:

enter image description here

If you want to detect whether the package user supplied a value for an option, say myoption:

% In mypackage.sty

\def\someDefaultValue{myDefaultValue}

\pgfkeys{
  /mypackage/myoption/.store in=\myoption,
  /mypackage/myoption=\someDefaultValue
}

\ProcessPgfPackageOptions{/mypackage}

\ifx\someDefaultValue\myoption
  % User did not supply myoption=value
\else
  % User supplied some value,
  % now stored in \myoption
\fi

For this last part, also see https://tex.stackexchange.com/a/53091/80468.

dow
  • 648
  • 4
  • 9