33

I'm trying to highlight simple YAML (the markup language, not the CSS framework) code. I know that there is a solution using pygments and minted, however, I would prefer a solution with \lstdefinelanguage.

This is my code so far:

\lstdefinelanguage{yaml}{
  keywords={true,false,null,y,n},
  keywordstyle=\color{darkgray}\bfseries,
  ndkeywords={},
  ndkeywordstyle=\color{black}\bfseries,
  identifierstyle=\color{black},
  sensitive=false,
  %moredelim=[l]{}{:},
  comment=[l]{#},
  morecomment=[s]{/*}{*/},
  commentstyle=\color{purple}\ttfamily,
  stringstyle=\color{blue}\ttfamily,
  %morestring=[l]{-}{},
  morestring=[b]',
  morestring=[b]"
}

Two things are missing, though:

  1. I would like to print all keys bold
  2. I would like to print all strings, also the ones without qotes, to be blue.

I tried to accomplish these two things with the commented lines in the code above. Unfortunately, they did not work. Any suggestions on how I can make this work?

Here is a small YAML example:

key: value
map:
    key1: value1
    key2: value2
list:
  - element1
  - element2
# This is a comment
listOfMaps:
  - key1: value1a
    key2: value1b
  - key1: value2a
    key2: value2b

This is the output I currently get:

enter image description here

8
  • 1
    Could you define "all strings, also the ones without quotes"? I'm not familiar with YAML and from the wikipedia page I cannot understand what other strings there are, apart from those in single or double quotes.
    – nickie
    Jan 7, 2014 at 16:20
  • I had a bad experience with listings and YAML in a manual I wrote; I used some delimiters in order to achieve syntax highlighting, but it's quite messy. Take a look at minted, it relies on pygments under the hood and it has built-in YAML support. Jan 7, 2014 at 16:28
  • 1
    Unfortunately, because YAML uses no delimiters for its keys, you'll have a hard time implementing the key style you want. One solution would be to declare all the key names you use as listings' keywords, and set the style for those keywords as you wish. Not a very satisfying solution but viable if the number of distinct key names is small.
    – jub0bs
    Jan 7, 2014 at 16:33
  • @nickie Sorry for not being clear on that. In YAML, the types of values are inferred and thus, strings are mostly not enclosed by quotes. key: value and key: "value" are equivalent, value is a string for both. I would like to color strings, either with or without quotes, in the same color. I hope, this makes it clear.
    – user37684
    Jan 7, 2014 at 16:40
  • @Jubobs I might consider that as a fallback. And thanks for the edit.
    – user37684
    Jan 7, 2014 at 16:41

1 Answer 1

28

Here is a partial solution involving some juggling with the literate and moredelim keys. The values, if delimited by double quotes, can contain colons.

Caveat: values that span multiple lines won't be correctly highlighted.

enter image description here

\documentclass{article}

\usepackage[dvipsnames]{xcolor}
\usepackage{listings}

\newcommand\YAMLcolonstyle{\color{red}\mdseries}
\newcommand\YAMLkeystyle{\color{black}\bfseries}
\newcommand\YAMLvaluestyle{\color{blue}\mdseries}

\makeatletter

% here is a macro expanding to the name of the language
% (handy if you decide to change it further down the road)
\newcommand\language@yaml{yaml}

\expandafter\expandafter\expandafter\lstdefinelanguage
\expandafter{\language@yaml}
{
  keywords={true,false,null,y,n},
  keywordstyle=\color{darkgray}\bfseries,
  basicstyle=\YAMLkeystyle,                                 % assuming a key comes first
  sensitive=false,
  comment=[l]{\#},
  morecomment=[s]{/*}{*/},
  commentstyle=\color{purple}\ttfamily,
  stringstyle=\YAMLvaluestyle\ttfamily,
  moredelim=[l][\color{orange}]{\&},
  moredelim=[l][\color{magenta}]{*},
  moredelim=**[il][\YAMLcolonstyle{:}\YAMLvaluestyle]{:},   % switch to value style at :
  morestring=[b]',
  morestring=[b]",
  literate =    {---}{{\ProcessThreeDashes}}3
                {>}{{\textcolor{red}\textgreater}}1     
                {|}{{\textcolor{red}\textbar}}1 
                {\ -\ }{{\mdseries\ -\ }}3,
}

% switch to key style at EOL
\lst@AddToHook{EveryLine}{\ifx\lst@language\language@yaml\YAMLkeystyle\fi}
\makeatother

\newcommand\ProcessThreeDashes{\llap{\color{cyan}\mdseries-{-}-}}

\begin{document}

\begin{lstlisting}[language=yaml]
---
key: value
map:
    key1: "foo:bar"
    key2: value2
list:
  - element1
  - element2
# This is a comment
listOfMaps:
  - key1: value1a
    key2: value1b
  - key1: value2a
    key2: value2b
---
\end{lstlisting}

\begin{lstlisting}[frame=single]
some
other
listing
\end{lstlisting}

\end{document}
4
  • 6
    Wow, it's awesome! :)` Jan 16, 2014 at 9:17
  • 1
    Is there any way to make that \lst@AddToHook{EOL}{\YAMLkeystyle} be yaml-specific? As of now, it's destroying the highlighting for other languages as well: i.stack.imgur.com/28HCE.png Apr 4, 2014 at 18:06
  • 1
    @SeanAllred See my edit.
    – jub0bs
    Apr 4, 2014 at 20:51
  • Can we decrease additinal space in between lines?
    – alper
    Jan 23, 2022 at 21:39

You must log in to answer this question.