2

Consider this MWE:

\documentclass[varwidth,tightpage,border=1bp]{standalone}

\usepackage{tikz}

\begin{document}
\begin{tikzpicture}

\makeatletter
\gdef\getMyInfoString{%
  \let\trfm\relax % ! Undefined control sequence.
  \pgfgettransform{\trfm}% with previous commented: ! Undefined control sequence. <argument> \trfm
  \edef\tout{%
    pgfgettransform: \trfm ; %
    pgf@pt@aa, pgf@pt@ba, pgf@pt@ab, pgf@pt@bb: \pgf@pt@aa, \pgf@pt@ba, \pgf@pt@ab, \pgf@pt@bb %
  }
  \tout % output tout
}
\makeatother

\pgfgettransform{\trfmX}%
\makeatletter
\typeout{Manually check: %
    pgfgettransform: \trfmX ; %
    pgf@pt@aa, pgf@pt@ba, pgf@pt@ab, pgf@pt@bb: \pgf@pt@aa, \pgf@pt@ba, \pgf@pt@ab, \pgf@pt@bb %
}
\makeatother

\typeout{This is via macro function: \getMyInfoString}%

\end{tikzpicture}
\end{document}

If you compile this, the first \typeout prints this to stdout:

Manually: pgfgettransform: {1.0}{0.0}{0.0}{1.0}{0.0pt}{0.0pt}; pgf@pt@aa, pgf@p
t@ba, pgf@pt@ab, pgf@pt@bb: 1.0, 0.0, 0.0, 1.0

... while the second \typeout raises an error:

