3

I try to make just a very minimalist example of pgfkeys — or other keystyle parameters package —, with a command like this one:

\mycommand{title="The new book", author="John Doe"}

to get a behavior like this:

Writer John Doe

Title The new book

And, possibly, if on key is missing, it line will not appear. For example, the command

\mycommand{title="The new book"}

Will only print:

Title The new book

I check in the web and also StackExchange but I only find very complicated examples including so much other things not directly related to key-value syntax.

So, how can I just put such a minimal key-value command?

  • well this is not really a "minimal" command. Beside setting up the keyval syntax you also need code to test for empty values, and to store the fix words (Writer, Title). Beside this your question is missing where you want to use this command, if the formatting should use a description list or something else and if there will be more keys ... – Ulrike Fischer May 12 at 12:57
  • What is the expected behavior if one of the keys is empty (ex: \mycommand{title=The new book,author=}? What if both are missing or empty (ex: \mycommand{})? – Paul Gaborit May 12 at 13:40
  • @UlrikeFischer I just try to understand the mechanism of the key-value commands. So yes it’s not too complex example, but a so minimalist example will not be enough instructive. – fauve May 12 at 16:24
4

I'm not sure what you really need. This can be something to start...

Assinging to title or author actually runs the code defined in pgfkeys. Nothing is stored.

\documentclass{article}

\usepackage{pgfkeys}

\pgfkeys{
    /bibliography/.cd, % family
    title/.code = {\ifx#1\empty A\else{\textbf{Title} #1\par}\fi},
    author/.code = {\ifx#1\empty A\else{\textbf{Author} #1\par}\fi},
}

\newcommand{\mycommand}[1]{
    \pgfkeys{
        /bibliography/.cd,
        #1,
    }
    \pgfkeysvalueof{/bibliography/title}
    \pgfkeysvalueof{/bibliography/author}
}
\begin{document}
One:\par
\mycommand{title = {Tikz \& PGF}, author={JD}}

Two:\par
\mycommand{author={JD}}

Three:\par
\mycommand{title = {Tikz \& PGF}}

Four:\par
\mycommand{}

Five:\par
\mycommand{title=, author=}

\end{document}

Edit

Please note that the .code is executed at "parameter time", so \mycommand{author={JD}, title = {Tikz \& PGF}} will print the author before the title.

Edit 2

This version uses \bibtitle and \bibauthor to store the data. As theses macros are global, you have to clear them (set to empty) in each call, otherwise previous values are remembered.

\documentclass{article}

\usepackage{pgfkeys}

\pgfkeys{
    /bibliography/.cd, % family
    title/.store in = \bibtitle,
    author/.store in = \bibauthor,
}

\newcommand{\mycommand}[1]{
    \pgfkeys{
        /bibliography/.cd,
        title = {},  % clear title
        author = {}, % clear author
        #1,
    }
    \ifx\bibtitle\empty\else\textbf{Title:} \bibtitle\par\fi
    \ifx\bibauthor\empty\else\textbf{Author:} \bibauthor\par\fi
}
\begin{document}
One:\par
\mycommand{title = {Tikz \& PGF}, author={JD}}
\mycommand{author={JD}, title = {Tikz \& PGF}}

\vspace{2ex}
Two:\par
\mycommand{author={JD}}

\vspace{2ex}
Three:\par
\mycommand{title = {Tikz \& PGF}}

\vspace{2ex}
Four:\par
\mycommand{}

\vspace{2ex}
Five:\par
\mycommand{title=, author=}

\end{document}
| improve this answer | |
  • If I understand /bibliography/ is a variable name you choose. It could be anything else? Is it a kind of namespace? – fauve May 12 at 16:26
  • 1
    @fauve bibliography is called a family and you can name it as you like. Think about it as a directory tree (as the manual says). Therefore you can have a title inside bibliography which is distinct from another title in other branch of the tree. – Jander May 12 at 17:16
  • Additional question: is it possible to force item apparition order? I mean, if I do \mycommand{title="The new book", author="John Doe"} or \mycommand{author="John Doe", title="The new book"} it always give “Writer John Doe Title The new book”. – fauve May 17 at 11:16
  • 1
    @fauve Please see the 'EDIT 2' in my answer. Just realized I inverted the lines, so in my example the title comes first... – Jander Jun 2 at 17:51
1

Here's an implementation with expl3 keys.

\documentclass{article}
\usepackage{xparse}

\ExplSyntaxOn

% define the keys
\keys_define:nn { fauve/books }
 {
  title  .tl_set:N = \l__fauve_books_title_tl, % the title
  author .tl_set:N = \l__fauve_books_author_tl, % the author
 }

% formatting
\NewDocumentCommand{\mycommand}{m}
 {
  \group_begin:
  \keys_set:nn { fauve/books } { #1 } % populate the keys

  % format the book
  \par\addvspace{\topsep}
  \fauve_books_author:V \l__fauve_books_author_tl
  \fauve_books_title:V \l__fauve_books_title_tl
  \par\addvspace{\topsep}
  \group_end:
 }

\cs_new_protected:Nn \fauve_books_title:n
 {
  \tl_if_empty:nF { #1 }
   {
    \par\noindent\textbf{Title:}~#1
   }
 }
\cs_new_protected:Nn \fauve_books_author:n
 {
  \tl_if_empty:nF { #1 }
   {
    \par\noindent\textbf{Writer:}~#1
   }
 }
\cs_generate_variant:Nn \fauve_books_title:n  {V}
\cs_generate_variant:Nn \fauve_books_author:n {V}

\ExplSyntaxOff

\begin{document}

\mycommand{title=The new book, author=John Doe}

\mycommand{title=Another book}

\end{document}

I have separated the formatting commands specific for each key, but that's optional.

enter image description here

| improve this answer | |
1

FWIW, I'll show how to write such a macro in ConTeXt. ConTeXt has a few key-value driven interfaces, but for something as simple as this, I would just piggyback oon the \setupvariables[...][..=..] and \getvariable{...}{...}.

\unprotect
\define\mycommand
    {\dosingleargument\mycommand_setup}

\def\mycommand_setup[#1]%
    {\bgroup
     \setvariables[mycommand][#1]%
     \mycommand_process
     \egroup}

\def\mycommand_process
    {\startlines
     \doifsomething{\getvariable{mycommand}{author}}
        {\bold{Writer:} \getvariable{mycommand}{author}\endgraf}%
     \doifsomething{\getvariable{mycommand}{title}}
        {\bold{Title:} \getvariable{mycommand}{title}}%
     \stoplines}
\protect

\starttext
\mycommand[title={The new book}, author={John Doe}]

\mycommand[title={The new book}]
\stoptext

Note that I modified the interface (use \mycommand[...] instead of \mycommand{...}) to match the ConTeXt convention that arguments in square brackets are for options and arguments in curly brackets are for text which is typeset.

| improve this answer | |

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.