2

This is a followup of this question. Briefly, I want to load from an external file the argument to give to \pgfkeys, but this is not trivial.

Here is an example of what I tried to do, which however does not work due to lots of strange error messages:

\begin{filecontents}{keys.def}
  key = {
     Hellò
  }
\end{filecontents}

\documentclass{article}
\usepackage[utf8]{inputenc}

\usepackage{pgfkeys}

\pgfkeys{
  /mykeys/key/.initial = {}
}

\pgfqkeys{/mykeys}{
  \input{keys.def}
}

\begin{document}
  Values: \pgfkeysvalueof{/mykeys/key}
\end{document}

As you see I need to load the contents of a file as-is (hence the attempt of using \input) and feed it to the \pgfkeys command.

The use-case is the following: I want to make my class extensible, so I defined a discrete number of keys, and I want it to be configurable from an external file. This is not done in the context of typesetting a document, but inside a more involved system of which TeX-ing the file is only a stage, thus the file will be edited by third-party people and I need to hide the fact that this is TeX, so I cannot simply include the \pgfkeys call itself in the file. That said, I don't want to forbid to anybody who does know that this is TeX from doing anything fancy, so i don't want to simply parse a list of key-value pairs, instead parsing directly the argument to \pgfkeys, so advanced users can do whatever they want.

From what written above the requirements are the simple:

1) I need to read the whole contents of the file as-is, without any special format nor restrictions, and 2) pass it to a \pgfkeys command as-if the above example that use \input had worked. 3) In the MWE I've intentionally included inputenc and an UTF8 character in the example input, because the real input will contain localized text and I need for UTF8 to work.

The accepted answer of the linked question uses expl3, and it originally used also l3keys for key handling. I cannot use l3keys as I already set up everything using pgfkeys. Adapting that solution to pgfkeys results in the following:

\documentclass{article}
\usepackage[utf8]{inputenc}
\usepackage{expl3,pgfkeys}

\begin{document}
\pgfkeys{
  gigabytes pgf/mykeys/.cd,
  key/.initial={},
}
\ExplSyntaxOn
\ior_new:N \l_gigabytes_stream
\ior_open:Nn \l_gigabytes_stream { keys.def }
\ior_map_inline:Nn \l_gigabytes_stream 
{
  \pgfkeys { gigabytes~pgf / mykeys/.cd, #1}
}
\ior_close:N \l_gigabytes_stream
\pgfkeysvalueof{gigabytes~pgf /mykeys / key}
\ExplSyntaxOff
\end{document}

However, the problem with this code is that the file is read with the cathode regime of expl3, thus all the spaces from the file are thrown away and this is not acceptable. Also, avoiding expl3 is better for me since I'm not used to it and all the rest of the system doesn't need it.

So how can I achieve my goal without using expl3?

  • Can you add some example keys that you'd like to "load". If you only want key-value pairs this is fairly trivial but if you want more complicated keys this is, well, more complicated. It also isn't clear to me why you can't just \input the file, – Andrew Dec 8 '17 at 8:50
  • Yes, I need arbitrary pgfkeys input. What I need to do is exactly to “just \input the file”. Just as \pgfkeys{\input{filename}}. The problem is that doing just that doesn’t work. Look at the previous question that I linked (I’ll repeat the MWE here as soon as I get back to a computer). – gigabytes Dec 8 '17 at 8:54
  • Because I want the file to be edited by 3rd parties in a format as neutral as possible, without TeX code (if one doesn’t want to) – gigabytes Dec 8 '17 at 9:08
  • Since full blown pgf keys can be very complicated, and as they follow a prescribed rather than neutral format (and they can contain arbitrary TeX commands), I don't understand your explanation. Adding a minimal working example to show what you are a really trying to achieve might help... – Andrew Dec 8 '17 at 9:15
  • I’ve already said that I’ll repeat the MWE from the linked question as soon as I can. The MWE is the same. That said, “why” I need to not include the \pgfkeys command itself in the file is irrelevant. I just need that. Simply using \input does not work, with hundreds of error messages. So can it be done? – gigabytes Dec 8 '17 at 9:29
1

Although I don't understand the use-case, using the MWE from the previous question the following might do what you want:

\documentclass{article}
\usepackage{pgfkeys}

\begin{filecontents}{keys.def}
  key = Hello
  second key=bye
\end{filecontents}

\pgfkeys{/mykeys/.is family, /mykeys,
  key/.initial =,
  % allow unknown keys
  .unknown/.code={\pgfkeyssetvalue{\pgfkeyscurrentpath/\pgfkeyscurrentname}{#1}},
}

\newread\pgfkeysfile% file handler
\def\apar{\par}% \ifx\par won't work but \ifx\apar will
\newcommand\AddPgfKey[1]{\expandafter\pgfkeys\expandafter{/mykeys, #1}}
\openin\pgfkeysfile=keys.def% open file for reading
\loop\unless\ifeof\pgfkeysfile% loop until end of file
  \read\pgfkeysfile to \pgfkeysline% read line from file
  \ifx\pgfkeysline\apar% test for, and ignore, \par
  \else%
    \ifx\pgfkeysline\empty\relax% skip over empty lines/comments
    \else\expandafter\AddPgfKey\expandafter{\pgfkeysline}
    \fi%
  \fi%
\repeat

\begin{document}

 \noindent Key values: \\
 key = \pgfkeysvalueof{/mykeys/key}\\
 second key = \pgfkeysvalueof{/mykeys/second key}

\end{document}

I use something similar in some of my code but rather than reading in arbitrary keys all that I want to do is set some some key-value pairs. The code above should work with arbitrary pgf-keys but only if each key is on one line. To support multi-line keys the code above could be modified to slurp the entire contents of the file into one string that is then fed to \pgfkeys{...}.

  • Actually I needed exactly to read multiline keys. The file data will be just normal code that would be suitable as an argument to \pgfkeys, thus I cannot assume that every key-value pair will be on its own line. – gigabytes Dec 8 '17 at 13:25
  • 1
    @gigabytes Then your MWE should contain such lines – Andrew Dec 8 '17 at 16:50

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.