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?
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.

| improve this answer | |
  • 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 '14 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! – Paul Stanley Apr 29 '14 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 '14 at 10:53

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.