3

How can I make this macro initially ignore the undefined key fn-special-text in the second argument? It is defined within the macro (because the name is generated from the text of the first argument; that all happens in the first two steps), then set using that argument only after that definition is generated.

\documentclass{article}
\usepackage{xstring}
\usepackage{keyval}
\begin{document}

% The command:
\newcommand\annMessageParseParse[2]{%
  % first step, search for the instance of `FN...` in arg #1
    \StrCut{#1}{FN}\partA\partB% take unique name starting after "FN"
    \StrCut{\partB}{ }\partC\partD% stop at the first space
  % generate a new key using that unique name:
    \makeatletter
    \define@key{mykeys}{fn-\partC-text}{\expandafter\def\csname fn\partC text\endcsname{#1}}
    \makeatother
  % set the key using arg #2
    \setkeys{mykeys}{#2}
  % create a command using the new name, which employs our new key (which is just a footnote command)
    \expandafter\def\csname FN\partC\endcsname{\expandarg\footnote{\expandafter\csname fn\partC text\endcsname}}
  % combine `FN` and `\partC` in order to use the so-named command we just made
    \edef\combinethem{FN\partC}
  % replace the old `FN...` with the new command
    \expandarg\def\thenewmessage{
      \StrSubstitute[0]{#1}{\combinethem}
      {\csname FN\partC\endcsname}
    }
  % spit out the message
    \thenewmessage
}

% use case:
  \annMessageParseParse
    {This is myFNspecial new message.}% will turn into `This is my^[1] new message`
    {fn-special-text={This is the special footnote}}
\end{document}

The issue is that, when the macro is called, keyval sees the undefined key immediately and errors out. Is there some way I can tell keyval (or xkeyval?) to just ignore undefined keys? Both the message and the yet to be defined key need to be made in arguments in the same command.

3
  • 1
    There is no problem here if you move the \makeatletter...\makeatother setting outside your definition of the macro \annMessageParseParse.
    – Werner
    Jun 15, 2016 at 19:07
  • But that doesn't answer your question regarding unknown keys, right?
    – Werner
    Jun 15, 2016 at 19:08
  • Right, but that's actually really good to know! Eventually I want to be able to make this process start by counting how many FN...'s are in the message, then do this stuff to each one - so it'll be much cleaner now to just wrap the whole macro def in \makeatletter/ \makeatother once. Jun 15, 2016 at 19:49

1 Answer 1

4

One could redefine \KV@errx which will be expanded in case of undefined keys. For example:

\documentclass{article}
\usepackage{keyval}

\begin{document}

%\setkeys{test}{unknown=something}

\makeatletter
\let\KV@errx@ORI\KV@errx   % Save original error handling

\let\KV@errx\@gobble       % Ignore unknown keys
\setkeys{test}{unknown=something}

\renewcommand\KV@errx[1]{% Ignore unknown keys, but print a warning
  \PackageWarning{test}{#1}}
\setkeys{test}{unknown=something}

\let\KV@errx\KV@errx@ORI   % Restore original error handling
\makeatother

\end{document}
2
  • Thanks Axel - this is exactly what I needed! I am writing the macro into an .sty document. Any reason why it only works if I redefine KV@errx at the end of the package? (That's no problem; it just might be useful to know why it works that way in the future). Jun 15, 2016 at 22:18
  • 1
    Redefining \KV@errx should work at any time after loading the keyval package. But it's a good idea to redefine it right before the usage of \setkeys and restore it immediately afterwards. Without restoring it this would affect all other packages using keyval as well which would be a very very bad idea.
    – user2574
    Jun 16, 2016 at 7:03

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .