add tmux plugin: tmux-sidebar

A sidebar with the directory tree for the current path. Tries to make tmux more IDE like.
This commit is contained in:
2016-07-10 16:46:40 +02:00
parent ed1f9b459c
commit b8052116c6
12 changed files with 545 additions and 3 deletions

View File

@@ -3,6 +3,15 @@ bin recurse
bin/dfm chmod 0755
.tmux/newpanes 0755
.tmux/prefix_highlight.tmux 0755
.tmux/scripts/check_tmux_version.sh 0755
.tmux/scripts/custom_tree.sh 0755
.tmux/scripts/helpers.sh 0755
.tmux/scripts/save_sidebar_width.sh 0755
.tmux/scripts/toggle.sh 0755
.tmux/scripts/tree_helpers.sh 0755
.tmux/scripts/variables.sh 0755
.tmux/sidebar.tmux 0755
.tmux/zoom 0755
.dotfiles/.iterm2 skip

5
.gitignore vendored
View File

@@ -1,4 +1,5 @@
tmux.start.sh
*.sublime-workspace
.config/mc/hotlist
.vim/.netrwhist
*.sublime-workspace
.tmux/sidebar/directory_widths.txt
tmux.start.sh

View File

@@ -147,4 +147,9 @@ run-shell ~/.tmux/prefix_highlight.tmux
set -g @prefix_highlight_fg 'white' # default is 'colour231'
set -g @prefix_highlight_bg 'blue' # default is 'colour04'
set -g @prefix_highlight_show_copy_mode 'on'
set -g @prefix_highlight_copy_mode_attr 'fg=black,bg=yellow,bold' # default is 'fg=default,bg=yellow'
set -g @prefix_highlight_copy_mode_attr 'fg=black,bg=yellow,bold' # default is 'fg=default,bg=yellow'
# tmux-sidebar (https://github.com/tmux-plugins/tmux-sidebar)
run-shell ~/.tmux/sidebar.tmux
set -g @sidebar-tree-position 'left'
set -g @sidebar-tree-width '40'

View File

@@ -0,0 +1,78 @@
#!/usr/bin/env bash
VERSION="$1"
UNSUPPORTED_MSG="$2"
get_tmux_option() {
local option=$1
local default_value=$2
local option_value=$(tmux show-option -gqv "$option")
if [ -z "$option_value" ]; then
echo "$default_value"
else
echo "$option_value"
fi
}
# Ensures a message is displayed for 5 seconds in tmux prompt.
# Does not override the 'display-time' tmux option.
display_message() {
local message="$1"
# display_duration defaults to 5 seconds, if not passed as an argument
if [ "$#" -eq 2 ]; then
local display_duration="$2"
else
local display_duration="5000"
fi
# saves user-set 'display-time' option
local saved_display_time=$(get_tmux_option "display-time" "750")
# sets message display time to 5 seconds
tmux set-option -gq display-time "$display_duration"
# displays message
tmux display-message "$message"
# restores original 'display-time' value
tmux set-option -gq display-time "$saved_display_time"
}
# this is used to get "clean" integer version number. Examples:
# `tmux 1.9` => `19`
# `1.9a` => `19`
get_digits_from_string() {
local string="$1"
local only_digits="$(echo "$string" | tr -dC '[:digit:]')"
echo "$only_digits"
}
tmux_version_int() {
local tmux_version_string=$(tmux -V)
echo "$(get_digits_from_string "$tmux_version_string")"
}
unsupported_version_message() {
if [ -n "$UNSUPPORTED_MSG" ]; then
echo "$UNSUPPORTED_MSG"
else
echo "Error, Tmux version unsupported! Please install Tmux version $VERSION or greater!"
fi
}
exit_if_unsupported_version() {
local current_version="$1"
local supported_version="$2"
if [ "$current_version" -lt "$supported_version" ]; then
display_message "$(unsupported_version_message)"
exit 1
fi
}
main() {
local supported_version_int="$(get_digits_from_string "$VERSION")"
local current_version_int="$(tmux_version_int)"
exit_if_unsupported_version "$current_version_int" "$supported_version_int"
}
main

4
.tmux/scripts/custom_tree.sh Executable file
View File

@@ -0,0 +1,4 @@
#!/usr/bin/env bash
find . -path '*/.git*' -prune -o -print |
sed -e 's;[^/]*/;|___;g;s;___|; |;g'

101
.tmux/scripts/helpers.sh Executable file
View File

