Skip to content

Instantly share code, notes, and snippets.

@evansd
Created October 23, 2020 12:12
Show Gist options
  • Save evansd/96edf2f45815624cac8084a51724e89d to your computer and use it in GitHub Desktop.
Save evansd/96edf2f45815624cac8084a51724e89d to your computer and use it in GitHub Desktop.
#!/bin/bash
set -euo pipefail
help_text="
Usage: bin/development-services [-h|--help] [-n|--no-attach]
Executes the commands listed in the 'Procfile.development' file, each in its
own pane of a new tmux session, and then attaches to that session.
If an appropriate tmux session already exists then we attach to it without
starting anything.
--no-attach: Don't attach to the session, just ensure it is started and
then wait for it to terminate
"
show_help=false
no_attach=false
unknown_arg=''
while [[ $# -gt 0 ]]; do
case "$1" in
-h|--help)
show_help=true;;
-n|--no-attach)
no_attach=true;;
*)
unknown_arg="$unknown_arg $1";;
esac
shift
done
if $show_help; then
echo "$help_text"
exit 0
fi
if [[ -n "$unknown_arg" ]]; then
echo "UNRECOGNISED ARGUMENT:$unknown_arg"
echo "$help_text"
exit 1
fi
# Change in the project root directory
unset CDPATH
cd "$( dirname "${BASH_SOURCE[0]}" )/.."
process_file="$PWD/Procfile.development"
# Default project data directory if not already set
: ${PROJECT_DATA_DIR:="$PWD/local-data"}
export PROJECT_DATA_DIR
socket_path="$PROJECT_DATA_DIR/tmux.socket"
# Check tmux is installed
if ! which tmux >/dev/null; then
echo "You must install tmux to use this script"
echo "Note: you can always run the commands listed in the '$process_file' file manually."
exit 1
fi
# tmux wrapper function which uses the correct socket file
_tmux() {
tmux -2 -S "$socket_path" "$@"
}
process_list="$(sed --regexp-extended --quiet 's/^([A-Za-z0-9_]+):\s*(.+)$/\1:\2/p' "$process_file")"
adjective='existing'
if ! _tmux has-session 2>/dev/null; then
adjective='new'
mkdir -p "$(dirname "$socket_path")"
_tmux new-session -d
# Show pane titles in their borders
_tmux set pane-border-status
# Enable mouse mode so clicking in a pane will select it
_tmux set mouse on
IFS=$'\n'
first=true
for process_definition in $process_list; do
# Extract substring up to first colon
process_name="${process_definition%%:*}"
# Extract substring after first colon
process_command="${process_definition#*:}"
if $first; then
first=false
else
# Split pane, giving 95% of remaining space to new pane so we have plenty
# of space to keep opening more panes (panes will be resized evenly at
# the end of the loop)
_tmux split-window -p 95
fi
echo "Starting service '$process_name': $process_command"
# Sets the current pane title to the process name using the required escape
# sequence. We use a tiny delay to avoid writing characters before the
# shell is ready (everything will still work if this happens, we may just
# get some extraneous characters appearing in the pane). We use a leading
# space to avoid polluting bash history.
sleep 0.01
_tmux send-keys " printf '\\033]2;%s\\033\\\\' '$process_name'; clear" enter
sleep 0.01
# Run the process command
_tmux send-keys "$process_command" enter
done
_tmux select-layout even-vertical
fi
if ! $no_attach; then
echo "Attaching to $adjective tmux session on $socket_path"
exec tmux -2 -S "$socket_path" attach-session
else
echo "Waiting for $adjective tmux session to close on $socket_path"
while _tmux has-session 2>/dev/null; do
sleep 1
done
echo 'Session closed'
fi
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment