使用 authoryear-comp 时安全且简约地创建自定义(非 comp)文本引用命令

使用 authoryear-comp 时安全且简约地创建自定义(非 comp)文本引用命令

我一直在尝试创建 Biblatex \textcite\textcites和命令的自定义变体。尽管我设法想出了一些看起来或多或少可以工作的代码,但我有两点保留意见\Textcite\Textcites

  1. 我不确定它是否安全。

  2. 这似乎不太可能是最优雅或最简约的解决方案。

有一个更好的方法吗?

下面的大部分代码由bibmacro来自 Biblatex 包的 s 等的重命名副本组成,尤其是来自authoryear.cbx,以及在较小程度上来自biblatex.def

原因是我通常使用authoryear-comp引用样式,它使用不同的定义。但是,该代码似乎要复杂得多,我无法弄清楚如何轻松创建自定义引用命令。

由于我不想comp让这些特定命令产生效果,因此我查看了更简单的示例,authoryear.cbx并根据其textcite宏和\textcite命令的定义编写了命令。

但是,这些定义自然地假设各种宏等的相应定义都来自相同的样式。因此,为了使其工作,我需要从authoryear.cbx和中复制这些定义biblatex.def

由于我不想弄乱authoryear-comp.cbx标准引用命令的定义,我重命名了这些副本并使用重命名的版本来解决问题。

但这基本上是一种蛮力和无知的方法,而且肯定不是更好的选择。

我在代码中留下了一些注释,以表明特定代码块是哪个特定 Biblatex 文件的(修改后的)副本。很抱歉,它不是最精简的,但这些似乎是我在测试中需要的最少部分。

梅威瑟:

\documentclass{article}
\usepackage[style=authoryear-comp,backend=biber]{biblatex}
\bibliography{biblatex-examples}

\newcounter{cfrcitereadingtotal}% stand-in for textcitetotal
\newcommand*{\iffinalcfrcitereadingdelim}{\iflastcitekey}% copy of \iffinalcitedelim from authoryear.cbx
\newbibmacro*{cfr:readingciteyear}{% copy of citeyear from authoryear.cbx
  \iffieldundef{shorthand}{%
    \iffieldundef{labelyear}{%
      \usebibmacro{cite:label}%
    }{%
      \usebibmacro{cite:labelyear+extrayear}%
    }%
  }{%
    \usebibmacro{cite:shorthand}%
  }%
}
\newbibmacro*{cfr:readingcite:postnote}{% copy of textcite:postnote from authoryear.cbx
  \iffieldundef{postnote}{%
    \ifbool{cbx:parens}{%
      \bibcloseparen
    }{}%
  }{%
    \ifbool{cbx:parens}{%
      \setunit{\postnotedelim}%
    }{%
      \setunit{\addspace\bibopenparen}%
    }%
    \printfield{postnote}%
    \bibcloseparen
  }%
}
%% this is basically a straight copy but using a custom counter so it doesn't get decremented the way the textcite equivalent does in authoryear-comp.cbx
\newcommand*{\cfrcitereadingdelim}{% modified from \textcitedelim in biblatex.def
  \iffinalcfrcitereadingdelim{%
    \ifnumgreater{\value{cfrcitereadingtotal}}{2}{%
      \iftextcitepunct{\finalandsemicolon}{\finalandcomma}%
    }{}%
    \addspace\bibstring{and}%
  }{%
    \iftextcitepunct{\addsemicolon}{\addcomma}%
  }%
  \space
}
%% this is the actual specialised bit, but based on textcite from the simpler style
\newbibmacro*{cfr:readingcite}{% modified from textcite in authoryear.cbx
  \printnames{labelname}%
  \setunit{\addcomma\space}%
  \printfield[citetitle]{labeltitle}%
  \setunit{%
    \global\booltrue{cbx:parens}%
    \addspace\bibopenparen
  }%
  \ifnumequal{\value{citecount}}{1}{%
    \usebibmacro{prenote}%
  }{}%
  \usebibmacro{cfr:readingciteyear}%
}
%% this uses the new macro cfr:readingcite and the copies of the other relevant bits from authoryear, avoiding the authoryear-comp textcite complexities
\DeclareCiteCommand{\citereading}% modified from \textcite in authoryear.cbx
{% precode
  \boolfalse{cbx:parens}%
}{% loopcode
  \usebibmacro{citeindex}%
  \iffirstcitekey{%
    \setcounter{cfrcitereadingtotal}{1}%
  }{%
    \stepcounter{cfrcitereadingtotal}%
    \cfrcitereadingdelim
  }%
  \usebibmacro{cfr:readingcite}%
}{% sepcode
  \ifbool{cbx:parens}{%
    \bibcloseparen\global\boolfalse{cbx:parens}%
  }{}%
}{% postcode
  \usebibmacro{cfr:readingcite:postnote}%
}
\newrobustcmd{\Citereading}{\bibsentence\citereading}
\DeclareMultiCiteCommand{\citereadings}{\citereading}{}
\newrobustcmd{\Citereadings}{\bibsentence\citereadings}

