Skip to content

Instantly share code, notes, and snippets.

@0xee
Created September 8, 2019 17:37
Show Gist options
  • Save 0xee/e5644097fa7e233d3a70c49cdc2634bb to your computer and use it in GitHub Desktop.
Save 0xee/e5644097fa7e233d3a70c49cdc2634bb to your computer and use it in GitHub Desktop.
Bash prompt test
#!/usr/bin/env bash
# Checks if the bash prompt is setup correctly, i.e. if all non-printable
# characters are escaped correctly using \[...\] and if wide characters
# (eg. emoji) are displayed correctly by the terminal.
#
# Should work on any bash prompt, including ones containing colors, multiple
# lines, unicode characters, etc.
#
# The tests are performed by running a shell in a clean tmux session,
# optionally also running a custom setup command ($1, if provided). The setup
# command is just typed into the shell, so even ssh to another host is
# possible.
#
# The tests can be watched by attaching to the tmux session from another
# terminal, eg. like this:
#
# > while true; do tmux attach -t test-bash-config; sleep 1; done
#
# In this case it might be useful to increase the delay in the pause function
# to see what happens in slow motion. This can also help if the tests fail
# due to slow execution.
# optional setup command which will be executed in the
setup="$1"
export -n TMUX
session="test-bash-config"
p="$session:0.0"
tmux kill-session -t $session
tmux new-session -d -s $session
function pause {
sleep 0.01
}
function send {
tmux send-keys -t $p "$@"
pause
}
function getLine {
offset=${1:-0}
tmux copy-mode -t $p
pause
for _ in $(seq $offset); do
send Up
pause
done
send -X select-line
pause
send -X copy-selection-and-cancel
pause
tmux show-buffer
}
# set terminal width to 40 characters to get a deterministic terminal size
tmux setw -t $session:0 force-width 40
sleep 1
if [[ -n "$setup" ]]; then
send "$setup"
send Enter
sleep 2
fi
send "cd ~"
send Enter
echo "Determining prompt"
pause
send X
promptWithDelim="$(getLine)"
send C-c
prompt="${promptWithDelim%X}"
echo "Detected prompt: '$prompt'"
echo
echo "Test 1:"
# Send as many characters as the terminal is wide and check if they wrap
# correctly to the next line. The previous line should then contain the prompt
# and the beginning of the typed sequence.
send true # clear error indicators from prompt
send Enter
pause
send xxxyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy
pause
line="$(getLine 1)"
send C-c
send Enter
echo "Expected: '$prompt ?xxxy.*'"
echo "Actual: '$line'"
if grep -e "${prompt} \?xxxy.*" <<<"$line"; then
echo "Success"
else
echo "Fail"
fi
echo
echo "Test 2:"
# Run a command that is exactly the width of the terminal, run another command,
# and check if the first command can be reproduced by typing arrow up two
# times. The previous line should contain the prompt and the beginning of the
# command.
send Enter
send "echo xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
send Enter
send "echo yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy"
send Enter
send Up
send Up
line="$(getLine 1)"
echo "Expected: '$prompt ?echo x.*'"
echo "Actual: '$line'"
if grep -e "${prompt} \?echo x.*" <<<"$line"; then
echo "Success"
else
echo "Fail"
fi
echo "Cleaning up"
tmux kill-session -t $session
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment