我正在写一篇论文,我大量使用了通过\url
或\url
在 内的超链接\footnote
。现在我想添加一个列表(有点像简化的参考书目,其中每个链接只出现一次),其中包含文档中的所有超链接。有没有办法自动为我生成这个列表?
答案1
下面的示例使用
hyperref
(问题中提到了“超链接”)并挂钩\hyper@linkurl
来获取 URL。捕获的 URL 被写入索引文件
\jobname-url.idx
:\urlentry{<hex coded URL>}{<page number>}
URL 采用十六进制编码,以避免特殊字符的困扰。
包
filecontents
帮助创建\jobname-url.mst
的样式文件makeindex
。Makeindex 自动查找与输入文件同名但扩展.mst
名为样式文件的文件。然后只需.idx
将文件作为 的参数给出即可makeindex
。Makeindex 生成文件
\jobname-url.ind
:\begin{theurls} \urlitem{<hex coded URL>}{<page list>} ... \end{theurls}
环境
theurls
并被\urlitem
适当地定义来打印 URL 列表。\listurlname
包含该部分的标题。
评论:
- Makeindex 负责排序并删除重复项。
- 挂钩
\hyper@linkurl
的优点是 URL 被规范化(例如,%
和\%
相同,%
catcode 为 12/other)。 - 十六进制编码的优点是,特殊字符(例如百分比、哈希值)或对 makeindex 有特殊含义的字符(at 符号,...)不需要特殊处理。
示例文件:
\RequirePackage{filecontents}
\begin{filecontents*}{\jobname-url.mst}
% Input style specifiers
keyword "\\urlentry"
% Output style specifiers
preamble "\\begin{theurls}"
postamble "\\end{theurls}\n"
group_skip ""
headings_flag 0
item_0 "\n\\urlitem{"
delim_0 "}{"
delim_t "}"
line_max 500
\end{filecontents*}
\documentclass{article}
\usepackage[colorlinks]{hyperref}
\usepackage{pdfescape}
\makeatletter
\newwrite\file@url
\openout\file@url=\jobname-url.idx\relax
\newcommand*{\write@url}[1]{%
\begingroup
\EdefEscapeHex\@tmp{#1}%
\protected@write\file@url{}{%
\protect\urlentry{\@tmp}{\thepage}%
}%
\endgroup
}
\let\saved@hyper@linkurl\hyper@linkurl
\renewcommand*{\hyper@linkurl}[2]{%
\write@url{#2}%
\saved@hyper@linkurl{#1}{#2}%
}
\newcommand*{\listurlname}{List of URLs}
\newcommand*{\printurls}{%
\InputIfFileExists{\jobname-url.ind}{}{}%
}
\newenvironment{theurls}{%
\section*{\listurlname}%
\@mkboth{\listurlname}{\listurlname}%
\let\write@url\@gobble
\ttfamily
\raggedright
}{%
\par
}
\newcommand*{\urlitem}[2]{%
\hangindent=1em
\hangafter=1
\begingroup
\EdefUnescapeHex\@tmp{#1}%
\expandafter\url\expandafter{\@tmp}%
\endgroup
\par
}
\makeatother
\usepackage[T1]{fontenc}
\usepackage[variablett]{lmodern}
\begin{document}
This this file answers the
\href{http://tex.stackexchange.com/q/121977/16967}{question}
on \href{http://tex.stackexchange.com/}{\TeX.SE}.
Further examples for URLs:
\url{http://www.dante.de/}\\
\url{http://www.ctan.org/}\\
\url{mailto:[email protected]/}\\
\url{ftp://ftp.dante.de/pub/tex/}\\
\url{http://www.example.com/\%7efoo/index.html}\\
\url{http://www.example.com/%7efoo/index.html}
\printurls
\end{document}
以下命令生成结果(linux/bash):
$ pdflatex test
生成test-url.mst
和test-url.idx
。
$ makeindex test-url
生成test-url.ind
。
$ pdflatex test
更新页码
页码的格式化方法有很多种。以下示例使用点将 URL 与行末出现的页码分开(类似于包的索引doc
)。根据要求p.
,如果后面只有一个页码,则页码以 为前缀,pp.
否则为前缀。这是在包的帮助下xstring
通过测试页码列表是否包含逗号分隔符或范围说明符中的连字符来实现的。
\RequirePackage{filecontents}
\begin{filecontents*}{\jobname-url.mst}
% Input style specifiers
keyword "\\urlentry"
% Output style specifiers
preamble "\\begin{theurls}"
postamble "\n\\end{theurls}\n"
group_skip ""
headings_flag 0
item_0 "\n\\urlitem{"
delim_0 "}{"
delim_t "}"
line_max 500
\end{filecontents*}
\documentclass{article}
\usepackage[colorlinks]{hyperref}
\usepackage{pdfescape}
\usepackage{xstring}
\makeatletter
\newwrite\file@url
\openout\file@url=\jobname-url.idx\relax
\newcommand*{\write@url}[1]{%
\begingroup
\EdefEscapeHex\@tmp{#1}%
\protected@write\file@url{}{%
\protect\urlentry{\@tmp}{\thepage}%
}%
\endgroup
}
\let\saved@hyper@linkurl\hyper@linkurl
\renewcommand*{\hyper@linkurl}[2]{%
\write@url{#2}%
\saved@hyper@linkurl{#1}{#2}%
}
\newcommand*{\listurlname}{List of URLs}
\newcommand*{\printurls}{%
\InputIfFileExists{\jobname-url.ind}{}{}%
}
\newenvironment{theurls}{%
\section*{\listurlname}%
\@mkboth{\listurlname}{\listurlname}%
\let\write@url\@gobble
\ttfamily
\raggedright
\setlength{\parfillskip}{0pt}%
}{%
\par
}
\newcommand*{\urlitem}[2]{%
\hangindent=1em
\hangafter=1
\begingroup
\EdefUnescapeHex\@tmp{#1}%
\expandafter\url\expandafter{\@tmp}%
\endgroup
\urlindex@pfill
\IfSubStr{#2}{,}{pp}{%
\IfSubStr{#2}{-}{pp}{p}%
}.\@\space\ignorespaces
#2%
\par
}
\newcommand*{\urlindex@pfill}{% from \pfill of package `doc'
\unskip~\urlindex@dotfill
\penalty500\strut\nobreak
\urlindex@dotfil~\ignorespaces
}
\newcommand*{\urlindex@dotfill}{% from \dotfill of package `doc'
\leaders\hbox to.6em{\hss .\hss}\hskip\z@ plus 1fill\relax
}
\newcommand*{\urlindex@dotfil}{% from \dotfil of package `doc'
\leaders\hbox to.6em{\hss .\hss}\hfil
}
\makeatother
\usepackage[T1]{fontenc}
\usepackage[variablett]{lmodern}
\begin{document}
This this file answers the
\href{http://tex.stackexchange.com/q/121977/16967}{question}
on \href{http://tex.stackexchange.com/}{\TeX.SE}.
Further examples for URLs:
\url{http://www.dante.de/}\\
\url{http://www.ctan.org/}\\
\url{mailto:[email protected]/}\\
\url{ftp://ftp.dante.de/pub/tex/}\\
\url{http://www.example.com/\%7efoo/index.html}\\
\url{http://www.example.com/%7efoo/index.html}
% further pages to generate more page numbers for testing the url index
\newpage
\url{http://www.ctan.org}
\newpage
\url{http://www.ctan.org}
\url{http://tex.stackexchange.com/}
\newpage
\printurls
\end{document}
答案2
注意:以下代码仅适用于简单 URL,即不包含特殊字符的 URL,例如%
。有关完整解决方案,请参阅 Heiko 的回答。
正如 Nicola 在评论中提到的,重新定义\url
可能是一个有趣的想法,但 URL 中的某些字符可能会导致问题。遗憾的是我的 TeX-fu 还不足以解决这个问题,但这是一个初步的开始:
\documentclass{article}
\usepackage{url}
\usepackage{imakeidx}
\let\originalurl\url
\makeindex[name=urls, title={Links found in this document}, columns=1]
\renewcommand{\url}[1]{\originalurl{#1}\index[urls]{\protect\originalurl{#1}}
}
\begin{document}
Hello, make sure to visit \url{http://www.google.com} and,
of course, our own place \url{http://tex.stackexchange.com}.
By the way, \url{http://tex.stackexchange.com} is awesome!
\printindex[urls]
\end{document}
然后生成列表:
希望能帮助到你。:)