4

I need some options of the listings package several times in my document. I am thus wondering if one can define (and later change) these options once somewhere in the preamble via a command/macro, for example, and use the command/macro later on if required? I tried the keyval package, but wasn't successful.

\documentclass{scrartcl}

\usepackage[T1]{fontenc}
\usepackage{lmodern}
\usepackage[american]{babel}
\usepackage{xcolor}
\usepackage{listings}
\usepackage{keyval}
\usepackage{filecontents}

% write dummy R file
\begin{filecontents*}{foo.R}
f <- function(x){
  t <- exp(-x) # just some dummy example
  sqrt(t) # return value
}
\end{filecontents*}

% general listings settings
\lstset{
  language=R,
  basicstyle=\ttfamily\small,
  keywords={if, else, repeat, while, function, for, in, next, break},
  otherkeywords={}
}

% define my own listings settings which frequently appear
\newcommand{\mylstset}{\setkeys{keywordstyle=\color{blue}, commentstyle=\itshape\color{red}}}

% specific listing environment
\xdefinecolor{blue}{RGB}{58, 95, 205}%
\xdefinecolor{red}{RGB}{178, 34, 34}%
\lstnewenvironment{Rinput}[1][]{%
  \lstset{\mylstset}% my listings settings
  #1% content
}{}

\begin{document}
Show \texttt{foo.R}:
\lstinputlisting[\mylstset]{foo.R}% my listings settings
\end{document}
8
  • It should work if you define the command without the \setkeys (\newcommand{\mylstset}{keywordstyle=\color{blue}, commentstyle=\itshape\color{red}}) and expand them first \expandafter\lstinputlisting\expandafter[\mylstset]{foo.R}
    – cgnieder
    Commented Nov 21, 2012 at 11:23
  • Thanks. Is there a solution which does not require the wrap-around of \lstinputlisting with \expandafter? Ideally, the call of \lstinputlisting should not be changed (by having to add \expandafter commands) Commented Nov 21, 2012 at 12:10
  • Yes, it should be possible to define a wrapper for \lstinputlisting that does the expansion for you. Try \newcommand\myinputlisting[1][]{\expandafter\lstinputlisting\expandafter[#1]} and then use \myinputlisting[\mylstset]{foo.R}
    – cgnieder
    Commented Nov 21, 2012 at 12:19
  • Thanks a lot. I tried to use your suggestion with \renewcommand\lstinputlisting..., but LaTeX hangs during compilation. Do you know why? Again, I would like to not change the actual call of \lstinputlisting since I don't want to change the code which is already working (it's a bit complicated to explain but basically a compatibility issue of several people working together). Commented Nov 21, 2012 at 13:24
  • 1
    You cannot redefine \lstinputlistingusing itself in the definition (that causes an infinite loop). You can try \let\myinputlisting\lstinputlisting \renewcommand\lstinputlisting[1][]{\expandafter\myinputlisting\expandafter[#1]} (that might or might not work. I cannot test until tonight)
    – cgnieder
    Commented Nov 21, 2012 at 13:45

1 Answer 1

5

Summarizing my comments in an answer:

First thing is to define the custom setting without \setkeys as a simple list of key/value pairs:

\newcommand*\mylstset{keywordstyle=\color{blue}, commentstyle=\itshape\color{red}}

Now, the main problem is, that this macro needs to be expanded once before fed to \lstinputlisting:

\expandafter\lstinputlisting\expandafter[\mylstset]{foo.R}

As this is tedious (and is not too good a style in the document body, anyway) when one has to do it more often it might be convenient to define a wrapper for this:

\newcommand\myinputlisting[1][]{\expandafter\lstinputlisting\expandafter[#1]}

Now one can use it as follows:

\myinputlisting[\mylstset,otherkey=...]{foo.R}

It should be noted, that \mylstset must be the first entry in the key/value list otherwise it won't be expanded first.

Since the requirement is not to use a custom command but the original syntax one needs to redefine \lstinputlisting. For this its definition needs to be saved first and can then be used in the redefinition:

% save original definition of \lstinputlisting:
\let\origlstinputlisting\lstinputlisting
% renew definition of \lstinputlisting:
\renewcommand\lstinputlisting[1][]{\expandafter\origlstinputlisting\expandafter[#1]}

This works but it should be noted that this kind of redefinition can fail with commands that have optional arguments. A safer way is to use \LetLtxMacro (from the letltxmacro package) instead of \let.

All in all there is a better way, imho: define a custom style and use it via the style option:

% preamble:
\lstdefinestyle{mystyle}{keywordstyle=\color{blue}, commentstyle=\itshape\color{red}}
% document
\lstinputlisting[style=mystyle]{foo.R}
0

You must log in to answer this question.

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