@@ -0,0 +1,101 @@
get_tmux_option() {
local option=$1
local default_value=$2
local option_value=$(tmux show-option -gqv "$option")
if [ -z "$option_value" ]; then
echo "$default_value"
else
echo "$option_value"
fi
}
set_tmux_option() {
local option=$1
local value=$2
tmux set-option -gq "$option" "$value"
}
# Ensures a message is displayed for 5 seconds in tmux prompt.
# Does not override the 'display-time' tmux option.
display_message() {
local message="$1"
# display_duration defaults to 5 seconds, if not passed as an argument
if [ "$#" -eq 2 ]; then
local display_duration="$2"
else
local display_duration="5000"
fi
# saves user-set 'display-time' option
local saved_display_time=$(get_tmux_option "display-time" "750")
# sets message display time to 5 seconds
tmux set-option -gq display-time "$display_duration"
# displays message
tmux display-message "$message"
# restores original 'display-time' value
tmux set-option -gq display-time "$saved_display_time"
}
stored_key_vars() {
tmux show-options -g |
\grep -i "^${VAR_KEY_PREFIX}-" |
cut -d ' ' -f1 | # cut just the variable names
xargs # splat var names in one line
}
# get the key from the variable name
get_key_from_option_name() {
local option="$1"
echo "$option" |
sed "s/^${VAR_KEY_PREFIX}-//"
}
get_value_from_option_name() {
local option="$1"
echo "$(get_tmux_option "$option" "")"
}
get_pane_info() {
local pane_id="$1"
local format_strings="#{pane_id},$2"
tmux list-panes -t "$pane_id" -F "$format_strings" |
\grep "$pane_id" |
cut -d',' -f2-
}
sidebar_dir() {
echo "$SIDEBAR_DIR"
}
sidebar_file() {
echo "$(sidebar_dir)/directory_widths.txt"
}
directory_in_sidebar_file() {
local pane_current_path="$1"
grep -q "^${pane_current_path}\t" $(sidebar_file) 2>/dev/null
}
width_from_sidebar_file() {
local pane_current_path="$1"
grep "^${pane_current_path}\t" $(sidebar_file) |
cut -f2
}
# function is used to get "clean" integer version number. Examples:
# `tmux 1.9` => `19`
# `1.9a` => `19`
_get_digits_from_string() {
local string="$1"
local only_digits="$(echo "$string" | tr -dC '[:digit:]')"
echo "$only_digits"
}
tmux_version_int() {
local tmux_version_string=$(tmux -V)
echo "$(_get_digits_from_string "$tmux_version_string")"
}

View File

@@ -0,0 +1,33 @@
#!/usr/bin/env bash
CURRENT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
source "$CURRENT_DIR/helpers.sh"
source "$CURRENT_DIR/variables.sh"
DIR_PATH="$(echo "$1" | tail -1)" # fixes a bug with invalid param
WIDTH="$2"
delimiter=$'\t'
replace_directory_width() {
sed "s|^${DIR_PATH}${delimiter}.*|${DIR_PATH}${delimiter}${WIDTH}|g" $(sidebar_file) > $(sidebar_file).bak
mv $(sidebar_file).bak $(sidebar_file)
}
add_directory_width() {
mkdir -p "$(sidebar_dir)"
echo "${DIR_PATH}${delimiter}${WIDTH}" >> $(sidebar_file)
}
save_sidebar_width() {
if directory_in_sidebar_file "$DIR_PATH"; then
replace_directory_width
else
add_directory_width
fi
}
main() {
save_sidebar_width
}
main

204
.tmux/scripts/toggle.sh Executable file
View File

