2

I still have some problems with parameter passing in my macros. The MWE below, compiles and runs fine. If you uncomment wide, it mismatches \begin{figure*} with \end{figure}. However, this error goes away, if you comment out also line with \MEListBalls. Without \MEListBalls, it works fine with and without wide.

A related question: how can I pass option like 'backgroundcolor=\color{black}'? Simple texts can be passed easily.

\documentclass{memoir}

\def\LecturePrintable{Book}             % It is a kind of printable format 
\def\MayFloat{YES}                          % Some environments are allowed to float
\def\lstsize{\scriptsize}

\usepackage[T1]{fontenc}
\usepackage[utf8]{inputenc}
\usepackage{xcolor}
\usepackage{xkeyval}    % Allow to use key-value pairs in arguments of macros
\usepackage{listingsutf8}   % Use program listings
    \usepackage{etoolbox}       % Utility package, mainly for packet 

    \usepackage[english,magyar]{babel}
    \definecolor{ForestGreen}{rgb}{0.0, 0.4, 0.0}
        \colorlet{HeadingColor}{ForestGreen}

\makeatletter
    \define@key{MEMacros}{color}{\def\ME@color{#1}}
    \define@key{MEMacros}{decorations}{\def\ME@decorations{#1}}
    \define@key{MEMacros}{language}{\def\ME@language{#1}}
    \define@key{MEMacros}{number}{\def\ME@number{#1}}
    \define@key{MEMacros}{options}{\def\ME@options{#1}}
    \define@key{MEMacros}{wide}[true]{\def\ME@wide{#1}}
    \presetkeys{MEMacros}{color=green}{}%
    \presetkeys{MEMacros}{number=1}{}%
    \presetkeys{MEMacros}{wide=false}{}%
%%%Usage \MESourceFile[keys]{source file}{caption}{label}
\makeatletter
%% Insert a source file in the text, with optional decorations
%%%Usage \MESourceFile[keys]{source file}{caption}{label}
\newcommand\MESourceFile[4][]{
    \setkeys{MEMacros}{wide=false,language={[ANSI]C},options={}, decorations={},#1}% 
    % % Define the environment: a 'Program' if it might float, a simple caption if not
    \ifx\MayFloat\undefined
        \vskip.2\baselineskip\color{HeadingColor}\bfseries\scriptsize #3\par\vskip\baselineskip
    \else
        \expandafter\ifstrequal\expandafter{\ME@wide}{true}
            {\begin{figure*}[h!btp] }
            {\begin{figure}[h!btp] }
    \fi
        \mbox{}\phantomsection
        \lstset{language=C,keywordstyle=\bfseries\color{magenta}}
        \ifx\MayFloat\undefined\else\caption{#3}\fi \vglue-.7\baselineskip
        \begingroup\edef\x{\endgroup\noexpand
            \lstinputlisting[language={\ME@language},\ME@options,label=#4, name=#4]{#2}}
        \x
        \ME@decorations % Decorating comments
    \ifx\MayFloat\undefined % nothing needed
    \else
        \expandafter\ifstrequal\expandafter{\ME@wide}{true}
            {\end{figure*}}
            {\end{figure}}
    \fi
}
\makeatother

\makeatletter
% % Put numbered balls after the line 'Lineno'  in source 'Source'
% Usage: \MEListBalls{ListingLabel}{List of lines}
\newcounter{qan}\newcounter{qano}
\newcommand\MEListBalls[3][]{%
    \setkeys{MEMacros}{color=orange,#1}% 
    \setkeys{MEMacros}{number=1,#1}% 
    \setcounter{qan}{\ME@number}
    \setcounter{qano}{0}
%   \begingroup%
    \foreach \x in {#3}
    {   
      \addtocounter{qano}{1}
    %   \only<\arabic{qano}>%
        {\tikz[remember picture,overlay]
            {\expandafter\node[circle, inner sep=2pt, draw,fill=\ME@color,ball color=\ME@color, shading=ball, font=\scriptsize\bfseries, drop shadow]
                at  ([xshift=+10pt,yshift=+2pt]{pic cs:line-#2-\x-end}) {\lstsize\arabic{qan}};\expandafter}}
      \addtocounter{qan}{1}
    }
%   \endgroup
}
\usepackage{float}      % For custom floats

\usepackage{tikz}   
\usetikzlibrary{
    calc,
    tikzmark,
    shadows,
}

\begin{document}

        \MESourceFile[language={[ANSI]C},
%       wide,
%       options={backgroundcolor=\color{black}}, 
        decorations={
            \MEListBalls{lst:HelloWorld.c}{3,1,4}
        }
        ]{HelloWorld.c}{Az egyszerű parancs értelmező }{lst:HelloWorld.c}

\end{document}

#include <stdio.h>

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

2 Answers 2

2

Here's one possible solution: Define macros \startsource and \stopsource which take on the values associated with your choices. This way you can specify a single block to import the listing.

\makeatletter
\define@key{MEMacros}{color}{\def\ME@color{#1}}
\define@key{MEMacros}{decorations}{\def\ME@decorations{#1}}
\define@key{MEMacros}{language}{\def\ME@language{#1}}
\define@key{MEMacros}{number}{\def\ME@number{#1}}
\define@key{MEMacros}{options}{\def\ME@options{#1}}
\define@boolkey{MEMacros}{wide}[true]{\def\ME@wide{#1}}
\presetkeys{MEMacros}{color=green}{}%
\presetkeys{MEMacros}{number=1}{}%
\presetkeys{MEMacros}{wide=false}{}%
%%%Usage \MESourceFile[keys]{source file}{caption}{label}

%% Insert a source file in the text, with optional decorations
%%%Usage \MESourceFile[keys]{source file}{caption}{label}
\newcommand\MESourceFile[4][]{
  \setkeys{MEMacros}{wide=false,language={[ANSI]C},options={}, decorations={},#1}% 
  % % Define the environment: a 'Program' if it might float, a simple caption if not
  \ifx\MayFloat\undefined
    \def\startsource{\vskip.2\baselineskip\color{HeadingColor}\bfseries\scriptsize #3\par\vskip\baselineskip}
    \def\stopsource{}
  \else
    \ifKV@MEMacros@wide
      \def\startsource{\begin{figure*}[h!btp]}
      \def\stopsource{\end{figure*}}
    \else
      \def\startsource{\begin{figure}[h!btp]}
      \def\stopsource{\end{figure}}
    \fi
  \fi
  \startsource
    \mbox{}\phantomsection
    \lstset{language=C,keywordstyle=\bfseries\color{magenta}}
    \ifx\MayFloat\undefined\else\caption{#3}\fi \vglue-.7\baselineskip
    \begingroup\edef\x{\endgroup\noexpand
        \lstinputlisting[language={\ME@language},\ME@options,label=#4, name=#4]{#2}}
    \x
    \ME@decorations % Decorating comments
  \stopsource
}
\makeatother

Since you're using xkeyval which offers "boolean keys", I've used \ifKV@MEMacros@wide <true>\else <false>\fi as a condition rather than the more cumbersome \expandafter\ifstrequal\expandafter{\ME@wide}{true}{<true>}{<false>}.

1
  • I was just about to post a similar but won't now, so just to comment that the reason the original failed is the ME@wide got set back to false by the inner calls to \setkeys as this is declared as a predefined key with default false. May 27, 2015 at 20:55
1

You should use a boolean key, rather than the \ifstrequal test; with

\define@boolkey{MEMacros}{wide}[true]{}

the conditional \ifKV@MEMacros@wide is set up; using wide in the option is equivalent to wide=true. Important: don't “preset” this key.

For options, pass it to \lstset:

\expandafter\lstset\expandafter{\ME@options}

This works because you have as many \lstset commands as you want.

\documentclass{memoir}

\def\LecturePrintable{Book}             % It is a kind of printable format 
\def\MayFloat{YES}                          % Some environments are allowed to float
\def\lstsize{\scriptsize}

\usepackage[T1]{fontenc}
\usepackage[utf8]{inputenc}
\usepackage{xcolor}
\usepackage{xkeyval}    % Allow to use key-value pairs in arguments of macros
\usepackage{listingsutf8}   % Use program listings
    \usepackage{etoolbox}       % Utility package, mainly for packet 

    \usepackage[english,magyar]{babel}
    \definecolor{ForestGreen}{rgb}{0.0, 0.4, 0.0}
        \colorlet{HeadingColor}{ForestGreen}

\makeatletter
    \define@key{MEMacros}{color}{\def\ME@color{#1}}
    \define@key{MEMacros}{decorations}{\def\ME@decorations{#1}}
    \define@key{MEMacros}{language}{\def\ME@language{#1}}
    \define@key{MEMacros}{number}{\def\ME@number{#1}}
    \define@key{MEMacros}{options}{\def\ME@options{#1}}
    \define@boolkey{MEMacros}{wide}[true]{}
    \presetkeys{MEMacros}{color=green}{}%
    \presetkeys{MEMacros}{number=1}{}%
%%%Usage \MESourceFile[keys]{source file}{caption}{label}
\makeatletter
%% Insert a source file in the text, with optional decorations
%%%Usage \MESourceFile[keys]{source file}{caption}{label}
\newcommand\MESourceFile[4][]{%
    \setkeys{MEMacros}{wide=false,language={[ANSI]C},options={}, decorations={},#1}% 
    % % Define the environment: a 'Program' if it might float, a simple caption if not
    \ifx\MayFloat\undefined
        \vskip.2\baselineskip\color{HeadingColor}\bfseries\scriptsize #3\par\vskip\baselineskip
    \else
      \ifKV@MEMacros@wide
        \begin{figure*}[h!btp]
      \else
        \begin{figure}[h!btp]
      \fi
    \fi
        \mbox{}\phantomsection
        \lstset{language=C,keywordstyle=\bfseries\color{magenta}}
        \expandafter\lstset\expandafter{\ME@options}
        \ifx\MayFloat\undefined\else\caption{#3}\fi \vglue-.7\baselineskip
        \begingroup\edef\x{\endgroup\noexpand
            \lstinputlisting[language={\ME@language},label=#4, name=#4]{#2}}
        \x
        \ME@decorations % Decorating comments
    \ifx\MayFloat\undefined % nothing needed
    \else
      \ifKV@MEMacros@wide
        \end{figure*}
      \else
        \end{figure}
      \fi
    \fi
}
\makeatother

\makeatletter
% % Put numbered balls after the line 'Lineno'  in source 'Source'
% Usage: \MEListBalls{ListingLabel}{List of lines}
\newcounter{qan}\newcounter{qano}
\newcommand\MEListBalls[3][]{%
    \setkeys{MEMacros}{color=orange,#1}% 
    \setkeys{MEMacros}{number=1,#1}% 
    \setcounter{qan}{\ME@number}
    \setcounter{qano}{0}
%   \begingroup%
    \foreach \x in {#3}
    {   
      \addtocounter{qano}{1}
    %   \only<\arabic{qano}>%
        {\tikz[remember picture,overlay]
            {\expandafter\node[circle, inner sep=2pt, draw,fill=\ME@color,ball color=\ME@color, shading=ball, font=\scriptsize\bfseries, drop shadow]
                at  ([xshift=+10pt,yshift=+2pt]{pic cs:line-#2-\x-end}) {\lstsize\arabic{qan}};\expandafter}}
      \addtocounter{qan}{1}
    }
%   \endgroup
}
\usepackage{float}      % For custom floats

\usepackage{tikz}   
\usetikzlibrary{
    calc,
    tikzmark,
    shadows,
}

\begin{document}

        \MESourceFile[language={[ANSI]C},
       wide,
       options={backgroundcolor=\color{gray!10}}, 
        decorations={
            \MEListBalls{lst:HelloWorld.c}{3,1,4}
        }
        ]{HelloWorld.c}{Az egyszerű parancs értelmező }{lst:HelloWorld.c}

\end{document}

#include <stdio.h>

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

enter image description here

I used options=\color{gray!10} because black will give a very ugly result.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.