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 中擴展我傳遞的巨集的某個地方。 (裝飾必須與清單保持在一起,因此我將它們強制放在圖中。也歡迎替代實作想法(作為解決方法),但最好的方法是修復巨集擴展錯誤。)

答案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}

在此輸入影像描述

相關內容