10

Problem:

The > symbol for HTML tags in the MWE has a different color than the < symbol. Would like to have both the same color.

Minimal Working Example:

\documentclass{scrreprt}
\makeatletter
\usepackage{color}
\definecolor{editorLightGray}{cmyk}{0.05, 0.05, 0.05, 0.1}
\definecolor{editorGray}{cmyk}{0.6, 0.55, 0.55, 0.2}
\definecolor{editorPurple}{cmyk}{0.5, 1, 0, 0}
\definecolor{editorWhite}{cmyk}{0, 0, 0, 0}
\definecolor{editorBlack}{cmyk}{1, 1, 1, 1}
\definecolor{editorOrange}{cmyk}{0, 0.8, 1, 0}
\definecolor{editorBlue}{cmyk}{1, 0.6, 0, 0}
\definecolor{editorPink}{cmyk}{0, 1, 0, 0}
\usepackage{upquote}
\usepackage{listings}
% CSS
\lstdefinelanguage{CSS}{
  keywords={color,background-image:,margin,padding,font,weight,display,position,top,left,right,bottom,list,style,border,size,white,space,min,width, transition:, transform:, transition-property, transition-duration, transition-timing-function}, 
  sensitive=true,
  morecomment=[l]{//},
  morecomment=[s]{/*}{*/},
  morestring=[b]',
  morestring=[b]",
  alsoletter={:},
  alsodigit={-}
}

% JavaScript
\lstdefinelanguage{JavaScript}{
  morekeywords={typeof, new, true, false, catch, function, return, null, catch, switch, var, if, in, while, do, else, case, break},
  morecomment=[s]{/*}{*/},
  morecomment=[l]//,
  morestring=[b]",
  morestring=[b]'
}

\lstdefinelanguage{HTML5}{
  language=html,
  sensitive=true,   
  alsoletter={<>=-+},   
  morecomment=[s]{<!-}{-->},
  tag=[s],
  otherkeywords={
  % General
  % >,
  % Standard tags
    <!DOCTYPE,
  </html, <html, <head, <title, </title, <style, </style, <link, </head, <meta, />,
    % body
    </body, <body,
    % Divs
    </div, <div, </div>, 
    % Paragraphs
    </p, <p, </p>,
    % scripts
    </script, <script,
  % More tags...
  <canvas, /canvas>, <svg, <rect, <animateTransform, </rect>, </svg>, <video, <source, <iframe, </iframe>, </video>, <image, </image>
  },
  ndkeywords={=,
  % General
  +=,
  % HTML attributes
   charset=, src=, id=, width=, height=, style=, type=, rel=, href=,
  % SVG attributes
  fill=, attributeName=, begin=, dur=, from=, to=, poster=, controls=, x=, y=, repeatCount=, xlink:href=,
  % CSS properties
  margin:, padding:, background-image:, border:, top:, left:, position:, width:, height:,
    % CSS3 properties
  transform:, -moz-transform:, -webkit-transform:,
  animation:, -webkit-animation:,
  transition:,  transition-duration:, transition-property:, transition-timing-function:,
  },
}

\lstdefinelanguage{PHP}{
        morestring=[s]{'}{'},
        morestring=[b]",
        sensitive=true,
        keywords=[1]{require_once, try, new, catch, die, echo},
        keywords=[2]{setAttribute, getMessage, PDO, sprintf},
        keywords=[3]{PDOException, PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION, php},
        keywords=[4]{athletics}
}

\lstset{%
  % General design
  backgroundcolor=\color{white},
  basicstyle={\small\ttfamily},   
  frame=l,
  % line-numbers
  xleftmargin={14pt},
  numbers=left,
  stepnumber=1,
  firstnumber=1,
  numberfirstline=true, 
  % Code design
  identifierstyle=\color{editorOrange},
  keywordstyle=[1]\color{editorPink},
  keywordstyle=[2]\color{editorBlue},
  keywordstyle=[3]\color{editorBlack},
  keywordstyle=[4]\color{editorBlue},
  commentstyle=\color{editorGray},
  stringstyle=\color{editorPurple},
  % Code
  language=HTML5,
  alsolanguage=CSS,
  alsolanguage=JavaScript,
  alsolanguage=PHP,
  alsodigit={.:},  
  tabsize=2,
  showtabs=false,
  showspaces=false,
  showstringspaces=false,
  extendedchars=true,
  breaklines=false,
  % German umlauts
  literate=%
  {Ö}{{\"O}}1
  {Ä}{{\"A}}1
  {Ü}{{\"U}}1
  {ß}{{\ss}}1
  {ü}{{\"u}}1
  {ä}{{\"a}}1
  {ö}{{\"o}}1
}

\makeatother
\begin{document}
\begin{lstlisting}
<!DOCTYPE html>
<html>
  <head>
    <title>Listings Style Test</title>
    <meta charset="UTF-8">
    <style>
      /* CSS Test */
      * {
        padding: 0;
        border: 0;
        margin: 0;
      }
    </style>
    <link rel="stylesheet" href="css/style.css" />
  </head>
  <body>
    <!-- Paragraphs are fine -->
    <div id="box">          
            <p>
              Hello World
            </p>
      <p>Hello World</p>
      <p id="test">Hello World</p>
            <p></p>
    </div>
    <div>Test</div>
    <!-- HTML script is not consistent -->
    <script src="js/benchmark.js"></script>
    <script>
      function createSquare(x, y) {
        // This is a comment.
        var square = document.createElement('div');
        square.style.width = square.style.height = '50px';
        square.style.backgroundColor = 'blue';

        /*
         * This is another comment.
         */
        square.style.position = 'absolute';
        square.style.left = x + 'px'; 
        square.style.top = y + 'px';

        var body = document.getElementsByTagName('body')[0];
        body.appendChild(square);
      };

      // Please take a look at +=
      window.addEventListener('mousedown', function(event) {
        // German umlaut test: Berührungspunkt ermitteln
        var x = event.touches[0].pageX;
        var y = event.touches[0].pageY;
        var lookAtThis += 1;
      });
    </script>
  </body>
</html>
\end{lstlisting}
\end{document}

Desired outcome:

The > symbol for comments should be grey while the > symbol for the HTML tags should be the same color as < symbol.

  • So, you have defined otherkeywords in forms of e.g, <div. Why not defining them like <div>? Is there any particular reasons for this? – Pouya Jun 29 '15 at 13:37
  • @Pouya If I do that, then some tags such as <html>, <head>, etc. will change to orange color instead of pink. If I remove the > from otherkeywords they will turn into the correct color (pink), but a new problem emerge. Tags like <!DOCTYPE html> and <meta charset="UTF-8"> will have their < and > turn into black instead of being pink and the tags will again turn into orange. I guess this is related to these having HTML attributes. – kexxcream Jun 29 '15 at 14:51
  • Well, I think you should add a screenshot because what I see and what you explained are completely different. When I compile your code, your keywords such as <html are blue (neither pink, nor orange!) and if I change them to <html> they remain blue. – Pouya Jun 29 '15 at 16:21
  • @Pouya Ok, it's updated. You should see the problem now with the > for HTML tags and for HTML comments. – kexxcream Jul 1 '15 at 20:48
15
+300

My very first attempt is something like morekeywords={>, etc}. But every > at the end of comments is colored pink. I cannot override its color by, say, moewkeywords=[9]{-->}. Then I found that it is probably because < and > are special in this case.

More precisely, Listings actually takes care of tags by the following: when you say language=html, everything from < to > are styled by tagstyle=. So I write tagstyle=\color{editorBlue} in the example. Notice the color of = and the pig part. (Keywords like div's and p's are not blue because keywordstlye= overrides it.)

\lstset{
  language=html,
  tagstyle=\color{editorBlue},
  basicstyle={\small\ttfamily},
  identifierstyle=\color{editorOrange},
  keywordstyle=\color{editorPink},
  commentstyle=\color{editorGray},
  stringstyle=\color{editorPurple}
}
\begin{lstlisting}
<!DOCTYPE html>
<html>
  <body>
    <!-- Paragraphs are fine -->
    <div id="box">
      <p>Hello World</p>
      <p id="test">Hello World</p>
            <pig weight=120kg></pig>
    </div>
    <div>Test</div>
  </body>
</html>
\end{lstlisting}

Part II

You may also notice that <!-- --> is not colored properly. Here is the story:

A comment declaration starts with <!, followed by zero or more comments, followed by >.
A comment starts and ends with --, and does not contain any occurrence of --.

So technically speaking Listings does it right, though it is not what we want. To color comments from <! to >, use morecomment=:

\lstdefinelanguage{HTML5}{
  language=html,
  tagstyle=\color{editorBlue},
  markfirstintag,
  morecomment=[s]{<!-}{-->},
}
\lstset{
  language=HTML5
}
\begin{lstlisting}
<!DOCTYPE html>
<html>
  <body>
    <!-- Paragraphs are fine -->
    <div id="box">
      <p>Hello World</p>
      <p id="test">Hello World</p>
            <pig weight=120kg></pig>
    </div>
    <div>Test</div>
  </body>
</html>
\end{lstlisting}

Part III

You can style tags further by hacking \lst@BeginTag and \lst@EndTag: (Notice that ='s are black.)

\makeatletter
\gdef\lst@BeginTag{%
    \lst@DelimOpen
        \lst@ifextags\else
        {\let\lst@ifkeywords\iftrue
         \lst@ifmarkfirstintag\lst@firstintagtrue\fi\color{editorBlack}}}
\gdef\lst@EndTag{\lst@DelimClose\lst@ifextags\else\color{editorBlue}}
\lstset{
  morekeywords=[2]{weight},
  keywordstyle=[2]\color{violet},
  morekeywords=[3]{kg},
  keywordstyle=[3]\color{brown},
  otherkeywords={120},
  morekeywords=[4]{120},
  keywordstyle=[4]\color{green},
}
\begin{lstlisting}
<!DOCTYPE html>
<html>
  <body>
    <!-- Paragraphs are fine -->
    <div id="box">
      <p>Hello World</p>
      <p id="test">Hello World</p>
            <pig weight=120kg></pig>
    </div>
    <div>Test</div>
  </body>
</html>
\end{lstlisting}

Part IV

(To be irresponsible, I want to say that it is not wise to mix HTML, CSS, javascript, and any backends.)

To be practical, the PHP parser for instance, is encoded in \lst@definelanguage{PHP} independently. I cannot see any relation between it and the HTML-part. The logic of alsolanguage= is to load all settings together without the ability of escaping from language_A to language_B. In fact, the document supports escaping to LATEX and says

  1. Don’t use any commands of the listings package when you have escaped to LATEX.

I am not sure what do you want to do with PHP codes. If you want to color the whole line monochromatically, try morecomment=[s][\color{PHP}]{<?}{?>}. In the worst case, you can leave lstlisting and enter it again with different language=. (line number? easy I guess.)

\begin{lstlisting}[language=HTML,numbers=left,firstnumber=100]
    <p>This is going to be ignored by PHP and displayed by the browser.</p>
    <p>This is going to be ignored by PHP and displayed by the browser.</p>
\end{lstlisting}
\vspace*{-10pt}
\begin{lstlisting}[language=PHP ,numbers=left,firstnumber=last]
    <?php echo 'While this is going to be parsed.'; ?>
    <?php echo 'While this is going to be parsed.'; ?>
\end{lstlisting}
\vspace*{-10pt}
\begin{lstlisting}[language=HTML,numbers=left,firstnumber=last]
    <p>This will also be ignored by PHP and displayed by the browser.</p>
    <p>This will also be ignored by PHP and displayed by the browser.</p>
\end{lstlisting}

Part V

According to this page:

  • characters ! and / use a consistent color to form !DOCTYPE and /html.
  • Attributes and = use the same color.
  • The right hand sides are always "string" by the standard.

So let me present my final version:

  • Set ! and / to be letters; Forget all tag names as keywords. They are colored simply because markfirstintag=true. (Add some back if you want to distinguish tag names. Remember to add XXX and /XXX at the same time)
  • Forget attributes as keywords; instead, hack \lst@BeginTag to color attributes and = at the same time. (Similarly, add YYY= back if needed)
  • Thank God the right hand side is covered by stringstyle=. (You probably can distinguish those strings by redefining \lst@stringstyle inside \lst@BeginTag.)

\lstdefinelanguage{HTML5}{
  language=html,
  alsoletter={!/},
  markfirstintag=true,
  morecomment=[s]{<!--}{-->},
  keywords={},
}
\lstset{
  language=HTML5,
  tagstyle=\color{editorBlue},
  basicstyle={\small\ttfamily},
  identifierstyle=\color{editorOrange},
  keywordstyle=\color{editorPink},
  commentstyle=\color{editorGray},
  stringstyle=\color{editorPurple},
}
\makeatletter
\gdef\lst@BeginTag{%
    \lst@DelimOpen
        \lst@ifextags\else
        {\let\lst@ifkeywords\iftrue
         \lst@ifmarkfirstintag\lst@firstintagtrue\fi\color{editorLightGray}}}
\gdef\lst@EndTag{\lst@DelimClose\lst@ifextags\else\color{editorBlue}}
\begin{lstlisting}
<!DOCTYPE html>
<html>
  <body>
    <!-- Paragraphs are fine -->
    <div id="box">
      <p>Hello World</p>
      <p id="test">Hello World</p>
            <pig weight="120kg" fat="100kg"></pig>
    </div>
    <div>Test</div>
  </body>
</html>
\end{lstlisting}
  • Thank you a million for this. I understand everything clearly except for Part III. Exactly how do you decide the color of the equal sign (=)? – kexxcream Jul 5 '15 at 5:56
  • @kexxcream it is currently affected by the color assignment in the definition of \lst@BeginTag. – Symbol 1 Jul 5 '15 at 6:01
  • I understand, but what part actually commands all equal signs to be black? I don't see that. – kexxcream Jul 5 '15 at 6:03
  • @kexxcream Roughly speaking, Listings treats everything between < and > as tags. And this is implemented by declaring <> as a pair of delimiter, and then insert \lst@BeginTag right after < and \lst@EndTag right before >. So you can also see that all / are black, too. For more information, look up \gdef\lst@TagKey#1#2 in lstmisc.sty. – Symbol 1 Jul 5 '15 at 6:13
  • Thanks but when I implement this I get the following: (1) Package keyval Error: tagstyle undefined. (2) Package keyval Error: markfirstintag undefined. – kexxcream Jul 5 '15 at 6:45

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.