根据biblatex-apa
文档(第 4.1 节)APA 规定括号内的引用不应包含额外的括号。因此,它提供了命令
\nptextcite[⟨prenote⟩][⟨postnote⟩]{⟨key⟩}⟨punctuation⟩
其工作原理类似\textcite
,但取消了括号。
\textcite
这一切都很好,除非你正在将你的文档从其他文档(例如 markdown)转换而来,在这种情况下你无法做出类似于和之间的区别\nptextcite
。所以我想知道是否有办法自动化这个使用 LuaTeX? 我们能否定义一个命令,根据当前括号级别\autotextcite
扩展为\textcite
和?\nptextcite
为了在实践中可用,它最好按以下方式工作:
- 它应该记住整个段落的括号级别,而不仅仅是单独的行,因此使用
process_input_buffer
回调逐行进行简单的正则表达式字符串替换是行不通的。 - 应该为每个新段落重置括号级别,以便忘记
)
文本中的某个地方不会弄乱文档的其余部分。 - 出于显而易见的原因,最好不要让字符
(
和)
处于活动状态(这会破坏许多其他接口)。同样,用类似和的字符串分别替换(
和也可能导致错误。)
(\directlua{parlevel=parlevel+1}
\directlua{parlevel=parlevel-1})
所以我希望的是这样的:
\begin{filecontents*}{ref.bib}
@online{tex.sx,
author={{egreg et al.}},
year={2022},
title={{TeX Stack Exchange}},
url={https://tex.stackexchange.com/},
}
\end{filecontents*}
\documentclass{article}
\usepackage[american]{babel}
\usepackage{csquotes}
\usepackage[style=apa]{biblatex}
\addbibresource{ref.bib}
\newcommand\autotextcite{%
\ifinsideparentheses
\nptextcite
\else
\textcite
\fi
}
\begin{document}
This follows from \autotextcite[front page]{tex.sx}. % Should yield \textcite
(It also follows from \autotextcite[front page]{tex.sx}.) % Should yield \nptextcite
(It also follows from
\autotextcite[front page]{tex.sx} % Should yield \nptextcite
among other places.)
(It also follows from other resources. % Here we forget a ")"
But \autotextcite[front page]{tex.sx} is a good start. %Should yield \textcite
\printbibliography
\end{document}
答案1
您可以使用 Lua 查看当前正在构建的列表。在段落中,这通常是当前段落,而在\hbox
(或\mbox
或类似)中,这只会查看当前 hbox。通常这应该会导致预期的结果:
\begin{filecontents*}{find_parens.lua}
-- From Marcel Krüger's answer at https://tex.stackexchange.com/a/654261/80496
-- How to translate boolean results to TeX macros selecting the right arguments
local bool_to_token = {[false] = token.create'use_ii:nn', [true] = token.create'use_i:nn'}
-- The codepoints we have to look for
local left_paren = string.byte'('
local right_paren = string.byte')'
-- Some boilerplate to define an unexpandable command sequence from Lua
local id = luatexbase.new_luafunction'ifInParensTF'
token.set_lua('ifInParensTF', id, 'protected')
lua.get_functions_table()[id] = function()
-- We want to look at the current list
local head = tex.nest.top.head
local level = 0
-- and look at all unprocessed characters
for _, char in node.traverse_char(head) do
-- Track the nesting level
if char == left_paren then
level = level + 1
elseif char == right_paren then
if level > 0 then
level = level - 1
else
-- Negative levels don't make sense, so we ignore the ) instead. Print a warning though to avoid surprises.
luatexbase.module_warning('find_parens', '\z
Unable to reliably determine if inside parentheses\n\z
since the paragraphs contains an unmatched `)`.\n\z
It will be ignored\z
')
end
end
end
-- Finally insert a macro which will select the first or second argument dependingon whether level > 0
token.put_next(bool_to_token[level > 0])
end
\end{filecontents*}
\begin{filecontents*}{ref.bib}
@online{tex.sx,
author={{egreg et al.}},
year={2022},
title={{TeX Stack Exchange}},
url={https://tex.stackexchange.com/},
}
\end{filecontents*}
\documentclass{article}
\usepackage[american]{babel}
\usepackage{csquotes}
\usepackage[style=apa]{biblatex}
\directlua{require'find_parens'}
\addbibresource{ref.bib}
\NewDocumentCommand \autotextcite {}{%
\ifInParensTF {%
\nptextcite
}{%
\textcite
}%
}
\begin{document}
This follows from \autotextcite[front page]{tex.sx}. % Should yield \textcite
(It also follows from \autotextcite[front page]{tex.sx}.) % Should yield \nptextcite
(It also follows from
\autotextcite[front page]{tex.sx} % Should yield \nptextcite
among other places.)
(It also follows from other resources. % Here we forget a ")"
But \autotextcite[front page]{tex.sx} is a good start. %Should yield \textcite
\printbibliography
\end{document}