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'm attempting to create a language definition in the listings package that mimics exactly the syntax highlighting in POV-Ray 3.6 for Windows (http://www.povray.org/download/). Here is a screenshot from POV, which I'm trying to imitate:

correct syntax highlighting

(The POV language definition in the listings package is not the same.)

I include below my attempt so far, but it has some flaws. First, I cannot get it to make numbers green, despite my attempt. Second, I cannot get it to make angle brackets (or other operators) red, despite my attempts. By contrast, my attempt to get curly braces to show up blue works fine, despite its similarity to the angle brackets problem/solution. I am obviously doing something wrong, but reading the reference manual for the listings package didn't clear up my confusion.

Here's an example of my wrong results:

incorrect syntax highlighting

Any tips?

\documentclass[12pt]{article}

\usepackage{listings}
\usepackage{color}

\definecolor{povcodered}{rgb}{0.75,0.25,0.25}
\definecolor{povcodegreen}{rgb}{0.25,0.75,0.25}
\definecolor{povcodeblue}{rgb}{0.25,0.25,0.75}
\definecolor{povcodepurple}{rgb}{0.5,0,0.35}
\definecolor{povcodebluegreen}{rgb}{0,0.5,0.5}

\lstdefinelanguage{myPOV}{
    alsoletter={\#\{\}\<\>},
    keywords={
        sphere, cone, and, so, on,
        \#include, \#declare, \#version},
    keywords={[2]\{,\}},
    keywords={[3]\<,\>},
    sensitive=true,
    string=[b]{"},
    comment=[l]{//},
    morecomment=[s]{/*}{*/}}

\lstset{language=myPOV,
    basicstyle=\ttfamily\bfseries,
    keywordstyle=\color{povcodepurple},
    keywordstyle=[2]\color{povcodeblue},
    keywordstyle=[3]\color{povcodered},
    stringstyle=\color{povcodered},
    commentstyle=\color{povcodegreen},
    numberstyle=\color{povcodebluegreen}}

\begin{document}

\begin{lstlisting}
#include "somefile.inc"
// now let's add a shape
sphere {
  <0,0,0>, 1
  translate <5,3,2>
}
\end{lstlisting}

\end{document}
share|improve this question
    
Welcome to TeX.sx! Usually, we don't put a greeting or a "thank you" in our posts. While this might seem strange at first, it is not a sign of lack of politeness, but rather part of our trying to keep everything very concise. Upvoting is the preferred way here to say "thank you" to users who helped you. –  Kurt Nov 13 '12 at 19:25
2  
While code snippets are useful in explanations, it is always best to compose a fully compilable MWE that illustrates the problem including the \documentclass and the appropriate packages so that those trying to help don't have to recreate it. While solving problems is fun, setting them up is not. Then those trying to help can simply cut and paste your MWE and get started on solving problem. –  Peter Grill Nov 13 '12 at 19:33
    
Also, please use a supported image format, and provide the correct and incorrect image for the same code snippet so it is easier to compare (and include the code snippet in your MWE). You should edit your question and upload the pictures using the picture icon button, and remove the !. Then other higher rep users here can simply remove the ! and you image will show up. –  Peter Grill Nov 13 '12 at 19:38
    
I've made edits in accordance with these directions. Feel free to put the exclamation points back in. Thanks! –  Nathan Nov 14 '12 at 16:12

2 Answers 2

up vote 2 down vote accepted

Based on your self-answer, it seems you're almost there. The last remaining problem is to highlight / and // differently and make sure // starts a comment.

How to highlight / and // differently (without breaking comments)

As you've noticed, any literate replacement of / will prevent you from using it in a comment delimiter; therefore, you have to resort to other means than a literate replacement of /. The approach shown in the code below solves the problem.

Caveat: if // is immediately preceded by a character that listings treats as "other" (for instance, *//), // will still start a comment but it won't be highlighted in comment style.

Side note: don't define { and } as "letters"

Defining { and } as "letters" via

alsoletter = {\{\}},

is a bad idea, at least in your case. Here is an example of where it could go wrong: listings, if it encounters the sequence of characters sphere{ (note the absence of space between sphere and {), would recognise it as a single identifier; the sphere part would not be recognised as a keyword and would therefore not be get highlighted as such. Here, literate replacements of { and } are preferable.

enter image description here

\documentclass{article}

\usepackage[T1]{fontenc} %<--- for nice braces in typewriter font
\usepackage{lmodern}
\usepackage{listings}
\usepackage{xcolor}


\lstdefinelanguage{myPOVlanguage}
{
  alsoletter  = {\#},
  keywords    =
  {
    \#include, \#declare, \#version,
    assumed_gamma,
    background, box,
    camera, color, color_map, cone, cylinder,
    direction,
    function,
    global_settings, gradient,
    light_source, location, look_at,
    matrix,
    no_shadow,
    object,
    pigment, pow,
    rgb, right, rotate,
    scale, sphere,
    translate, 
    x, y, z,        
  },
  sensitive   = true,
  string      = [b]{"},
  comment     = [l]{//},
  morecomment = [s]{/*}{*/},
}

% --- color definitions ---
\definecolor{povcodered}{rgb}{0.75,0.25,0.25}
\definecolor{povcodegreen}{rgb}{0.25,0.75,0.25}
\definecolor{povcodeblue}{rgb}{0.25,0.25,0.75}
\definecolor{povcodepurple}{rgb}{0.5,0,0.35}
\definecolor{povcodebluegreen}{rgb}{0,0.5,0.5}

\lstdefinestyle{myPOVstyle}
{
  language           = myPOVlanguage,
  frame              = single,
  framextopmargin    = 3mm,
  framexbottommargin = 3mm,
  basicstyle         = \ttfamily\bfseries,
  keywordstyle       = \color{povcodepurple},
  stringstyle        = \color{povcodered},
  commentstyle       = \color{povcodegreen}\itshape,
  literate =*
    {0}{{{\color{povcodebluegreen}0}}}1
    {1}{{{\color{povcodebluegreen}1}}}1
    {2}{{{\color{povcodebluegreen}2}}}1
    {3}{{{\color{povcodebluegreen}3}}}1
    {4}{{{\color{povcodebluegreen}4}}}1
    {5}{{{\color{povcodebluegreen}5}}}1
    {6}{{{\color{povcodebluegreen}6}}}1
    {7}{{{\color{povcodebluegreen}7}}}1
    {8}{{{\color{povcodebluegreen}8}}}1
    {9}{{{\color{povcodebluegreen}9}}}1
    {+}{{{\color{povcodered}+}}}1
    {-}{{{\color{povcodered}-}}}1
    {*}{{{\color{povcodered}*}}}1
    {<}{{{\color{povcodered}<}}}1
    {>}{{{\color{povcodered}>}}}1
    {\{}{{{\color{povcodeblue}\{}}}1
    {\}}{{{\color{povcodeblue}\}}}}1
}

% --- patch to get proper highlighting of / and // ---
\makeatletter
\lst@AddToHook{OutputOther}
{%
  \edef\@tempa{\the\lst@token\relax}%
  %
  % apply \color{povcodered} if / is found
  \expandafter\expandafter\expandafter\ifx\expandafter\@firstoftwo\@tempa/%
    \def\lst@thestyle{\color{povcodered}}%
    %
    % apply comment style if // is found
    \expandafter\expandafter\expandafter\ifx\expandafter\@secondoftwo\@tempa/%
      \def\lst@thestyle{\lst@commentstyle}%
    \fi  
  \fi
}
\makeatother

\lstset{style=myPOVstyle}

\begin{document}
\begin{lstlisting}
#include "somefile.inc"
// now let's add a shape
sphere {
  <0,0,0>, 1
  translate <5,3,2>

  sdf/sdf
}
\end{lstlisting}
\end{document} 
share|improve this answer
    
This did indeed solve the slash problem, so I'm going to mark it as the correct answer. However, in my document, curly braces render in the normal document's font, not in the ttfamily, as they do in yours. Should I start a separate question for that? Sorry, not sure what the protocol is... –  Nathan Mar 19 at 14:12
    
Did you use \usepackage[T1]{fontenc}? –  Jubobs Mar 19 at 15:04
    
Boy that really proves that I should read the whole solution, doesn't it? Thanks, that (embarrassingly) fixed it! –  Nathan Mar 19 at 20:24
    
@Nathan No problem :) Glad I was able to help. –  Jubobs Mar 19 at 20:25

I think I've mostly answered my own question. By reading some of the other related questions I cobbled together the following POV language definition file that does most of what I want, or at least is extensible enough that it will be able to do most of what I want after it's done evolving.

The essential fix was to use literate in a way that's not really its intended use, but just as a generic mechanism for replacing any character sequence with any other. This allows me to choose specific digits, operators, etc., and assign them colors.

Here is POV code that isn't fully complete (not all operators and keywords) but I'll extend it as I hit new operators and keywords that aren't on this list. You get the idea. The code is below.

The one thing that isn't yet solved by this is that the double-slash for a one-line comment is now treated like two adjacent single-slashes, so there is no such thing as a one-line comment anymore. It seems that literate overrides everything else. That question therefore remains.

\lstdefinelanguage{myPOV}{
    alsoletter={\#\{\}},
    keywords={
        sphere, cone, cylinder, box, object,
        rotate, translate, scale, matrix,
        camera, location, direction, right, look_at,
        pigment, gradient, color_map, color, rgb,
        x, y, z, pow, function,
        light_source, background, no_shadow,
        global_settings, assumed_gamma,
        \#include, \#declare, \#version},
    keywords={[2]\{,\}},
    sensitive=true,
    string=[b]{"},
    comment=[l]{//},
    morecomment=[s]{/*}{*/},
    literate=%
       *{0}{{{\color{povcodebluegreen}0}}}1
        {1}{{{\color{povcodebluegreen}1}}}1
        {2}{{{\color{povcodebluegreen}2}}}1
        {3}{{{\color{povcodebluegreen}3}}}1
        {4}{{{\color{povcodebluegreen}4}}}1
        {5}{{{\color{povcodebluegreen}5}}}1
        {6}{{{\color{povcodebluegreen}6}}}1
        {7}{{{\color{povcodebluegreen}7}}}1
        {8}{{{\color{povcodebluegreen}8}}}1
        {9}{{{\color{povcodebluegreen}9}}}1
        {+}{{{\color{povcodered}+}}}1
        {-}{{{\color{povcodered}-}}}1
        {*}{{{\color{povcodered}*}}}1
        {/}{{{\color{povcodered}/}}}1
        {<}{{{\color{povcodered}<}}}1
        {>}{{{\color{povcodered}>}}}1}

\lstset{language=myPOV, frame=single,
    basicstyle=\ttfamily\bfseries,
    keywordstyle=\color{povcodepurple},
    keywordstyle=[2]\color{povcodeblue},
    stringstyle=\color{povcodered},
    commentstyle=\color{povcodegreen},
    framextopmargin=3mm,
    framexbottommargin=3mm
    }
share|improve this answer
    
Move the definition of comment=[l]{//} behind the assignment of {/}{{{\color{povcodered}/}}}1, i.e. move it behind all literate assignments. A similar case can be found somewhere in the listings documentation. –  Speravir Nov 20 '12 at 21:32
    
@Speravir: This did not make a difference. The literate assignments, even if they are put before the comment= lines, seem to take precedence over them. –  Nathan Nov 21 '12 at 14:20
    
Aah, I forgot, that the comment sign itself is not in markup. But you could include a second literate entry behind the existing one with {//}{{<your wanted formatting>}}2, see in the manual under “Literate Programming”. BTW according to this you have one too many pair of braces in each of your entries. And add this into the answer! –  Speravir Nov 21 '12 at 18:22
    
And: What I’ve overread in the manual until now: “The optional star indicates that literate replacements should not be made in strings, comments, and other delimited text.”, a reminder there would be useful, that this does not apply to the comment/string/delimiter signs themselves (--> kind of bug report). –  Speravir Nov 21 '12 at 18:27

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.