#!/bin/bash set -e set -f set -o pipefail shopt -s lastpipe BOT_SIZE=8 BOT_TITLE=input BOT_CMD='PS1="$BOT_TITLE\$ " bash --noprofile --norc -i' TOP_CMD='PS1="$TOP_TITLE\$ " bash --noprofile --norc -i' TOP_TITLE=output TWOPANE=$(mktemp -d) export TWOPANE TOP_CMD BOT_CMD TOP_TITLE BOT_TITLE BOT_SIZE trap 'rm -r "$TWOPANE"' EXIT STY=twopane.${TWOPANE##*/} save_file() { out=$TWOPANE/${1:?$0: filename cannot be empty string} cat > "$out" } save_screenrc() { save_file screenrc"${1:+.$1}" } save_screenrc <<'.' unbindall escape \0\0 caption string '%t' layout new split focus bottom resize $BOT_SIZE screen -ln -t "$BOT_TITLE" 0 bash "$TWOPANE"/bashrc source "$TWOPANE"/screenrc.startpane . save_screenrc 'startpane' <<'.' focus top screen -ln -t "$TOP_TITLE" 1 sh -c "$TOP_CMD; screen -X focus top; screen -X remove" exec :!. socat -u UNIX-RECV:"$TWOPANE"/socket STDOUT title 'output' focus bottom layout save 0 . save_screenrc 'restart' <<'.' layout new split focus bottom resize $BOT_SIZE select 0 title 'input' source "$TWOPANE"/screenrc.startpane . save_file bashrc <<'.' trap "screen -X quit" EXIT restart() { screen -X source "$TWOPANE"/screenrc.restart } sendp() { socat -u STDIN UNIX-SENDTO:"$TWOPANE"/socket } sendc() { printf '%s' "$*" | sendp } send() { sendc "$*"$'\n' } start() { while read -r -N1 do sendc "$REPLY" done } export -f restart sendp sendc send start bash -c "$BOT_CMD" || read -p "Error: process terminated with exit code $? Press enter to quit." . screen -c "$TWOPANE"/screenrc -m -S "$STY" -ln