惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

人人都是产品经理
人人都是产品经理
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
P
Privacy International News Feed
Simon Willison's Weblog
Simon Willison's Weblog
I
Intezer
Spread Privacy
Spread Privacy
The Hacker News
The Hacker News
P
Palo Alto Networks Blog
TaoSecurity Blog
TaoSecurity Blog
S
Secure Thoughts
Google Online Security Blog
Google Online Security Blog
H
Heimdal Security Blog
N
News | PayPal Newsroom
Attack and Defense Labs
Attack and Defense Labs
Recent Commits to openclaw:main
Recent Commits to openclaw:main
博客园 - 【当耐特】
Webroot Blog
Webroot Blog
小众软件
小众软件
Help Net Security
Help Net Security
D
Darknet – Hacking Tools, Hacker News & Cyber Security
N
News and Events Feed by Topic
Hacker News - Newest:
Hacker News - Newest: "LLM"
PCI Perspectives
PCI Perspectives
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
The Cloudflare Blog
Cloudbric
Cloudbric
AI
AI
WordPress大学
WordPress大学
博客园 - 聂微东
Jina AI
Jina AI
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
博客园 - 三生石上(FineUI控件)
Hacker News: Ask HN
Hacker News: Ask HN
H
Hacker News: Front Page
博客园 - Franky
V
V2EX
Schneier on Security
Schneier on Security
G
GRAHAM CLULEY
S
SegmentFault 最新的问题
有赞技术团队
有赞技术团队
H
Help Net Security
量子位
S
Security @ Cisco Blogs
大猫的无限游戏
大猫的无限游戏
cs.AI updates on arXiv.org
cs.AI updates on arXiv.org
Recorded Future
Recorded Future
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
J
Java Code Geeks
C
Cisco Blogs
S
Security Affairs

Oskar Wickström

Coding on Paper Catching Typos on My Website with Browser Testing The Bombadil Terminal Experiment There and Back Again: From Quickstrom to Bombadil Computer Says No: Error Reporting for LTL A Year with the Daylight Computer Finding Bugs in a Coding Agent with Lightweight DST Machine: Learning; Human: Unlearning; How I Built “The Monospace Web” A Flexible Minimalist Neovim for 2024 Statically Typed Functional Programming with Python 3.12 Specifying State Machines with Temporal Logic Clearing Weeds and Planting Trees Introducing Quickstrom: High-confidence browser testing The TodoMVC Showdown: Testing with WebCheck Time Travelling and Fixing Bugs with Property-Based Testing Property-Based Testing in a Screencast Editor, Case Study 3: Integration Testing Property-Based Testing in a Screencast Editor, Case Study 2: Video Scene Classification Property-Based Testing in a Screencast Editor, Case Study 1: Timeline Flattening Property-Based Testing in a Screencast Editor: Introduction Why I’m No Longer Taking Donations Writing a Screencast Video Editor in Haskell Declarative GTK+ Programming with Haskell Finite-State Machines, Part 2: Explicit Typed State Transitions Modeling with Haskell Data Types Motor: Finite-State Machines in Haskell Tagless Final Encoding of a Test Language Hyper: Elegant Weapons for a More Civilized Page Taking a Step Back from Oden Custom Formatting in HTML and LaTeX Code Listings using Pandoc Paramount Color Scheme for Vim
Automating the Build of your Technical Presentation
Oskar Wickström · 2017-09-24 · via Oskar Wickström

Writing technical presentations that include code samples and diagrams can be really tedious. In mainstream presentation software, such as Keynote and PowerPoint, your workflow is likely to manually copy-and-paste source code from your editor into your slides. If you’re not using the drawing capabilities of your presentation software, you have to perform similar steps to include diagrams.

In my process of writing a technical presentation, code samples and diagrams are not written first, and included in the slides at the last minute – I work iteratively on slide content, source code, and diagrams, all at the same time. Having to repeat the time-consuming and error-prone process of updating code samples in slides, each time my original source code changes, breaks my creative flow completely. I also want to have my source code compiled and executable, so that I can be confident it is correct.

The main features I’m looking for in a technical presentation setup includes:

  • Text-based sources for everything (slides, code samples, diagrams, presentation template, styling, and build script)
  • The ability to include sections of external source code files into slides
  • Repeatable and fully-automated builds
  • PDF output with and without notes

I’m less interested in:

  • Slide transitions and animation
  • Videos and GIFs

This article demonstrates a setup that fulfills these goals, using Pandoc Markdown, Beamer, Graphviz and Make. I have also created a template based on my setup, that you can use if you like this approach.

Writing Slides with Pandoc Markdown

One of my favorite tools in technical writing is Pandoc. I use it for documentation, talks, Markdown preview, this website, and for converting existing documents to more desirable formats1.

A very nice feature of Pandoc is slideshow output formats. You can write your slides in Markdown using regular headings, with the slide content below:

---
title:    My Awesome Topic
subtitle: Ramblings on the Subject
author:   Alice
date:     September 2017
---

# Introduction

- Something
- Another thing
- The last one

# I Can LaTeX

\centerline{\Large{\textit{I can embed LaTeX as well.}}}

# A Program

``` javascript
function coolTools() {
    return ["pandoc", "beamer"];
}
```

Build the LaTeX source code using Pandoc and the beamer target, and then generate the PDF using pdflatex:

pandoc -t beamer -o slides.tex slides.md
pdflatex slides.tex

Voilà! You have a PDF, such as this one.

