Skip to content

Instantly share code, notes, and snippets.

@xstasi
Created October 20, 2024 20:41
Show Gist options
  • Save xstasi/dd391f55e1c6b8795489919d25edec13 to your computer and use it in GitHub Desktop.
Save xstasi/dd391f55e1c6b8795489919d25edec13 to your computer and use it in GitHub Desktop.
A terminal presentation session with speaker notes using kitty and presenterm
Put these two files in the same place, then name your presentation `main.md` and your speaker notes `speaker-notes.md`. Make sure they have the same number of slides.
Requires kitty 0.36+
#!/usr/bin/python3
import curses
# curses code shamelessly copied from https://www.codehaven.co.uk/python/using-arrow-keys-with-inputs-python/
from os import system
from sys import exit
from shutil import which
import argparse
parser = argparse.ArgumentParser()
parser.add_argument("presenter_id")
parser.add_argument("speaker_id")
args = parser.parse_args()
speaker = args.speaker_id
presenter = args.presenter_id
if not which('kitten'):
print("kitten not found in path, exiting")
exit()
def left():
system(f"kitten @ send-key -m id:{speaker} left")
system(f"kitten @ send-key -m id:{presenter} left")
def right():
system(f"kitten @ send-key -m id:{speaker} right")
system(f"kitten @ send-key -m id:{presenter} right")
# get the curses screen window
screen = curses.initscr()
# turn off input echoing
curses.noecho()
# respond to keys immediately (don't wait for enter)
curses.cbreak()
# map arrow keys to special values
screen.keypad(True)
try:
while True:
char = screen.getch()
if char == ord('q'):
break
elif char == curses.KEY_RIGHT:
# print doesn't work with curses, use addstr instead
screen.addstr(0, 0, '> next slide')
right()
elif char == curses.KEY_LEFT:
screen.addstr(0, 0, '> prev slide')
left()
finally:
# shut down cleanly
curses.nocbreak(); screen.keypad(0); curses.echo()
curses.endwin()
#!/bin/bash
dir_path=$(readlink -f "${BASH_SOURCE}")
if [ ! -f main.md ] || [ ! -f speaker-notes.md ] ; then
echo "Cannot see presentation or speaker notes, exiting."
exit
fi
presenter_id=$(kitten @ launch --title 'Presenter screen' --type=os-window --cwd $PWD --os-window-state=maximized)
speaker_id=$(kitten @ launch --title 'Speaker screen' --type=os-window --cwd $PWD --os-window-state=maximized)
sleep 1
ctrl_id=$(kitten @ launch -m id:${speaker_id} --title 'Speaker control' --location=hsplit --cwd $PWD)
kitten @ resize-window -m id:${ctrl_id} -i -100 -a vertical
sleep 3
kitten @ send-text -m id:${presenter_id} "presenterm --image-protocol kitty-local main.md"
kitten @ send-text -m id:${speaker_id} "presenterm --image-protocol kitty-local speaker-notes.md"
kitten @ send-text -m id:${ctrl_id} "${dir_path}/controller.py ${presenter_id} ${speaker_id}"
for i in $presenter_id $speaker_id $ctrl_id ; do
kitten @ send-key -m id:${i} enter
done
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment