|
| 1 | +#!/bin/bash |
| 2 | +# |
| 3 | + |
| 4 | +set -e |
| 5 | + |
| 6 | +# Create terminal for Software Carpentry lesson |
| 7 | +# with the log of the commands at the top. |
| 8 | + |
| 9 | +# Session name. Defaults to 'swc', but you can override from the |
| 10 | +# calling process. |
| 11 | +SESSION="${SESSION:-swc}" |
| 12 | + |
| 13 | +# Where we'll store the executed history. Defaults to /tmp/log-file, |
| 14 | +# but you can override from the calling process. For example: |
| 15 | +# |
| 16 | +# LOG_FILE=/tmp/my-log ./swc-shell-split-window.sh |
| 17 | +LOG_FILE="${LOG_FILE:-/tmp/$SESSION-split-log-file}" |
| 18 | + |
| 19 | +#erase existing history if passed --clean_history |
| 20 | +for arg in "$@"; do |
| 21 | + if [ "$arg" == "--clean_history" ] || [ "$arg" == "-c" ]; then |
| 22 | + echo "" > "${LOG_FILE}" |
| 23 | + break |
| 24 | + fi |
| 25 | +done |
| 26 | + |
| 27 | +# The number of lines of history to show. Defaults to 5, but you can |
| 28 | +# override from the calling process. |
| 29 | +HISTORY_LINES="${HISTORY_LINES:-5}" |
| 30 | + |
| 31 | +# If $LOG_FILE exists, truncate it, otherwise create it. |
| 32 | +# Either way, this leaves us with an empty $LOG_FILE for tailing. |
| 33 | +# > "${LOG_FILE}" |
| 34 | + |
| 35 | +# Prompt colour |
| 36 | +CYAN="[1;36m" |
| 37 | + |
| 38 | +# Create the session to be used |
| 39 | +# * don't attach yet (-d) |
| 40 | +# * name it $SESSION (-s "${SESSION}") |
| 41 | +tmux new-session -d -s "${SESSION}" "\ |
| 42 | + # * start reading the log |
| 43 | + tail -f '${LOG_FILE}' | \ |
| 44 | + # * extract the line numbers |
| 45 | + stdbuf -o 0 nl -s'%' -n'ln' -w1 | \ |
| 46 | + # * ignore lines starting with '#' since |
| 47 | + # they are the history file's internal timestamps |
| 48 | + stdbuf -o 0 grep -v '%#' | \ |
| 49 | + # * colour the line numbers |
| 50 | + awk -F'%' '{print \"\033${CYAN}\"\$1\"\033[0m\",\$2}'" |
| 51 | + |
| 52 | +# Get the unique (and permanent) ID for the new window |
| 53 | +WINDOW=$(tmux list-windows -F '#{window_id}' -t "${SESSION}") |
| 54 | + |
| 55 | +# Get the unique (and permanent) ID for the log pane |
| 56 | +LOG_PANE=$(tmux list-panes -F '#{pane_id}' -t "${WINDOW}") |
| 57 | +LOG_PID=$(tmux list-panes -F '#{pane_pid}' -t "${WINDOW}") |
| 58 | + |
| 59 | +# Split the log-pane (-t "${LOG_PANE}") vertically (-v) |
| 60 | +# * make the new pane the current pane (no -d) |
| 61 | +# * load history from the empty $LOG_FILE (HISTFILE='${LOG_FILE}') |
| 62 | +# * lines which begin with a space character are not saved in the |
| 63 | +# history list (HISTCONTROL=ignorespace) |
| 64 | +# * append new history to $HISTFILE after each command |
| 65 | +# (PROMPT_COMMAND='history -a') |
| 66 | +# * launch Bash since POSIX doesn't specify shell history or HISTFILE |
| 67 | +# (bash) |
| 68 | +# * when the Bash process exits, kill the log process |
| 69 | +tmux split-window -v -t "${LOG_PANE}" \ |
| 70 | + "HISTFILE='${LOG_FILE}' HISTCONTROL=ignorespace PROMPT_COMMAND='history -a' bash --norc; kill '${LOG_PID}'" |
| 71 | + |
| 72 | +# Get the unique (and permanent) ID for the shell pane |
| 73 | +SHELL_PANE=$(tmux list-panes -F '#{pane_id}' -t "${WINDOW}" | |
| 74 | + grep -v "^${LOG_PANE}\$") |
| 75 | + |
| 76 | +tmux send-keys -t "${SHELL_PANE}" " cd" enter |
| 77 | + |
| 78 | +# Unset all aliases to keep your environment from diverging from the |
| 79 | +# learner's environment. |
| 80 | +tmux send-keys -t "${SHELL_PANE}" " unalias -a" enter |
| 81 | + |
| 82 | +# Set nice prompt displaying |
| 83 | +# with colour |
| 84 | +# the command number and |
| 85 | +# the '$'. |
| 86 | +tmux send-keys -t "${SHELL_PANE}" " export PS1=\"\[\033${CYAN}\]\! $\[\033[0m\] \"" enter |
| 87 | + |
| 88 | +#A prompt showing `user@host:~/directory$ ` can be achieved with: |
| 89 | +# tmux send-keys -t "${SHELL_PANE}" " export PS1=\"\\[\\e]0;\\u@\\h: \\w\\a\\]${debian_chroot:+($debian_chroot)}\\[\\033[01;32m\\]\u\\[\\033[00m\\]:\\[\\033[01;34m\\]\\w\\[\\033[00m\\]\\$ \"" enter |
| 90 | + |
| 91 | +# Modified PS1 that uses SCRIPT_HOME as the base directory |
| 92 | +SCRIPT_HOME="$(pwd)" |
| 93 | +tmux send-keys -t "${SHELL_PANE}" " export SCRIPT_HOME='${SCRIPT_HOME}'" enter |
| 94 | +tmux send-keys -t "${SHELL_PANE}" " export PS1=\"\\[\\e]0;\\u@\\h: \\w\\a\\]${debian_chroot:+($debian_chroot)}\\[\\033[01;32m\\]\u\\[\\033[00m\\]:\\[\\033[01;34m\\]\\\${PWD/#\\\$SCRIPT_HOME/\~}\\[\\033[00m\\]\\$ \"" enter |
| 95 | +tmux send-keys -t "${SHELL_PANE}" " cd $SCRIPT_HOME" enter |
| 96 | + |
| 97 | + |
| 98 | +#Set terminal colours |
| 99 | +if [ ! -z "$BGCOLOR" ]; then |
| 100 | + tmux select-pane -t "${SHELL_PANE}" -P bg="colour$BGCOLOR" |
| 101 | + tmux select-pane -t "${LOG_PANE}" -P bg="colour$BGCOLOR" |
| 102 | +fi |
| 103 | + |
| 104 | +sleep 0.1 |
| 105 | + |
| 106 | +# Clear the history so it starts over at number 1. |
| 107 | +# The script shouldn't run any more non-shell commands in the shell |
| 108 | +# pane after this. |
| 109 | +# tmux send-keys -t "${SHELL_PANE}" "history -c" enter |
| 110 | + |
| 111 | +# Send Bash the clear-screen command (see clear-screen in bash(1)) |
| 112 | +tmux send-keys -t "${SHELL_PANE}" "C-l" |
| 113 | + |
| 114 | +# Wait for Bash to act on the clear-screen. We need to push the |
| 115 | +# earlier commands into tmux's scrollback before we can ask tmux to |
| 116 | +# clear them out. |
| 117 | +sleep 0.1 |
| 118 | + |
| 119 | +# Clear tmux's scrollback buffer so it matches Bash's just-cleared |
| 120 | +# history. |
| 121 | +tmux clear-history -t "${SHELL_PANE}" |
| 122 | + |
| 123 | +# Need add an additional line because Bash writes a trailing newline |
| 124 | +# to the log file after each command, tail reads through that trailing |
| 125 | +# newline and flushes everything it read to its pane. |
| 126 | +LOG_PANE_HEIGHT=$((${HISTORY_LINES} + 1)) |
| 127 | + |
| 128 | +# Resize the log window to show the desired number of lines |
| 129 | +tmux resize-pane -t "${LOG_PANE}" -y "${LOG_PANE_HEIGHT}" |
| 130 | + |
| 131 | +# Turn off tmux's status bar, because learners won't have one in their |
| 132 | +# terminal. |
| 133 | +# * don't print output to the terminal (-q) |
| 134 | +# * set this option at the window level (-w). I'd like new windows in |
| 135 | +# this session to get status bars, but it doesn't seem like there |
| 136 | +# are per-window settings for 'status'. In any case, the -w doesn't |
| 137 | +# seem to cause any harm. |
| 138 | +tmux set-option -t "${WINDOW}" -q -w status off |
| 139 | + |
| 140 | +tmux attach-session -t "${SESSION}" |
0 commit comments