将字符串转换为文件名并在 \href 中使用

将字符串转换为文件名并在 \href 中使用

我有一堆单独的 .tex 文件,希望能够单击其中一个 PDF 文件中的链接并打开相应的 PDF 文件。这些文件很小,因此实际上不需要对它们进行索引,只需打开它们即可。

要打开的文件名(在大多数情况下)可以从描述性链接文本中确定——下面的算法。在某些情况下,文件名无法轻易确定,因此我希望能够手动指定它。因此,我定义:

\NewDocumentCommand{\CrossReference}{O{\NoValue} m}

在哪里

#1 = optional file name (determined from #2 if not provided)
#2 = link text

我遇到过这种情况,我手动指定了下面 MWE 中的文件名。但是,由于文件名很容易确定,所以我想不必提供它。这就是它\ConvertToFileNameWithPath应该发挥作用的地方。

文件命名算法:

如果未指定文件名,则通过以下方式从给定的链接文本中获取:

  1. 将所有字符改为小写。
  2. 用破折号替换所有空白。
  3. 添加.pdf扩展

笔记:

  1. 为了使下面的 MWE 起作用(即测试链接是否可点击),该文件equation-of-circle.pdf必须存在于当前目录中。

  2. 最终,宏\ConvertToFileNameWithPath将在特定目录列表中搜索此文件名——下一步将解决这个问题。所以这将是上述算法中的第 4 步。

  3. 我确实看过包裹xr不确定它是否适合这种情况,主要是因为笔记2(可能有多个同名的文件)。

参考/失败的尝试:

  • 我尝试改编 Joseph Wright 的回答\MakeUppercase 是否有纯粹可扩展的变体?,但没有成功。在同一个问题上,它还提到\tl_expandable_lowercase:n现在可用,所以这肯定会有所帮助。但我不明白expl3,我不能再进一步了。

  • 我这样做是基于 Bruno Le Floch 对我的问题的回答:输出不应显示的文本。虽然我在这方面没有取得很大进展,但也许这可以帮助其他人解决这个问题。

  • 我也尝试使用一系列的\StrSubstitute{\Temp}{A}{A}[\Temp]\StrSubstitute{\Temp}{B}{b}[\Temp]进行转换,但是这会遇到扩展问题,而使用\tl_expandable_lowercase:n应该更容易。

代码:

当上方和下方的文本\hrule相同时,这应该可以工作:当然假设您equation-of-circle.pdf在当前目录中,并且可以通过第 1 行和第 3 行打开它。目前我只能通过第 1 行打开它,其中我手动指定了文件名:

在此处输入图片描述

\documentclass{article}
\usepackage{xparse}
\usepackage{xcolor}
\usepackage{hyperref}


%\ExplSyntaxOn -- am guessing that this will be needed...
\DeclareExpandableDocumentCommand{\ConvertToFileNameWithPath}{o m}{%
    % This will eventually also locate a file in a given path 
    \IfNoValueTF{#1}{% file name not specified so need to figure it out
        % ????????? What goes here ???????
        ./#2.pdf% Need to convert #2 to a file name. ????????
    }{% We were given, the file name -- Even I can handle this case
        ./#1.pdf%
    }%
  }
%\ExplSyntaxOff

\NewDocumentCommand{\CrossReference}{O{\NoValue} m}{%
    % #1 = optional file name (determined from #2 if not provided)
    % #2 = link text
    \edef\PdfFileName{\ConvertToFileNameWithPath[#1]{#2}}%
    \IfFileExists{\PdfFileName}{%
        \href{run:\PdfFileName}{#2}%
    }{%
        \fcolorbox{red}{yellow}{#2}%
        \footnote{Unable to locate \PdfFileName}%
    }%
}%

\begin{document}
Manual References: \CrossReference[equation-of-circle]{Equation of Circle}%

Manual References: \CrossReference[non-existant-file]{Non Existant File}%

\medskip\hrule\medskip

Automatic References: \CrossReference{Equation of Circle}%

Automatic References: \CrossReference{Non Existant File}%
\end{document} 

答案1

\documentclass{article}
\usepackage{xparse}
\usepackage{xcolor}
\usepackage{hyperref}

\ExplSyntaxOn
\NewDocumentCommand{\CrossReference}{ o m }
  {
   \IfNoValueTF{#1}
     { \grill_convert_name:n { #2 } }
     { \tl_set:Nn \l_grill_file_name_tl { #1 } }
   \grill_set_link:n { #2 }
  }

\tl_new:N \l_grill_file_name_tl

\cs_new:Npn \grill_convert_name:n #1
  {
   \tl_to_lowercase:n { \tl_set:Nn \l_grill_file_name_tl { #1 } }
   \tl_replace_all:Nnn \l_grill_file_name_tl { ~ } { - }
  }

\cs_new:Npn \grill_set_link:n #1
  {
   \file_if_exist:nTF { \l_grill_file_name_tl .pdf }
     {
      \group_begin:
      \cs_set:Npx\grill_temp:
        {
         \group_end:
         \exp_not:N \href{run\token_to_str:N : \l_grill_file_name_tl .pdf}{ #1 }
        }
      \grill_temp:
     }
     {
      \fcolorbox{red}{yellow}{#1}
      \footnote{Unable~to~locate~\l_grill_file_name_tl}
     }
  }



\ExplSyntaxOff

\begin{document}
\CrossReference{Abc Def}
\CrossReference[abc-def]{abc def}
\end{document}

用连字符替换空格并转换为小写很容易。

答案2

我无法想象为什么你需要在这里使用小写字母扩展(这样链接就无法使用了),那么为什么不直接

\def\foo#1#2{{%
\lccode`\ `\-%
\lowercase{#1{#2.pdf}}}}

\foo{\write20}{AB cd  / eFG}

\bye

生成结果:

 tex lc
This is TeX, Version 3.1415926 (Web2C 2010)
(./lc.tex [1
ab-cd-/-efg.pdf
] )

在 LaTeX 中使用它并稍微调整以匹配你的 MWE:

在此处输入图片描述

\documentclass{article}

\textheight10\baselineskip
\usepackage{hyperref,color}

\def\xCrossReference#1#2{%
\IfFileExists{#1}{%
\href{#1}{#2}}{%
 \fcolorbox{red}{yellow}{#2}%
 \footnote{Unable to locate #1}}}

\newcommand\CrossReference[2][\relax]{%
  \ifx\relax#1%
     \bgroup\lccode`\ `\-\lowercase{\egroup
        \xCrossReference{#2.pdf}}{#2}%
  \else
   \xCrossReference{#1.pdf}{#2}%
   \fi}


\begin{document}
Manual References: \CrossReference[equation-of-circle]{Equation of Circle}%

Manual References: \CrossReference[non-existant-file]{Non Existant File}%

\medskip\hrule\medskip

Automatic References: \CrossReference{Equation of Circle}%

Automatic References: \CrossReference{Non Existant File}%
\end{document}

\end{document}

相关内容