1

With the help of this post (Is there a way to set a *global* key value using `pgfkeys`?), I found a simpler way to implement a solution to my own question (How can I create commands using multiple arguments with pgfkeys in custom environments with tabulars?). I call it simpler because I don't understand the described solutions of the post, due to my lack of deep knowledge in LaTeX.

The code with my solution is the following:

\documentclass{article}
\usepackage{pgfkeys}

\def\showstatus{%
    (level: \the\currentgrouplevel\ -- 
     globaldefs: \the\globaldefs\ --
     foo: \pgfkeysvalueof{/rpath/tpath/var3} --
     bar: \pgfkeysvalueof{/rpath/tpath/var4})
}

\def\customvarset{\pgfqkeys{/rpath}}

\newenvironment{customenvtab}{%
    \newcommand*{\resetvarsettab}{%
        \customvarset{%
                      tpath/.cd,%
                      var3/.initial=var3 tbd,%
                      var4/.initial=var4 tbd
        }
    }
    \resetvarsettab
    \def\tabval##1{\pgfkeysvalueof{/rpath/tpath/##1}}
    \newcommand{\cmdtab}[1]{%
        \globaldefs=1
        \customvarset{tpath/.cd, ##1}
        \tabval{var3} & \tabval{var4}
        \globaldefs=1
        \resetvarsettab
    }
    \begin{tabular}{c|c}
}{%
    \end{tabular}
}

\begin{document}
\section{Now Working}
%\showstatus
\begin{customenvtab}
\cmdtab{}\\
\cmdtab{var3=test var3}\\
\cmdtab{var4=test var4}\\
\cmdtab{var3=blo, var4=bli}
\end{customenvtab}
%\showstatus

\end{document}

own solution using \globaldefs=1

The question is now: is it dangerous to use \globaldefs=1 for this purpose? If yes, what do I have to be cautious with? Or should I not use this at all?

Thank you in advance for your help!

3
  • 5
    It is never safe to use \globaldefs anywhere, unless you have reviewed every line of code in its scope, and you personally maintain that code, so you can be sure a change won't invalidate the global definitions. Reviewing the tikz path parser or pgf key settings sounds like more work than is reasonable. Jun 30, 2022 at 9:14
  • 1
    @DavidCarlisle Seems like an answer to me
    – Joseph Wright
    Jun 30, 2022 at 10:40
  • 1
    I have a question: Why stick to pgfkeys for your code? If you need global assignments, why not use a key=value package that supports global assignments? Or use one of the possibilities to smuggle values out of a group. And if you have any questions about one of my answers, feel free to ask, I'll try to explain what you don't understand.
    – Skillmon
    Jun 30, 2022 at 15:57

1 Answer 1

1

As David Carlisle pointed out in his comment:

"It is never safe to use \globaldefs anywhere, unless you have reviewed every line of code in its scope, and you personally maintain that code, so you can be sure a change won't invalidate the global definitions."

So let's focus on finding another approach:

The problem you seem to wish to circumvent via setting \globaldefs is that setting keys is restricted to the current table-cell.

More recent TeX-engines bring along the expandable primitive \expanded. That might be of interest to you so you can probably do without modifying \globaldefs:

\documentclass{article}
\usepackage{pgfkeys}

\newcommand*\showstatus{%
    (level: \the\currentgrouplevel\ -- 
     globaldefs: \the\globaldefs\ --
     foo: \pgfkeysvalueof{/rpath/tpath/var3} --
     bar: \pgfkeysvalueof{/rpath/tpath/var4})%
}

\newcommand*\customvarset{\pgfqkeys{/rpath}}

\newenvironment{customenvtab}{%
    \newcommand*\resetvarsettab{%
        \customvarset{%
                      tpath/.cd,%
                      var3/.initial=var3 tbd,%
                      var4/.initial=var4 tbd
        }%
    }%
    \resetvarsettab
    \newcommand*\tabval[1]{\pgfkeysvalueof{/rpath/tpath/##1}}%
    \newcommand\cmdtab[1]{%
        \customvarset{tpath/.cd, ##1}%
        {\let\protect\noexpand\expandafter}%
        \expandafter\resetvarsettab
        \expanded{bold value: \textbf{\tabval{var3}} & italic value: \textit{\tabval{var4}}}%
    }%
    \begin{tabular}{c|c}%
}{%
    \end{tabular}%
}

\begin{document}
\section{Now Working}
%\showstatus
\begin{customenvtab}
\cmdtab{}\\
\cmdtab{var3=test var3}\\
\cmdtab{var4=test var4}\\
\cmdtab{var3=blo, var4=bli}
\end{customenvtab}
%\showstatus
\end{document}

own solution using \expanded



If you wish fine-grained expansion-control be aware that \tabval requires four expansion-steps to deliver the result:

Step 1 delivers \pgfkeysvalueof.
Step 2 delivers \csname...\endcsname.
Step 3 delivers the control-sequence-token.
Step 4 delivers the toplevel-expansion of the control-sequence token.


Four expansion-steps in turn imply 24-1=15 \expandafter ...

If you are not familiar with \expandafter and expansion-trickery you might be interested in the question How can I know the number of expandafters when appending to a csname macro? and its answers.

\expandafter affects the next and the next but one token:
The toplevel-expansion of \expandafter is the token next to \expandafter and

  • if the next-but one token is expandable: the toplevel-expansion of the next-but one token.
  • if tthe next-but one token is not expandable: the next-but one token.

\documentclass{article}
\usepackage{pgfkeys}

\newcommand*\showstatus{%
    (level: \the\currentgrouplevel\ -- 
     globaldefs: \the\globaldefs\ --
     foo: \pgfkeysvalueof{/rpath/tpath/var3} --
     bar: \pgfkeysvalueof{/rpath/tpath/var4})%
}

\newcommand*\customvarset{\pgfqkeys{/rpath}}

\chardef\stopromannumeral=`\^^00
\newcommand\exchange[2]{#2#1}
\newcommand\passfirsttosecond[2]{#2{#1}}
\newcommand\obtaintabvalandexchange[3]{%
  % #1 <tokens to prepend to brace-nested value of pgf-"variable">
  % #2 pgf-"variable"
  % #3 <stuff to prepend>
  % yields
  % <stuff to prepend><tokens to prepend to brace-nested value of pgf-"variable">{<value of pgf-"variable">}
  \expandafter\exchange\expandafter{\romannumeral
     \expandafter\passfirsttosecond\expandafter{%
       \romannumeral
       \expandafter\expandafter\expandafter\expandafter\expandafter\expandafter\expandafter
       \expandafter\expandafter\expandafter\expandafter\expandafter\expandafter\expandafter
       \expandafter\stopromannumeral
       \tabval{#2}%
     }{\stopromannumeral#1}%
  }{#3}%
}%
\newenvironment{customenvtab}{%
    \newcommand*\resetvarsettab{%
        \customvarset{%
                      tpath/.cd,%
                      var3/.initial=var3 tbd,%
                      var4/.initial=var4 tbd
        }%
    }%
    \resetvarsettab
    \newcommand*\tabval[1]{\pgfkeysvalueof{/rpath/tpath/##1}}%
    \newcommand\cmdtab[1]{%
        \customvarset{tpath/.cd, ##1}%
        \obtaintabvalandexchange{italic value: \textit}{var4}{%
           % You can nest \obtaintabvalandexchange in
           % \obtaintabvalandexchange's 3rd argument.
           % The last nesting-level then denotes the value in the
           % leftmost table-cell.
           \obtaintabvalandexchange{bold value: \textbf}{var3}{\resetvarsettab} & 
        }%
    }%
    \begin{tabular}{c|c}%
}{%
    \end{tabular}%
}

\begin{document}
\section{Now Working}
%\showstatus
\begin{customenvtab}
\cmdtab{}\\
\cmdtab{var3=test var3}\\
\cmdtab{var4=test var4}\\
\cmdtab{var3=blo, var4=bli}
\end{customenvtab}
%\showstatus
\end{document}

enter image description here

3
  • Thank you very much, @Ulrich. I am going to have to look into fine grained expansion, since in my complete example, I am formatting my table entries (e.g. with \textbf{\tabval{val3}}). And when I use \expanded{...}, I get the error TeX capacity exceeded, sorry [input stack size=10000].
    – frankieee
    Jun 30, 2022 at 14:21
  • @frankieee I just edited my second example so that with \obtaintabvalandexchange you can specify formatting-commands/tokens wheret the obtained value is appended as undelimited/brace-nested argument. Jun 30, 2022 at 14:47
  • @frankieee I just edited my first example so that \expanded obeys the expansion-protection-mechanism of LaTeX 2e. With the values provided via \cmdtab's argument you may need to prepend \protect to some tokens here and there. Jun 30, 2022 at 15:10

You must log in to answer this question.

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