Re: Factor

Factor: the language, the theory, and the practice.

Marp

Friday, August 15, 2025

#slides

Marp, also known as the Markdown Presentation Ecosystem, is a way to “create beautiful slide decks using an intuitive Markdown experience”.

If you’ve seen a presentation about Factor before, you might notice that we have a slides vocabulary that allows us to build presentations in Factor and then present it using the Factor UI. Many of our previous talks are shared in the factor-talks repository, including the slides for the SVFIG talk.

Today, I thought it would be fun to merge these two concepts together, and allow us to build slides in Factor but do the presentation using Marp.

What does a Factor slide look like?

Let’s start by examining a $slide, and see what it looks like:

{ $slide "Quotations"
    "Quotation: un-named blocks of code"
    { $code "[ \"Hello, World\" print ]" }
    "Combinators: words taking quotations"
    { $code "10 dup 0 < [ 1 - ] [ 1 + ] if ." }
    { $code "{ -1 1 -2 0 3 } [ 0 max ] map ." }
}

As with most businessy slides, it starts with a title, and then has a sequence of various blocks to render.

What would a Marp slide look like?

We can manually translate this to a similar-looking slide using Markdown:

---

# Quotations
- Quotation: un-named blocks of code
```factor
[ "Hello, World" print ]
```

- Combinators: words taking quotations
```factor
10 dup 0 < [ 1 - ] [ 1 + ] if .
```

```factor
{ -1 1 -2 0 3 } [ 0 max ] map .
```

Can we automate this?

Of course!

Our slides vocabulary uses elements from the help system to provide markup (which is how we render it in the Factor user interface). These elements are specified as a kind of array, with typing provided by their first argument.

We can leverage this to manually support a few types:

GENERIC: write-marp ( element -- )

M: string write-marp write ;

M: array write-marp
    unclip {
        { \ $slide [ write-slide ] }
        { \ $code [ write-code ] }
        { \ $link [ write-link ] }
        { \ $vocab-link [ write-vocab-link ] }
        { \ $url [ write-url ] }
        { \ $snippet [ write-snippet ] }
        [ write-marp [ write-marp ] each ]
    } case ;

Using that, we can create a Marp file, with some chosen style:

: write-marp-file ( slides -- )
    "---
marp: true
theme: gaia
paginate: true
backgroundColor: #1e1e2e
color: #cdd6f4
style: |
  section {
    font-family: 'SF Pro Display', 'Segoe UI', sans-serif;
  }
  h1 {
    color: #89b4fa;
  }
  h2 {
    color: #94e2d5;
  }
  h3 {
    color: #f5c2e7;
  }
  code {
    background-color: #313244;
    color: #cdd6f4;
    border-radius: 0.25em;
  }
  pre {
    background-color: #313244;
    border-radius: 0.5em;
  }
  ul {
    list-style: none;
    padding-left: 0;
  }
  ul li::before {
    content: \"▸ \";
    color: #89b4fa;
    font-weight: bold;
  }" print [ write-marp ] each ;

And now we can use that to generate a Marp file of our talk!

IN: scratchpad "~/FACTOR.md" utf8 [
                   svfig-slides write-marp-file
               ] with-file-writer

And then use the Marp CLI to convert it to HTML and open in a browser!

$ marp FACTOR.md
[  INFO ] Converting 1 markdown...
[  INFO ] FACTOR.md => FACTOR.html

$ open -a Safari FACTOR.html

And then view the slides, embedded below for convenience:

This is available on my GitHub.