Tinkering with Marp and Shell History

decorator
How I hosted presentation with marp and mean while learnt cool things about history while writing this blog.
Published on 16 Nov 2024
# marp # cli # talk

https://upload.wikimedia.org/wikipedia/commons/thumb/7/72/OHP-sch.JPG/1280px-OHP-sch.JPG Overhead project in Operation - got to know about this from ankush.

Recently, I was giving a talk at FOSS Bangalore Meetups about how aryak and I hosted IndiaFOSS 2024 livestreams and I was traveling from my hometown to Bangalore. I reached Bangalore around 9:30 AM with a half-baked presentation in Figma and I was still editing a lot of things because of my other work-related things. And, I am someone who really likes to make beautiful-looking and very appealing presentations. Sometimes, It is a lot more painful to carry your laptop, open your PowerPoint viewer, and all of those things. Instead with Marp and some hack, you can just host it on your personal website.

Somehow, out of random I remembered about marp-cli and I thought I’ll check it out. Now, here marp-cli and my presentation had nothing to do with each other. Marp is basically a tool that makes presentations from markdown. So, you basically have to write your content in markdown and marp will manage everything else. You can also add styling to your presentation with some on-top customizations marp has done.

I tried it out and I obviously did not have time to feed my curious little brain by doing something cool at the last moment. I downloaded all my presentation frames as separate pdf’s inside a zip file.

Well, now you would think why I do this every single time when I’m going to give a talk. I do this because figma is bad for me when I download all my slides as a single file, if I change the sequence of my slides everything will be messed up and I will have to manually rename all the frames right in the sequence. Hence, I use ghostscript to combine everything into a single slide and then convert that one file into PDF (can I do .pptx (?)) and then use it to for the talks.

So, its quite simple. I found a gist of how to do this long back (in 2023 during my first talk) and the oneliner turns out to be something like this:

gs -dNOPAUSE -sDEVICE=pdfwrite -sOUTPUTFILE=combine.pdf 
-dBATCH 'frame-{1..14}.pdf'

Which is cool? Nah, it’s very dumb to do that. But while I was tinkering with map, I found --imagewhere you can convert slide deck notes to separate images. I exported every frame as png this time and proceeded ahead with trying to use image inputs to convert into HTML.

I go ahead and do

# I don't remember the command properly 
# because this was 20-30 days ago now.
marp frame-{1..14.png} output.html 

This is quite dumb in the first place because marp will generate only from a *.md file obviously.

When I asked GPT it suggested I link all the separate PNG frames in the markdown file and that seemed to work. The format of adding images in markdown is ![name](url) and I wanted to automate this so I wrote a quick for loop.

for i in {1..15}; do
echo "![Slide {1..15}](./slide-$i)"
done

Looks like a clean for loop right? But, this for loop won’t work. I honestly don’t remember how I did or what help I took from the Internet to get it working, because while I’m writing this for a loop didn’t work. And bash ends up returning "![ event not found". I honestly don’t know what that means. But after beating my scratching my head a lot I ended up asking Annoyingly Irregular about the error and after 3-4 prompts it caught up with my problem and talked about “History Expansion”.

What is History Expansion?

Every Linux user who has reached the Level 9999 Max makes heavy use of something called the “reverse-i-search” which is invoked on ^+Shift+r. That is a kind of interactive example of History Expansion. Bash records every single command the user executes and stores it in .bash_history. History expansion allows the user to bring back the already executed commands, pass arguments to it, or manipulate those commands and execute them as a new fresh instance of the command.

The reason why I was getting that event not found was because ‘!’ is the character that is used to invoke history expansion. For example, you can open your terminal and do !<first alphabet from the previous command> and you’ll see that command getting executed. I found this to be very cool honestly. There are a lot more cooler things about history functions on the man page and they are very interesting to read, and the man page also has some specific parts from the codebase that talks about the implementation of the function. So, damn cool right?

You can temporarily escape history expansion by adding ‘' or backticks before and after the! Character. But that doesn’t work in my situation because the shell ends up rendering everything as \!\[Slide 1] and backticks somehow did not work in my case. Another accurate way to do this is by using the command. And after that, the for loop looks something like the below.

# enable 
set +H 
for i in {1..15}; do
echo "![Slide {1..15}](./slide-$i)"
done
# disable 
set -H

P.S: I have discovered all the above history expansion stuff while writing this blog :). Some of you might already know about this and it might be very common already. Perhaps, the blog has been delayed 3 more hours already because of this.

The final steps

In the above for loops, as you can say, it just echoes the output. Now all we are left to do is redirect all the stdout to a markdown file and enable the marp archetype/front-matter code.

# looks something like this
---
marp: true
style: |
  body {
    margin: 0;
    height: 100vh;
    width: 100vw;
    overflow: hidden;
  }
---

![](slide-1.png)
# and so on.

And you’re good to go and compile the markdown file into html file.

marp livestream.md livestream.html

After starting the marp server you get what you want.

Finally, all I was left to do was rsync the generated html file to my server hosting my website at /var/www/html/talks and I am ready to go ahead and give the talk.

You can check out the example :). Clean, efficient, and suckless right? This is so handy whenever you are in a rush, and you’re a design freak who wants to make beautiful customized presentations.

That history expansion part reminds me of one of my friends - Pystardust who used to always say “Just read the whole man page for dash, bash, and everything!”. Miss you, buddy!

Ref: