44

I'm trying to convert a Markdown file into a PDF file using Pandoc.

I have a lot of code blocks in my Markdown, and if I have a line of code that is too long, it will just be cut off in the PDF. How can I make Pandoc wrap lines that are too long?

Here's the line I'm using right now:

pandoc input.md --highlight-style tango -o output.pdf;
3

5 Answers 5

45

(See Update at the end, to get proper colors)

By default pandoc uses its own highlighting engine, but it can be changed to use package listings instead. Simply add --listings option to your pandoc command line.

However, the format used by listings does not break long lines either, but you can prepare all the required options in a separate tex file, for example:

% Contents of listings-setup.tex
\usepackage{xcolor}

\lstset{
    basicstyle=\ttfamily,
    numbers=left,
    numberstyle=\footnotesize,
    stepnumber=2,
    numbersep=5pt,
    backgroundcolor=\color{black!10},
    showspaces=false,
    showstringspaces=false,
    showtabs=false,
    tabsize=2,
    captionpos=b,
    breaklines=true,
    breakatwhitespace=true,
    breakautoindent=true,
    linewidth=\textwidth
}

And then compile with the line:

pandoc test.md --listings -H listings-setup.tex -o output.pdf

Unfortunately, this solution cannot use the --highlight-style option too. If you want to get the tango colorscheme, you have to code it yourself as options for the listing packages, and include them in the \lstset above.

Given the file test.md as follows:

% Title
% Author

# First section

Some code with long lines:

```java
public class Test {
    static Set<Thread> updateThreads = new HashSet<Thread>();

    public static void main(String[] args) {
        ConcurrentMap<Integer, String> concurrentMap = new ConcurrentHashMap<Integer, String>();
        for (int i = 0; i < 1000; i++) {
            startUpdateThread(i, concurrentMap);
        }
        for (Map.Entry<Integer, String> entry : concurrentMap.entrySet()) {
            System.out.println("Key :" + entry.getKey() + " Value:" + entry.getValue());
        }
        for (Thread thread : updateThreads) {
            thread.interrupt();
        }
    }
}
```

That's it.

The result generated by the previous pandoc command line is:

Output

Update

In order to mimic closely the result obtained with --highlight-style tango option (and no listings package), I ran pandoc asking for the intermediate .tex file to discover how the colors were defined for that case.

I wrote the following setup using listings options, which use the same colors (only where applicable, for example listings has no mean to set a specific color for numeric constants or other syntactic elements). In addition I reduced the spacing among chars, which were too far apart with default setup. This is the new setup:

% Contents of listings-setup.tex
\usepackage{xcolor}

\lstset{
    basicstyle=\ttfamily,
    numbers=left,
    keywordstyle=\color[rgb]{0.13,0.29,0.53}\bfseries,
    stringstyle=\color[rgb]{0.31,0.60,0.02},
    commentstyle=\color[rgb]{0.56,0.35,0.01}\itshape,
    numberstyle=\footnotesize,
    stepnumber=1,
    numbersep=5pt,
    backgroundcolor=\color[RGB]{248,248,248},
    showspaces=false,
    showstringspaces=false,
    showtabs=false,
    tabsize=2,
    captionpos=b,
    breaklines=true,
    breakatwhitespace=true,
    breakautoindent=true,
    escapeinside={\%*}{*)},
    linewidth=\textwidth,
    basewidth=0.5em,
}

Using those settings, i.e. running pandoc with options:

pandoc test.md --listings -H listings-setup.tex -o output.pdf

the following result is obtained:

Result with listings

For reference, compare it with the result without --listings but with --highlight-syntax tango instead:

Without listings

As you can see, the style is very close (except for numeric constants, which are blue using tango, but black using listings). Note also how the lines were wrapped with listings. I also added line numbers which refer to the original lines (before wrapping).

