
Я создал библиотеку BibLaTeX, которую использую для организации всех своих устных и постерных презентаций. Это фактически настраиваемая библиотека с новыми типами данных и командами цитирования. Все идеи я взял изздесьиздесь.
После некоторого времени программирования я получил следующий код, который работает довольно хорошо. Я могу использовать свою собственную команду \printcontrib{BiB_entry}
в любом тексте, но также я могу сделать некоторый листинг в конце, например, вызвав все записи Bib через последнюю команду. Прежде чем я покажу код, я хотел бы извиниться уже здесь, что мой код, вероятно, является каким-то (злым?) хаком. ;-)
МВЭ
\RequirePackage{filecontents}
% The BibTeX library
\begin{filecontents*}{\jobname.bib}
@Contribution{Oral_2016_1,
Type = {Oral},
Invited = {True},
Author = {{\textbf{Author, One} and Author, Two and Author, Three}},
Presenter = {{Author, One}},
Title = {{Some cool stuff about the Nanoworld}},
Event = {{Conference about XYZ}},
Eventtype = {Conference},
Place = {},
City = {Helsinki (Finland) - Stockholm (Sweden)},
Country = {},
Date = {May 1$^{\rm st}$ - June 2$^{\rm nd}$},
Period = {},
Year = {2016},
Note = {}
}
@Contribution{Oral_2015_1,
Type = {Oral},
Invited = {Ture},
Author = {{\textbf{Author, One}}},
Presenter = {{Author, One}},
Title = {{Exciting research on cool Nanostuff}},
Event = {{6$^{\rm th}$ Nanotechnology workshop}},
Eventtype = {Workshop},
Place = {},
City = {Giessen},
Country = {Germany},
Date = {September 24$^{\rm th}$},
Period = {},
Year = {2015},
Note = {}
}
@Contribution{Oral_2015_2,
Type = {Oral},
Invited = {False},
Author = {{Author, One and Author, Two and \textbf{Author, Three}}},
Presenter = {{Author, Three}},
Title = {{Nanochemistry at its edge}},
Event = {{18$^{\rm th}$ Summer School of Nanochemistry}},
Eventtype = {School},
Place = {},
City = {Cassis},
Country = {France},
Date = {September 9$^{\rm th}$},
Period = {},
Year = {2015},
Note = {}
}
\end{filecontents*}
% The declaration of the entries.
\begin{filecontents}{contribution.dbx}
\DeclareDatamodelEntrytypes{contribution}
\DeclareDatamodelFields[type=field,datatype=literal]{
type,
invited,
title,
event,
eventtype,
place,
city,
country,
date,
period,
year,
note
}
\DeclareDatamodelFields[type=list,datatype=name]{
author,
presenter
}
\DeclareDatamodelEntryfields[contribution]{
type,
invited,
author,
presenter,
title,
event,
eventtype,
place,
city,
country,
date,
period,
year,
note}
\end{filecontents}
% The standard LaTeX head, with a link to the chem-acs style and biber. The
% datamodel 'contribution' is also declared.
\documentclass[english]{book}
\usepackage{babel}
\usepackage{ifmtarg}
\usepackage{xstring}
\usepackage{ifthen}
\usepackage[datamodel=contribution,
style=chem-acs,
natbib=true,
backend=biber]
{biblatex}
\addbibresource{\jobname.bib}
% Declare cite commands, the most important ones. Others will be added.
\DeclareCiteCommand{\citeevent}
{\boolfalse{citetracker}%
\boolfalse{pagetracker}%
\usebibmacro{prenote}}
{\printtext{\printfield{event}}}
{\multicitedelim}
{\usebibmacro{postnote}}
\DeclareCiteCommand{\citedate}
{\boolfalse{citetracker}%
\boolfalse{pagetracker}%
\usebibmacro{prenote}}
{\printtext{\printfield{date}}}
{\multicitedelim}
{\usebibmacro{postnote}}
\DeclareCiteCommand{\citeyear}
{\boolfalse{citetracker}%
\boolfalse{pagetracker}%
\usebibmacro{prenote}}
{\printtext{\printfield{year}}}
{\multicitedelim}
{\usebibmacro{postnote}}
\DeclareCiteCommand{\citecity}
{\boolfalse{citetracker}%
\boolfalse{pagetracker}%
\usebibmacro{prenote}}
{\printtext{\printfield{city}}}
{\multicitedelim}
{\usebibmacro{postnote}}
\DeclareCiteCommand{\citecountry}
{\boolfalse{citetracker}%
\boolfalse{pagetracker}%
\usebibmacro{prenote}}
{\printtext{\printfield{country}}}
{\multicitedelim}
{\usebibmacro{postnote}}
\DeclareCiteCommand{\citetitle}
{\boolfalse{citetracker}%
\boolfalse{pagetracker}%
\usebibmacro{prenote}}
{\printtext{\printfield{title}}}
{\multicitedelim}
{\usebibmacro{postnote}}
\DeclareCiteCommand*{\citeauthor}
{\defcounter{maxnames}{99}%
\defcounter{minnames}{99}%
\defcounter{uniquename}{2}%
\boolfalse{citetracker}%
\boolfalse{pagetracker}%
\usebibmacro{prenote}}
{\ifciteindex{\indexnames{labelname}}{}\printnames{labelname}}
{\multicitedelim}
{\usebibmacro{postnote}}
% My own command, which puts into format and prints the contribution.
\newcommand{\printcontrib}[1]{
\citeauthor*{#1},
\citetitle*{#1},
\citeevent{#1},
\citecity{#1}
%
% This works, but there is no 'if' that might find an empty 'country' field.
% I would like to have:
% If : Country = {} => Do not print '(\citecountry{#1})'
% Else: print (\citecountry{#1})
(\citecountry{#1}),
%
%
% Here is my first test amongst many others:
% It works but there is a error: "! Illegal unit of measure (pt inserted)."
%
% \newlength{\strlen}\settowidth{\strlen}{\citecountry{#1}}
% \ifdim\strlen=0\else(\citecountry{#1})\fi,
% \let\strlen\relax
%
\citedate{#1} (\citeyear{#1})
}
\begin{document}
\chapter{Oral contributions}
\printcontrib{Oral_2016_1}\\\\
%
\noindent\printcontrib{Oral_2015_2}\\\\
%
\noindent\printcontrib{Oral_2015_1}\\\\
%
\end{document}
Пока все хорошо. Теперь в одной записи BibLaTeX могут быть некоторые записи (см., например, Oral_2016_1 => Country = {}), в которых нет текста внутри двух {}, поскольку некоторая информация отсутствует (обратите внимание, что я хотел бы сохранить эти скобки по нескольким причинам ... .)
Я хотел бы иметь часть 'if ... do ... else do ...' в коде, которая проверяет, является ли запись 'пустой', поэтому здесь Country = {}
. В противном случае, как в данном случае, в тексте отображаются две скобки ().
Я хотел бы иметь это условие, в частности, в этой команде:
% My own command, which puts into format and prints the contribution.
\newcommand{\printcontrib}[1]{
\citeauthor*{#1},
\citetitle*{#1},
\citeevent{#1},
\citecity{#1}
%
% This works, but there is no 'if' that might find an empty 'country' field.
% I would like to have:
% If : Country = {} => Do not print '(\citecountry{#1})'
% Else: print (\citecountry{#1})
(\citecountry{#1}),
%
%
% Here is my first test amongst many others:
% It works but there is a error: "! Illegal unit of measure (pt inserted)."
%
% \newlength{\strlen}\settowidth{\strlen}{\citecountry{#1}}
% \ifdim\strlen=0\else(\citecountry{#1})\fi,
% \let\strlen\relax
%
\citedate{#1} (\citeyear{#1})
}
Команда (\citecountry{#1})
(обратите внимание на скобки (
и )
) будет выполнена только в том случае, если запись country
содержит какой-либо текст, другими словами, отсутствует Country = {}
в файле BibLaTeX.
Я перепробовал дюжину вещей. Например, я пробовал несколько условий if с помощью пакетов ifmtarg
, xstring
и ifthen
, но безуспешно. Единственное half-solution
в кавычках % (под текстом % Here is my first test
в MWE) работает, хотя и с ошибками (вам нужно раскомментировать это, чтобы оно скомпилировалось LaTeX).
решение1
В biblatex
, форматирование полей, такое как скобки, выделение или курсив, в большинстве случаев не следует записывать в макрос напрямую, их следует выполнять с помощью \DeclareFieldFormat
. Таким образом, вы можете быть уверены, что biblatex
сможете правильно определять пустые поля и ничего не делать в этом случае.
Вы могли бы просто сделать
\DeclareFieldFormat{country}{\mkbibparens{#1}}
\DeclareCiteCommand{\citecountry}
{\boolfalse{citetracker}%
\boolfalse{pagetracker}%
\usebibmacro{prenote}}
{\printfield{country}}
{\multicitedelim}
{\usebibmacro{postnote}}
Поле затем оборачивается скобками всякий раз, когда оно отображается, и игнорируется в противном случае. Обратите внимание, что нет необходимости оборачивать один \printfield
в \printtext
без аргумента, \printfield{country}
будет делать то же самое, что и \printtext{\printfield{country}}
.
Вместо того, чтобы определять \citecontrib
так, как вы делаете сейчас, вам, вероятно, следует просто определить драйвер библиографии, например, @contribution
так (это всего лишь первый грубый набросок, но вы поняли идею)
\DeclareFieldFormat{country}{\mkbibparens{#1}}
\DeclareFieldFormat[contribution]{title}{\mkbibemph{#1}}
\newbibmacro*{event+venue+city+country+date}{%
\printfield{eventtitle}%
\newunit
\printfield{eventtitleaddon}%
\newunit
\printeventdate
\newunit
\printfield{city}
\setunit{\addspace}%
\printfield{country}
\newunit}
\DeclareBibliographyDriver{contribution}{%
\usebibmacro{bibindex}%
\usebibmacro{begentry}%
\usebibmacro{author/editor+others/translator+others}%
\setunit{\printdelim{nametitledelim}}\newblock
\usebibmacro{title}%
\newunit
\printlist{language}%
\newunit\newblock
\usebibmacro{byauthor}%
\newunit\newblock
\usebibmacro{event+venue+city+country+date}%
\newunit\newblock
\printfield{howpublished}%
\newunit\newblock
\printfield{note}%
\newunit\newblock
\usebibmacro{location+date}\printdate%
\newunit\newblock
\iftoggle{bbx:url}
{\usebibmacro{url+urldate}}
{}%
\newunit\newblock
\usebibmacro{addendum+pubstate}%
\setunit{\bibpagerefpunct}\newblock
\usebibmacro{pageref}%
\newunit\newblock
\iftoggle{bbx:related}
{\usebibmacro{related:init}%
\usebibmacro{related}}
{}%
\usebibmacro{finentry}}
Затем вы можете просто использовать его \fullcite
и все готово.
решение2
Вам следует проверить, существует ли поле как часть \DeclareCiteCommand
использования\iffieldundef
или что-то подобное; см. раздел4.6.2 Отдельные тестывbiblatex
документация):
\DeclareCiteCommand{\citecountry}
{\boolfalse{citetracker}%
\boolfalse{pagetracker}%
\usebibmacro{prenote}}
{\iffieldundef{country}{}{(\printtext{\printfield{country}})}}
{\multicitedelim}
{\usebibmacro{postnote}}
и вот \printcontrib
:
\newcommand{\printcontrib}[1]{%
\citeauthor*{#1},
\citetitle*{#1},
\citeevent{#1},
\citecity{#1}
\citecountry{#1},
\citedate{#1} (\citeyear{#1})
}
Вы также можете написать более крупное \DeclareCiteCommand
решение, используя \printcontrib
.