3

Following an update to my packages with TeXLive2020 I am seeing different behaviour than in TeXLive2019. The following test is run in the directory Testing/ which besides the MWE in the file entitiled foo-x-bar.tex & foo-x-bar.pdf contains only the MacOS .DS_Store (but no other files).

With TeXLive 2020 (with latest updates applied), it outputs:

enter image description here

where as with TeXLive2019 I obtain the correct results:

enter image description here

Notes:

  • The other change I had to make with an update to the packages in TeXLive2020 is to handle the fact that \themainfile is sometimes reported as ./foo-x-bar.tex whereas with TeXLive2019 (and earlier TeXLive2020 before the package updates) it was foo-x-bar.tex (ie, without the leading ./). The use of \IfBeginWith resolves that issue, but including it here so that this code works either way.

  • Surprisngly, in my actual use case I am seeing the opposite results. The file exists but is being reported with an updated TeXLive202 as it does not exist!! Will continue to attempt to produce an MWE with that result if the solution to this does not resolve my issue.

\listfiles 2020

 article.cls    2020/04/10 v1.4m Standard LaTeX document class
  size10.clo    2020/04/10 v1.4m Standard LaTeX file (size option)
  xparse.sty    2020-10-27 L3 Experimental document command parser
   expl3.sty    2020-12-07 L3 programming layer (loader) 
l3backend-pdftex.def    2020-09-24 L3 backend support: PDF output (pdfTeX)
 xstring.sty    2019/02/06 v1.83 String manipulations (CT)
currfile.sty    2020/09/29 v0.7d Provides the file path elements of the current
 input file
kvoptions.sty    2020-10-07 v3.14 Key value format for package options (HO)
  keyval.sty    2014/10/28 v1.15 key=value parser (DPC)
 ltxcmds.sty    2020-05-10 v1.25 LaTeX kernel commands for general use (HO)
kvsetkeys.sty    2019/12/15 v1.18 Key value parser (HO)
filehook.sty    2020/09/29 v0.8a Hooks for input files
filehook-2020.sty    2020/09/29 v0.8a Hooks for input files
currfile-abspath.sty    2020/09/29 v0.7d Provides absolute file paths, the pare
nt working directory and the main file name

\listfiles 2019

 article.cls    2019/10/25 v1.4k Standard LaTeX document class
  size10.clo    2019/10/25 v1.4k Standard LaTeX file (size option)
  xparse.sty    2019-10-11 L3 Experimental document command parser
   expl3.sty    2019-11-07 L3 programming layer (loader) 
expl3-code.tex    2019-11-07 L3 programming layer 
l3deprecation.def    2019-04-06 v L3 Deprecated functions
l3backend-pdfmode.def    2019-04-06 L3 backend support: PDF mode
 xstring.sty    2019/02/06 v1.83 String manipulations (CT)
currfile.sty    2015/04/23 v0.7c Provides the file path elements of the current
 input file
kvoptions.sty    2016/05/16 v3.12 Key value format for package options (HO)
  keyval.sty    2014/10/28 v1.15 key=value parser (DPC)
 ltxcmds.sty    2016/05/16 v1.23 LaTeX kernel commands for general use (HO)
kvsetkeys.sty    2016/05/16 v1.17 Key value parser (HO)
infwarerr.sty    2016/05/16 v1.4 Providing info/warning/error messages (HO)
etexcmds.sty    2016/05/16 v1.6 Avoid name clashes with e-TeX commands (HO)
ifluatex.sty    2019/10/25 v1.5 ifluatex legacy package. Use iftex instead.
   iftex.sty    2019/11/07 v1.0c TeX engine tests
filehook.sty    2019/10/03 v0.6 Hooks for input files
currfile-abspath.sty    2015/04/23 v0.7c Provides absolute file paths, the pare
nt working directory and the main file name

Code:

To match the results, create a directory Testing/ and save the following MWE as Testing/foo-x-bar.tex.

\documentclass{article}
\usepackage{xparse}
\usepackage{xstring}
\usepackage[realmainfile]{currfile}%

\AtBeginDocument{% \getmainfile \IfBeginWith{\themainfile}{./}{% \StrBetween[1,2]{\themainfile}{./}{.}[\FileNameNoExtension]% \typeout{Used Used \string\StrBetween}% }{% \StrBefore{\themainfile}{.}[\FileNameNoExtension]% \typeout{Used \string\StrBefore}% }% }%

\NewDocumentCommand{\GetTexFileNameWithPath}{}{% ../Testing/\FileNameNoExtension.texxx% }%

\listfiles \begin{document} The file name extracted from \verb|\themainfile| is \FileNameNoExtension.

\def\FileNameWithPath{\GetTexFileNameWithPath}% \IfFileExists{\FileNameWithPath}{% File \FileNameWithPath'' exist.% }{% File\FileNameWithPath'' does \emph{NOT} exist.% }% \end{document}

Peter Grill
  • 223,288

1 Answers1

3

Two strange things are at play here, and I don't know if the fault is only yours or mine too (hopefully not mine ;-)

You are defining a file name using \NewDocumentCommand, but commands defined with that are always \protected, and should not expand in expansion-only contexts (like file names), so in part this is a duplicate of Robust command not expanding as \input argument. There were indeed changes to how LaTeX parses file names, and one of these changes is that \protected macros do not expand, because they should not indeed.

In older versions it worked because xparse supports some \protected commands to be used in some expansion contexts, like in a \csname...\endcsname (used to expand a file name), and your file name macro would expand correctly (after all it just expands to a string) to the file name. You can see the difference in behaviour with this simpler test:

\documentclass{article}
\protected\def\FileNameWithPath{../Testing/foo-x-bar.texxx}%
\begin{document}
File ``\FileNameWithPath''
\IfFileExists{\FileNameWithPath}{}{\emph{NOT} }exist.
\end{document}

So the proper solution to the problem is to not use \protected to define a file name, because it is at least weird to make something that you need to expand, \protected. In your case you can replace \NewDocumentCommand by \NewExpandableDocumentCommand or even better \newcommand to avoid the overhead of xparse.


That said, the result of the test above with a current LaTeX is indeed strange. I would expect it to check for the file FileNameWithPath (the name of the macro), and fail. But instead, it is somehow dropping the .texxx extension and then checking for ../Testing/foo-x-bar which, adding the default .tex extension does exist and the test returns true. I will investigate this bit because it should not do that.

  • I am pretty sure its my fault. This is really old code, so I tend to leave it alone if it works as desired. – Peter Grill Dec 23 '20 at 00:44
  • @PeterGrill I know what you mean (and sorry about breaking your code). But now LaTeX's file name parsing is (hopefully) consistent, and expanding a \protected macro is definitely not the right thing to do, so I'm afraid this behaviour will stay (though I still have to check why it drops the extension for the test). But you can easily fix by making the command expandable (I don't see any reason for it being robust). – Phelype Oleinik Dec 23 '20 at 00:57
  • @Yeah, using \NewExpandableDocumentCommand does indeed fix the test case given here. However that is not sufficient in my actual use case for some reason. Must be an expansion problem somewhere, so will keep digging... – Peter Grill Dec 23 '20 at 01:25
  • @PeterGrill Maybe (I'm guessing) you use it in an \edef and trust it won't expand being \protected, but now it does, so maybe you need to add some \noexpand here and there before \GetTexFileNameWithPath. Anyhow, feel free to ask. Oh, also if you won't use any new features from 2020 you can rollback with \RequirePackage[2020-02-02]{latexrelease} at the very beginning of your document – Phelype Oleinik Dec 23 '20 at 01:29