\begin{document}
  \citereading{westfahl:space,gillies,doody}

  \citereading[pre][post]{westfahl:space,gillies,doody}

  \citereading[][post]{westfahl:space,gillies,doody}

  \citereading[post]{westfahl:space,gillies,doody}

  \citereading[pre][]{westfahl:space,gillies,doody}

  \citereading{westfahl:space}

  \citereading[pre][post]{westfahl:space}

  \citereading[][post]{westfahl:space}

  \citereading[post]{westfahl:space}

  \citereading[pre][]{westfahl:space}

  \Citereading{westfahl:space,gillies,doody}

  \Citereading[pre][post]{westfahl:space,gillies,doody}

  \Citereading[][post]{westfahl:space,gillies,doody}

  \Citereading[pre]{westfahl:space,gillies,doody}

  \Citereading[pre][]{westfahl:space,gillies,doody}

  \Citereading{westfahl:space}

  \Citereading[pre][post]{westfahl:space}

  \Citereading[][post]{westfahl:space}

  \Citereading[pre]{westfahl:space}

  \Citereading[pre][]{westfahl:space}

  \citereadings{westfahl:space}{gillies}{doody}

  \citereadings(pre)(post)[pre1][post1]{westfahl:space}[pre2][post2]{gillies}[pre3][post3]{doody}

  \citereadings[][post1]{westfahl:space}[][post2]{gillies}[post3]{doody}

  \citereadings[post1]{westfahl:space}{gillies}[post3]{doody}

  \citereadings[pre1][]{westfahl:space}[pre2][]{gillies}[pre3][post3]{doody}

  \Citereadings(pre)(post){westfahl:space}{gillies}{doody}

  \Citereadings[pre1][post1]{westfahl:space}[post2]{gillies}[pre3][]{doody}

  \Citereadings[][post1]{westfahl:space}{gillies}[pre3][]{doody}

  \Citereadings[pre1]{westfahl:space}{gillies}{doody}

  \Citereadings(pre)(post)[pre1][]{westfahl:space}{gillies}{doody}

\end{document}

示例输出(似乎如我所料 - 但结果不是我所担心的!):

示例输出

答案1

宏系列\textcite是一些使用非常高级的代码实现的更具挑战性的风格。修改这些命令很容易积累大量的代码行。

话虽如此,但在我看来,您的解决方案非常安全。任何可能干扰您风格中常用引用命令的东西都已重命名,因此发生冲突的可能性很小。

当然,一开始的长度有点让人难以接受,但这是可以预料到的。

您的解决方案的最大优点是复制所有命令可以使代码适用于几乎所有样式。


这部分答案假设你总是使用-comp-type 样式

\textcite但是,我认为,通过保持接近in的定义authoryear-comp并仅修改几个位,应该可以减少复制这么多宏的需要。

authoryear-comp那么,该解决方案取决于和中定义的一些结构和宏authoryear-icomp,经过短暂的修改(添加\providebibmacro{citeyear}{\printfield{year}}),它也可以与一起使用authortitle-(ti)comp

我的主要想法是,由于本质上我们想要禁用-comp我们只需要调用的功能cite:reinit,这个宏会biblatex忘记姓氏和年份,以便引用不再被压缩。

首先cfr:readingcite是的简化版本,添加了authoryear-comp textcite必要的位printfield[citetitle]{labeltitle}(也可以citeyear直接使用)

\newbibmacro*{cfr:readingcite}{% modified from textcite in authoryear-comp.cbx
  \printnames{labelname}%
  \setunit{\addcomma\space}%
  \printfield[citetitle]{labeltitle}%
  \setunit{%
    \global\booltrue{cbx:parens}%
    \addspace\bibopenparen}%
  \ifnumequal{\value{citecount}}{1}
    {\usebibmacro{prenote}}
    {}%
  \usebibmacro{citeyear}%
  \stepcounter{textcitecount}%
  \setunit{%
    \ifbool{cbx:parens}
      {\bibcloseparen\global\boolfalse{cbx:parens}}
      {}%
  \textcitedelim}}

\textcite然后我们只需复制所有可以实现的设施authoryear-comp

“主要”变化是添加cite:reinit\cbx@readingcite(执行实际引用的宏)以禁用该-comp行为

\DeclareCiteCommand{\cbx@readingcite}
  {\usebibmacro{cite:init}}
  {\usebibmacro{cite:reinit}%
   \usebibmacro{citeindex}%
   \usebibmacro{cfr:readingcite}}
  {}
  {\usebibmacro{textcite:postnote}}

其余的是原始代码,authoryear-comp略微重命名并\cbx@lasthash删除了一个测试

\DeclareCiteCommand{\citereading}[\cbx@textcite@init\cbx@readingcite]
  {\gdef\cbx@savedkeys{}%
   \citetrackerfalse%
   \pagetrackerfalse%
   \DeferNextCitekeyHook%
   \usebibmacro{cite:init}}
  {\ifthenelse{\iffirstcitekey\AND\value{multicitetotal}>0}
     {\protected@xappto\cbx@savedcites{()(\thefield{multipostnote})}%
      \global\clearfield{multipostnote}}
     {}%
   \xappto\cbx@savedkeys{\thefield{entrykey},}%
   \stepcounter{textcitetotal}}
  {}
  {\protected@xappto\cbx@savedcites{%
     [\thefield{prenote}][\thefield{postnote}]{\cbx@savedkeys}}}

\DeclareMultiCiteCommand{\cbx@readingcites}{\cbx@readingcite}{}
\DeclareMultiCiteCommand{\citereadings}[\cbx@textcites@init\cbx@readingcites]{\citereading}{}

\newrobustcmd{\Citereading}{\bibsentence\citereading}
\newrobustcmd{\Citereadings}{\bibsentence\citereadings}

平均能量损失

\documentclass{article}
\usepackage[style=authoryear-comp,bibstyle=authoryear,backend=biber]{biblatex}
\bibliography{biblatex-examples}

\makeatletter
\newbibmacro*{cfr:readingcite}{% modified from textcite in authoryear-comp.cbx
  \printnames{labelname}%
  \setunit{\addcomma\space}%
  \printfield[citetitle]{labeltitle}%
  \setunit{%
    \global\booltrue{cbx:parens}%
    \addspace\bibopenparen}%
  \ifnumequal{\value{citecount}}{1}
    {\usebibmacro{prenote}}
    {}%
  \usebibmacro{citeyear}%
  \stepcounter{textcitecount}%
  \setunit{%
    \ifbool{cbx:parens}
      {\bibcloseparen\global\boolfalse{cbx:parens}}
      {}%
  \textcitedelim}}

