tikz/pgf 업그레이드 및 장식

tikz/pgf 업그레이드 및 장식

pgf의 주요 업그레이드 이후 내 코드는 더 이상 컴파일되지 않습니다. 장식은 일부 선 강조 표시(MWE 참조), 일부 선의 공, 이미지 등과 같을 수 있는 "장식된" 소스 목록을 만들려고 합니다. 장식은 선택 사항이며 매크로 인수로 전달합니다. 여기 내 MWE가 있습니다

    \documentclass{book}
    \usepackage{xcolor}
    \usepackage{xkeyval}
    \usepackage{listings}
    \usepackage{tikz}   
\usetikzlibrary{shapes,positioning,arrows,fit,backgrounds,calc,tikzmark,shadows}%

    \definecolor{ForestGreen}{rgb}{0.0, 0.4, 0.0}
    \definecolor{burntorange}{rgb}{0.8, 0.33, 0.0}
    \newlength{\mywidth} % Used in defining listing width
    \definecolor{ivory}{rgb}{1.0, 1.0, 0.94}
        \colorlet{SeparatorColor}{burntorange}

        \makeatletter
        \define@key{MEMacros}{decorations}{\def\ME@decorations{#1}}
        \define@key{MEMacros}{language}{\def\ME@language{#1}}
        \define@key{MEMacros}{number}{\def\ME@number{#1}}
        \presetkeys{MEMacros}{number=1}{}%
    \makeatother


    %%Usage \MESourceFile[keys]{source file}{caption}{label}
    \makeatletter
    \newcommand\MESourceFile[4][]{
    \setkeys{MEMacros}{ %language={[ANSI]C},
     decorations={},#1}% 
          \begingroup%
            \lstset{    language={[ANSI]C}      }   

             {\begin{figure*}[h!btp] }
             \caption{#3}
            \begingroup\edef\x{\endgroup\noexpand\lstinputlisting[label=#4, name=#4] {#2}
                {\ME@decorations} % Decorating comments
                }\x
            {\end{figure*}}
      \endgroup%
    }
    \makeatother
    % % Prepare for some decorations on the listing files
        \makeatletter
        \newif\iflst@linemark

        \lst@AddToHook{EveryLine}{%
     \begingroup
     \advance\c@lstnumber by 1\relax
     \pgfmark{line-\lst@name-\the\c@lstnumber-start}%
     \endgroup
        }

        \lst@AddToHook{EOL}{\pgfmark{line-\lst@name-\the\c@lstnumber-end}%
        \global\lst@linemarktrue
        }

        \lst@AddToHook{OutputBox}{%
     \iflst@linemark
     \pgfmark{line-\lst@name-\the\c@lstnumber-first}%
     \global\lst@linemarkfalse
     \fi
        }

        \def\tkzlst@fnum#1\relax#2\@STOP{%
     \def\@test{#2}%
     \ifx\@test\@empty
     \def\tkzlst@start{0}%
     \else
     \@tempcnta=#1\relax
     \advance\@tempcnta by -1\relax
     \def\tkzlst@start{\the\@tempcnta}%
     \fi
        }

        \lst@AddToHook{Init}{%
     \expandafter\tkzlst@fnum\lst@firstnumber\relax\@STOP
     \pgfmark{line-\lst@name-\tkzlst@start-start}%
        }

    % % Put a balloon around some lines in a source
    % Usage: \MEHighlightLines{BallonName}{SourceName}{FirstLine}{LastLine}
    \newcommand\MEHighlightLines[4]{%
      \pgfmathtruncatemacro\pgf@temp{%
       #3-1
      }%
      \iftikzmark{line-#2-\pgf@temp-start}{%
       \iftikzmark{line-#2-#3-first}{%
         \xdef\b@lines{({pic cs:line-#2-\pgf@temp-start} -| {pic           cs:line-#2-#3-first})}%
       }{%
         \iftikzmark{line-#2-#3-start}{%
           \xdef\b@lines{({pic cs:line-#2-\pgf@temp-start} -| {pic             cs:line-#2-#3-start})}%
         }{%
           \xdef\b@lines{(pic cs:line-#2-\pgf@temp-start)}%
         }%
       }%
      }{%
       \xdef\b@lines{}%
      }%
      \foreach \k in {#3,...,#4} {%
       \iftikzmark{line-#2-\k-first}{%
         \xdef\b@lines{\b@lines (pic cs:line-#2-\k-first) }
       }{}
       \iftikzmark{line-#2-\k-end}{%
         \xdef\b@lines{\b@lines (pic cs:line-#2-\k-end) }
       }{}
      }%
      \ifx\b@lines\pgfutil@empty
      \else
      \edef\pgf@temp{\noexpand\tikz[remember picture,overlay]\noexpand\node[fit={\b@lines}, color=ForestGreen,yshift=-2pt,
         draw, fill=green!30, opacity=0.4,  inner sep=1pt, rounded corners=5pt] (#1) {};
      }%
            \pgf@temp
      \fi
            }
    \makeatother

    \begin{document}
    \MESourceFile[decorations={
    %\MEHighlightLines{HelloWorldsystem}{lst:HelloWorld.c}{1}{3}
    }
    ]{HelloWorld.c}{Hello world}{lst:HelloWorld.c}
    \MEHighlightLines{HelloWorldsystem}{lst:HelloWorld.c}{1}{3}
    \end{document}

그리고 내가 꾸미고 싶은 멋진 코드

#include <stdio.h>

int main()
{
     printf("hello, world\n");
}

코드의 의도는 라인 1-3 주위에 강조 표시된 상자를 배치하는 것입니다. 코드는 있는 그대로 작동합니다. 이는 단지 \MEHighlightLines 매크로가 제대로 작동한다는 것을 보여주기 위한 것입니다. 이제 해당 매크로가 포함된 마지막 줄 앞 부분을 주석 처리하고 그 위에 있는 동일한 매크로 3줄이 포함된 줄의 주석 처리를 제거할 수 있습니다.

이제 오류 메시지가 나타납니다.

! Undefined control sequence.
\pgfmathsetcount ... \pgfmath@onquick #2\pgfmath@ 
                                                  {\afterassignment \pgfmath...

유일한 차이점은 이제 매크로가 직접 호출되지 않고 인수로 전달된다는 점이므로 새 pgf에서 매크로를 확장하는 데 원인이 숨겨져 있지 않을까 싶습니다. 인수 전달 방법은 다음과 같습니다.

\begingroup\edef\x{\endgroup\noexpand\lstinputlisting[label=#4, name=#4] {#2}
    {\ME@decorations} % Decorating comments
    }\x

업그레이드된 pgf에서 전달된 매크로를 확장하는 중에 오류가 발생했습니다. (장식은 목록과 함께 유지되어야 하므로 \Figure에 강제로 적용합니다. 대체 구현 아이디어도 (해결 방법으로) 환영하지만 가장 좋은 방법은 매크로 확장 버그를 수정하는 것입니다.)

답변1

글쎄, 오류는 매우 분명합니다. 코드

\begingroup\edef\x{\endgroup\noexpand\lstinputlisting[label=#4, name=#4] {#2}
{\ME@decorations} % Decorating comments
}\x

해야한다

\lstinputlisting[label=#4, name=#4] {#2}
\ME@decorations % Decorating comments

여기서 트릭 을 사용할 이유가 전혀 없으며 \edef\x문제는 할당(예: )이 포함되어 있기 때문에 \ME@decorations살아남지 못한다 는 것입니다 .\edef\pgfmathtruncatemacro

그건 그렇고, 또한 {\begin{figure*}[htbp]}잘못되어 {\end{figure*}}\lstset따라갈 수 있으므로 \begin{figure*}주변이 불필요해 \begingroup집니다 \endgroup.

다음은 수정된(및 형식이 변경된) 버전입니다.

\documentclass{book}
\usepackage{xcolor}
\usepackage{xkeyval}
\usepackage{listings}
\usepackage{tikz}   
\usetikzlibrary{
  shapes,
  positioning,
  arrows,
  fit,
  backgrounds,
  calc,
  tikzmark,
  shadows,
}

\definecolor{ForestGreen}{rgb}{0.0, 0.4, 0.0}
\definecolor{burntorange}{rgb}{0.8, 0.33, 0.0}
\newlength{\mywidth} % Used in defining listing width
\definecolor{ivory}{rgb}{1.0, 1.0, 0.94}
\colorlet{SeparatorColor}{burntorange}

\makeatletter
\define@key{MEMacros}{decorations}{\def\ME@decorations{#1}}
\define@key{MEMacros}{language}{\def\ME@language{#1}}
\define@key{MEMacros}{number}{\def\ME@number{#1}}
\presetkeys{MEMacros}{number=1}{}%
\makeatother

%%Usage \MESourceFile[keys]{source file}{caption}{label}
\makeatletter
\newcommand\MESourceFile[4][]{%
  \setkeys{MEMacros}{%
    %language={[ANSI]C},%
    decorations={},%
    #1%
  }%
  \begin{figure*}[h!btp]
  \lstset{language={[ANSI]C}}
  \caption{#3}
  \lstinputlisting[label=#4, name=#4]{#2}%
  \ME@decorations % Decorating comments
  \end{figure*}
}
%% Prepare for some decorations on the listing files
\newif\iflst@linemark

\lst@AddToHook{EveryLine}{%
  \begingroup
  \advance\c@lstnumber by \@ne
  \pgfmark{line-\lst@name-\the\c@lstnumber-start}%
  \endgroup
}

\lst@AddToHook{EOL}{%
  \pgfmark{line-\lst@name-\the\c@lstnumber-end}%
  \global\lst@linemarktrue
}

\lst@AddToHook{OutputBox}{%
  \iflst@linemark
    \pgfmark{line-\lst@name-\the\c@lstnumber-first}%
    \global\lst@linemarkfalse
  \fi
}

\def\tkzlst@fnum#1\relax#2\@STOP{%
  \def\@test{#2}%
  \ifx\@test\@empty
    \def\tkzlst@start{0}%
  \else
    \@tempcnta=#1\relax
    \advance\@tempcnta by \m@ne
    \def\tkzlst@start{\the\@tempcnta}%
  \fi
}

\lst@AddToHook{Init}{%
  \expandafter\tkzlst@fnum\lst@firstnumber\relax\@STOP
  \pgfmark{line-\lst@name-\tkzlst@start-start}%
}

%% Put a balloon around some lines in a source
% Usage: \MEHighlightLines{BallonName}{SourceName}{FirstLine}{LastLine}
\newcommand\MEHighlightLines[4]{%
  \pgfmathtruncatemacro\pgf@temp{#3-1}%
  \iftikzmark{line-#2-\pgf@temp-start}
    {%
     \iftikzmark{line-#2-#3-first}
       {%
        \xdef\b@lines{({pic cs:line-#2-\pgf@temp-start} -| {pic cs:line-#2-#3-first})}%
       }
       {%
        \iftikzmark{line-#2-#3-start}
          {%
           \xdef\b@lines{({pic cs:line-#2-\pgf@temp-start} -| {pic cs:line-#2-#3-start})}%
          }
          {%
           \xdef\b@lines{(pic cs:line-#2-\pgf@temp-start)}
          }%
       }%
    }
    {%
     \xdef\b@lines{}%
    }%
  \foreach \k in {#3,...,#4} {%
     \iftikzmark{line-#2-\k-first}
       {%
         \xdef\b@lines{\b@lines (pic cs:line-#2-\k-first) }
       }
       {}%
       \iftikzmark{line-#2-\k-end}
         {%
          \xdef\b@lines{\b@lines (pic cs:line-#2-\k-end) }
         }
         {}%
  }%
  \ifx\b@lines\pgfutil@empty
  \else
    \edef\pgf@temp{%
      \noexpand\tikz[remember picture,overlay]
      \noexpand\node[
        fit={\b@lines}, color=ForestGreen,yshift=-2pt,
        draw, fill=green!30, opacity=0.4,  inner sep=1pt, rounded corners=5pt
      ] (#1) {};
    }%
    \pgf@temp
  \fi
}
\makeatother

\begin{document}

\MESourceFile[%
  decorations={
    \MEHighlightLines{HelloWorldsystem}{lst:HelloWorld.c}{1}{3}
  }%
]{HelloWorld.c}{Hello world}{lst:HelloWorld.c}

\end{document}

여기에 이미지 설명을 입력하세요

관련 정보