在这个项目中,目录结构和文件名基于三个参数,但两者都有一个例外。
目录路径:\GetTexFilePath{}{}{}
目录路径基于顶级目录(#1
),这是传递给宏的第一个参数。
通常路径的形式为../#1/xxx#2/#3/
,除非#1=\SpecialCase
在这种情况下,xxx
是不是路径的一部分。
文件名:\GetTexFileName{}{}{}
文件名取决于当前的代币的价值:\the\CurrentTokenValue
。
文件名称的形式为#1-#2-#3
,但有一种特殊情况除外,即\the\CurrentTokenValue=\SpecialCase
,在这种情况下,文件名就是#3
。
下面我使用的expl3
解决方案改编自输出不应显示的文本。
根据@egreg的要求,我在开头添加了一个部分来测试各种情况,并在注释中添加了预期的输出。还为失败的输出添加了红色,为正确的输出添加了蓝色。
上述列表之后的前两部分工作正常,但第三种情况(其中文件名取决于的值)\the\CurrentTokenValue
失败。
还请注意,在第 3 节中,#1=\the\CurrentTokenValue
目录名称正确不是有xxx
(这是正确的)。但文件名并没有缩短。第 3 节得出:
../特殊/02/z/特殊-02-z
但案例 3 的正确值应该是
../特殊/02/z/z
问题:
- 我该如何调整
\GetTexFileName
以便文件名取决于令牌? - 为什么这个标记的扩展问题在用于文件路径(仅用于文件名)时没有问题?
我需要使用路径和文件名宏的连接输出(/
中间带有)才能检查\IfFileExists
。
回答:
- 我已经确认,按照@egreg 的回答将 更改为 适用于所有这些情况。我担心的是,我不知道这是否会对 的使用产生任何其他影响
\def\SpecialValue{special}
,因此最好使用和本地的解决方案。\protected\def\SpecialValue{special}
\SpecialValue
\GetTexFilePath
\GetTexFileName
\expandafter\empty
Bruno 建议在第一个参数之前添加\str_if_eq:xxTF
,以用于此测试,但由于某种原因,在我的实际使用中失败了。
笔记:
- 关于文件未找到的抱怨不是问题。
- 所有工作案例均为蓝色。
- 所有失败的案例都以红色显示。
代码:
\documentclass{article}
\usepackage{xcolor}
\usepackage{xparse}
\def\SpecialValue{special}
\newtoks{\CurrentTokenValue}
\ExplSyntaxOn
% Determine path: Always #1/xxx#2/#3 unless #1=\SpecialValue
\NewDocumentCommand{\GetTexFilePath}{m m m}{%
\str_if_eq:xxTF{#1}{\SpecialValue}{../#1/#2/#3}{../#1/xxx#2/#3}%
}%
% Determine file name: Always #1-#2-#3 unless \the\CurrentTokenValue=\SpecialValue.
\NewDocumentCommand{\GetTexFileName}{m m m}{%
\str_if_eq:xxTF{\the\CurrentTokenValue}{\SpecialValue}{#3}{#1-#2-#3}%
}%
\ExplSyntaxOff
\newcommand*{\GetFileNameWithPath}[3]{%
\GetTexFilePath{#1}{#2}{#3}/%
\GetTexFileName{#1}{#2}{#3}%
}%
\newcommand*{\TestFile}[2][red]{%
\noindent%
Token Value = \the\CurrentTokenValue%
\par\noindent%
\IfFileExists{#2}{%
\textcolor{#1}{File \FileWithPath\ found.}%
}{%
\textcolor{#1}{File \FileWithPath\ not found.}%
}%
}%
\begin{document}
\CurrentTokenValue={NonSpecial}%
\color{blue}% These work (up until the change to red color)
1a. \GetTexFilePath{A}{B}{C} \par% ../A/xxxB/C Note: xxx
2a. \GetTexFilePath{\SpecialValue}{B}{C} \par% ../special/B/C Note: no xxx
3a. \GetTexFilePath{\the\CurrentTokenValue}{B}{C} \par% ../NonSpecial/xxxB/C Note: xxx
% ----------------
4a. \GetTexFileName{A}{B}{C} \par% A-B-C
5a. \GetTexFileName{\SpecialValue}{B}{C} \par% special-B-C
6a. \GetTexFileName{\the\CurrentTokenValue}{B}{C} \par% NonSpecial-B-C
\smallskip\hrule\smallskip
% Changing the value of \CurrentTokenValue to this one special value,
% should only change the file name, and should not effect the
% file path. Absolutely no reason why the first two here should be
% any different than above, but included here for completeness.
\CurrentTokenValue={\SpecialValue}%
1b. \GetTexFilePath{A}{B}{C} \par% ../A/xxxB/C Note: xxx
2b. \GetTexFilePath{\SpecialValue}{B}{C} \par% ../special/B/C Note: no xxx
\color{red}% These next 4 fail
3b. \GetTexFilePath{\the\CurrentTokenValue}{B}{C} \par% ../special/B/C ** FAILS **
% ---------------
4b. \GetTexFileName{A}{B}{C} \par% C ** FAILS **
5b. \GetTexFileName{\SpecialValue}{B}{C} \par% C ** FAILS **
6b. \GetTexFileName{\the\CurrentTokenValue}{B}{C} \par% C ** FAILS **
\color{black}
\bigskip\hrule\hrule\bigskip
\CurrentTokenValue={NonSpecial}
\section{Normal Case: Works}
Neither the first parameter, nor the \verb|\the\CurrentTokenValue| is \verb|\SpecialValue| so should have \verb|xxx| in the path, and a file name with two dashes:
\edef\FileWithPath{\GetFileNameWithPath{NonSpecial}{02}{z}}%
\TestFile[blue]{\FileWithPath}
\section{Top directory is special case: Works}
The first parameter is \verb|\SpecialValue|, but not \verb|\the\CurrentTokenValue| so should \textbf{not} have \verb|xxx| in the path, and a file name with two dashes:
\edef\FileWithPath{\GetFileNameWithPath{\SpecialValue}{02}{z}}%
\TestFile[blue]{\FileWithPath}
\section{Both Top directory and TokenValue are special cases}
Since both the first parameter is \verb|\SpecialValue| and \verb|\the\CurrentTokenValue| are a special case, we should \textbf{not} have \verb|xxx| in the path, and a file name should be short:
\CurrentTokenValue={\SpecialValue}
\edef\FileWithPath{\GetFileNameWithPath{\the\CurrentTokenValue}{02}{z}}%
\TestFile{\FileWithPath}
\bigskip
\noindent
Correct result for the above case is
\def\FileWithPath{../special/02/z/z}%
\TestFile[blue]{\FileWithPath}
\end{document}
答案1
我会使用令牌列表,但简单的修复
\protected\def\SpecialValue{special}
似乎给出了所需的输出:在第 3 部分中我得到
令牌值 =
未找到特殊文件 ../special/02/z/z。此案例的正确值是
Token Value = special
File ../special/02/z/z not found。
在“特殊”情况下,比较恰好在\SpecialValue
和之间\SpecialValue
(未扩展)。
另一种方法是避免使用令牌寄存器:
\ExplSyntaxOn
\tl_new:N \SpecialValue
\tl_set:Nn \SpecialValue {special}
\tl_new:N \l_grill_current_value_tl
\NewDocumentCommand{\CurrentTokenValue}{m}
{
\tl_set:Nn \l_grill_current_value_tl { #1 }
}
\DeclareExpandableDocumentCommand{\GetCurrentTokenValue}{ }
{
\tl_use:N \l_grill_current_value_tl
}
% Determine path: Always #1/xxx#2/#3 unless #1=\SpecialValue
\NewDocumentCommand{\GetTexFilePath}{m m m}
{
\str_if_eq:xxTF{#1}{\SpecialValue}{../#1/#2/#3}{../#1/xxx#2/#3}
}
% Determine file name: Always #1-#2-#3 unless \the\CurrentTokenValue=\SpecialValue.
\NewDocumentCommand{\GetTexFileName}{m m m}
{
\str_if_eq:xxTF{\l_grill_current_value_tl}{\SpecialValue}{#3}{#1-#2-#3}%
}
\ExplSyntaxOff
现在将语法改为\CurrentTokenValue={...}
和\CurrentTokenValue{...}
就\the\CurrentTokenValue
足够了\GetCurrentTokenValue
。