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.

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}
share|improve this question
    
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 Nov 21 '12 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) –  Marius Hofert Nov 21 '12 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 Nov 21 '12 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). –  Marius Hofert Nov 21 '12 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 Nov 21 '12 at 13:45
show 3 more comments

1 Answer

up vote 5 down vote accepted

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}
share|improve this answer
    
Thanks a lot. Cheers, Marius. –  Marius Hofert Nov 22 '12 at 11:42
add comment

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.