将 \cftpagenumbersoff 应用于多个节级别

将 \cftpagenumbersoff 应用于多个节级别

这可能是一个非常基本的问题,由于对 LaTeX 语法缺乏更好的了解,请原谅。

我想使用\cftpagenumbersofftocloft包来隐藏某些(但不是全部)分区级别的页码(和点),比如sectionsubsection

我知道在序言中我可以写

\usepackage{tocloft}
\cftpagenumbersoff{section}
\cftpagenumbersoff{subsection}

但我想知道我是否可以写一些类似的东西

\usepackage{tocloft}
\cftpagenumbersoff{section,subsection}

而不是(这不起作用)。我知道这只能节省一行,但我很想知道正确的(和有效的)表达方式是什么 - 如果可能的话。谢谢!


只是为了解释我的动机:我看到了一个例子

\uspepackage[titles,subfigure]{tocloft}

被使用,所以我认为该部分中也可能有多个参数{},例如用逗号分隔。

答案1

在像这样的简单情况下,实际上只需一行代码就可以为逗号分隔列表的每个元素调用一个宏:\forcsvlist{\cftpagenumbersoff}{subsection,section}这就是您所需要的。

\forcsvlist{<handler>}{<csv list>}命令由包提供etoolbox。它以 a 作为第一个参数处理程序,它必须是一个宏(或宏序列),它只吸收一个尾随参数,并为每个元素调用csv 列表

\documentclass{report}
\usepackage{tocloft}
\usepackage{etoolbox}

\forcsvlist{\cftpagenumbersoff}{subsection,section}

\begin{document}

\tableofcontents
\chapter{A chapter title}

\section{A section title}
\subsection{A subsection title}
\end{document}

答案2

除非命令被编写为接受以逗号分隔的参数列表,否则没有通用的方法让它接受一个参数,除非重写该命令,这可能比多次应用该命令需要更多的工作。

创建一个以逗号分隔的列表为参数的新命令,然后将另一个命令应用于该列表,这并不困难,但对于大多数现有命令而言,这可能不值得付出努力。从此处调整已接受的答案解析以逗号分隔的带空格的命令名称列表对于您的问题,我们可以做以下事情:

\documentclass{report}
\usepackage{tocloft}
\usepackage{etoolbox}

\newcommand\docftpagenumbersoff[1]{\cftpagenumbersoff{#1}}
\newcommand*\mycftpagenumbersoff{
  \let\do\docftpagenumbersoff
  \docsvlist
}
\mycftpagenumbersoff{subsection,section}
\begin{document}

\tableofcontents
\chapter{A chapter title}

\section{A section title}
\subsection{A subsection title}
\end{document}

答案3

我也相信你最好使用两个命令;但是,只是为了展示的力量expl3,这里有一个(复杂的)解决方案\cftpagenumbersoff(也是互补的\cftpagenumberson

\documentclass{book}
\usepackage{tocloft,xparse}

\ExplSyntaxOn

% A table of equivalents: \cftchapname (=chapter) -> chap and so on
\prop_new:N \g_cft_names_prop
\cs_generate_variant:Nn \prop_gput:Nnn { Nv }
\clist_map_inline:nn
 {chap,sec,subsec,subsubsec,para,subpara,fig,subfig,tab,subtab}
 {
  \prop_gput:Nvn \g_cft_names_prop { cft#1name } { #1 }
 }

\NewDocumentCommand{\xcftpagenumbersoff}{m}
 {
  \clist_map_inline:nn { #1 } { \cft_pagenumbersoff:n { ##1 } }
 }

% \cftpagenumbersoff is a gigantic sequence of \ifx, using \@cftpnumoff
% If the argument is section, it is compared to all known \cftXname commands
% and action is taken; with a property list it's easier

% First we store a copy of \@cftpnumoff
\cs_set_eq:Nc \cft_pnumoff:n { @cftpnumoff }
% We also define a variant that does complete expansion
\cs_generate_variant:Nn \cft_pnumoff:n { x }
\cs_new_protected:Npn \cft_pagenumbersoff:n #1
 {
  \prop_if_in:NnTF \g_cft_names_prop { #1 }
   {% if the argument is in the table, we get from it the abbreviation (chapter->chap)
    \cft_pnumoff:x { \prop_get:Nn \g_cft_names_prop { #1 } }
   }
   {% otherwise we use directly the argument
    \cft_pnumoff:n { #1 }
   }
 }

\NewDocumentCommand{\xcftpagenumberson}{m}
 {
  \clist_map_inline:nn { #1 } { \cft_pagenumberson:n { ##1 } }
 }

\cs_set_eq:Nc \cft_pnumon:n { @cftpnumon }
\cs_generate_variant:Nn \cft_pnumon:n { x }
\cs_new_protected:Npn \cft_pagenumberson:n #1
 {
  \prop_if_in:NnTF \g_cft_names_prop { #1 }
   {
    \cft_pnumon:x { \prop_get:Nn \g_cft_names_prop { #1 } }
   }
   {
    \cft_pnumon:n { #1 }
   }
 }
\ExplSyntaxOff

\xcftpagenumbersoff{subsection,section}
\begin{document}

\tableofcontents
\chapter{A chapter title}

\section{A section title}
\subsection{A subsection title}

\addtocontents{toc}{\xcftpagenumberson{section,subsection}}

\section{X}
\subsection{Y}

\end{document}

在此处输入图片描述


让我们从更一般的角度来解决这个问题。给定一个\foo接受参数并对其执行一些后台操作的宏,定义\xfoo对以逗号分隔列表指定的多个参数执行相同操作。

\textbf请注意,这对于排版其参数的命令来说没有意义。

\usepackage{xparse} % access to expl3
\ExplSyntaxOn
\NewDocumentCommand{\xfoo}{m}
 {
  \clist_map_inline:nn { #1 } { \foo {##1} }
 }
\ExplSyntaxOff

就足够了。

之前的解决方案可以简单地写成

\ExplSyntaxOn
\NewDocumentCommand{\xcftpagenumbersoff}{m}
 {
  \clist_map_inline:nn { #1 } { \cftpagenumbersoff {##1} }
 }
\ExplSyntaxOff

但我更喜欢避免在基本命令上使用太多层\@cftpnumoff,提出一些关于 LaTeX3 编程的想法。

有人可能会想到保存一份 的副本\foo并重新定义它,但这会带来新的问题,因为\foo可能用 来定义\DeclareRobustCommand,而简单的\let\originalfoo\foo是不够的。在这种情况下也有办法做到这一点(用\LetLtxMacro),但一般来说,最好不要彻底改变现有命令的语法。

相关内容