Take the 2-minute tour ×
TeX - LaTeX Stack Exchange is a question and answer site for users of TeX, LaTeX, ConTeXt, and related typesetting systems. It's 100% free, no registration required.

While trying to provide an answer to this question, I've run into a stumbling block that I can't seem to get over. The listings package (like many others) uses keyval to handle configuration. What should be done if part of that configuration is a macro that must be expanded prior?

All (admittedly semirandom) configurations of \expandafter produce some sort of error or another. The closest I got was getting an error that complained about the fact that TeX was encountering text (keys) before \begin{document}.

Is there any way to get around this?

MWE

\documentclass[a4paper, 12pt,english]{article}
\usepackage{color,forloop}
\definecolor{gray}{rgb}{0.4,0.4,0.4}
\definecolor{darkgreen}{rgb}{0.0,0.4,0.0}
\definecolor{darkred}{rgb}{0.6,0.0,0.0}

\newcounter{ct}
\newcommand{\lstkeygenr}{%
  \forloop{ct}{0}{\value{ct} < 50}{%
    r\arabic{ct},
  }
}

\usepackage{listings}
\lstdefinelanguage{mylanguage}
                  {keywords=[1]{add,sub,test},
                   keywords=[2]{r0,r1,r2,\lstkeygenr},
                   keywords=[3]{p00,p01,p10,p11},
                   moredelim=[s][\footnotesize\textit]{<}{>},
                   keywordstyle=[1]\normalsize\color{gray}\bfseries\ttfamily,
                   keywordstyle=[2]\color{red},
                   keywordstyle=[3]\color{darkred}}

\begin{document}

\lstset{numbers=left, numberstyle=\tiny, stepnumber=1, numbersep=5pt,language=mylanguage}
\begin{lstlisting}
  p00 add r0 , r1 , r2 , r3 , r4
\end{lstlisting}

\end{document}
share|improve this question

1 Answer 1

up vote 6 down vote accepted

You don't want to pass a macro with a loop in as the key value, you want to pass in a list generated by such a loop, so you need to invert your calling order:

enter image description here

\documentclass[a4paper, 12pt,english]{article}
\usepackage{color,forloop}
\definecolor{gray}{rgb}{0.4,0.4,0.4}
\definecolor{darkgreen}{rgb}{0.0,0.4,0.0}
\definecolor{darkred}{rgb}{0.6,0.0,0.0}

\newcounter{ct}
\makeatletter
\def\rlist{\@gobble}
\forloop{ct}{0}{\value{ct} < 50}{%
    \edef\rlist{\rlist,r\arabic{ct}}
  }

\makeatother
\def\listwithrs#1\relax{%
\lstdefinelanguage{mylanguage}
                  {keywords=[1]{add,sub,test},
                   keywords=[2]{#1},
                   keywords=[3]{p00,p01,p10,p11},
                   moredelim=[s][\footnotesize\textit]{<}{>},
                   keywordstyle=[1]\normalsize\color{gray}\bfseries\ttfamily,
                   keywordstyle=[2]\color{red},
                   keywordstyle=[3]\color{darkred}}}

\usepackage{listings}
\expandafter\listwithrs\rlist\relax

\begin{document}

\lstset{numbers=left, numberstyle=\tiny, stepnumber=1, numbersep=5pt,language=mylanguage}
\begin{lstlisting}
  p00 add r0 , r1 , r2 , r3 , r4
\end{lstlisting}

\end{document}

as requested a versuion defining xlist instead of rlist that takes a macro defining the prefix letter (so \xlist r is same as the original \rlist)

\documentclass[a4paper, 12pt,english]{article}
\usepackage{color,forloop}
\definecolor{gray}{rgb}{0.4,0.4,0.4}
\definecolor{darkgreen}{rgb}{0.0,0.4,0.0}
\definecolor{darkred}{rgb}{0.6,0.0,0.0}

\newcounter{ct}
\makeatletter
\def\xxlist{\@gobble}
\let\xhash\relax
\forloop{ct}{0}{\value{ct} < 50}{%
    \edef\xxlist{\xxlist,\xhash1\arabic{ct}}
  }
\let\xhash#
\expandafter\def\expandafter\xlist\expandafter#\expandafter1\expandafter{\xxlist}

\typeout{^^J\string\xlist^^J\meaning\xlist}

\makeatother
\def\listwithrs#1\relax{%
\lstdefinelanguage{mylanguage}
                  {keywords=[1]{add,sub,test},
                   keywords=[2]{#1},
                   keywords=[3]{p00,p01,p10,p11},
                   moredelim=[s][\footnotesize\textit]{<}{>},
                   keywordstyle=[1]\normalsize\color{gray}\bfseries\ttfamily,
                   keywordstyle=[2]\color{red},
                   keywordstyle=[3]\color{darkred}}}

\usepackage{listings}

\expandafter\listwithrs\xlist r\relax

\begin{document}

\lstset{numbers=left, numberstyle=\tiny, stepnumber=1, numbersep=5pt,language=mylanguage}
\begin{lstlisting}
  p00 add r0 , r1 , r2 , r3 , r4
\end{lstlisting}

\end{document}
share|improve this answer
    
What's that \@gobble business? –  Sean Allred Feb 26 '13 at 19:55
    
@vermiculus \@gobble is defined in latex by \def\@gobble#1{} so it throws away its argument, in this case the argument is the , before the first real item, saves testing for the first one and not putting the comma in. –  David Carlisle Feb 26 '13 at 19:57
    
Is there any way to make this solution (namely \rlist) take an a prefix argument (r1, r2 ... r50 vs. p01,p02,...p50), or would it make things drastically more complicated? Just curious; I don't think the original asker needs that. –  Sean Allred Feb 26 '13 at 20:01
    
@vermiculus answer updated –  David Carlisle Feb 26 '13 at 20:41
    
I'll have to remember \typeout. Also, this is so cool! Thanks for updating! –  Sean Allred Feb 26 '13 at 20:50

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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