├── LICENSE ├── README.md ├── screenshot.png └── swc-shell-split-window.sh /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | Copyright (c) 2015 Raniere Silva 3 | 4 | Permission is hereby granted, free of charge, to any person obtaining a copy 5 | of this software and associated documentation files (the "Software"), to deal 6 | in the Software without restriction, including without limitation the rights 7 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | copies of the Software, and to permit persons to whom the Software is 9 | furnished to do so, subject to the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be included in all 12 | copies or substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 15 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 16 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 17 | IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, 18 | DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR 19 | OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE 20 | OR OTHER DEALINGS IN THE SOFTWARE. 21 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Software Carpentry Shell Split Window 2 | 3 | This is a script to split window for the shell lesson. 4 | 5 | ## License 6 | 7 | Under MIT. 8 | 9 | ## Requirement 10 | 11 | - [tmux](https://tmux.github.io/) 12 | 13 | ## Use 14 | 15 | ~~~ 16 | $ ./swc-shell-split-window.sh 17 | ~~~ 18 | 19 | Various environment variables affect the behaviour of the script, these are: 20 | 21 | * `SESSION`: The name of the session (default: swc) 22 | * `LOG_FILE`: The location where the log file will be stored (default: /tmp/swc-split-log-file) 23 | * `HISTORY_LINES`: How many lines of history to be shown (default: 5) 24 | * `BGCOLOR`: Background colour of the session 25 | 26 | These can be used with, e.g.: 27 | 28 | LOG_FILE=/tmp/log HISTORY_LINES=10 ./swc-shell-split-window.sh 29 | 30 | ## Notes 31 | 32 | ### Mouse scrolling 33 | 34 | To enable mouse scrolling of the output edit `$HOME/.tmux.conf` to include the 35 | line: 36 | 37 | ~~~ 38 | setw -g mouse on 39 | ~~~ 40 | 41 | ### Background colours 42 | 43 | You may wish to set the background color of a session in case you have to role 44 | play to different people. This comes in handy if, for instance, you are teaching 45 | about Git Conflicts. 46 | 47 | To do so, you would want to start to sessions in separate terminal windows with, 48 | e.g.: 49 | 50 | SESSION=swc1 BGCOLOR=12 ./swc-shell-split-window.sh 51 | SESSION=swc2 BGCOLOR=90 ./swc-shell-split-window.sh 52 | 53 | You can print all the available colours using: 54 | 55 | for i in {0..255}; do 56 | printf "\x1b[38;5;${i}mcolour${i}\x1b[0m\n" 57 | done 58 | 59 | ## Screenshot 60 | 61 | ![Screenshot of swc-shell-split-window](screenshot.png "Screenshot - only commands appear in top part of the shell, while instructor types in the bottom part and output is interleaved with commands") 62 | -------------------------------------------------------------------------------- /screenshot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UCL-ARC/swc-shell-split-window/cf005c996b4cd4d472ac508da234844a82da9ec0/screenshot.png -------------------------------------------------------------------------------- /swc-shell-split-window.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # 3 | # Create terminal for Software Carpentry lesson 4 | # with the log of the commands at the top. 5 | 6 | # Session name. Defaults to 'swc', but you can override from the 7 | # calling process. 8 | SESSION="${SESSION:-swc}" 9 | 10 | # Where we'll store the executed history. Defaults to /tmp/log-file, 11 | # but you can override from the calling process. For example: 12 | # 13 | # LOG_FILE=/tmp/my-log ./swc-shell-split-window.sh 14 | LOG_FILE="${LOG_FILE:-/tmp/$SESSION-split-log-file}" 15 | 16 | # The number of lines of history to show. Defaults to 5, but you can 17 | # override from the calling process. 18 | HISTORY_LINES="${HISTORY_LINES:-5}" 19 | 20 | # If $LOG_FILE exists, truncate it, otherwise create it. 21 | # Either way, this leaves us with an empty $LOG_FILE for tailing. 22 | > "${LOG_FILE}" 23 | 24 | # Prompt colour 25 | CYAN="[1;36m" 26 | 27 | # Create the session to be used 28 | # * don't attach yet (-d) 29 | # * name it $SESSION (-s "${SESSION}") 30 | tmux new-session -d -s "${SESSION}" "\ 31 | # * start reading the log 32 | tail -f '${LOG_FILE}' | \ 33 | # * extract the line numbers 34 | stdbuf -o 0 nl -s'%' -n'ln' -w1 | \ 35 | # * ignore lines starting with '#' since 36 | # they are the history file's internal timestamps 37 | stdbuf -o 0 grep -v '%#' | \ 38 | # * colour the line numbers 39 | awk -F'%' '{print \"\033${CYAN}\"\$1\"\033[0m\",\$2}'" 40 | 41 | # Get the unique (and permanent) ID for the new window 42 | WINDOW=$(tmux list-windows -F '#{window_id}' -t "${SESSION}") 43 | 44 | # Get the unique (and permanent) ID for the log pane 45 | LOG_PANE=$(tmux list-panes -F '#{pane_id}' -t "${WINDOW}") 46 | LOG_PID=$(tmux list-panes -F '#{pane_pid}' -t "${WINDOW}") 47 | 48 | # Split the log-pane (-t "${LOG_PANE}") vertically (-v) 49 | # * make the new pane the current pane (no -d) 50 | # * load history from the empty $LOG_FILE (HISTFILE='${LOG_FILE}') 51 | # * lines which begin with a space character are not saved in the 52 | # history list (HISTCONTROL=ignorespace) 53 | # * append new history to $HISTFILE after each command 54 | # (PROMPT_COMMAND='history -a') 55 | # * launch Bash since POSIX doesn't specify shell history or HISTFILE 56 | # (bash) 57 | # * when the Bash process exits, kill the log process 58 | tmux split-window -v -t "${LOG_PANE}" \ 59 | "HISTFILE='${LOG_FILE}' HISTCONTROL=ignorespace PROMPT_COMMAND='history -a' bash --norc; kill '${LOG_PID}'" 60 | 61 | # Get the unique (and permanent) ID for the shell pane 62 | SHELL_PANE=$(tmux list-panes -F '#{pane_id}' -t "${WINDOW}" | 63 | grep -v "^${LOG_PANE}\$") 64 | 65 | tmux send-keys -t "${SHELL_PANE}" " cd" enter 66 | 67 | # Unset all aliases to keep your environment from diverging from the 68 | # learner's environment. 69 | tmux send-keys -t "${SHELL_PANE}" " unalias -a" enter 70 | 71 | # Set nice prompt displaying 72 | # with colour 73 | # the command number and 74 | # the '$'. 75 | tmux send-keys -t "${SHELL_PANE}" " export PS1=\"\[\033${CYAN}\]\! $\[\033[0m\] \"" enter 76 | 77 | #A prompt showing `user@host:~/directory$ ` can be achieved with: 78 | #tmux send-keys -t "${SHELL_PANE}" " export PS1=\"\\[\\e]0;\\u@\\h: \\w\\a\\]${debian_chroot:+($debian_chroot)}\\[\\033[01;32m\\]user@host\\[\\033[00m\\]:\\[\\033[01;34m\\]\\w\\[\\033[00m\\]\\$ \"" enter 79 | 80 | #Set terminal colours 81 | if [ ! -z "$BGCOLOR" ]; then 82 | tmux select-pane -t "${SHELL_PANE}" -P bg="colour$BGCOLOR" 83 | tmux select-pane -t "${LOG_PANE}" -P bg="colour$BGCOLOR" 84 | fi 85 | 86 | sleep 0.1 87 | 88 | # Clear the history so it starts over at number 1. 89 | # The script shouldn't run any more non-shell commands in the shell 90 | # pane after this. 91 | tmux send-keys -t "${SHELL_PANE}" "history -c" enter 92 | 93 | # Send Bash the clear-screen command (see clear-screen in bash(1)) 94 | tmux send-keys -t "${SHELL_PANE}" "C-l" 95 | 96 | # Wait for Bash to act on the clear-screen. We need to push the 97 | # earlier commands into tmux's scrollback before we can ask tmux to 98 | # clear them out. 99 | sleep 0.1 100 | 101 | # Clear tmux's scrollback buffer so it matches Bash's just-cleared 102 | # history. 103 | tmux clear-history -t "${SHELL_PANE}" 104 | 105 | # Need add an additional line because Bash writes a trailing newline 106 | # to the log file after each command, tail reads through that trailing 107 | # newline and flushes everything it read to its pane. 108 | LOG_PANE_HEIGHT=$((${HISTORY_LINES} + 1)) 109 | 110 | # Resize the log window to show the desired number of lines 111 | tmux resize-pane -t "${LOG_PANE}" -y "${LOG_PANE_HEIGHT}" 112 | 113 | # Turn off tmux's status bar, because learners won't have one in their 114 | # terminal. 115 | # * don't print output to the terminal (-q) 116 | # * set this option at the window level (-w). I'd like new windows in 117 | # this session to get status bars, but it doesn't seem like there 118 | # are per-window settings for 'status'. In any case, the -w doesn't 119 | # seem to cause any harm. 120 | tmux set-option -t "${WINDOW}" -q -w status off 121 | 122 | tmux attach-session -t "${SESSION}" 123 | --------------------------------------------------------------------------------