@@ -0,0 +1,204 @@
#!/usr/bin/env bash
CURRENT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
source "$CURRENT_DIR/helpers.sh"
source "$CURRENT_DIR/variables.sh"
# script global vars
ARGS="$1" # example args format: "tree | less,right,20,focus"
PANE_ID="$2"
COMMAND="$(echo "$ARGS" | cut -d',' -f1)" # "tree | less"
POSITION="$(echo "$ARGS" | cut -d',' -f2)" # "right"
SIZE="$(echo "$ARGS" | cut -d',' -f3)" # "20"
FOCUS="$(echo "$ARGS" | cut -d',' -f4)" # "focus"
PANE_WIDTH="$(get_pane_info "$PANE_ID" "#{pane_width}")"
PANE_CURRENT_PATH="$(get_pane_info "$PANE_ID" "#{pane_current_path}")"
supported_tmux_version_ok() {
$CURRENT_DIR/check_tmux_version.sh "$SUPPORTED_TMUX_VERSION"
}
sidebar_registration() {
get_tmux_option "${REGISTERED_PANE_PREFIX}-${PANE_ID}" ""
}
sidebar_pane_id() {
sidebar_registration |
cut -d',' -f1
}
sidebar_pane_args() {
echo "$(sidebar_registration)" |
cut -d',' -f2-
}
register_sidebar() {
local sidebar_id="$1"
set_tmux_option "${REGISTERED_SIDEBAR_PREFIX}-${sidebar_id}" "$PANE_ID"
set_tmux_option "${REGISTERED_PANE_PREFIX}-${PANE_ID}" "${sidebar_id},${ARGS}"
}
registration_not_for_the_same_command() {
local registered_args="$(sidebar_registration | cut -d',' -f2-)"
[[ $ARGS != $registered_args ]]
}
sidebar_exists() {
local pane_id="$(sidebar_pane_id)"
tmux list-panes -F "#{pane_id}" 2>/dev/null |
\grep -q "^${pane_id}$"
}
has_sidebar() {
if [ -n "$(sidebar_registration)" ] && sidebar_exists; then
return 0
else
return 1
fi
}
current_pane_width_not_changed() {
if [ $PANE_WIDTH -eq $1 ]; then
return 0
else
return 1
fi
}
kill_sidebar() {
# get data before killing the sidebar
local sidebar_pane_id="$(sidebar_pane_id)"
local sidebar_args="$(sidebar_pane_args)"
local sidebar_position="$(echo "$sidebar_args" | cut -d',' -f2)" # left or defults to right
local sidebar_width="$(get_pane_info "$sidebar_pane_id" "#{pane_width}")"
$CURRENT_DIR/save_sidebar_width.sh "$PANE_CURRENT_PATH" "$sidebar_width"
# kill the sidebar
tmux kill-pane -t "$sidebar_pane_id"
# check current pane "expanded" properly
local new_current_pane_width="$(get_pane_info "$PANE_ID" "#{pane_width}")"
if current_pane_width_not_changed "$new_current_pane_width"; then
# need to expand current pane manually
local direction_flag
if [[ "$sidebar_position" =~ "left" ]]; then
direction_flag="-L"
else
direction_flag="-R"
fi
# compensate 1 column
tmux resize-pane "$direction_flag" "$((sidebar_width + 1))"
fi
PANE_WIDTH="$new_current_pane_width"
}
sidebar_left() {
[[ $POSITION =~ "left" ]]
}
no_focus() {
if [[ $FOCUS =~ (^focus) ]]; then
return 1
else
return 0
fi
}
size_defined() {
[ -n $SIZE ]
}
desired_sidebar_size() {
local half_pane="$((PANE_WIDTH / 2))"
if directory_in_sidebar_file "$PANE_CURRENT_PATH"; then
# use stored sidebar width for the directory
echo "$(width_from_sidebar_file "$PANE_CURRENT_PATH")"
elif size_defined && [ $SIZE -lt $half_pane ]; then
echo "$SIZE"
else
echo "$half_pane"
fi
}
# tmux version 2.0 and below requires different argument for `join-pane`
use_inverted_size() {
[ tmux_version_int -le 20 ]
}
split_sidebar_left() {
local sidebar_size=$(desired_sidebar_size)
if use_inverted_size; then
sidebar_size=$((PANE_WIDTH - $sidebar_size - 1))
fi
local sidebar_id="$(tmux new-window -c "$PANE_CURRENT_PATH" -P -F "#{pane_id}" "$COMMAND")"
tmux join-pane -hb -l "$sidebar_size" -t "$PANE_ID" -s "$sidebar_id"
echo "$sidebar_id"
}
split_sidebar_right() {
local sidebar_size=$(desired_sidebar_size)
tmux split-window -h -l "$sidebar_size" -c "$PANE_CURRENT_PATH" -P -F "#{pane_id}" "$COMMAND"
}
create_sidebar() {
local position="$1" # left / right
local sidebar_id="$(split_sidebar_${position})"
register_sidebar "$sidebar_id"
if no_focus; then
tmux last-pane
fi
}
current_pane_is_sidebar() {
local var="$(get_tmux_option "${REGISTERED_SIDEBAR_PREFIX}-${PANE_ID}" "")"
[ -n "$var" ]
}
current_pane_too_narrow() {
[ $PANE_WIDTH -lt $MINIMUM_WIDTH_FOR_SIDEBAR ]
}
execute_command_from_main_pane() {
# get pane_id for this sidebar
local main_pane_id="$(get_tmux_option "${REGISTERED_SIDEBAR_PREFIX}-${PANE_ID}" "")"
# execute the same command as if from the "main" pane
$CURRENT_DIR/toggle.sh "$ARGS" "$main_pane_id"
}
exit_if_pane_too_narrow() {
if current_pane_too_narrow; then
display_message "Pane too narrow for the sidebar"
exit
fi
}
toggle_sidebar() {
if has_sidebar; then
kill_sidebar
# if using different sidebar command automatically open a new sidebar
# if registration_not_for_the_same_command; then
# create_sidebar
# fi
else
exit_if_pane_too_narrow
if sidebar_left; then
create_sidebar "left"
else
create_sidebar "right"
fi
fi
}
main() {
if supported_tmux_version_ok; then
if current_pane_is_sidebar; then
execute_command_from_main_pane
else
toggle_sidebar
fi
fi
}
main

42
.tmux/scripts/tree_helpers.sh Executable file
View File

@@ -0,0 +1,42 @@
# file sourced from ./sidebar.tmux
custom_tree_command="$CURRENT_DIR/scripts/custom_tree.sh"
command_exists() {
local command="$1"
type "$command" >/dev/null 2>&1
}
tree_command() {
local user_command="$(tree_user_command)"
if [ -n "$user_command" ]; then
echo "$user_command"
elif command_exists "tree"; then
echo "$TREE_COMMAND"
else
echo "$custom_tree_command"
fi
}
tree_user_command() {
get_tmux_option "$TREE_COMMAND_OPTION" ""
}
tree_key() {
get_tmux_option "$TREE_OPTION" "$TREE_KEY"
}
tree_focus_key() {
get_tmux_option "$TREE_FOCUS_OPTION" "$TREE_FOCUS_KEY"
}
tree_pager() {
get_tmux_option "$TREE_PAGER_OPTION" "$TREE_PAGER"
}
tree_position() {
get_tmux_option "$TREE_POSITION_OPTION" "$TREE_POSITION"
}
tree_width() {
get_tmux_option "$TREE_WIDTH_OPTION" "$TREE_WIDTH"
}

26
.tmux/scripts/variables.sh Executable file
View File

@@ -0,0 +1,26 @@
VAR_KEY_PREFIX="@sidebar-key"
REGISTERED_PANE_PREFIX="@-sidebar-registered-pane"
REGISTERED_SIDEBAR_PREFIX="@-sidebar-is-sidebar"
MINIMUM_WIDTH_FOR_SIDEBAR="71"
TREE_KEY="Tab"
TREE_OPTION="@sidebar-tree"
TREE_FOCUS_KEY="Bspace"
TREE_FOCUS_OPTION="@sidebar-tree-focus"
TREE_COMMAND="tree"
TREE_COMMAND_OPTION="@sidebar-tree-command"
TREE_PAGER='sh -c "LESS= less --dumb --chop-long-lines --tilde --IGNORE-CASE --RAW-CONTROL-CHARS"'
TREE_PAGER_OPTION="@sidebar-tree-pager"
TREE_POSITION="left"
TREE_POSITION_OPTION="@sidebar-tree-position"
TREE_WIDTH="40"
TREE_WIDTH_OPTION="@sidebar-tree-width"
SUPPORTED_TMUX_VERSION="1.9"
SIDEBAR_DIR="$HOME/.tmux/sidebar"

38
.tmux/sidebar.tmux Executable file
View File

@@ -0,0 +1,38 @@
#!/usr/bin/env bash
CURRENT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
SCRIPTS_DIR="$CURRENT_DIR/scripts"
source "$SCRIPTS_DIR/helpers.sh"
source "$SCRIPTS_DIR/variables.sh"
source "$SCRIPTS_DIR/tree_helpers.sh"
set_default_key_binding_options() {
local tree_command="$(tree_command)"
local tree_key="$(tree_key)"
local tree_focus_key="$(tree_focus_key)"
local tree_pager="$(tree_pager)"
local tree_position="$(tree_position)"
local tree_width="$(tree_width)"
set_tmux_option "${VAR_KEY_PREFIX}-${tree_key}" "$tree_command | ${tree_pager},${tree_position},${tree_width}"
set_tmux_option "${VAR_KEY_PREFIX}-${tree_focus_key}" "$tree_command | ${tree_pager},${tree_position},${tree_width},focus"
}
set_key_bindings() {
local stored_key_vars="$(stored_key_vars)"
local search_var
local key
local pattern
for option in $stored_key_vars; do
key="$(get_key_from_option_name "$option")"
value="$(get_value_from_option_name "$option")"
tmux bind-key "$key" run-shell "$SCRIPTS_DIR/toggle.sh '$value' '#{pane_id}'"
done
}
main() {
set_default_key_binding_options
set_key_bindings
}
main

View File

@@ -0,0 +1 @@
/Users/eragos/.dotfiles/.tmux/scripts 115