3

I would like to be able to specify a list that will create categories and add entries to them.

I am using pgffor for specifying the category name and the heading title in a convenient way. The categories I am using in this example is arbitrary, but the use of a field value and categories in general is not.

MWE

\documentclass{article}
\usepackage[utf8]{inputenc}
\usepackage[T1]{fontenc}
\usepackage[defernumbers=true,sorting=ydnt,doi=false,eprint=false,isbn=false]{biblatex}
\renewcommand*{\bibfont}{\footnotesize}
\usepackage{pgffor}

\xdef\bibcats{}

\newcommand*{\addcat}[2]{%
  \DeclareBibliographyCategory{#1}%
  \defbibheading{#1}{\subsection*{#2}}%
}

\foreach \catg/\head in {phdthesis/PhD. Thesis,article/Articles}{%
  \edef\tmp{\noexpand\addcat{\catg}{\head}}
  \tmp
  \listxadd{\bibcats}{\catg}
}

\addbibresource{biblatex-examples.bib}

\AtDataInput{%
  \ifboolexpr{%
    not test {\iffieldundef{type}}
    and
    test {\xifinlist{\thefield{type}}{\bibcats}}
  }
    {\addtocategory{\strfield{type}}{\strfield{entrykey}}}%
    {\ifboolexpr{%
        test {\ifnumgreater{\thefield{year}}{2000}}
        and
        test {\xifinlist{\thefield{entrytype}}{\bibcats}}
      }%
      {\addtocategory{\strfield{entrytype}}{\strfield{entrykey}}}%
      {}%
    }%
}

\begin{document}

\nocite{*}

\printbibheading
\bibbycategory

\end{document}

Result

The above works except for setting the headings and throws the error Package biblatex Error: Heading <phdthesis/article> could not be found. resulting in:

foreach loop result

Desired Result

The result I hope to achieve works by replacing the foreach loop with

\addcat{phdthesis}{PhD. Thesis}
\addcat{article}{Articles}
\forcsvlist{\listxadd\bibcats}{phdthesis,article}

giving

no foreach loop

Questions

I would like to have the creation of categories depend on a list. Given that the non-foreach loop method works, I suspect the problem mainly comes from expansion problems.

  • How do I create categories and corresponding headings based on lists?
  • Why does the way I have tried to deal with expansion not work?

1 Answer 1

3

I think the problem is that your \defbibheading is getting executed in a group so that the command that is defined there (with \newcommand) is not available when you need it.

Stealing code for a global renewcommand from egreg's answer on defining such a command, we redefine the internal workings of biblatex's \defbibheading to make use of such a global redefinition:

\makeatletter
\def\gnewcommand{\g@star@or@long\gnew@command}
\def\grenewcommand{\g@star@or@long\grenew@command}
\def\g@star@or@long#1{% 
  \@ifstar{\let\l@ngrel@x\global#1}{\def\l@ngrel@x{\long\global}#1}}
\def\gnew@command#1{\@testopt{\@gnewcommand#1}0}
\def\@gnewcommand#1[#2]{%
  \kernel@ifnextchar [{\@gxargdef#1[#2]}%
                {\@argdef#1[#2]}}
\let\@gxargdef\@xargdef
\patchcmd{\@gxargdef}{\def}{\gdef}{}{}
\let\grenew@command\renew@command
\patchcmd{\grenew@command}{\new@command}{\gnew@command}{}{}

\def\blx@defbibheading#1[#2]{%
  \csundef{#1}%
  \expandafter\gnewcommand\csname#1\endcsname[1][#2]}
\makeatother

Now all works as expected. I don't know whether there is a different way to avoid your loop executing inside a group and hiding the redefinition.

3
  • Interesting, if I understand correctly, it has to do with the way \foreach from pgffor works in combination with \defbibheading from biblatex. A slightly modified version using a \docsvloop from etoolbox does not cause an issue without using the \gnewcommand.
    – Alex Grede
    Apr 29, 2014 at 10:42
  • 1
    That's very possible. Sounds like \foreach must run inside a group, or something like that. I tend to use etoolbox anyway, since biblatex loades it, and that sounds like a better option; perhaps you might put that as an answer. Your code was essentially perfect! Apr 29, 2014 at 10:46
  • Thanks, my etoolbox solution was very hacked together quickly. I don't think I will find the elegant way I was hoping for, for this specific case :)
    – Alex Grede
    Apr 29, 2014 at 10:53

You must log in to answer this question.

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