! Undefined control sequence.
\getMyInfoString ->\let \trfm 
                              \relax \pgfgettransform {\trfm }\edef \tout {p...
l.30 \typeout{This is: \getMyInfoString}
                                        %
? 

Clearly, latex wants to execute the \trfm control sequence/command/token/macro - while I intend it to be a "local variable", which will be used as an "argument" to \pgfgettransform (which will then populate it with data).

Is there a way to "protect" this \trfm macro -- so the \getMyInfoString executes correctly, and returns a string (in an expandable way, I guess, since the intent is to use it in \typeout), when called?

4
  • 1
    You are trying to use \getMyInfoString in an expansion context (\typeout): presumably you need to define \getMyInfoString to store the result (\tout) but not print it, then use \tout inside \typeout.
    – Joseph Wright
    Jun 18, 2014 at 13:09
  • Thanks for the comment, @JosephWright - I have discovered (see below) that a global definition of the "local" tokens beforehand seems to somewhat help. But I now vaguely remember doing something like you suggest in the past; is there a rule of thumb to help one remember what to do when a complex printout is required (e.g. do you "return a string", or "typeout" directly from the macro)? Cheers!
    – sdaau
    Jun 18, 2014 at 13:21
  • 1
    Anything that performs an assignment is not expandable. There are a few expansion contexts, but the key ones are \edef and \write, and thus derivatives of these. Anything writing to the log, such as \typeout, is related to \write so is an expansion context.
    – Joseph Wright
    Jun 18, 2014 at 13:23
  • Thanks for that @JosephWright - feel free to post that as an answer, I'll accept it. Cheers!
    – sdaau
    Jun 18, 2014 at 13:27

3 Answers 3

4

If you want to get the current transform data in the log file, just execute the commands before the \typeout.

\documentclass{article}

\usepackage{tikz}

\makeatletter
\def\getMyInfoString{%
  \pgfgettransform{\trfm}%
  \edef\tout{%
    \space\space pgfgettransform: \trfm ;^^J%
    \space\space pgf@pt@aa: \pgf@pt@aa;^^J%
    \space\space pgf@pt@ba: \pgf@pt@ba;^^J%
    \space\space pgf@pt@ab: \pgf@pt@ab;^^J%
    \space\space pgf@pt@bb: \pgf@pt@bb
  }%
  \typeout{Here's the current transform:^^J\tout} % output tout
}
\makeatother

\begin{document}
\begin{tikzpicture}
\getMyInfoString
\end{tikzpicture}
\end{document}

The output in the log file is

Here's the current transform:
  pgfgettransform: {1.0}{0.0}{0.0}{1.0}{0.0pt}{0.0pt};
  pgf@pt@aa: 1.0;
  pgf@pt@ba: 0.0;
  pgf@pt@ab: 0.0;
  pgf@pt@bb: 1.0

You cannot perform assignments in a \typeout; a definition is an assignment.

1
  • Many thanks for the answer, @ egreg - as you and @JosephWright pointed out: "a definition is an assignment" and "anything that performs an assignment is not expandable" - I hope I won't be forgetting these soon; cheers!
    – sdaau
    Jun 18, 2014 at 14:25
1

How about:

\documentclass{scrartcl}
\usepackage{tikz}
\begin{document}
\begin{tikzpicture}
\pgfgettransformentries{ \a }{\b }{ \c }{ \d }{ \sx }{ \sy }
\typeout{a=\a, b=\b, c=\c, d=\d, sx=\sx, sy=\sy}
\end{tikzpicture}
\end{document}

which produces a=1.0, b=0.0, c=0.0, d=1.0, sx=0.0pt, sy=0.0pt and avoids nasty plain TeX hacks?

Edit: Ok, after your comment I understand that you are in the usual hell of what command is expanded when. It seems like typeout is pretty nasty here. Unfortunately I can not give you some \expandafter magic which solves this case, but a simple workaround would be to split setting variables and producing output like

\documentclass{scrartcl}
\usepackage{tikz}
\newcommand\setVars{\pgfgettransformentries{\a}{\b}{\c}{\d}{\sx}{\sy}}
\newcommand\printVars{a=\a, b=\b, c=\c, d=\d, sx=\sx, sy=\sy}
\begin{document}
\setVars\typeout{\printVars}
\end{document}
1
  • Thanks for that, @Echsecutor - unfortunately, what I specifically want is to compose a string for an (eventually more complex) typeout; meaning I wanted to avoid direct typeouts like in your answer. Cheers!
    – sdaau
    Jun 18, 2014 at 13:22
0

I'll post this as an answer, as it does somewhat help - if the crashing "local option" macros are "predefined" beforehand with \gdef (just the relevant snippet here):

\makeatletter
\gdef\tout{}\gdef\trfm{} % ** this
\gdef\getMyInfoString{%
  \let\trfm\relax % ! Undefined control sequence.
  \pgfgettransform{\trfm}% with previous commented: ! Undefined control sequence. <argument> \trfm
  \edef\tout{%
    pgfgettransform: \trfm ; %
    pgf@pt@aa, pgf@pt@ba, pgf@pt@ab, pgf@pt@bb: \pgf@pt@aa, \pgf@pt@ba, \pgf@pt@ab, \pgf@pt@bb %
  }
  \tout % output tout
}
\makeatother

... then the MWE seems to pass without compilation errors; and it prints out:

Manually check: pgfgettransform: {1.0}{0.0}{0.0}{1.0}{0.0pt}{0.0pt}; pgf@pt@aa,
 pgf@pt@ba, pgf@pt@ab, pgf@pt@bb: 1.0, 0.0, 0.0, 1.0
This is via macro function: \let \relax \edef {{1.0}{0.0}{0.0}{1.0}{0.0pt}{0.0p
t}} \edef {pgfgettransform: ; pgf@pt@aa, pgf@pt@ba, pgf@pt@ab, pgf@pt@bb: 1.0, 
0.0, 0.0, 1.0} 

Obviously, the printout via the macro is not exactly as intended - which is why it would be nice to have a proper answer; but at least in this case, the required info leaks to stdout - and that is good enough for me for now :)

2
  • 1
    This still doesn't actually work: all that happens is you avoid an error as \let\trfm\relax now expands to \let\relax, as both \let and \relax are unexpandable and \trfm now expands to nothing rather than being undefined.
    – Joseph Wright
    Jun 18, 2014 at 13:25
  • Ah, thanks for noting that, @JosephWright - I was more happy about getting some numbers printed to stdout, than what actual mechanism led to those printouts :); good to keep this in mind. Cheers!
    – sdaau
    Jun 18, 2014 at 13:29

You must log in to answer this question.

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