You might want to customize some of the Beamer styling, which is done by including a .tex file using the -H command line parameter of Pandoc. The full template described below uses this technique to change the styling.

Including Source Code from External Files

As stated in the introduction of this article, I want my source code samples to compile, and possibly be executable. If I have to write code directly in the slides, I will most likely make mistakes, and there will be no compiler or toolchain to tell me about it.

There are a number of ways to include code from external files with Pandoc, but I will shamelessly refer to my own filter called pandoc-include-code, which I use extensively. To include a source code file, write an empty fenced code block and use the include attribute to specify the path to the external file:

``` {.javascript include=my-program.js}
```

Now, suppose you have a Haskell program in a file Sample.hs.

module Sample where

data Animal = Dog | Cat

isAfraidOf :: Animal -> Animal -> Bool
isAfraidOf Cat Dog = True
isAfraidOf _ _     = False

result :: Bool
result = Dog `isAfraidOf` Cat

The issue is you want to include just the Animal data type and the isAfraidOf definition, not the top module declaration and the result definition. By wrapping the content in two special comments, start snippet <name> and end snippet <name>, you create a named snippet:

module Sample2 where

-- start snippet animals
data Animal = Dog | Cat

isAfraidOf :: Animal -> Animal -> Bool
isAfraidOf Cat Dog = True
isAfraidOf _ _     = False
-- end snippet animals

result :: Bool
result = Dog `isAfraidOf` Cat

In the Markdown source, refer to the snippet’s name when including:

``` {.haskell include=Sample2.hs snippet=animals}
```

The included code will be only that in your snippet:

data Animal = Dog | Cat

isAfraidOf :: Animal -> Animal -> Bool
isAfraidOf Cat Dog = True
isAfraidOf _ _     = False

You can still compile the code, load it in the REPL, and write tests for it, while including interesting parts into your slides. You are not depending on specific line number ranges, which of course becomes a nightmare once you edit your source code.

The last feature of pandoc-include-code I want to demonstrate is the dedent attribute. Let’s say we have a Javascript file with a class method that you’re interested in:

class Foo {
  // start snippet bar
  bar() {
    return "bar";
  }
  // end snippet bar
}

When including snippets of indented source code, you might want to “dedent”, i.e. remove extra leading whitespace. This is easily accomplished with the dedent attribute, specifying how many whitespace characters you want removed:

``` {.javascript include=sample1.js snippet=bar dedent=2}
```

The included code will be “dedented” to the first column:

Generating Diagrams

Often I want a couple of diagrams in a presentation, to illustrate some design or flow in a program. I enjoy generating diagrams from plain text sources, instead of drawing by hand or using special drawing software with binary formats. Both Graphviz and PlantUML are powerful tools that are relatively easy to integrate with the presentation build in a Makefile.

Let’s say I want to generate a state diagram. The following Graphviz source code generates a simple yet beautiful diagram:

digraph door_states {
  graph [ dpi = 300 ];
  splines=true;
  esep=5;
  rankdir=LR;

  size="8,5";

  edge [ fontname = "Ubuntu" ];
  node [ fontname = "Ubuntu Bold" ];

  node [shape = point, width = .25, height = .25 ];
  Start;

  node [shape = circle];
  Opened;
  Closed;

  Start -> Closed
  Closed -> Opened  [ label = "open" ];
  Opened -> Closed  [ label = "close" ];
}

Generate a PNG file using the dot command:

dot -Tpng -o door.png door.dot

The generated PNG image looks like this:

The state diagram generated by Graphviz.

To automate this process with Make, you can find all .dot files, transform those paths into a list of target paths, and have Make run the dot command to generate all targets.

DIAGRAM_SRCS=$(shell find src -name '*.dot')
DIAGRAMS=$(DIAGRAM_SRCS:src/%.dot=target/%.png)

.PHONY: all
all: $(DIAGRAMS)

target/%.png: src/%.dot
    mkdir -p $(shell dirname $@)
    dot -Tpng $< -o $@

A similar setup can be used with PlantUML, although you might want the JAR file to download automatically:

PLANTUML=deps/plantuml.jar

UML_SRCS=$(shell find src -name '*.uml.txt)
UMLS=$(UML_SRCS:src/%.uml.txt=target/%.png)

.PHONY: all
all: $(UMLS)

target/%.png: src/%.uml.txt $(PLANTUML)
    mkdir -p $(shell dirname $@)
    cat $< | java -jar $(PLANTUML) -tpng -pipe > $@

$(PLANTUML):
    mkdir -p $(shell dirname $@)
    wget http://sourceforge.net/projects/plantuml/files/plantuml.jar/download -O $@

I have used PlantUML in this blog, just as described above, to generate diagrams for posts. See the post Hyper: Elegant Weapons for a More Civilized Page for an example.

Wrapping Up

Based on the techniques described in this post, I have created a template that you can use for your own presentations. It is published at GitHub. I hope this will be useful to someone, and that it can be a good complement to this article.

What I really like about the tools and techniques demonstrated in this article is that they are not limited to writing presentations. I use the same tools for writing documentation, and for writing this blog. Pandoc is an amazing piece of software, and I have just scratched the surface of what it can do. For instance, if you do not want PDF output for your talk, there’s a number of Javascript-based formats for slideshows available.

Now go on and write some cool tech talks!


  1. I once needed to convert a technical manual from ODF to reStructuredText. A single Pandoc command later, and I had the sources for a proper Sphinx build.↩︎