以编程方式构建引用命令的字符串

以编程方式构建引用命令的字符串

我有一个相关问题在这里其解决方案被以下错误“缺少 \endcsname 插入”阻止:

\documentclass[british]{article}
\usepackage[T1]{fontenc}
\usepackage{babel}
\usepackage{csquotes}
%\usepackage{subcitations}

\usepackage{listofitems}
\usepackage{xifthen}
\usepackage{xstring}

\usepackage[backend=biber, style=numeric, subentry]{biblatex}

\begin{filecontents}{\jobname2.bib}
@set{two,
entryset = {twomain,twosub1},
}
@article{twomain,
author = {Yoon},
title = {A paper},
journaltitle = {Journal Title},
date         = 2020,
}
@article{twosub1,
url={http://sub1.com}
}

@article{one,
url={http://other2.example.com}
}

@article{three,
url={http://other3.example.com}
}
\end{filecontents}
\addbibresource{\jobname2.bib}


\begin{document}

\newcommand{\subcite}[2]{
    % Split the names of the references and the sub-citations on commas
    \readlist*\mains{#1}
    \readlist*\subs{#2}

    % Define string to hold citations
    \def\citations{\foreachitem\x\in\mains[]{\ifthenelse{\xcnt>1}{,}{}\x{\ifthenelse{\xcnt>\subslen}{}{\subs[\xcnt]}}}}
    
    Citations: \citations  % => Citations: one,twosub1,three
    
    %\cite{\citations} % This errors with "Missing \endcsname inserted."
}


\def\citations1{one,twosub1,three}

1. \cite{one,twosub1,three}        % works fine => 1. [1,2,3]
2. \cite{\citations1}        % works fine => 2. [1,2,3]
3. \subcite{one,two,three}{,sub1}  % errors => 3. Citations: one,twosub1,three

\printbibliography
\end{document}

有没有办法避免/解决这个错误?

答案1

您的\citations扩展性不强。这是解决此问题的众多方法之一。(顺便说一句,\def\citations1{...}有点“意外”地起作用。)

\documentclass[british]{article}
\usepackage[T1]{fontenc}
\usepackage{babel}
\usepackage{csquotes}
%\usepackage{subcitations}

\usepackage{listofitems}
\usepackage{xifthen}
\usepackage{xstring}

\usepackage[backend=biber, style=numeric, subentry]{biblatex}

\begin{filecontents}{\jobname2.bib}
@set{two,
entryset = {twomain,twosub1},
}
@article{twomain,
author = {Yoon},
title = {A paper},
journaltitle = {Journal Title},
date         = 2020,
}
@article{twosub1,
url={http://sub1.com}
}

@article{one,
url={http://other2.example.com}
}

@article{three,
url={http://other3.example.com}
}
\end{filecontents}
\addbibresource{\jobname2.bib}


\begin{document}

\newcommand{\subcite}[2]{%
    % Split the names of the references and the sub-citations on commas
    \readlist*\mains{#1}%
    \readlist*\subs{#2}%
    % Define string to hold citations
    \edef\citations{}%
    \foreachitem\x\in\mains[]{\ifnum\xcnt>1\relax
        \edef\citations{\citations,\x}%
        \else   
        \edef\citations{\citations\x}%
        \fi
    \ifnum\xcnt>\subslen
    \else
    \edef\citations{\citations\subs[\xcnt]}%
    \fi}%
    \expandafter\cite\expandafter{\citations}% This errors with "Missing \endcsname inserted."
}


\def\citations1{one,twosub1,three}

1. \cite{one,twosub1,three}        % works fine => 1. [1,2,3]
2. \cite{\citations1}        % works fine => 2. [1,2,3]
3. \subcite{one,two,three}{,sub1}  % works fine => 1. [1,2,3]

\printbibliography
\end{document}

在此处输入图片描述

答案2

我提出一个expl3有根据的答案。它与您的方法并没有什么不同,但具有很多优点:

  1. 输入中逗号周围的空格将被忽略
  2. 不存在覆盖现有命令的风险
  3. 不需要根据计数器做出不同的选择来使事情复杂化
\begin{filecontents}{\jobname.bib}
  @set{two,
  entryset = {twomain,twosub1},
}
@article{twomain,
  author = {Yoon},
  title = {A paper},
  journaltitle = {Journal Title},
  date = 2020,
}
@article{twosub1,
  url = {http://sub1.com}
}

@article{one,
  url = {http://other2.example.com}
}

@article{three,
  url = {http://other3.example.com}
}
\end{filecontents}

\documentclass{article}
\usepackage{csquotes}
\usepackage[backend=biber, style=numeric, subentry]{biblatex}
%\usepackage{xparse} % uncomment if using LaTeX prior to release 2020-10-01

\addbibresource{\jobname.bib}

\ExplSyntaxOn

\NewDocumentCommand{\subcite}{mm}
 {
  \ajp_subcite:nn { #1 } { #2 }
 }

\seq_new:N \l_ajp_subcite_main_seq
\seq_new:N \l_ajp_subcite_sub_seq
\seq_new:N \l_ajp_subcite_final_seq

\cs_new_protected:Nn \ajp_subcite:nn
 {
  % split the first and second arguments at commas
  \seq_set_split:Nnn \l_ajp_subcite_main_seq { , } { #1 }
  \seq_set_split:Nnn \l_ajp_subcite_sub_seq { , } { #2 }
  % merge the items in a new sequence
  \seq_clear:N \l_ajp_subcite_final_seq
    % here ##1 is the index, ##2 the entry in the first sequence
    % \seq_item:Nn returns nothing if the sequence is shorter
  \seq_map_indexed_inline:Nn \l_ajp_subcite_main_seq
   {
    \seq_put_right:Nx \l_ajp_subcite_final_seq { ##2 \seq_item:Nn \l_ajp_subcite_sub_seq { ##1 } }
   }
  % make the citations: deliver all items separated by a comma
  \cite
   {
    \seq_use:Nn \l_ajp_subcite_final_seq { , }
   }
 }

\ExplSyntaxOff

\newcommand\citationtest{one,twosub1,three}

\begin{document}

1. \cite{one,twosub1,three}

2. \cite{\citationtest}

3. \subcite{one,two,three}{,sub1}

4. \subcite{one, two, three}{ , sub1}

\printbibliography

\end{document}

在此处输入图片描述

当心:与\def\citations1{...}重新定义 \citations,这是命令中使用的宏\subcite。您不能用 定义名称中带有数字的命令\def(除非您使用\csname,但随后必须使用相同的命令来调用宏,这使得它并不实用)。

尝试使用 Lazy squirrel 的答案中提出的代码

1. \cite{one,twosub1,three}        % works fine => 1. [1,2,3]
2. \subcite{one,two,three}{,sub1}  % works fine => 1. [1,2,3]
3. \cite{\citations1}        % doesn't work!

你将会感到惊喜。

还要注意,TeX 不是自由格式的。空格是相关的,空行会生成一个\par标记。此外,结束行会转换为空格(除非您使用 来%屏蔽结束行)。即使是经验丰富的 TeX 程序员有时也会犯错(例如,在我编辑之前,Lazy squirrel 的答案有两个虚假的空格。)

相关内容