#!/bin/bash if [ $# -lt 1 ]; then echo "Usage: $0 SCENEID" >&2 exit 1 fi mypath="$( dirname $0 )" sceneid="$1" scenepath="$mypath/../scenes/$sceneid" scene="$( < "$scenepath" )" spacecont="[Press Space to continue]" setval="$mypath/setval" getval="$mypath/getval" getconf() { grep -m 1 "^$1 " <<< "$cdata" \ | cut -d' ' -f2- } setscene() { $setval _scene $1 } parsevals() { local data=$( cat ) local vals=$( grep -o '%[a-zA-Z0-9]\+%' <<< "$data" ) local pre=$1 local post=$2 local replace='' for val in $vals; do result=$( $getval $( sed 's/^%\|%$//g' <<< "$val" ) 2>/dev/null ) replace="$replace;s/$val/$pre$result$post/" done sed "$replace" <<< "$data" echo } if [ ! -r "$scenepath" ]; then echo "Scene not found" >&2 exit 2 fi # all configuration options appear before the first empty line cdata=$( awk '/^$/ { stop=1 } { if ( !stop ) print }' \ <<< "$scene" ) type="$( getconf TYPE )" nextscene="$( getconf NEXT )" # clear the screen to prepare to render the scene clear # output the story, as identified by the STORY line, using a pager (less) in the # event that the page is too long for the terminal awk '/STORY/ { found=1; getline } { if ( found ) print } END { print "" } ' <<< "$scene" \ | parsevals \ | less -EF inputs=$( awk '/INPUT/,/^$/ { if ( ! $0 ) { print "" } else { printf "%s ", $0 } } ' <<< "$scene" ) IFS=" " for inline in $inputs; do dest="$( cut -d' ' -f2 <<< "$inline" )" text="$( cut -d' ' -f3- <<< "$inline" )" echo "$text" echo input='' while [ ! "$input" ]; do read -p '> ' input done $setval "$dest" "$input" done branches=$( awk '/^BRANCH /' <<< "$scene" | parsevals \" \" ) IFS=" " for branch in $branches; do dest=$( cut -d' ' -f2 <<< "$branch" ) teststr=$( cut -d' ' -f3- <<< "$branch" ) eval test $teststr && { nextscene="$dest" # don't check any other branches break } done # input handling is defined by the scene type case "$type" in action) read -p '> ' input ;; trans|transition) read -s -d ' ' -p "$spacecont" echo ;; end) read -s -d ' ' -p '[Press Space to end]' exit 100 ;; input) # input should have already been done ;; *) echo "WARNING: Unknown scene type: $type" >&2 read -s -d ' ' ;; esac # if no next scene was provided, then there's nothing we can do if [ ! "$nextscene" ]; then setscene err-scene exit 1 fi # set the next scene (this is persistent, allowing the user to quit at any time) setscene "$nextscene"