all repos — shlide @ e18d60c5a139eb30d997979b13787c0bf489ae84

slide deck presentation tool written in pure bash

shlide (view raw)

  1#!/usr/bin/env bash
  2# 
  3# Usage: shlide path/to/slides/
  4# Each slide is a textfile under path/to/slides
  5
  6# Color definitions
  7
  8BLK="\e[38;5;30m"
  9RED="\e[38;5;31m"
 10GRN="\e[38;5;32m"
 11YLW="\e[38;5;33m"
 12BLU="\e[38;5;34m"
 13PUR="\e[38;5;35m"
 14CYN="\e[38;5;36m"
 15RST="\e[0m"
 16
 17lines() {
 18    mapfile -tn 0 lines < "$1"
 19    printf '%s\n' "${#lines[@]}"
 20}
 21
 22longest_line() {
 23    max=0 
 24    local IFS=
 25    while read -r line; do
 26        l=$(ansi_filter $(colorify "$line"))
 27        if [ "${#l}" -gt "$max" ]; then max="${#l}"; fi
 28    done < "$1"
 29    printf '%s\n' "$max"
 30}
 31
 32colorify() {
 33    # 'eval' hack to achieve substitution for colors.
 34    eval "declare dummy=\"$1\""
 35    printf '%b' "$dummy"
 36}
 37
 38# Filter out color sequences.
 39shopt -s extglob
 40ansi_filter() {
 41    local IFS=
 42    echo "${1//$'\e'[\[(]*([0-9;])[@-n]/}"
 43    #" A little fix to prevent vim syntax highlighting from breaking.
 44}
 45
 46
 47display() {
 48    # 1 - slide contents
 49    # 2 - slide name
 50    # 3 - current slide nr.
 51    # 4 - total nr. of slides
 52
 53    slide_contents="$1"
 54
 55    # Hides the cursor.
 56    printf '\e[?25l'
 57
 58    # Clear the screen.
 59    printf '\e[2J'
 60
 61    # Get screen size
 62    shopt -s checkwinsize; (:;:)
 63
 64    # Write slide number at bottom left
 65    printf '\e[H'
 66    printf '\e[%sB%s/%s' "$LINES" "$(($3+1))" "$4"
 67
 68    # Custom calculations to center text
 69    height=$(lines "$2")
 70    width=$(longest_line "$2")
 71
 72    # Rough estimates for the true center.
 73    ((l=$LINES/2 - $height/2))
 74    ((c=$COLUMNS/2 - $width/2))
 75
 76    printf '\e[%s;%sH' "$l" "$c"
 77
 78    while IFS= read -r line; do
 79        reduce=0
 80        # Print the contents of the slide file, 
 81        # line by line.
 82        l=$(colorify "$line")
 83        printf '%s' "$l"
 84        case $line in
 85            "" | "\n")
 86                ((++reduce));;
 87        esac
 88        # Move down and back after each print.
 89        l=$(ansi_filter "$l")
 90        printf '\e[%sD\e[B' "$((${#l} - $reduce))"
 91    done <<< "$slide_contents"
 92
 93}
 94
 95die() {
 96    printf '\e[2J'
 97    printf '\e[?25h'
 98    exit 0
 99}
100
101display_end() {
102    read -r LINES COLUMNS < <(stty -F /dev/tty size)
103    ((l=$LINES/2))
104    ((c=$COLUMNS/2 - 8))
105    printf '\e[2J'
106    printf '\e[0;%sH' "$c"
107    printf 'END. Press q to quit.'
108}
109
110main() {
111
112    slides_dir="${1:-./}"
113    slides=("$slides_dir"/[0-9]*.txt)
114    i=0
115    while true; do
116        # Clear the screen.
117        printf '\e[2J'
118
119        # Capture Ctrl+C.
120        trap 'die' INT
121
122        # Display END reached prompt, and then exit
123        [[ "$i" -eq "${#slides[@]}" ]] && {
124            display_end
125            read -rsn1 input
126            case "$input" in
127                "j"|"n"|"q")
128                    die
129                    ;;
130                *)
131                    ((--i))
132                    ;;
133            esac
134        }
135
136        # Don't go below 0.
137        [[ "$i" -lt 0 ]] && i=0
138
139        # Navigate on j/k/n/p and quit on q.
140        display "$(<${slides[$i]})" "${slides[$i]}" "$i" "${#slides[@]}"
141        read -rsn1 input
142        case "$input" in 
143            "j"|"n")
144                ((++i))
145                ;;
146            "k"|"p")
147                ((--i))
148                ;;
149            "q")
150                # Return the cursor on exit.
151                die
152                ;;
153        esac
154    done
155
156    # Return the cursor.
157    printf '\e[?25h'
158
159}
160
161main "$@"