6
  • 1
    I added "--latex-engine=xelatex" and it works! What's the easiest way to add back some syntax highlight to the code?
    – pimpampoum
    Commented May 23, 2014 at 12:39
  • I managed to get some highlight using tex.stackexchange.com/questions/89574/… but it doesn't look great. Are there any other way? Thanks.
    – pimpampoum
    Commented May 23, 2014 at 13:39
  • @pimpampoum Look at the updated answer.
    – JLDiaz
    Commented May 23, 2014 at 19:09
  • One may want to add showlines=true to avoid trailing newlines being cut off. stackoverflow.com/a/2588916/461834
    – jtpereyda
    Commented Sep 30, 2018 at 0:02
  • This works, but it will not just fail on numbers when it comes to highlighting, but also classes and global objects (i.e. console in JavaScript). I wish the syntax highlighting would be better. stringstyle also fails on JavaScript and identifierstyle would match too much (I was hoping it would help here, but it's not). Commented Apr 22, 2020 at 14:48
11

There is a really simple solution, using fvextra, recently suggested by jannick0.

Modify your YAML header options to include

\usepackage{fvextra}
\DefineVerbatimEnvironment{Highlighting}{Verbatim}{breaklines,commandchars=\\\{\}}

and compile with xelatex.

For instance,

---
header-includes:
 - \usepackage{fvextra}
 - \DefineVerbatimEnvironment{Highlighting}{Verbatim}{breaklines,commandchars=\\\{\}}
---

~~~~~{.java}
this is a very long long long long long long long long long long long long long line which is broken
~~~~~~

when compiled with

pandoc input.md -o output.pdf

gives enter image description here

3
  • 1
    Given that using lstlistings has a number of side-effects, this is surely a less invasive solution.
    – MPi
    Commented Apr 3, 2019 at 14:07
  • 3
    One can also add breakanywhere to make it also break long lines with no spaces, like: \DefineVerbatimEnvironment{Highlighting}{Verbatim}{breaklines,breakanywhere,commandchars=\\\{\}}
    – ha7ilm
    Commented Aug 11, 2020 at 15:19
  • 1
    This works much better than the accepted answer.
    – shivams
    Commented Jun 22, 2022 at 16:43
9
+100

One does not need a listings-setup.tex in order for this to work.

Just add this to your YAML-Header include:

header-includes:
    - \usepackage{xcolor}
    - \lstset{breaklines=true}
    - \lstset{language=[Motorola68k]Assembler}
    - \lstset{basicstyle=\small\ttfamily}
    - \lstset{extendedchars=true}
    - \lstset{tabsize=2}
    - \lstset{columns=fixed}
    - \lstset{showstringspaces=false}
    - \lstset{frame=trbl}
    - \lstset{frameround=tttt}
    - \lstset{framesep=4pt}
    - \lstset{numbers=left}
    - \lstset{numberstyle=\tiny\ttfamily}
    - \lstset{postbreak=\raisebox{0ex}[0ex][0ex]{\ensuremath{\color{red}\hookrightarrow\space}}}

and compile with --listings. If there are compile errors try to add --pdf-engine=xelatex or --pdf-engine=lualatex.

0
1

This is only an apostille to Clement's (ihmo best) solution that cannot be illustrated in a comment. The highlight can be fixed in the YAML header. On the other hand, the lines of code can be numbered passing the option .numberLines to the code chunk:

Example stealing the code of JLDiaz's answer:


mwe


---
classoption: twocolumn # for more code line breaks
header-includes:
- \usepackage{fvextra}
- \DefineVerbatimEnvironment{Highlighting}{Verbatim}{breaklines,commandchars=\\\{\}}
output:
  pdf_document: 
    highlight: tango
---

# First section

Some code with long lines:


```{.java .numberLines}

public class Test {
    static Set<Thread> updateThreads = new HashSet<Thread>();

    public static void main(String[] args) {
        ConcurrentMap<Integer, String> concurrentMap = new ConcurrentHashMap<Integer, String>();
        for (int i = 0; i < 1000; i++) {
            startUpdateThread(i, concurrentMap);
        }
        for (Map.Entry<Integer, String> entry : concurrentMap.entrySet()) {
            System.out.println("Key :" + entry.getKey() + " Value:" + entry.getValue());
        }
        for (Thread thread : updateThreads) {
            thread.interrupt();
        }
    }
}

```
That's it.
0

If you only want to add line breaks and not modify the rest of the default code blocks layout, you can use hda's method in a simplified version, and modified to keep the original font spacing thanks to decrease monotype letter spacing in lstlisting.

TL;DR: Add this on top of your .md file:

---
header-includes:
    - \lstset{basicstyle=\small\ttfamily, basewidth=0.5em}
    - \lstset{breaklines=true}
---

and compile it with:

pandoc test.md -o test.pdf --listings

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .