├── scripts ├── scratch_cmd.bash ├── helpers.sh ├── pane_died_hook.bash ├── debug.bash └── scratch_pane.bash ├── scratchpad.tmux ├── LICENSE.md └── README.md /scripts/scratch_cmd.bash: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | declare -r CURRENT_DIR=$(dirname $(readlink -f ${BASH_SOURCE[0]})) 3 | 4 | tmux command-prompt -p "[scratchpad] Enter command:" \ 5 | "run-shell -b '${CURRENT_DIR}/scratch_pane.bash \"%%\"'" 6 | 7 | -------------------------------------------------------------------------------- /scripts/helpers.sh: -------------------------------------------------------------------------------- 1 | #!bash 2 | declare -r HELPERS_DIR=$(dirname $(readlink -f ${BASH_SOURCE[0]})) 3 | 4 | function tmux-get-option() { 5 | local option="$1" default_value="$2" option_value 6 | option_value=$(tmux show-option -gqv "$option") 7 | if [[ -z "$option_value" ]]; then 8 | echo "$default_value" 9 | else 10 | echo "$option_value" 11 | fi 12 | } 13 | 14 | -------------------------------------------------------------------------------- /scratchpad.tmux: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | declare -r CURRENT_DIR=$(dirname $(readlink -f ${BASH_SOURCE[0]})) 3 | declare -r SCRIPTS_DIR="${CURRENT_DIR}/scripts" 4 | source $SCRIPTS_DIR/helpers.sh 5 | 6 | function main() { 7 | # Bind scratch_cmd.sh 8 | tmux bind-key $(tmux-get-option '@scratch-command-key' 'C-s') \ 9 | run-shell -b ${SCRIPTS_DIR}/scratch_cmd.bash 10 | exit 0 11 | } 12 | 13 | main 14 | 15 | -------------------------------------------------------------------------------- /scripts/pane_died_hook.bash: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # Find original pane ID 4 | scratch_pane_id="$(tmux display-message -p '#{pane_id}')" 5 | original_pane_id="$( 6 | tmux list-windows -a -F '#{pane_id} #{window_name}' | 7 | awk "(\$2==\"[scratch-$scratch_pane_id]\") { print \$1; exit }" 8 | )" 9 | 10 | # If found, swap and kill 11 | if [[ -n "$original_pane_id" ]]; then 12 | tmux swap-pane -s "$scratch_pane_id" -t "$original_pane_id" 13 | tmux kill-pane -t "$scratch_pane_id" 14 | fi 15 | 16 | -------------------------------------------------------------------------------- /scripts/debug.bash: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # Run this scrip to print tmux settings 3 | PAGER=cat 4 | #PAGER='less -R' 5 | { 6 | echo -e "\$TMUX_PANE='$TMUX_PANE'" 7 | echo -e "\n\e[40;1mHOOKS \e[0m" 8 | tmux show-hooks -t "$TMUX_PANE" 9 | echo -e "\n\e[40;1mOPTIONS \e[0m" 10 | tmux show-options -t "$TMUX_PANE" 11 | echo -e "\n\e[40;1mWINDOW-OPTIONS \e[0m" 12 | tmux show-window-options -t "$TMUX_PANE" 13 | #echo -e "\n\e[40;1mGLOBAL-OPTIONS \e[0m" 14 | #tmux show-options -g 15 | #echo -e "\n\e[40;1mGLOBAL-WINDOW-OPTIONS \e[0m" 16 | #tmux show-window-options -g 17 | } | $PAGER 18 | 19 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019 Todd Yamakawa 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /scripts/scratch_pane.bash: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | declare -r CURRENT_DIR="$(dirname "$(readlink -f "${BASH_SOURCE[0]}")")" 3 | 4 | # ============================================================================== 5 | # FUNCTIONS 6 | # ============================================================================== 7 | function tmux-print() { 8 | eval tmux display-message -p "'$@'" 9 | } 10 | 11 | 12 | # ============================================================================== 13 | # MAIN 14 | # ============================================================================== 15 | 16 | # Parse args 17 | cmd="$@" 18 | if [[ -z $cmd ]]; then 19 | tmux display-message 'scratchpad: command not specified' 20 | exit 21 | fi 22 | 23 | # Get pane information 24 | # TODO: Get scroll position 25 | read -r pane_id pane_height mode scroll_pos <<<$( 26 | tmux display-message -p \ 27 | '#{pane_id} #{pane_height} #{?pane_in_mode,1,0} #{scroll_position}' 28 | ) 29 | 30 | # Check command 31 | if [[ "$cmd" == 'pager' ]]; then 32 | cmd="tmux capture-pane -e -J -p -t '$pane_id' -S - | less -r +G" 33 | else 34 | cmd=$(eval tmux-print "'$@'") 35 | fi 36 | 37 | # Create new window for scratchpad 38 | read -r scratch_window_id scratch_pane_id <<<$( 39 | eval tmux new-window -P -d \ 40 | -F '"#{window_id} #{pane_id}"' \ 41 | "'$cmd'" 42 | ) 43 | scratch_name="[scratch-$scratch_pane_id]" 44 | tmux swap-pane -s "$pane_id" -t "$scratch_pane_id" 45 | tmux rename-window -t "$pane_id" "$scratch_name" 46 | 47 | # Close tmux pane on exit 48 | tmux set-window-option -t "$scratch_pane_id" remain-on-exit on 49 | tmux set-hook -t "$scratch_pane_id" pane-died "run-shell $CURRENT_DIR/pane_died_hook.bash" 50 | 51 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | tmux-scratchpad 3 | ================================================================================ 4 | 5 | Description 6 | -------------------------------------------------------------------------------- 7 | Quickly replaces the current pane with a scratchpad, where you can run commands or edit files. The original pane gets restored when finished. 8 | 9 | [//]: # (TODO: Add gif.) 10 | 11 | 12 | Installation 13 | -------------------------------------------------------------------------------- 14 | 15 | ### Via TPM (recommended) 16 | 17 | ``` tmux 18 | set -g @plugin 'toddyamakawa/tmux-scratchpad' 19 | ``` 20 | 21 | [//]: # (TODO: Add mannual installation.) 22 | 23 | 24 | Usage 25 | -------------------------------------------------------------------------------- 26 | 27 | ``` tmux 28 | # Prompts user for command to run in scratchpad 29 | # The default binding is prefix + C-s 30 | set-option -g @scratch-command-key 'C-s' 31 | ``` 32 | 33 | Opening the `scratchpad command prompt` will look like this: 34 | 35 | ``` 36 | [scratchpad] Enter command: 37 | ``` 38 | 39 | When the command is finished, the original pane will be restored. `tmux` variables will be expanded. Here are some useful commands: 40 | ``` 41 | man tmux 42 | git status #{pane_current_path} | less 43 | ``` 44 | 45 | It's also possible to bind useful commands: 46 | ```tmux 47 | # Run git status with prefix + g 48 | bind-key g run-shell -b "$HOME/.tmux/plugins/tmux-scratchpad/scripts/scratch_pane.bash 'git -C #{pane_current_path} status | less'" 49 | ``` 50 | 51 | 52 | About 53 | -------------------------------------------------------------------------------- 54 | 55 | ### Author 56 | [toddyamakawa](https://github.com/toddyamakawa) 57 | 58 | ### License 59 | [MIT](LICENSE.md) 60 | 61 | --------------------------------------------------------------------------------