有没有什么办法可以标记文本中的单词,以便以后在列表中使用它们?
例子:
Hi my name is \addmark{Kris}, I need a \addmark{list} of words containing all the
\addmark{marked words} by the end of the \addmark{document}.
\begin{itemize}
\item \addmark{fancy list}
\end{itemize}
\printmark
看起来像这样:
你好,我叫克里斯,我需要一个包含文档末尾所有标记单词的单词列表。
- 幻想清单
Kris、列表、标记单词、文档和花式列表。
答案1
那么带有和序列的东西怎么样expl3
?:)
\documentclass{article}
\usepackage{expl3}
\usepackage{xparse}
\ExplSyntaxOn
\seq_new:N \g_khaurum_wordlist_seq
\NewDocumentCommand{ \addmark }{ m }{
\seq_gput_right:Nn \g_khaurum_wordlist_seq { #1 }
#1
}
\NewDocumentCommand{ \printmarks }{s}{
\seq_gremove_duplicates:N \g_khaurum_wordlist_seq
\seq_use:Nnnn \g_khaurum_wordlist_seq { ~ and ~ } { , ~ } { ~ and ~ }
\IfBooleanT { #1 } {
\seq_gclear:N \g_khaurum_wordlist_seq
}
}
\ExplSyntaxOff
\begin{document}
Hi my name is \addmark{Kris}, I need a \addmark{list} of words
containing all the \addmark{marked words} by the end of the
\addmark{document}.
\begin{itemize}
\item I'm a list of \addmark{items}
\item Ducks are \addmark{cool}
\end{itemize}
\vspace{1em}
\printmarks
\vspace{1em}
Another \addmark{value} here.
\vspace{1em}
\printmarks*
\vspace{1em}
The starred version cleared the \addmark{sequence}, so now
we can add new \addmark{entries} again from start.
\vspace{1em}
\printmarks
\end{document}
当使用时\printmarks*
,序列被打印然后被清除;因此我们可以开始一个新的序列并在之后添加新的条目。
希望能帮助到你。:)
感谢 Marco Daniel 和 egreg 对代码做出改进。:)
答案2
由于 Paulo 已经提供了 LaTeX3 版本,我将坚持使用经典方法。我只添加了一个开关,用于将文本中标记的单词打印为红色,这在文档编写时可能会很有用。
\documentclass{article}
\usepackage{xcolor}
\newif\ifshowmarked
\makeatletter
\newtoks\mark@toks
\mark@toks={\@gobble}
\newcommand{\mark@comma}{, }
\newcommand{\addmark}[1]{%
\@ifundefined{addmark@\detokenize{#1}}
{% New marked word
\global\@namedef{addmark@\detokenize{#1}}{#1}%
\global\mark@toks=\expandafter{\the\mark@toks\mark@comma\@nameuse{addmark@\detokenize{#1}}}%
}
{
% Already marked word, do nothing
}%
\ifshowmarked
\textcolor{red}{#1}%
\else
#1%
\fi
}
\newcommand{\printmarks}{%
\the\mark@toks\relax
\@ifstar{\global\mark@toks{\@gobble}}{}%
}
\makeatletter
\begin{document}
Hi my name is \addmark{Kris}, I need a \addmark{list} of words
containing all the \addmark{marked words} by the end of the
\addmark{document}.
\begin{itemize}
\item I'm a list of \addmark{items}
\item Ducks are \addmark{cool}
\end{itemize}
\vspace{1em}
\printmarks
\vspace{1em}
Another \addmark{value} here.
\vspace{1em}
\printmarks*
\vspace{1em}
\showmarkedtrue
The starred version cleared the \addmark{sequence}, so now
we can add new \addmark{entries} again from start.
\vspace{1em}
\printmarks
\end{document}
参数\addmark
用来构建控制序列;如果此命令已定义,则我们什么也不做,否则定义控制序列并将其添加到前面带有逗号和空格的令牌寄存器中。令牌寄存器初始化为包含\@gobble
,因此不会打印第一个逗号。最后,打印单词(如果开关打开,则为红色)。
该\printmarked
宏的工作方式相同:传递令牌寄存器的内容;如果*
使用-variant,则重新初始化令牌寄存器。
请注意,LaTeX3 更胜一筹,因为它允许以多种不同方式使用标记单词列表。在“经典”版本中也可以做到这一点,但需要多次重新发明轮子。此外,\detokenize
使用 LaTeX3 无需任何技巧来处理标记单词中的特殊字符,因为单词只是按原样存储的。
只需比较代码就能清楚地显示出 LaTeX3 方法的优越性。
添加 LaTeX3 版本的开关很容易。添加
\bool_new:N \g_khaurum_highlight_bool
\NewDocumentCommand{\showmarkedtrue}{}
{
\bool_gset_true:N \g_khaurum_highlight_bool
}
\NewDocumentCommand{\showmarkedfalse}{}
{
\bool_gset_false:N \g_khaurum_highlight_bool
}
并将的定义更改\addmark
为
\NewDocumentCommand{ \addmark }{ m }
{
\seq_gput_right:Nn \g_khaurum_wordlist_seq { #1 }
\bool_if:NTF \g_khaurum_highlight_bool { \textcolor}{red}{#1} } { #1 }
}