有没有一种简单的方法来标记 LaTeX 文档中的内容?

有没有一种简单的方法来标记 LaTeX 文档中的内容?

我正在编写一个文档,其中包含许多小段文本(大约一页),可能按章节或小节组织。对于每个这样的章节,我想从预定义列表中附加几个“标签”。在文档的不同位置,我想列出所有标签以及与每个标签关联的章节。

如果标签列表出现在文档末尾,我有一个想法,如何制作一个非常原始的标记系统(例如,我可以连续重新定义一个命令,向其中添加文本;稍后我可以放置此命令来列出内容)。有人知道更好的解决方案吗?理想情况下,我想在文档的开头、目录之后组织我的标签。我觉得可能有一个包可以做到这一点,但我找不到。

答案1

你可以将标签放入“目录”中。我采纳了 egreg 的妙招,将每个标签放入ToC 文件,然后反复重读,每次都停用“错误”的标签。这要求我\input手动读取 ToC 文件,从而绕过通常的机制\listofX(此处,X = 标签),实际上创建这个文件(或者覆盖它,这就是为什么我不能多次使用它),所以我包含了一个相当多余的功能,即使用这个宏在底部(在它们的引用列表下面)打印所有标签的简单列表,以便一切都正确设置。

我最近读了一个答案(我相信是 Ahmed Musa 写的),它使用环境{filecontents}来构建一个内联包,因为这显然是呈现这种示例的正确方法,所以我也在这里使用它。

\documentclass{article}
\usepackage{filecontents}

% Here's the package file
\begin{filecontents*}{tagstoc.sty}
\usepackage{tocloft,etoolbox}

% Declare the master TOC.  This will contain:
% * A list of tags
% * A sequence of entries where tags are referenced
% and it will be used multiple times to generate lists of tag usage
\newlistof{tags}{tags}{All tags}
\renewcommand*\cfttagstitlefont{\Large\bfseries}% For example

