158 lines
4.1 KiB
Bash
Executable File
158 lines
4.1 KiB
Bash
Executable File
#!/bin/sh
|
|
|
|
# Support vim's text objects in tmux's copy-mode.
|
|
|
|
get_var() {
|
|
tmux display-message -p "#{$1}"
|
|
}
|
|
|
|
command_prompt() {
|
|
tmux command-prompt -k -I "$2" -p "$1" 'display-message -p "%%"'
|
|
}
|
|
|
|
mode="$(get_var pane_mode)"
|
|
if [ "$mode" != copy-mode ]; then
|
|
>&2 printf "%s: Not in copy mode\n" "$0"
|
|
exit 1
|
|
fi
|
|
|
|
# cancel copy-mode when not in 'visual' mode (i.e. selection is present)
|
|
selection_present="$(get_var selection_present)"
|
|
if [ "$selection_present" -eq 0 ]; then
|
|
tmux send -X cancel
|
|
exit 0
|
|
fi
|
|
|
|
# get motion
|
|
motion="$(command_prompt "(operator-pending)")"
|
|
|
|
# ignore any args
|
|
set --
|
|
|
|
case "$motion" in
|
|
w)
|
|
# TODO: merge all get_var calls
|
|
copy_x="$(get_var copy_cursor_x)"
|
|
copy_line="$(get_var copy_cursor_line)"
|
|
|
|
# Do nothing if the cursor sits on a space
|
|
# TODO: Do the same for other non-word characters
|
|
# NOTE: Using grep here, as cut does not support UTF-8
|
|
char_curr="$(printf %s "$copy_line" | grep -Po "^.{$copy_x}\\K.")"
|
|
[ "$char_curr" != " " ] || return 0
|
|
|
|
copy_line_post="$(printf %s "$copy_line" | grep -Po "^.{$copy_x}\\K.*")"
|
|
copy_line_pre="$(printf %s "$copy_line" | grep -Po "^..{$copy_x}")"
|
|
copy_word="$(get_var copy_cursor_word)"
|
|
|
|
# send "boe"
|
|
if [ "${copy_line_post#"$copy_word"}" = "$copy_line_post" ];
|
|
then
|
|
# not on beginning of word
|
|
set -- "$@" send -X previous-word \;
|
|
set -- "$@" send -X other-end \;
|
|
fi
|
|
if [ "${copy_line_pre%"$copy_word"}" = "$copy_line_pre" ];
|
|
then
|
|
# not on end of word
|
|
set -- "$@" send -X next-word-end \;
|
|
fi
|
|
;;
|
|
W)
|
|
copy_x="$(get_var copy_cursor_x)"
|
|
copy_line="$(get_var copy_cursor_line)"
|
|
|
|
# Do nothing if the cursor sits on the space
|
|
char_curr="$(printf %s "$copy_line" | grep -Po "^.{$copy_x}\\K.")"
|
|
[ "$char_curr" != " " ] || return 0
|
|
|
|
char_pre="$(printf %s "$copy_line" | grep -Po "^.{$((copy_x - 1))}\\K.")"
|
|
char_post="$(printf %s "$copy_line" | grep -Po "^..{$copy_x}\\K.")"
|
|
|
|
# default to a space if the cursor is at the beginning or end of
|
|
# the line
|
|
: "${char_pre:= }"
|
|
: "${char_post:= }"
|
|
|
|
# send "BoE"
|
|
if [ "$char_pre" != " " ]; then
|
|
# not on beginning of WORD
|
|
set -- "$@" send -X previous-space \;
|
|
set -- "$@" send -X other-end \;
|
|
fi
|
|
if [ "$char_post" != " " ]; then
|
|
# not on end of WORD
|
|
set -- "$@" send -X next-space-end \;
|
|
fi
|
|
;;
|
|
p)
|
|
# send "{j0o}k$"
|
|
|
|
set -- "$@" send -X previous-paragraph \;
|
|
|
|
scroll_pos="$(get_var scroll_position)"
|
|
hist_size="$(get_var history_size)"
|
|
cursor_y="$(get_var copy_cursor_y)"
|
|
# don't move down if we're at the very first paragraph
|
|
if [ "$scroll_pos" -lt "$hist_size" ] || [ "$cursor_y" -gt 0 ]
|
|
then
|
|
set -- "$@" send -X cursor-down \;
|
|
fi
|
|
|
|
set -- "$@" send -X start-of-line \;
|
|
set -- "$@" send -X other-end \;
|
|
set -- "$@" send -X next-paragraph \;
|
|
|
|
scroll_pos="$(get_var scroll_position)"
|
|
cursor_y="$(get_var copy_cursor_y)"
|
|
pane_height="$(get_var pane_height)"
|
|
: "$((pane_height -= 1))"
|
|
# don't move up if we're at the very last paragraph
|
|
if [ "$scroll_pos" -gt 0 ] || [ "$cursor_y" -lt "$pane_height" ]
|
|
then
|
|
set -- "$@" send -X cursor-up \;
|
|
fi
|
|
|
|
set -- "$@" send -X end-of-line \;
|
|
;;
|
|
# TODO: All following break when the cursor sits on the start or end
|
|
\")
|
|
set -- "$@" send -X jump-to-backward '"' \;
|
|
set -- "$@" send -X other-end \;
|
|
set -- "$@" send -X jump-to-forward '"' \;
|
|
;;
|
|
\')
|
|
set -- "$@" send -X jump-to-backward "'" \;
|
|
set -- "$@" send -X other-end \;
|
|
set -- "$@" send -X jump-to-forward "'" \;
|
|
;;
|
|
\`)
|
|
set -- "$@" send -X jump-to-backward '`' \;
|
|
set -- "$@" send -X other-end \;
|
|
set -- "$@" send -X jump-to-forward '`' \;
|
|
;;
|
|
'[|]')
|
|
set -- "$@" send -X jump-to-backward '[' \;
|
|
set -- "$@" send -X other-end \;
|
|
set -- "$@" send -X jump-to-forward ']' \;
|
|
;;
|
|
'b|(|)')
|
|
set -- "$@" send -X jump-to-backward '(' \;
|
|
set -- "$@" send -X other-end \;
|
|
set -- "$@" send -X jump-to-forward ')' \;
|
|
;;
|
|
'<|>')
|
|
set -- "$@" send -X jump-to-backward '<' \;
|
|
set -- "$@" send -X other-end \;
|
|
set -- "$@" send -X jump-to-forward '>' \;
|
|
;;
|
|
'B|{|}')
|
|
# TODO: make this work over multiple lines
|
|
set -- "$@" send -X jump-to-backward '{' \;
|
|
set -- "$@" send -X other-end \;
|
|
set -- "$@" send -X jump-to-forward '}' \;
|
|
;;
|
|
esac
|
|
|
|
[ $# -eq 0 ] || tmux "$@"
|