Bearbeiten 1

Bearbeiten 1

Ich versuche, eine Template-Infrastruktur zu erstellen, die stark von den Stilen von pgfkeys abhängt, um das Erscheinungsbild einiger Textteile in meinem Dokument einfach anpassen zu können. Allerdings bin ich auf ein Problem gestoßen, als ich versucht habe, einem Stil weitere Schlüssel-Wert-Paare anzuhängen, der aufgrund seiner Aufgabe bereits weitere Codes oder Stile definiert hat.

Das folgende Beispiel zeigt das Problem, von dem ich spreche:

\documentclass{minimal}
\usepackage{pgfkeys}
\begin{document}

\pgfkeys{
  /my package/.cd,
  fancy/.style = {
    format/.code = \textbf{##1},
  },
  fancy,
  format=hello, % typesets `hello' in boldface
  fancy/.append style = { },
  fancy,
  format=hello, % nothing is typeset
%  format/.show code, % uncomment to see the definition of format
}

\end{document}

Das Entfernen des Kommentars aus der letzten Zeile des Befehls zeigt, dass der Code im Schlüssel \pgfkeysnach dem Versuch, ihn an den Stil anzuhängen , durch Folgendes ersetzt wurde:fancyformat

\textbf {\pgfkeysnovalue }

und daher ist auf der zweiten nichts gesetzt format=hello.

Ich verstehe (irgendwie), warum das passiert. Aus demselben Grund, aus dem ich ##1beim Definieren des Codes innerhalb des Stils schreiben musste. Gibt es jedoch eine Lösung oder einen Workaround, um den Stil „robust“ genug zu machen, sodass man ihn anhängen kann, ohne ihn zu beschädigen?


Bearbeiten 1

Dank des Kommentars von Joseph Wright und des Antwortversuchs von Percusse habe ich herausgefunden, dass das zu lösende Problem – auf der niedrigeren Ebene – das folgende ist: Bei einem bereits definierten Makro, das ein Argument annimmt (dies sind jetzt Codes/Stile in pgfkeys, die intern definiert sind), patchen Sie den Ersetzungstext des Makros, indem Sie weiteren Text anhängen.

Nun, von etoolboxdortIstein Makro, das genau dies tut: \apptocmd. Das Folgende ist ein Beispiel dafür, wie eine Lösung mit diesem Makro wahrscheinlich aussehen sollte:

\documentclass{minimal}
\usepackage{etoolbox}
\tracingpatches
\begin{document}
\ttfamily
\def\fancy#1\pgfeov{\pgfkeysalso{format/.code=\textbf{##1}}}
\meaning\fancy\par
\apptocmd\fancy{\pgfkeysalso{color=red}}{Ok!}{Fail.}\par
\meaning\fancy\par
\apptocmd\fancy{\pgfkeysalso{format/.code=\textit{##1}}}{Ok!}{Fail.}\par
\meaning\fancy\par
\end{document}

Das einzige Problem ist, dass der zweite Patchversuch nicht funktioniert und etoolbox Folgendes als Debug-Informationen anzeigt:

[debug] tracing \apptocmd on input line 10
[debug] analyzing '\fancy'
[debug] ++ control sequence is defined
[debug] ++ control sequence is a macro
[debug] ++ control sequence is a macro with parameters
[debug] -- nested patching command and parameters in patch
[debug] -> the patching command seems to be nested in the
[debug]    argument to some other command
[debug] -> the patch text seems to contain # characters
[debug] -> either avoid nesting or use # characters with
[debug]    category code 12 in the patch text
[debug] -> simply doubling the # characters will not work

Wäre es möglich, ein zu haben, das auch mit Zeichen im neuen Ersetzungstext \apptocmdfunktioniert ?#

Haftungsausschluss:Ich habe jetzt einen Workaround für meinen speziellen Fall, der nur funktioniert, weil meine fancyStile tatsächlich keine Argumente annehmen müssen ( formatmuss, fancymuss aber nicht). Anstatt den Code also als Stil zu speichern, speichere ich ihn als normalen Wert und erweitere .codeihn auf diesen Wert. Später /.appendkann ein einfacher verwendet werden, um den „falschen“ Stil zu patchen.

Trotzdem hätte ich sehr gern eine Lösung für das ursprüngliche Problem, so dass man auch Stile anhängen kann, die sowohl Argumente als auch (nennen wir sie) Unterargumente enthalten. Ich weiß allerdings nicht, ob das technisch möglich ist. Also, das ist mein Angebot: Wenn jemand glaubt, dass eine allgemeine Lösung machbar ist, und mich das einfach durch einen Kommentar wissen lässt,Ich bin bereit, eine 300-Kopfprämie meines Rufs für eine funktionierende Lösung des allgemeinen Falls zu eröffnen. Wenn die Leute jedoch der Meinung sind, dass dies entweder einfach zu schwierig oder technisch unmöglich ist (und ich vermute das, weil ich etoolboxes nicht implementiert habe), dann werde ich mich einfach mit meiner alberneren Problemumgehung zufrieden geben und eine vollständige Antwort posten, in der ich darauf eingehe.

Antwort1

Das sieht nach einem Fehler in aus pgfkeys. Wenn Sie

\pgfkeys{
  /my package/.cd,
  fancy/.style = {
    format/.code = \textbf{##1},
  },
  fancy/.show code,
  fancy/.append style = { },
  fancy/.show code
}

du siehst

\pgfkeysalso { format/.code = \textbf {##1}, }

das erste Mal, aber

\pgfkeysalso { format/.code = \textbf {#1}}\pgfkeysalso { }

das zweite Mal: ​​Beachten Sie den Verlust von a #.

Der zugrunde liegende Code .append styleist

\pgfkeys{/handlers/.add code/.code 2 args=%
  % Find out, whether with args or not.
  \pgfkeysifdefined{\pgfkeyscurrentpath/.@args}%
  {% Yes, so add to body and reuse args
    \pgfkeysaddvalue{\pgfkeyscurrentpath/.@body}{#1}{#2}%
    % Redefine code
    {%
      \pgfkeysgetvalue{\pgfkeyscurrentpath/.@args}{\pgfkeys@tempargs}%
      \pgfkeysgetvalue{\pgfkeyscurrentpath/.@body}{\pgfkeys@tempbody}%
      \def\pgfkeys@marshal{\expandafter\gdef\expandafter\pgfkeys@global@temp\pgfkeys@tempargs}%
      \expandafter\pgfkeys@marshal\expandafter{\pgfkeys@tempbody}%
    }%
    \pgfkeysifdefined{\pgfkeyscurrentpath/.@@body}{%
      % support for \pgfkeysndefargs:
      \pgfkeyslet{\pgfkeyscurrentpath/.@@body}{\pgfkeys@global@temp}%
    }{%
      % support for \pgfkeysdefargs:
      \pgfkeyslet{\pgfkeyscurrentpath/.@cmd}{\pgfkeys@global@temp}%
    }%
  }%
  {%
    % No, so single argument (simple \pgfkeysdef). Redefine accordingly.
    {%
      \toks0{#1}%
      \pgfkeysifdefined{\pgfkeyscurrentpath/.@cmd}%
      {\pgfkeys@temptoks\expandafter\expandafter\expandafter{\csname pgfk@\pgfkeyscurrentpath/.@cmd\endcsname##1\pgfeov}}%
      {\pgfkeys@temptoks{}}%
      \toks1{#2}%
      \xdef\pgfkeys@global@temp{\the\toks0 \the\pgfkeys@temptoks \the\toks1 }%
    }%
    \expandafter\def\expandafter\pgfkeys@temp\expandafter##\expandafter1\expandafter\pgfeov\expandafter{\pgfkeys@global@temp}%
    \pgfkeyslet{\pgfkeyscurrentpath/.@cmd}\pgfkeys@temp%
  }%
}

Das Problem ist die Linie gegen Ende

\expandafter\def\expandafter\pgfkeys@temp\expandafter##\expandafter1\expandafter\pgfeov\expandafter{\pgfkeys@global@temp}%

Da dies einfach erweitert wird \pgfkeys@global@temp, wird TeX alle #darin enthaltenen Verdoppelungen rückgängig machen. Stattdessen \edefsollte ein Pluszeichen verwendet werden:

\toks0\expandafter{\pgfkeys@global@temp}%
\edef\pgfkeys@temp##1\pgfeov{\the\toks0}%

verwandte Informationen