7

I would like to add more keywords to an existing language definition so that when I use \begin{lstlisting} ... \end{lstlisting}, the new keywords are highlighted along with the predefined ones.

This question has been asked many times but I've found that none of the solutions work.

Let's review some of the previous work:

  1. At this question, the selected answer was to either define a new language, or define a new style for the language. But I don't want to define a new language or style. I want to add keywords to an existing language, using the existing styling.

  2. At this other question, marked duplicate, the comment was made to use \lstset{language=Lisp, morekeywords={define}}, which doesn't work (for me). One commenter told the OP to refer to section 3.2 of the manual, which doesn't actually say anything about modifying existing language definitions.

  3. At yet another question, the solution was to not set the keywords but just tell the listings package to emphasize the new list of words, which means you have to duplicate the style for emphasis with the style for keywords.

If any of these solutions is in fact the correct one and it just isn't working for me, then please help me point out what it is that I'm doing wrong. Here is my MWE:

\documentclass{article}
\usepackage{listings}
\begin{document}
Listing 1:
\begin{lstlisting}[language=Haskell, morekeywords={fix}]
fibs = fix ((0:) . scanl (+) 1)
\end{lstlisting}    
Listing 2:
\begin{lstlisting}[language=Haskell]
fibs = fix ((0:) . scanl (+) 1)
\end{lstlisting}
\end{document}

If you process this document, you'll find that the first listing has fix highlighted and the second listing doesn't, because fix is not in the list of predefined keywords. Using morekeywords adds it for that one listing.

enter image description here

I thought adding the following in the preamble (immediately above \begin{document}) would make it apply to all listings, but it doesn't. The output is identical to the output above.

  \lstset{language=Haskell, morekeywords={fix}}

You'll notice this is the same as the recommendation in the second question I referenced above.

How do you do this globally for all listings?

7

Why morekeywords doesn't seem to work

Your question stems from a misunderstanding of the morekeywords key. Contrary to what you think, writing

\lstset{language=Haskell, morekeywords={fix}}

does not alter the definition of listings' Haskell language. That's why the fix identifier is not highlighted in your second listing.

How to modify an existing language

The listings does not provide a mechanism for "renewing" or modifying an existing language. Of the three approaches you mention, the first one makes the most sense. Note that you don't have to redefine a language from scratch; you can simply define a custom language based on the existing one with your modifications,

\lstdefinelanguage{Haskellana}{%
  language     = Haskell,
  morekeywords = {fix},
}

and then invoke it where needed in place of the original language:

\documentclass{article}

\usepackage{listings}
\lstdefinelanguage{Haskellana}{
  language     = Haskell,
  morekeywords = {fix},
}

\begin{document}
Listing 1:
\begin{lstlisting}[language=Haskellana]
fibs = fix ((0:) . scanl (+) 1)
\end{lstlisting}
Listing 2:
\begin{lstlisting}[language=Haskellana]
fibs = fix ((0:) . scanl (+) 1)
\end{lstlisting}
\end{document}

enter image description here

As a Haskeller, strive for laziness :)

To avoid having to invoke the language for each Haskell listing, I suggest declaring a custom lstlisting environment:

\documentclass{article}

\usepackage{listings}
\lstdefinelanguage{Haskellana}{
  language     = Haskell,
  morekeywords = {fix},
}

\lstnewenvironment{haskellcode}
  {\lstset{language = Haskellana}}
  {}

\begin{document}
Listing 1:
\begin{haskellcode}
fibs = fix ((0:) . scanl (+) 1)
\end{haskellcode}
Listing 2:
\begin{haskellcode}
fibs = fix ((0:) . scanl (+) 1)
\end{haskellcode}
\end{document}
2

I had the same problem. It does not seem to be possible to add keywords to an existing language definition, when you do not always want to explicitly set it before opening a listing (i.e. there is no \lstupdatelanguage equivalent to \lstdefinelanguage).

However, I found it convenient to use the \lstnewenvironment command to define a new environment which adds the additional keywords (in my case 'yield' for Python):

% new environment for Python with the extra keyword 'yield'
\lstnewenvironment{Python}[1][]{\lstset{language=python, morekeywords={yield}, #1}}{}
% this is for using inline Python code with the extra keyword:
\newcommand{\py}{\lstinline[language=python, morekeywords={yield}]}

Using the new commands looks like the following:

% The new environment:
\begin{Python}
code goes here...
\end{Python}

% or inline:
Now the \py|yield| Keyword is also highlighted

Hope this helps

  • 1
    Welcome to TeX.SX! Thanks for answering here and for participating in helping others. It would be nice, if you make your snippet a compilable document as it is best practise here. Thank you. – LaRiFaRi May 19 '15 at 9:08

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.