\DeclareCiteCommand{\cbx@readingcite}
  {\usebibmacro{cite:init}}
  {\usebibmacro{cite:reinit}%
   \usebibmacro{citeindex}%
   \usebibmacro{cfr:readingcite}}
  {}
  {\usebibmacro{textcite:postnote}}

\DeclareCiteCommand{\citereading}[\cbx@textcite@init\cbx@readingcite]
  {\gdef\cbx@savedkeys{}%
   \citetrackerfalse%
   \pagetrackerfalse%
   \DeferNextCitekeyHook%
   \usebibmacro{cite:init}}
  {\ifthenelse{\iffirstcitekey\AND\value{multicitetotal}>0}
     {\protected@xappto\cbx@savedcites{()(\thefield{multipostnote})}%
      \global\clearfield{multipostnote}}
     {}%
   \xappto\cbx@savedkeys{\thefield{entrykey},}%
   \stepcounter{textcitetotal}}
  {}
  {\protected@xappto\cbx@savedcites{%
     [\thefield{prenote}][\thefield{postnote}]{\cbx@savedkeys}}}

\DeclareMultiCiteCommand{\cbx@readingcites}{\cbx@readingcite}{}
\DeclareMultiCiteCommand{\citereadings}[\cbx@textcites@init\cbx@readingcites]{\citereading}{}

\newrobustcmd{\Citereading}{\bibsentence\citereading}
\newrobustcmd{\Citereadings}{\bibsentence\citereadings}
\makeatother

\begin{document}
  \citereading{knuth:ct:a,knuth:ct:b,knuth:ct:c}

  \citereading{knuth:ct:b,knuth:ct:c}

  \citereading{knuth:ct:a,knuth:ct:b}

  \citereading{westfahl:space,gillies,doody}

  \citereading[pre][post]{westfahl:space,gillies,doody}

  \citereading[][post]{westfahl:space,gillies,doody}

  \citereading[post]{westfahl:space,gillies,doody}

  \citereading[pre][]{westfahl:space,gillies,doody}

  \citereading{westfahl:space}

  \citereading[pre][post]{westfahl:space}

  \citereading[][post]{westfahl:space}

  \citereading[post]{westfahl:space}

  \citereading[pre][]{westfahl:space}

  \Citereading{westfahl:space,gillies,doody}

  \Citereading[pre][post]{westfahl:space,gillies,doody}

  \Citereading[][post]{westfahl:space,gillies,doody}

  \Citereading[pre]{westfahl:space,gillies,doody}

  \Citereading[pre][]{westfahl:space,gillies,doody}

  \Citereading{westfahl:space}

  \Citereading[pre][post]{westfahl:space}

  \Citereading[][post]{westfahl:space}

  \Citereading[pre]{westfahl:space}

  \Citereading[pre][]{westfahl:space}

  \citereadings{westfahl:space}{gillies}{doody}

  \citereadings(pre)(post)[pre1][post1]{westfahl:space}[pre2][post2]{gillies}[pre3][post3]{doody}

  \citereadings[][post1]{westfahl:space}[][post2]{gillies}[post3]{doody}

  \citereadings[post1]{westfahl:space}{gillies}[post3]{doody}

  \citereadings[pre1][]{westfahl:space}[pre2][]{gillies}[pre3][post3]{doody}

  \Citereadings(pre)(post){westfahl:space}{gillies}{doody}

  \Citereadings[pre1][post1]{westfahl:space}[post2]{gillies}[pre3][]{doody}

  \Citereadings[][post1]{westfahl:space}{gillies}[pre3][]{doody}

  \Citereadings[pre1]{westfahl:space}{gillies}{doody}

  \Citereadings(pre)(post)[pre1][]{westfahl:space}{gillies}{doody}

\end{document}

MWE 输出的详细信息

相关内容