1

The best way to ask this question is to present two MWEs, one of which works and one of which does not. Naturally, I would like to get this into the second form, but I am at a loss as to what is happening. I believe this is an order-of-expansion issue. I tried this originally with the TeX primitives \csname and \endcsname and, failing that, went with the etoolbox utility instead thinking that it would know what I was doing wrong and have built-in safeguards. But I am getting the same errors. Without further ado, why does

\documentclass[inline]{svmono}

\usepackage{xstring,etoolbox}

\usepackage{fontspec}
\setmainfont[Mapping=tex-text]{TeX Gyre Termes}
\setsansfont[Scale=0.9,Mapping=tex-text]{TeX Gyre Heros}
\setmonofont[Scale=0.9]{Consolas}

\DeclareDocumentCommand{\extract}{m}{%
    \edef\c{\detokenize{#1}}%
    \StrCount{\c}{\string /}[\lastslash]%
    \StrCount{\c}{\string .}[\lastdot]%
    \StrBetween[\lastslash,\lastdot]{\c}{\string /}{\string .}[\temp]%
    \csedef{\temp}{true}
}

\DeclareDocumentCommand{\mark}{m}{%
    \csedef{\extract{#1}}{true}
}

\begin{document}
    \extract{\input{../../Lyx/MacroMasterXeTeX.tex}}
    \MacroMasterXeTeX
\end{document}

work, but (showing only changes)

\DeclareDocumentCommand{\extract}{m}{%
    \edef\c{\detokenize{#1}}%
    \StrCount{\c}{\string /}[\lastslash]%
    \StrCount{\c}{\string .}[\lastdot]%
    \StrBetween[\lastslash,\lastdot]{\c}{\string /}{\string .}[\temp]%
    \temp
}

\DeclareDocumentCommand{\mark}{m}{%
    \csedef{\extract{#1}}{true}
}

\begin{document}
    \mark{\input{../../Lyx/MacroMasterXeTeX.tex}}
%   \MacroMasterXeTeX
\end{document}

not work? (I commented out the last line in the document because that macro is never getting defined.) I would like to reuse the extraction code and would prefer to separate it from the "marking" process.

4
  • 5
    \extract is not expandable and you can't use it inside a \csname. No chance at all. Commented Jun 21 at 15:35
  • 3
    \DeclareDocumentCommand{\mark}{m}{% \csedef{\extract{#1}}{true} } er you really don't want to do that, that will break latex, \mark is a tex primitive Commented Jun 21 at 15:49
  • 2
    generally avoid xstring latex has built in (expl3) functions for almost all that functionality, mostly with expandable variants where that is possible Commented Jun 21 at 15:50
  • 1
    if you want to use xstring remove the \temp from the end of your extract and then use \temp to expand in the csedef. (that is why xstring defines its command to return result in a specified csname, so you can do teh comamdn first and then use the result by expansion Commented Jun 21 at 15:52

1 Answer 1

1

First off, redefining \c and \mark is not a good idea: the former is an accent command, the latter is nothing less than a TeX primitive.

I see no reason for passing \input to the \MARK command; if you actually want to input the file, you can just do it in the code of the macro.

With this simplification, we can use built-in functions:

\documentclass{article}

\ExplSyntaxOn

\NewDocumentCommand{\MARK}{m}
 {
  \tl_set:cn { \exp_last_unbraced:Ne \use_ii:nnn { \file_parse_full_name:n { #1 } } } { true }
  %\file_input:n { #1 }
 }

\ExplSyntaxOff

\begin{document}

\MARK{../../Lyx/MacroMasterXeTeX.tex}

\MacroMasterXeTeX

\end{document}

Explanation:

  1. \file_parse_full_name:n { ../../Lyx/MacroMasterXeTeX.tex } will leave {../../Lyx}{MacroMasterXeTeX}{tex} on the input stream;

  2. with \exp_last_unbraced:Ne, the \file_parse_full_name:n function is performed before passing control to \use_ii:nnn;

  3. as a result, the input stream will have \use_ii:nn {../../Lyx}{MacroMasterXeTeX}{tex} and this just expands to MacroMasterXeTeX;

  4. finally, a tl variable with that name is set to true.

4
  • Thank you for posting this. I have been trying to figure out how to do it with expl3 since I read David Carlisle 's comment. I am still trying to get the hang of expansion order and I never really understood that some things weren't expandable until today after reading what Ulrike Fischer wrote. After that I went into research mode, but it is very hard to find examples of this syntax on the web. Your explanation is priceless. The reason I am passing in \input is to make this compatible with LyX. I do need to actually input the file (once) in XeTeX, but LyX needs to see it too.
    – Mike Pugh
    Commented Jun 21 at 18:14
  • @MikePugh Sorry, but I consider LyX nothing to bother with.
    – egreg
    Commented Jun 21 at 19:33
  • Please be patient. Someone familiar with LyX will be able to help you. Commented Jun 21 at 21:07
  • When I say that LyX needs to see it too, I just mean that I have to use the built-in function to insert \input{<...>} so that LyX will also read the macros contained therein. The only way that the LaTeX (XeTeX) function needs to change is that it accepts the entire command, including the \input statement and braces. After that, the only thing it needs to do differently is extract the filename and actually execute the \input.
    – Mike Pugh
    Commented Jun 21 at 21:17

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .