Add better mouse plugin to tmux to adjust sensitive scrolling

This commit is contained in:
Shaun Reed 2020-02-19 15:52:34 +00:00
parent fccfc90ace
commit e1d466362d
8 changed files with 352 additions and 3 deletions

View File

@ -109,8 +109,12 @@ set -g default-terminal "screen-256color"
# Mode
set -g mode-style bg=colour100,fg=colour235
# List of plugins
#set -g @plugin 'tmux-plugins/tpm'
# List of plugins and their settings
set -g @plugin 'tmux-plugins/tpm'
set -g @plugin 'nhdaly/tmux-better-mouse-mode'
set -g @scroll-speed-num-lines-per-scroll 2
#set -g @plugin 'tmux-plugins/tmux-sensible'
#set -g @plugin 'kristijanhusak/tmux-simple-git-status'
@ -120,5 +124,5 @@ set -g mode-style bg=colour100,fg=colour235
# set -g @plugin 'git@bitbucket.com/user/plugin'
# Initialize TMUX plugin manager (keep this line at the very bottom of tmux.conf)
#run -b '~/.tmux/plugins/tpm/tpm'
run -b '~/.tmux/plugins/tpm/tpm'

View File

@ -0,0 +1,10 @@
language: bash
before_script:
- curl -L "https://github.com/tmux/tmux/releases/download/2.2/tmux-2.2.tar.gz" | tar zx
- cd tmux-2.2; ./configure && make; cd ..
- curl -L "https://storage.googleapis.com/google-code-archive-downloads/v2/code.google.com/shunit2/shunit2-2.1.6.tgz" | tar zx
script:
- bash tests/*.sh

View File

@ -0,0 +1,21 @@
The MIT License (MIT)
Copyright (c) 2015 Nathan Daly
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

View File

@ -0,0 +1,103 @@
# Tmux Better Mouse Mode
A tmux plugin to better manage the mouse.
Provides options to control mouse behavior in tmux, so it will behave exactly how you want:
- Emulate mouse-support for full-screen programs like `less` that don't provide built in mouse support.
- Exit `copy-mode` and return to your prompt by scrolling back all the way down to the bottom.
- Adjust your scrolling speed.
- And more!
Finally, `tmux` version 2.1 introduced backwards-incompatible changes to the mouse behavior, and this plugin restores the old mouse behavior. `tmux` version 2.2 mostly restores the 2.0 mouse behavior, but this plugin improves tmux mouse mode beyond those changes and provides you with more control.
### Requirements
This plugin is intended for `tmux` version 2.1 and higher. It does not work for 2.0 or below.
NOTE: This plugin provides options to *change* the mouse-mode behavior, but does not enable mouse-mode.
To enable mouse-mode in tmux 2.1+, put the following line in your `~/.tmux.conf`:
set-option -g mouse on
### Key bindings
This plugin will overwrite the values for `WheelUpPane` and `WheelDownPane` in tmux in order to configure mouse scrolling.
To see your current setting for these variables, check the output of `tmux list-keys -T root`.
### Installation with [Tmux Plugin Manager](https://github.com/tmux-plugins/tpm) (recommended)
1. Add this plugin to the list of TPM plugins in `.tmux.conf`:
set -g @plugin 'nhdaly/tmux-better-mouse-mode'
1. Press `prefix` + <kbd>I</kbd> or run `$TMUX_PLUGIN_MANAGER_PATH/tpm/scripts/install_plugins.sh` to fetch the plugin and source it. You should now be able to
use the plugin.
1. To enable mouse-mode in tmux 2.1+, put the following line in your `.tmux.conf`:
set-option -g mouse on
### Manual Installation
1. Clone the repo:
$ git clone https://github.com/nhdaly/tmux-better-mouse-mode ~/clone/path
1. Add this line to the bottom of `.tmux.conf`:
run-shell ~/clone/path/scroll_copy_mode.tmux
1. Reload TMUX environment:
# type this in terminal
$ tmux source-file ~/.tmux.conf
You should now be able to use the plugin.
### Configuration
Set these options in `.tmux.conf`. For example, `set -g @scroll-down-exit-copy-mode "off"` to disable scrolling down exits copy-mode.
- `scroll-down-exit-copy-mode` - When enabled, the pane exits `copy-mode` when scrolling hits the bottom of the scroll-back history.
- "on" (default) - Scrolling can exit `copy-mode`.
- "off" - Scrolling to bottom will stay in `copy-mode`.
- `scroll-without-changing-pane` - When enabled, scrolling the mouse will not select the moused-over pane, allowing you to scroll a window just to read previous output and then keep typing in the current pane. Enabling this feature is a change from `tmux 2.0` settings, but may be an improvement.
- "on" - Scroll events are sent to moused-over pane.
- "off" (default) - Scroll events stay in currently selected pane.
- `scroll-in-moused-over-pane` - When enabled, scrolling with your mouse over a pane will perform the scroll in that pane, instead of the currently selected one. If `scroll-without-changing-pane` is set to `"off"`, this will also select the moused-over pane.
- "on" (default) - Scroll events select and scroll the moused-over pane.
- "off" - Scroll events are ingored unless the mouse is over the currently selected pane.
- `scroll-speed-num-lines-per-scroll` - Sets the number of lines to scroll per mouse wheel scroll event. The default option is 3, which was the scroll speed in `tmux 2.0`. Larger numbers scroll faster. To slow down scrolling to slower than one line per wheel click, set the value to a decimal between 0.0 and 1.0. With a decimal value, only that fraction of wheel events will take effect. The value must be > 0. Examples:
- "3" (default) - Scroll three lines per every mouse wheel click.
- "1" - One line per mouse wheel scroll click (smoothest).
- "0.5" - Scroll one line only on every other mouse wheel scroll click.
- "0.25" - Scroll one line only on every fourth mouse wheel scroll click.
- `emulate-scroll-for-no-mouse-alternate-buffer` - When enabled, tmux will emulate scrolling for "full-screen", alternate buffer programs, such as `less`, `man`, or `vi` that don't themselves already support mouse interactions. It will not enter `copy-mode` and will not scroll through pane output history, but will instead send `<up-arrow>` (<kbd>&uparrow;</kbd>) and `<down-arrow>`(<kbd>&downarrow;</kbd>) keys to the application. The scroll speed is also set by `@scroll-speed-num-lines-per-scroll` above.
This option defaults to "off", which matches the behavior in `tmux 2.0`. Note, though, that this default behavior may be undesirable since the pane history gets munged when entering a full-screen alternate buffer program. It's a pretty great option is all I'm saying.
- "on" - <kbd>&uparrow;</kbd> and <kbd>&downarrow;</kbd> keys are passed to the alternate buffer program on scroll events.
- "off" (default) - Scroll event causes scrollback in pane output.
### Contributions
[@nhdaly](https://github.com/nhdaly)
[@corv89](https://github.com/corv89)
[@pallxk ](https://github.com/pallxk )
[@hughdavenport](https://github.com/hughdavenport)
[@giddie](https://github.com/giddie)
[@pochemuto](https://github.com/pochemuto)
[@zeorin](https://github.com/zeorin)
[@alcesleo](https://github.com/alcesleo)
[@iamjamestl](https://github.com/iamjamestl)
### Inspiration
Inspired by David Verhasselt's in depth article on Tmux 2.1's changes to Mouse support and scrolling:
http://www.davidverhasselt.com/better-mouse-scrolling-in-tmux/
### License
[MIT](LICENSE.md)

View File

@ -0,0 +1,22 @@
#!/usr/bin/env bash
num_scrolls_to_scroll=$1
get_count_cmd=`tmux show-environment -g __scroll_copy_mode__slow_scroll_count`
eval $get_count_cmd
# Save the current count so we can use it in the return statement at the end.
CURRENT_COUNT=$__scroll_copy_mode__slow_scroll_count
# Now increment and loop around if we've finished the scroll cycle.
__scroll_copy_mode__slow_scroll_count=$(( (__scroll_copy_mode__slow_scroll_count + 1) % num_scrolls_to_scroll))
# Store the new value in tmux.
tmux set-environment -g __scroll_copy_mode__slow_scroll_count $__scroll_copy_mode__slow_scroll_count
# Return true if this is the first scroll for this scroll-cycle, and false if we haven't hit the end of the cycle.
[ $CURRENT_COUNT -eq 0 ]

View File

@ -0,0 +1,15 @@
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
}
get_tmux_version() {
tmux -V | cut -d " " -f 2
}

View File

@ -0,0 +1,100 @@
#!/usr/bin/env bash
CURRENT_DIR="$( dirname "$0" )"
. "$CURRENT_DIR/scripts/helpers.sh"
scroll_down_exit_copy_mode_option="@scroll-down-exit-copy-mode"
scroll_in_moused_over_pane_option="@scroll-in-moused-over-pane"
scroll_without_changing_pane_option="@scroll-without-changing-pane"
scroll_speed_num_lines_per_scroll_option="@scroll-speed-num-lines-per-scroll"
deprecated_prevent_scroll_for_fullscreen_alternate_buffer_option="@prevent-scroll-for-fullscreen-alternate-buffer"
emulate_scroll_for_no_mouse_alternate_buffer_option="@emulate-scroll-for-no-mouse-alternate-buffer"
get_repeated_scroll_cmd() {
local scroll_speed_num_lines_per_scroll=$(get_tmux_option "$scroll_speed_num_lines_per_scroll_option" "3")
local cmd=""
if echo - | awk "{ if ($scroll_speed_num_lines_per_scroll >= 1) { exit 0 } else { exit 1 } }" ; then # Positive whole number speed (round down).
for ((i = 1; i <= scroll_speed_num_lines_per_scroll; i++)); do
cmd=$cmd"send-keys $1 ; "
done
elif echo - | awk "{ if ($scroll_speed_num_lines_per_scroll > 0) { exit 0 } else { exit 1 } }" ; then # Positive decimal between 0 and 1 (treat as percent).
# Skip enough scrolls so that we scroll only on the specified percent of scrolls.
local num_scrolls_to_scroll=`echo - | awk "{print int( 1/$scroll_speed_num_lines_per_scroll ) }"`
tmux set-environment __scroll_copy_mode__slow_scroll_count 0;
cmd="if -t = \\\"$CURRENT_DIR/only_scroll_sometimes.sh $num_scrolls_to_scroll\\\" \\\"send-keys $1\\\" \\\"\\\"";
fi
echo "$cmd"
}
better_mouse_mode_main() {
local scroll_down_to_exit=$(get_tmux_option "$scroll_down_exit_copy_mode_option" "on")
local scroll_in_moused_over_pane=$(get_tmux_option "$scroll_in_moused_over_pane_option" "on")
local scroll_without_changing_pane=$(get_tmux_option "$scroll_without_changing_pane_option" "off")
local deprecated_prevent_scroll_for_fullscreen_alternate_buffer=$(get_tmux_option "$deprecated_prevent_scroll_for_fullscreen_alternate_buffer_option" "off")
local emulate_scroll_for_no_mouse_alternate_buffer=$(get_tmux_option "$emulate_scroll_for_no_mouse_alternate_buffer_option" "$deprecated_prevent_scroll_for_fullscreen_alternate_buffer")
local enter_copy_mode_cmd="copy-mode"
local select_moused_over_pane_cmd=""
local check_for_fullscreen_alternate_buffer=""
if [ "$scroll_down_to_exit" = 'on' ] ; then
enter_copy_mode_cmd="copy-mode -e"
fi
if [ "$scroll_in_moused_over_pane" = 'on' ] ; then
select_moused_over_pane_cmd="select-pane -t= ;"
fi
if [ "$scroll_without_changing_pane" = 'on' ] ; then
enter_copy_mode_cmd="$enter_copy_mode_cmd -t="
select_moused_over_pane_cmd=""
fi
if [ "$emulate_scroll_for_no_mouse_alternate_buffer" = 'on' ] ; then
check_for_fullscreen_alternate_buffer="#{alternate_on}"
fi
# Start copy mode when scrolling up and exit when scrolling down to bottom.
# The "#{mouse_any_flag}" check just sends scrolls to any program running that
# has mouse support (like vim).
# NOTE: the successive levels of quoting commands gets a little confusing
# here. Tmux uses quoting to denote levels of the if-blocks below. The
# pattern used here for consistency is " \" ' \\\" \\\" ' \" " -- that is,
# " for top-level quotes, \" for the next level in, ' for the third level,
# and \\\" for the fourth (note that the fourth comes from inside get_repeated_scroll_cmd).
tmux bind-key -n WheelUpPane \
if -Ft= "#{mouse_any_flag}" \
"send-keys -M" \
" \
if -Ft= '$check_for_fullscreen_alternate_buffer' \
\"$(get_repeated_scroll_cmd "-t= up")\" \
\" \
$select_moused_over_pane_cmd \
if -Ft= '#{pane_in_mode}' \
'$(get_repeated_scroll_cmd -M)' \
'$enter_copy_mode_cmd ; $(get_repeated_scroll_cmd -M)' \
\" \
"
# Enable sending scroll-downs to the moused-over-pane.
# NOTE: the quoting pattern used here and in the above command for
# consistency is " \" ' \\\" \\\" ' \" " -- that is, " for top-level quotes,
# \" for the next level in, ' for the third level, and \\\" for the fourth
# (note that the fourth comes from inside get_repeated_scroll_cmd).
tmux bind-key -n WheelDownPane \
if -Ft= "#{mouse_any_flag}" \
"send-keys -M" \
" \
if -Ft= \"$check_for_fullscreen_alternate_buffer\" \
\"$(get_repeated_scroll_cmd "-t= down")\" \
\"$select_moused_over_pane_cmd $(get_repeated_scroll_cmd -M)\" \
"
# For tmux 2.4+ you have to set the mouse wheel options seperately for copy-mode than from root.
local tmux_version=$(get_tmux_version)
if echo - | awk "{ if ($tmux_version >= 2.4) { exit 0 } else { exit 1 } }" ; then # Use copy-mode tables to set scroll speed.
local scroll_speed_num_lines_per_scroll=$(get_tmux_option "$scroll_speed_num_lines_per_scroll_option" "3")
tmux bind-key -Tcopy-mode WheelUpPane send -N"$scroll_speed_num_lines_per_scroll" -X scroll-up
tmux bind-key -Tcopy-mode WheelDownPane send -N"$scroll_speed_num_lines_per_scroll" -X scroll-down
tmux bind-key -Tcopy-mode-vi WheelUpPane send -N"$scroll_speed_num_lines_per_scroll" -X scroll-up
tmux bind-key -Tcopy-mode-vi WheelDownPane send -N"$scroll_speed_num_lines_per_scroll" -X scroll-down
fi
}
better_mouse_mode_main

View File

@ -0,0 +1,74 @@
#!/usr/bin/env bash
# Setup
#tmux() {
# # Forward the "getter" calls to actual tmux, but change the setters to just
# # echo, so we can test what its setting.
# if [[ "$1" == "show-option" ]] ; then
# tmux-2.2/tmux "$@"
# else
# echo "$@"
# fi
#}
tmux() {
tmux-2.2/tmux "$@"
}
export -f tmux
# ------ Unit Tests -----------------------
testBasicBindKeysAreCalled() {
bash scroll_copy_mode.tmux
assertNotNull "`tmux list-keys -T root | grep 'WheelUpPane'`"
assertNotNull "`tmux list-keys -T root | grep 'WheelDownPane'`"
}
checkScrollSpeedSetCorrectly() {
testSpeed="$1"
expectedValue="$2"
tmux set -g @scroll-speed-num-lines-per-scroll $testSpeed
bash scroll_copy_mode.tmux
# Make sure send-keys shows up correct number of times in up and down scroll bindings.
assertEquals 'number of `send-keys` per scroll up not equal to user setting' $expectedValue `tmux list-keys -T root | grep 'WheelUpPane' | grep -o "'send-keys[^']*'" | head -n 1 | grep -o 'send-keys' | wc -l`
assertEquals 'number of `send-keys` per scroll down not equal to user setting' $expectedValue `tmux list-keys -T root | grep 'WheelDownPane' | grep -o "'send-keys[^']*'" | head -n 1 | grep -o 'send-keys' | wc -l`
}
testValidIntegerScrollSpeeds() {
checkScrollSpeedSetCorrectly 1 1
checkScrollSpeedSetCorrectly 2 2
checkScrollSpeedSetCorrectly 10 10
checkScrollSpeedSetCorrectly 0 0
checkScrollSpeedSetCorrectly 2.5 2
}
testInvalidIntegerScrollSpeeds() {
checkScrollSpeedSetCorrectly "-1" 0
checkScrollSpeedSetCorrectly "-10" 0
checkScrollSpeedSetCorrectly "-0.1" 0
}
checkFractionalScrollSpeedSetCorrectly() {
testSpeed="$1"
expectedNumScrollsBeforeScroll="$2"
tmux set -g @scroll-speed-num-lines-per-scroll $testSpeed
bash scroll_copy_mode.tmux
assertNotNull "`tmux list-keys -T root | grep 'WheelUpPane' | grep \"only_scroll_sometimes.sh $expectedNumScrollsBeforeScroll\"`"
assertNotNull "`tmux list-keys -T root | grep 'WheelDownPane' | grep \"only_scroll_sometimes.sh $expectedNumScrollsBeforeScroll\"`"
assertNotNull "`tmux show-environment __scroll_copy_mode__slow_scroll_count`"
}
testValidFractionalScrollSpeeds() {
checkFractionalScrollSpeedSetCorrectly 0.5 2
checkFractionalScrollSpeedSetCorrectly 0.25 4
checkFractionalScrollSpeedSetCorrectly 0.33 3
}
# --------- Run tests command -------------
. shunit2-2.1.6/src/shunit2