% Use this in the preamble to make a new tag.
\newcommand*\declaretag[1]{%
 \newlistentry[tags]{tag#1}{tags}{0}%
 \listadd\Tags{#1}%
 \addtocontents{tags}{(#1) }%
}
% This is only true when printing the list of tags
\newif\ifprintingtags
% This makes sure that the list of tags is not printed most of the time...
\addtocontents{tags}{\protect\ifprintingtags}
% ...because it wraps the entire TOC from the preamble
\AtBeginDocument{\addtocontents{tags}{\protect\fi}}

% This is a rather inefficient way to selectively print particular tags.
% Presumably, I should just pop each tag from the list as I go,
% but etoolbox doesn't seem to handle stacks.  Probably I'm missing something.
\newcommand*\deactivatetag[1]{%
 \expandafter\let\csname l@tag#1\endcsname=\@gobbletwo
}
\newcommand*\activatetag[1]{%
 \forlistloop\deactivatetag\Tags
 \expandafter\let\csname l@tag#1\endcsname=\l@section
}

% These are hooks for the user
\providecommand*\currenttag{}
\providecommand*\listoftagstitle{}
% This prints all the references to a particular tag.
% Effectively, it's a partial ToC for that tag.
\newcommand*\dotag[1]{%
 \renewcommand*\currenttag{#1}%
 \begingroup
  \activatetag{#1}%
  \section*{\listoftagstitle}%
  \@input{\jobname.tags}%
 \endgroup
}%
% This prints the snippets, placed (with repeats) beneath their tags.
% It also prints a list of defined tags, more or less as an excuse
% to have \listoftags handle the .tags auxiliary ToC file.
\newcommand*\snippetsbytag{%
 \forlistloop\dotag\Tags
 \activatetag{}
 \printingtagstrue
 \listoftags
}

% This is how to proclaim a snippet, which is what gets tagged.
\newcounter{snippet}
\providecommand*\snippetname{}
\newcommand*\snippettitle{\thesnippet. \snippetname}
\newcommand*\snippet[1]{%
 \refstepcounter{snippet}%
 \renewcommand*\snippetname{#1}%
 \noindent{\Large\bfseries\snippettitle.}%
}

% In case of no hyperref
\providecommand\phantomsection{}
% This is how you place a tag beneath a snippet.
\newcommand*\placetag[1]{%
 \phantomsection% In case of hyperref
 \addcontentsline{tags}{tag#1}{\snippettitle}%
 (tag~#1)%
}
\end{filecontents*}

\usepackage{tagstoc}

\renewcommand*\listoftagstitle{Snippets tagged with \currenttag}
% Preferred way to declare tags.  They will be printed in this order.
\forcsvlist\declaretag{A,B}

\begin{document}
 \snippetsbytag
 \newpage

 \snippet{First snippet}
 \placetag{A}

 \newpage

 \snippet{Second snippet}
 \placetag{A} \placetag{B}
\end{document}

答案2

只是为了提出 Ryan 的优秀解决方案的另一种方法。

这类问题中,TeX 轻而易举地击败了 Python。TeX 提供了一种使用 来自动创建控制序列的方法\csname...\endcsname。我们利用这一点为每个单独的标签创建一个宏,该宏将保存每个标签包含的部分列表。

我假设您引用的标签与网络上博客中使用的标签类似。我们将标签保存在一个列表中:

  \tags{Mathematics,Biology,...,}

每个标签都有自己的列表,其中包含用该特定标签标记的部分编号,

   \Art{1,5,6,7,8}

我们定义宏来以类似于的方式标记某个部分,\index通过将其调用为\tag{tag name}

MWE 如下所示:

\documentclass{article}
\usepackage{lstdoc}
\makeatletter
\def\tags{Physics,Computer Science,Chemistry,}
%% sorts the tags for later on
\def\tags@sorted{\lst@BubbleSort\tags}
\tags@sorted
%% we automatically create macros for each tag
 \def\macrofy@#1\@nil{%
      \expandafter\def\csname#1\endcsname{}
  }
\def\addtags#1{\g@addto@macro\tags{#1,}
   \tags@sorted
   \macrofy@@
}
%% Make macros to hold the lists for each tag
%% 
\def\macrofy@@{\@for\next:=\tags\do{%
    \expandafter\macrofy@\next\@nil
}}
\macrofy@@

\def\addtotag#1\@nil#2{%
   \expandafter\ifx\csname#2\endcsname\@empty
        \expandafter\g@addto@macro\csname#2\endcsname{#1}
    \else
        \expandafter\g@addto@macro\csname#2\endcsname{,#1}
    \fi
}
\def\tag#1{%
   \expandafter\addtotag\the\c@section\@nil{#1}
}
\def\thetags{%
%% we now print the tags or save them to a file
  \section*{The Tags}  
  \@for\next:=\tags\do{%
     \ifx\next\@empty\else\next: See Section(s) \@nameuse{\next}\par\fi
  }
}
\parindent0pt
\begin{document}
% add some tags
   \addtags{Mathematics,Art}
% test to see everything ok and list is sorted   
   \tags
% example text    
   \section{Einstein}
      \tag{Physics}\tag{Mathematics}
   \section{D E Knuth}
      \tag{Computer Science}\tag{Art}
    \section{Riemann}
       \tag{Mathematics}
   \section{Lamport}
      \tag{Computer Science}
   \section{Botticelli}
      \tag{Art}
   \section{Avogadro}
      \tag{Chemistry}
%% prints the tags with the sections
\thetags
\end{document}

我们定义一个命令来打印标签(我们保持排序)为\thetags。列表保存在内存中并在末尾打印。如果我们想在文档开头打印它们,那么我们需要将它们存储在我们导入的文件中。为了简洁起见,我省略了这一点,因为它很简单,并且希望保持代码简短易读。它产生如下输出:

在此处输入图片描述

答案3

我不知道 egreg 会如何处理\do此解决方案中的一个 ' 中的 16 个井号字符,但目的是使用作为章节编号的最后一个连接词。

\documentclass{article}
\usepackage{catoptions}[2011/12/07]
\makeatletter
\new@def*\tag@hook{}
\robust@def*\tags#1{%
  \iflacus#1\dolacus\else
    \ifnum\c@section=\z@pt\else
      \docommalist{#1}{%
        \oifinsetTF{##1}\tag@hook{%
          \def\reserved@a####1##1####2####3\@nil{%
            \xifinsetTF{\detokenize\expandafter{\expandafter{\the\c@section}}}%
              {\detokenize{####2}}{}{%
              \xdef\tag@hook{####1;##1{####2{\the\c@section}};####3}%
            }%
          }%
          \expandafter\reserved@a\tag@hook\@nil
        }{%
          \xdef\tag@hook{\cptliststack;\tag@hook##1{{\the\c@section}}}%
        }%
      }%
    \fi
  \fi
}
\def\ignoretags#1{%
  \cptfiltermergecsv\tag@ignore{#1}\nofilter
}
\robust@def*\printtags{%
  \ifx\protect\@typeset@protect
    \def\csv@do##1{%
      \defpass\reserveda####1####{%
        \defpass\reserveda########1\@nil{%
          \oifinset@sp@TF,{####1}\tag@ignore{}{%
            \def\reservedb{########1}%
            \cptnumbersort\reservedb<%
            \cptexpandbracenext\tag@formatsecnos\reservedb
            \tagnameformat{####1}: %
            See section\ifnum\reservedc=\@ne\else s\fi~%
            \def\do################1{%
              \ifnum\indrisnr>\@ne
                \iflastindris\@space and\@space\else,\@space\fi
              \fi
              ################1%
            }%
            \indrisloop*\reservedb\do
            \tagseparator
          }%
        }%
      }%
      ##1\@nil
    }%
    \csv@@parse*[;]\tag@hook
  \else
    \@latex@error{Wrong location of '\string\printtags'}\@ehc
  \fi
}
\robust@def*\tag@formatsecnos#1{%
  \begingroup
  \@tempcnta\z@pt
  \def\reservedb{}%
  \def\do##1##2\@nil{%
    \ifblankTF{##1}{%
      \do##2\@nil
    }{%
      \advance\@tempcnta\@ne
      \edef\reservedb{\cptliststack,\reservedb##1}%
      \ifnot@nil{##2}{\do##2\@nil}%
    }%
  }%
  \do#1{\@nil}\@nil
  \cptexpanded{\endgroup
    \def\noexpand\reservedb{\reservedb}%
    \def\noexpand\reservedc{\number\@tempcnta}%
  }%
}
\newletcsset{\tag=\tags,\noprinttags=\ignoretags,\tagseparator=\newline,
  \tagnameformat=\textit}

\parindent0pt
\begin{document}
\tag{Physics}
\section{Einstein}
\tags{Physics, Mathematics, Physics}

\section{D E Knuth}
\tags{Computer Science, Art, Physics}

\section{Riemann}
\tags{Mathematics, Art}

\section{Lamport}
\tag{Computer Science}

\section{Botticelli}
\tags{Art, Physics}

\section{Avogadro}
\tags{Chemistry, Literature, Art}

\printtags
\end{document}

在此处输入图片描述

答案4

hyperref的书签或bookmark包有什么帮助吗?

相关内容