我正在创建包含许多多级枚举列表的文档,并且正在寻找简化符号的方法。
理想情况下,我想写如下内容:
\documentclass{article}
\usepackage{enumitem}
\begin{document}
Some text here
\i first item
\i second item
more text
\i third item
\par third item continues
\i fourth item
\ii fifth item
\ii sixth item
\ii seventh item
more text
\ii eighth item
\i ninth item
\end{document}
我希望它被翻译成:
\documentclass{article}
\usepackage{enumitem}
\begin{document}
Some text here
\begin{enumerate}[resume=level1]
\item\setcounter{enumii}{0} first item
\item\setcounter{enumii}{0} second item
\end{enumerate}
more text
\begin{enumerate}[resume=level1]
\item\setcounter{enumii}{0} third item
\par third item continues
\item\setcounter{enumii}{0} fourth item
\begin{enumerate}[resume=level2]
\item fifth item
\item sixth item
\item seventh item
\end{enumerate}
\end{enumerate}
more text
\begin{enumerate}[resume=level1]
\item[]
\begin{enumerate}[resume=level2]
\item eighth item
\end{enumerate}
\item\setcounter{enumii}{0} ninth item
\end{enumerate}
\end{document}
进一步来说:
- 如果
\i
前面没有其他项目,则将\begin{enumerate}[resume=level1]
其添加到前面。 - 如果
\i
后面没有不以\i
或开头的段落\ii
,则\end{enumerate}
在其后添加 。 - 如果段落分隔符用 \par 标记而不是两个行分隔符,则它将包含在前一项中,并且列表不会终止。
- 2 级项目
\ii
位于 和 之前或\begin{enumerate}[resume=level2]
之后\end{enumerate}
。 - 如果
\ii
前面没有 1 级项或 2 级项,则还会添加\begin{enumerate}[resume=level1]
一个虚拟的 1 级项。\item[]
\ii
如果中间没有 1 级项目,则应该从之前的 2 级编号恢复。
是否可以通过合理的努力来定义可以实现这一目标的宏?
答案1
这是一个基于 LuaLaTeX 的解决方案。它的三个主要工作假设是:(A) 有两个级别的枚举列表,(B) 字符串\i
和\ii
出现在行首,但可能以空格开头,(C) 任何带有\par
指令的行都是不是前面都是空行。第三个假设不在(至少没有明确地)原始作者的工作假设列表中;但是,如果没有这个假设,本来就很复杂的代码会变得更加复杂。
大部分工作由名为 的 Lua 函数执行FancyEnum
。两个实用的 LaTeX 宏(称为\FancyEnumOn
和\FancyEnumOff
)用于激活和停用 Lua 函数对输入流的操作。当然,您应该提前阅读\FancyEnumOff
包含字符串\i
和的逐字材料\ii
。
更新在收到来自 OP 的有关指令用途的更多信息后\setcounter{enumii}{0}
。(其目的是确保“新的”2 级列表(其中“新的”表示至少有一个中间的 1 级指令)从 0 开始。)通过运行而不是每当新的 2 级列表开始时\item
运行,可以更轻松地实现此目的。我已经相应地更新了 Lua 代码。\begin{enumerate}[series=level2]
\begin{enumerate}[resume=level2]
下面的截图展示了Lua函数对原始博文建议的示例(稍作修改的形式)在左侧执行操作的结果,以及对右侧执行相应的硬编码枚举列表执行操作的结果。
% !TEX TS-program = lualatex
\documentclass{article}
\usepackage{enumitem}
\usepackage{multicol} % to create two-column output
\usepackage{luacode} % for 'luacode*' environment
\begin{luacode*}
-- Begin by defining 2 Boolean variables. They will be set to 'true' if
-- LaTeX is in a level-1 or level-2 enumerated environment, respectively.
local in_enumi =false
local in_enumii=false
-- The Lua function 'FancyEnum' does most of the work.
function FancyEnum ( s )
-- Input line starts with '\i' (possibly preceded by whitespace):
if s:find ( "^%s-\\i " ) then
if in_enumii==true then -- need to fall back one list level
s = s:gsub ( "^%s-\\i " , "\\end{enumerate}\\item " )
in_enumii=false
elseif in_enumi==true then -- continue at level 1
s = s:gsub ( "^%s-\\i " , "\\item " )
else -- neither in_enumi nor in_enumii are true -- start a level-1 list
s = s:gsub ( "^%s-\\i " , "\\begin{enumerate}[resume=level1] \\item " )
in_enumi=true
end
-- Input line starts with '\ii' (possibly preceded by whitespace):
elseif s:find ( "^%s-\\ii " ) then
if in_enumii==true then -- continue at level 2
s = s:gsub ( "^%s-\\ii " , "\\item " )
elseif in_enumi==true then -- Moving from level 1 to level 2. Hence,
-- we use '[series=level2]' rather than '[resume=level2]'
in_enumii=true
s = s:gsub ( "^%s-\\ii " , "\\begin{enumerate}[series=level2]\\item " )
else -- jumping straight to level-2 list
in_enumi=true
in_enumii=true
s = s:gsub ( "^%s-\\ii " , "\\begin{enumerate}[resume=level1]\\item[]" ..
"\\begin{enumerate}[resume=level2]\\item " )
end
-- Input line is all-blank. Terminate 'enumerate' if 'in_enumi' and/or
-- 'in_enumii' are 'true'.
elseif s=="" then
if in_enumii==true then -- terminate two 'enumerate' levels
s = "\\end{enumerate}\\end{enumerate}"
in_enumii=false
in_enumi=false
elseif in_enumi==true then -- terminate one 'enumerate' level
s = "\\end{enumerate}"
in_enumi=false
end
end
-- Place 's' back on the input stream, for further processing by LaTeX.
return s
end -- end of Lua function
\end{luacode*}
%% Two LaTeX utility macros that activate and deactivate 'FancyEnum':
\newcommand\FancyEnumOn{\directlua{luatexbase.add_to_callback(
"process_input_buffer", FancyEnum, "FancyEnum")}}
\newcommand\FancyEnumOff{\directlua{luatexbase.remove_from_callback(
"process_input_buffer", "FancyEnum")}}
\begin{document}
\begin{multicols}{2}
\FancyEnumOn % activate the Lua function 'FancyEnum'
\verb+\FancyEnum+ on
\i first item
\i second item
more text
\i third item
\par third item continues % note: no blank line before this line
\i fourth item
\ii fifth item
\ii sixth item
\par sixth item continues % note: no blank line before this line
\i seventh item
\ii eighth item % note: no blank line before this line
more text
\ii ninth item
\i tenth item
\FancyEnumOff % deactivate 'FancyEnum'
\columnbreak % optional
\verb+\FancyEnum+ off (explicit lists)
\begin{enumerate}[series=level1] % not [resume=level1]
\item first item
\item second item
\end{enumerate}
more text
\begin{enumerate}[resume=level1]
\item third item
third item continues
\item fourth item
\begin{enumerate}[series=level2]
\item fifth item
\item sixth item
sixth item continues
\end{enumerate}
\item seventh item
\begin{enumerate}[series=level2]
\item eighth item
\end{enumerate}
\end{enumerate}
more text
\begin{enumerate}[resume=level1]
\item[]
\begin{enumerate}[resume=level2]
\item ninth item
\end{enumerate}
\item tenth item
\end{enumerate}
\end{multicols}
\end{document}
答案2
我认为你想使用易清单包。它并没有完全满足您的所有需求,但已经非常接近了。例如,代码:
\documentclass{article}
\usepackage[sharp]{easylist}% sharp => # is used for \item
\begin{document}
Some text here
\begin{easylist}[articletoc]
# first item
# second item
more text
# third item
\par third item continues
# fourth item
## fifth item
## sixth item
## seventh item
more text
## eighth item
# ninth item
\end{easylist}
\end{document}
生产
可以使用 控制许多额外选项\ListProperties
,例如Hang=<n>
设置悬挂缩进。手册非常易读。
编辑 以下内容可能非常接近您想要的。您可以使用以下命令禁用第一级列表的计数器
\ListProperties(
Hang=true,
Hide1=1,
Hide2=1,
Hide3=1,
Hide4=1,
Progressive*=2em,
Style1*=\theblank,
Indent1=0em,
)
因此,以下代码
\begin{easylist}
# Some text here
## first item
## second item
# more text
## third item
\par third item continues
## fourth item
### fifth item
### sixth item
### seventh item
# more text
### eighth item
## ninth item
\end{easylist}
生产
因此,每一行至少有一个#
,对应不在列表中,而带有 的行##
位于第一个列表(第 1 级)内,带有 的行###
位于第 2 级,依此类推。
完整代码如下:
\documentclass{article}
\usepackage[sharp]{easylist}% sharp => # is used for \item
\begin{document}
\ListProperties(
Hang=true,
Hide1=1, % hide counter 1 on level 1
Hide2=1, % hide counter 1 on level 2
Hide3=1, % hide counter 1 on level 3
Hide4=1, % hide counter 1 on level 4
Progressive*=2em,
Style1*=\theblank,
Indent1=0em,
)
\begin{easylist}
# Some text here
## first item
## second item
# more text
## third item
\par third item continues
## fourth item
### fifth item
### sixth item
### seventh item
# more text
### eighth item
## ninth item
\end{easylist}
\end{document}