나는 내 문서에서 일부 텍스트가 조판되는 방식의 모양을 쉽게 사용자 정의하기 위해 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}%