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.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .