편집 1

편집 1

나는 내 문서에서 일부 텍스트가 조판되는 방식의 모양을 쉽게 사용자 정의하기 위해 pgfkeys의 스타일에 크게 의존하는 일부 템플릿 인프라를 만들려고 합니다. 그러나 이미 더 많은 코드나 스타일을 정의한 스타일에 더 많은 키-값 쌍을 추가하려고 할 때 몇 가지 문제에 부딪혔습니다.

다음 예는 내가 말하는 문제를 보여줍니다.

\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}

명령 에서 마지막 줄의 주석 처리를 제거하면 \pgfkeys스타일에 추가하려고 시도한 후 키 fancy의 코드가 format다음으로 대체되었음을 알 수 있습니다.

\textbf {\pgfkeysnovalue }

따라서 두 번째 에는 아무것도 조판되지 않습니다 format=hello.

나는 왜 이런 일이 발생하는지 이해합니다. ##1스타일 내에서 코드를 정의할 때 작성해야 했던 이유와 같습니다 . 그러나 스타일을 손상시키지 않고 추가할 수 있을 정도로 스타일을 충분히 "강건"하게 만드는 수정 사항이나 해결 방법이 있습니까?


편집 1

Joseph Wright의 의견과 percusse의 답변 시도 덕분에 낮은 수준에서 해결해야 할 문제는 다음과 같습니다. 하나의 인수를 취하는 이미 정의된 매크로가 있는 경우(이제 pgfkeys의 코드/스타일은 다음과 같습니다. 내부적으로 정의됨), 더 많은 텍스트를 추가하여 매크로의 대체 텍스트를 패치합니다.

이제 , etoolbox거기 에서~이다이 작업을 수행하기 위한 매크로: \apptocmd. 다음은 이 매크로를 사용하는 솔루션이 어떻게 보이는지에 대한 예입니다.

\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}

유일한 문제는 두 번째 패치 시도가 작동하지 않고 etoolbox가 디버그 정보로 다음을 표시한다는 것입니다.

[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

새로운 대체 텍스트의 문자 \apptocmd에서도 작동하는 를 가질 수 있습니까 ?#

부인 성명:이제 내 특정 사례에 대한 몇 가지 해결 방법이 있습니다. 이는 내 fancy스타일이 실제로 인수를 취할 필요가 없기 때문에 작동합니다( format있으나 fancy그렇지 않음). 따라서 코드를 스타일로 저장하는 대신 일반 일반 값으로 저장하고 .code이 값으로 확장합니다. 나중에 간단한 것을 /.append사용하여 "가짜" 스타일을 패치할 수 있습니다.

그래도 나는 원래 문제에 대한 해결책을 매우 원하므로 두 인수와 하위 인수(이를 호출하겠습니다)를 모두 포함하는 스타일에 추가할 수도 있습니다. 그러나 이것이 기술적으로 가능한지는 모르겠습니다. 그래서 이것이 제가 할 일입니다. 누군가가 일반적인 해결책이 가능하다고 믿고 댓글을 게시하여 이를 알려준다면,나는 일반적인 사례에 대한 효과적인 해결책을 위해 내 담당자에게 300 현상금을 기꺼이 열겠습니다.. 그러나 사람들이 이것이 너무 어렵거나 기술적으로 불가능하다고 생각한다면(그리고 etoolbox구현하지 않았기 때문에 이것이 의심되는 경우) 나는 더 어리석은 해결 방법에 만족하고 이에 대한 전체 답변을 게시할 것입니다.

답변1

이것은 의 버그처럼 보입니다 pgfkeys. 만약 당신이

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

알다시피

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

처음이지만

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

두 번째: a 의 손실에 주목하세요 #.

기본 코드는 다음 .append style과 같습니다.

\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%
  }%
}

문제는 끝을 향한 선이다.

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

이것이 단순히 확장됨에 따라 TeX는 포함된 \pgfkeys@global@temp모든 것을 두 배로 푼다 . #대신 \edef플러스 토크를 사용해야 합니다.

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

관련 정보